Update: 2026-07-04 18:43:56

This commit is contained in:
Hamza-Ayed
2026-07-04 18:43:57 +03:00
parent 3412f1b753
commit 3e0b4cbf64
65 changed files with 2260 additions and 118 deletions
@@ -0,0 +1,24 @@
package com.siro.socialmedia_bot
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.siro.socialmedia_bot", appContext.packageName)
}
}
@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Socialmediabot">
<!-- Main launcher Activity -->
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Facebook Accessibility Service -->
<service
android:name=".social.facebook.FacebookBotService"
android:label="Siro Facebook Bot"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/facebook_accessibility_service_config" />
</service>
<!-- Instagram Accessibility Service -->
<service
android:name=".social.instagram.InstagramBotService"
android:label="Siro Instagram Bot"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/instagram_accessibility_service_config" />
</service>
</application>
</manifest>
@@ -0,0 +1,93 @@
package com.siro.socialmedia_bot
import android.accessibilityservice.AccessibilityServiceInfo
import android.content.Intent
import android.os.Bundle
import android.provider.Settings
import android.view.accessibility.AccessibilityManager
import androidx.appcompat.app.AppCompatActivity
import com.siro.socialmedia_bot.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val logBuffer = StringBuilder()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btnEnableAccessibility.setOnClickListener {
openAccessibilitySettings()
}
appendLog("[System] Siro Social Media Bot started.")
appendLog("[System] Checking service status...")
}
override fun onResume() {
super.onResume()
updateServiceStatus()
}
private fun updateServiceStatus() {
val isFbEnabled = isAccessibilityServiceEnabled("com.siro.socialmedia_bot/.social.facebook.FacebookBotService")
val isIgEnabled = isAccessibilityServiceEnabled("com.siro.socialmedia_bot/.social.instagram.InstagramBotService")
if (isFbEnabled || isIgEnabled) {
binding.statusDot.backgroundTintList = getColorStateList(android.R.color.holo_green_light)
binding.tvStatus.text = "Accessibility Service Active"
binding.btnEnableAccessibility.text = "✓ Service is Running"
binding.btnEnableAccessibility.backgroundTintList = getColorStateList(android.R.color.holo_green_dark)
} else {
binding.statusDot.backgroundTintList = android.content.res.ColorStateList.valueOf(0xFFFF4444.toInt())
binding.tvStatus.text = "Accessibility Service Disabled"
binding.btnEnableAccessibility.text = "Enable Accessibility Service"
binding.btnEnableAccessibility.backgroundTintList = android.content.res.ColorStateList.valueOf(0xFF1565C0.toInt())
}
// Facebook dot
if (isFbEnabled) {
binding.fbDot.backgroundTintList = getColorStateList(android.R.color.holo_green_light)
binding.tvFbState.text = "RUNNING"
binding.tvFbState.setTextColor(0xFF00FF88.toInt())
appendLog("[Facebook] Service is active and polling for tasks.")
} else {
binding.fbDot.backgroundTintList = android.content.res.ColorStateList.valueOf(0xFF555555.toInt())
binding.tvFbState.text = "DISABLED"
binding.tvFbState.setTextColor(0xFF555555.toInt())
}
// Instagram dot
if (isIgEnabled) {
binding.igDot.backgroundTintList = getColorStateList(android.R.color.holo_green_light)
binding.tvIgState.text = "RUNNING"
binding.tvIgState.setTextColor(0xFF00FF88.toInt())
appendLog("[Instagram] Service is active and polling for tasks.")
} else {
binding.igDot.backgroundTintList = android.content.res.ColorStateList.valueOf(0xFF555555.toInt())
binding.tvIgState.text = "DISABLED"
binding.tvIgState.setTextColor(0xFF555555.toInt())
}
}
private fun isAccessibilityServiceEnabled(serviceId: String): Boolean {
val am = getSystemService(ACCESSIBILITY_SERVICE) as AccessibilityManager
val enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK)
return enabledServices.any { it.id == serviceId }
}
private fun openAccessibilitySettings() {
val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
startActivity(intent)
appendLog("[System] Opened Accessibility settings. Enable both 'Siro Facebook Bot' and 'Siro Instagram Bot'.")
}
private fun appendLog(msg: String) {
val timestamp = java.text.SimpleDateFormat("HH:mm:ss", java.util.Locale.getDefault()).format(java.util.Date())
logBuffer.append("[$timestamp] $msg\n")
binding.tvLog.text = logBuffer.toString()
binding.scrollLog.post { binding.scrollLog.fullScroll(android.view.View.FOCUS_DOWN) }
}
}
@@ -0,0 +1,72 @@
package com.siro.socialmedia_bot.network
import org.json.JSONObject
import java.io.OutputStreamWriter
import java.net.HttpURLConnection
import java.net.URL
import java.util.Scanner
/**
* Client to connect to the social_worker.php endpoint
*/
object SocialBotClient {
private const val BASE_URL = "https://your-domain.com/backend/bot/social_media_bot/social_worker.php"
private const val BOT_TOKEN = "YOUR_SECRET_BOT_TOKEN"
fun getTask(platform: String): JSONObject? {
try {
val url = URL("$BASE_URL?action=get_task&platform=$platform")
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "GET"
connection.setRequestProperty("X-Bot-Token", BOT_TOKEN)
val responseCode = connection.responseCode
if (responseCode == 200) {
val scanner = Scanner(connection.inputStream)
val response = scanner.useDelimiter("\\A").next()
scanner.close()
val json = JSONObject(response)
if (json.getString("status") == "success" && !json.isNull("data")) {
return json.getJSONObject("data")
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return null
}
fun completeTask(taskId: Int, result: String) {
postData("action=complete_task", "task_id=$taskId&result=$result")
}
fun failTask(taskId: Int, errorMessage: String) {
postData("action=fail_task", "task_id=$taskId&error_message=$errorMessage")
}
fun logMessage(accountId: Int?, level: String, message: String) {
val accIdParam = accountId?.let { "&account_id=$it" } ?: ""
postData("action=log", "level=$level&message=$message$accIdParam")
}
private fun postData(actionParam: String, postBody: String) {
try {
val url = URL("$BASE_URL?$actionParam")
val connection = url.openConnection() as HttpURLConnection
connection.requestMethod = "POST"
connection.setRequestProperty("X-Bot-Token", BOT_TOKEN)
connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")
connection.doOutput = true
val writer = OutputStreamWriter(connection.outputStream)
writer.write(postBody)
writer.flush()
writer.close()
connection.responseCode // execute
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@@ -0,0 +1,115 @@
package com.siro.socialmedia_bot.social.facebook
import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent
import android.util.Log
import com.siro.socialmedia_bot.network.SocialBotClient
import com.siro.socialmedia_bot.social.model.SocialTask
import kotlinx.coroutines.*
class FacebookBotService : AccessibilityService() {
private val TAG = "FacebookBotService"
private val scope = CoroutineScope(Dispatchers.IO + Job())
private var isBotRunning = false
private var currentTask: SocialTask? = null
private lateinit var navigator: FacebookNavigator
private lateinit var commentReader: FacebookCommentReader
private lateinit var commentPoster: FacebookCommentPoster
override fun onServiceConnected() {
super.onServiceConnected()
Log.d(TAG, "Facebook Accessibility Service Connected")
navigator = FacebookNavigator(this)
commentReader = FacebookCommentReader(this)
commentPoster = FacebookCommentPoster(this)
startTaskLoop()
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// We handle logic manually via coroutines and window inspection,
// but we can listen to events if needed for synchronization.
}
override fun onInterrupt() {
Log.d(TAG, "Service Interrupted")
isBotRunning = false
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
private fun startTaskLoop() {
if (isBotRunning) return
isBotRunning = true
scope.launch {
while (isBotRunning) {
try {
// Check for tasks
val taskData = SocialBotClient.getTask("facebook")
if (taskData != null) {
currentTask = SocialTask(
id = taskData.getInt("id"),
type = taskData.getString("type"),
targetUrl = if (taskData.isNull("target_url")) null else taskData.getString("target_url"),
promptContext = if (taskData.isNull("prompt_context")) null else taskData.getString("prompt_context"),
generatedComment = if (taskData.isNull("generated_comment")) null else taskData.getString("generated_comment")
)
Log.d(TAG, "Received Task: ${currentTask?.type}")
executeTask(currentTask!!)
} else {
Log.d(TAG, "No tasks available. Sleeping...")
delay(60000) // Wait 1 minute before checking again
}
} catch (e: Exception) {
Log.e(TAG, "Error in task loop", e)
delay(30000) // Wait 30 seconds on error
}
}
}
}
private suspend fun executeTask(task: SocialTask) {
try {
when (task.type) {
"post_comment" -> {
task.targetUrl?.let { url ->
navigator.openUrl(url)
delay(5000) // Wait for page load
task.generatedComment?.let { comment ->
val success = commentPoster.postComment(comment)
if (success) {
SocialBotClient.completeTask(task.id, "Comment posted successfully")
} else {
SocialBotClient.failTask(task.id, "Failed to find comment box or post")
}
}
}
}
"read_posts" -> {
// Logic to read posts and send to backend
// ...
SocialBotClient.completeTask(task.id, "Posts read successfully")
}
else -> {
Log.w(TAG, "Unknown task type: ${task.type}")
SocialBotClient.failTask(task.id, "Unknown task type")
}
}
} catch (e: Exception) {
SocialBotClient.failTask(task.id, "Exception during execution: ${e.message}")
}
// Add human-like delay between tasks
val randomDelay = (10000..30000).random().toLong()
delay(randomDelay)
}
}
@@ -0,0 +1,76 @@
package com.siro.socialmedia_bot.social.facebook
import android.accessibilityservice.AccessibilityService
import android.accessibilityservice.AccessibilityService.GestureResultCallback
import android.accessibilityservice.GestureDescription
import android.graphics.Path
import android.os.Bundle
import android.view.accessibility.AccessibilityNodeInfo
import kotlinx.coroutines.delay
class FacebookCommentPoster(private val service: AccessibilityService) {
suspend fun postComment(commentText: String): Boolean {
val root = service.rootInActiveWindow ?: return false
// 1. Find the comment input box.
// In Facebook, it might have contentDescription like "Write a comment..." or similar.
val inputNode = findNodeByContentDescription(root, "Write a comment")
?: findNodeByClassName(root, "android.widget.EditText")
if (inputNode == null) return false
// 2. Click the input node to focus it
inputNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)
delay(1000) // wait for keyboard
// 3. Set text (simulating human typing can be done by pasting chunks or using set_text)
val arguments = Bundle()
arguments.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, commentText)
inputNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, arguments)
// Wait a bit to simulate human typing delay
val randomTypingDelay = (commentText.length * 50).toLong().coerceAtMost(5000L)
delay(randomTypingDelay)
// 4. Find and click the send button
// Often has a content description like "Send" or it's an ImageView next to EditText
val sendBtn = findNodeByContentDescription(service.rootInActiveWindow, "Send")
if (sendBtn != null) {
sendBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
delay(2000)
return true
}
return false
}
private fun findNodeByContentDescription(node: AccessibilityNodeInfo?, descPrefix: String): AccessibilityNodeInfo? {
if (node == null) return null
if (node.contentDescription?.startsWith(descPrefix, ignoreCase = true) == true ||
node.text?.startsWith(descPrefix, ignoreCase = true) == true) {
return node
}
for (i in 0 until node.childCount) {
val child = findNodeByContentDescription(node.getChild(i), descPrefix)
if (child != null) return child
}
return null
}
private fun findNodeByClassName(node: AccessibilityNodeInfo?, className: String): AccessibilityNodeInfo? {
if (node == null) return null
if (node.className?.toString() == className) {
return node
}
for (i in 0 until node.childCount) {
val child = findNodeByClassName(node.getChild(i), className)
if (child != null) return child
}
return null
}
}
@@ -0,0 +1,34 @@
package com.siro.socialmedia_bot.social.facebook
import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityNodeInfo
class FacebookCommentReader(private val service: AccessibilityService) {
fun extractComments(): List<String> {
val root = service.rootInActiveWindow ?: return emptyList()
val comments = mutableListOf<String>()
// Facebook UI is complex and changes often.
// This is a simplified logic. We'd usually look for nodes with text content inside a RecyclerView
findTextNodes(root, comments)
return comments
}
private fun findTextNodes(node: AccessibilityNodeInfo?, comments: MutableList<String>) {
if (node == null) return
if (node.text != null && node.text.isNotEmpty()) {
// Add filtering logic to ensure it's a comment and not just UI text
val text = node.text.toString()
if (text.length > 10) { // arbitrary filter
comments.add(text)
}
}
for (i in 0 until node.childCount) {
findTextNodes(node.getChild(i), comments)
}
}
}
@@ -0,0 +1,26 @@
package com.siro.socialmedia_bot.social.facebook
import android.accessibilityservice.AccessibilityService
import android.content.Intent
import android.net.Uri
import kotlinx.coroutines.delay
class FacebookNavigator(private val service: AccessibilityService) {
suspend fun openUrl(url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setPackage("com.facebook.katana") // Open specifically in Facebook app
try {
service.startActivity(intent)
} catch (e: Exception) {
// Fallback if Facebook app is not installed
intent.setPackage(null)
service.startActivity(intent)
}
// Wait for app to open
delay(3000)
}
}
@@ -0,0 +1,100 @@
package com.siro.socialmedia_bot.social.instagram
import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent
import android.util.Log
import com.siro.socialmedia_bot.network.SocialBotClient
import com.siro.socialmedia_bot.social.model.SocialTask
import kotlinx.coroutines.*
/**
* Instagram Accessibility Service – mirrors the Facebook bot architecture
* but targets the Instagram package (com.instagram.android).
*/
class InstagramBotService : AccessibilityService() {
private val TAG = "InstagramBotService"
private val scope = CoroutineScope(Dispatchers.IO + Job())
private var isBotRunning = false
private lateinit var navigator: InstagramNavigator
override fun onServiceConnected() {
super.onServiceConnected()
Log.d(TAG, "Instagram Accessibility Service Connected")
navigator = InstagramNavigator(this)
startTaskLoop()
}
override fun onAccessibilityEvent(event: AccessibilityEvent?) {
// Observe events when needed for synchronization
}
override fun onInterrupt() {
Log.d(TAG, "Service Interrupted")
isBotRunning = false
}
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
private fun startTaskLoop() {
if (isBotRunning) return
isBotRunning = true
scope.launch {
while (isBotRunning) {
try {
val taskData = SocialBotClient.getTask("instagram")
if (taskData != null) {
val task = SocialTask(
id = taskData.getInt("id"),
type = taskData.getString("type"),
targetUrl = if (taskData.isNull("target_url")) null else taskData.getString("target_url"),
promptContext = if (taskData.isNull("prompt_context")) null else taskData.getString("prompt_context"),
generatedComment = if (taskData.isNull("generated_comment")) null else taskData.getString("generated_comment")
)
Log.d(TAG, "Received Task: ${task.type}")
executeTask(task)
} else {
Log.d(TAG, "No Instagram tasks. Sleeping...")
delay(60_000)
}
} catch (e: Exception) {
Log.e(TAG, "Error in task loop", e)
delay(30_000)
}
}
}
}
private suspend fun executeTask(task: SocialTask) {
try {
when (task.type) {
"post_comment" -> {
task.targetUrl?.let { url ->
navigator.openUrl(url)
delay(5_000)
task.generatedComment?.let { comment ->
val success = navigator.postComment(comment)
if (success) {
SocialBotClient.completeTask(task.id, "IG comment posted")
} else {
SocialBotClient.failTask(task.id, "Could not find IG comment input")
}
}
}
}
else -> {
Log.w(TAG, "Unknown task type: ${task.type}")
SocialBotClient.failTask(task.id, "Unknown task type")
}
}
} catch (e: Exception) {
SocialBotClient.failTask(task.id, "Exception: ${e.message}")
}
delay((15_000..45_000).random().toLong()) // human-like cooldown
}
}
@@ -0,0 +1,89 @@
package com.siro.socialmedia_bot.social.instagram
import android.accessibilityservice.AccessibilityService
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.accessibility.AccessibilityNodeInfo
import kotlinx.coroutines.delay
/**
* Handles navigation and interaction within the Instagram app.
* Instagram's package name: com.instagram.android
*/
class InstagramNavigator(private val service: AccessibilityService) {
suspend fun openUrl(url: String) {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
intent.setPackage("com.instagram.android")
try {
service.startActivity(intent)
} catch (e: Exception) {
intent.setPackage(null)
service.startActivity(intent)
}
delay(4_000) // Wait for Instagram to load
}
suspend fun postComment(commentText: String): Boolean {
val root = service.rootInActiveWindow ?: return false
// On Instagram the comment field usually has a hint "Add a comment…"
val inputNode = findNodeByHint(root, "Add a comment")
?: findNodeByClassName(root, "android.widget.EditText")
?: return false
inputNode.performAction(AccessibilityNodeInfo.ACTION_CLICK)
delay(1_000)
val args = Bundle()
args.putCharSequence(AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, commentText)
inputNode.performAction(AccessibilityNodeInfo.ACTION_SET_TEXT, args)
delay((commentText.length * 40L).coerceAtMost(4_000L)) // typing simulation
// Look for "Post" button
val postBtn = findNodeByText(service.rootInActiveWindow, "Post")
if (postBtn != null) {
postBtn.performAction(AccessibilityNodeInfo.ACTION_CLICK)
delay(2_000)
return true
}
return false
}
// ─── Utility helpers ───────────────────────────────────────────────────────
private fun findNodeByHint(node: AccessibilityNodeInfo?, hint: String): AccessibilityNodeInfo? {
if (node == null) return null
if (node.hintText?.contains(hint, ignoreCase = true) == true) return node
for (i in 0 until node.childCount) {
val found = findNodeByHint(node.getChild(i), hint)
if (found != null) return found
}
return null
}
private fun findNodeByText(node: AccessibilityNodeInfo?, text: String): AccessibilityNodeInfo? {
if (node == null) return null
if (node.text?.equals(text, ignoreCase = true) == true ||
node.contentDescription?.equals(text, ignoreCase = true) == true) return node
for (i in 0 until node.childCount) {
val found = findNodeByText(node.getChild(i), text)
if (found != null) return found
}
return null
}
private fun findNodeByClassName(node: AccessibilityNodeInfo?, className: String): AccessibilityNodeInfo? {
if (node == null) return null
if (node.className?.toString() == className) return node
for (i in 0 until node.childCount) {
val found = findNodeByClassName(node.getChild(i), className)
if (found != null) return found
}
return null
}
}
@@ -0,0 +1,7 @@
package com.siro.socialmedia_bot.social.model
data class Account(
val id: Int,
val platform: String,
val username: String
)
@@ -0,0 +1,7 @@
package com.siro.socialmedia_bot.social.model
data class Comment(
val author: String,
val content: String,
val time: String
)
@@ -0,0 +1,9 @@
package com.siro.socialmedia_bot.social.model
data class SocialTask(
val id: Int,
val type: String, // 'join_group', 'read_posts', 'post_comment', 'share_link'
val targetUrl: String?,
val promptContext: String?,
val generatedComment: String?
)
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#FFFFFF" />
</shape>
@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>
@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
@@ -0,0 +1,185 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="24dp"
android:background="#0D0D0D"
tools:context=".MainActivity">
<!-- Header -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="🤖 Siro Social Bot"
android:textSize="26sp"
android:textStyle="bold"
android:textColor="#FFFFFF"
android:gravity="center"
android:layout_marginTop="24dp"
android:layout_marginBottom="4dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Social Media Automation Engine"
android:textSize="13sp"
android:textColor="#888888"
android:gravity="center"
android:layout_marginBottom="32dp" />
<!-- Status Card -->
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:backgroundTint="#1A1A2E">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Service Status"
android:textColor="#888888"
android:textSize="12sp"
android:layout_marginBottom="8dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<View
android:id="@+id/statusDot"
android:layout_width="12dp"
android:layout_height="12dp"
android:background="@drawable/circle_indicator"
android:backgroundTint="#FF4444"
android:layout_marginEnd="10dp" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Accessibility Service Disabled"
android:textColor="#FFFFFF"
android:textSize="15sp" />
</LinearLayout>
<!-- Facebook Service Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="12dp">
<View
android:id="@+id/fbDot"
android:layout_width="10dp"
android:layout_height="10dp"
android:background="@drawable/circle_indicator"
android:backgroundTint="#555555"
android:layout_marginEnd="10dp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Facebook Bot"
android:textColor="#CCCCCC"
android:textSize="13sp" />
<TextView
android:id="@+id/tvFbState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="IDLE"
android:textColor="#555555"
android:textSize="11sp" />
</LinearLayout>
<!-- Instagram Service Row -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_marginTop="8dp">
<View
android:id="@+id/igDot"
android:layout_width="10dp"
android:layout_height="10dp"
android:background="@drawable/circle_indicator"
android:backgroundTint="#555555"
android:layout_marginEnd="10dp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Instagram Bot"
android:textColor="#CCCCCC"
android:textSize="13sp" />
<TextView
android:id="@+id/tvIgState"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="IDLE"
android:textColor="#555555"
android:textSize="11sp" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<!-- Enable Accessibility Button -->
<Button
android:id="@+id/btnEnableAccessibility"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginBottom="12dp"
android:text="Enable Accessibility Service"
android:backgroundTint="#1565C0"
android:textColor="#FFFFFF"
android:textSize="15sp" />
<!-- Logs Card -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Live Log"
android:textColor="#888888"
android:textSize="12sp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp" />
<ScrollView
android:id="@+id/scrollLog"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#111111"
android:padding="12dp">
<TextView
android:id="@+id/tvLog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="[System] Bot initialized...\n"
android:textColor="#00FF88"
android:textSize="12sp"
android:fontFamily="monospace" />
</ScrollView>
</LinearLayout>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Socialmediabot" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SocialMedia Bot</string>
<string name="accessibility_service_description">Social Media Bot Accessibility Service for automating Facebook interactions.</string>
</resources>
@@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Socialmediabot" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older than API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews|flagReportViewIds"
android:canRetrieveWindowContent="true"
android:canPerformGestures="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
android:packageNames="com.facebook.katana" />
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged|typeWindowContentChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault|flagRetrieveInteractiveWindows|flagIncludeNotImportantViews|flagReportViewIds"
android:canRetrieveWindowContent="true"
android:canPerformGestures="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100"
android:packageNames="com.instagram.android" />
@@ -0,0 +1,17 @@
package com.siro.socialmedia_bot
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}