Update: 2026-07-05 22:59:19
This commit is contained in:
@@ -26,7 +26,7 @@ class AccountManager {
|
|||||||
// Order by last_active ascending to rotate through them (least recently used first).
|
// Order by last_active ascending to rotate through them (least recently used first).
|
||||||
|
|
||||||
$stmt = $this->con->prepare("
|
$stmt = $this->con->prepare("
|
||||||
SELECT id, username, total_posts, total_comments
|
SELECT id, username, total_posts, total_comments, proxy_ip, proxy_port, proxy_username, proxy_password
|
||||||
FROM social_accounts
|
FROM social_accounts
|
||||||
WHERE platform = ?
|
WHERE platform = ?
|
||||||
AND status = 'active'
|
AND status = 'active'
|
||||||
|
|||||||
@@ -0,0 +1,206 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# ==============================================================================
|
||||||
|
# Siro Autonomous Android Automation Client (Guerrilla Marketing Bot)
|
||||||
|
# ==============================================================================
|
||||||
|
# This template automates Facebook/Telegram interactions on an Android device
|
||||||
|
# via ADB (Android Debug Bridge) with built-in proxy shifting and anti-ban delays.
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# 1. Python 3.x
|
||||||
|
# 2. Android device with USB Debugging enabled, connected to PC.
|
||||||
|
# 3. ADB installed and added to System PATH.
|
||||||
|
# 4. Target apps (Facebook/Telegram) installed and logged in.
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import random
|
||||||
|
import subprocess
|
||||||
|
import requests
|
||||||
|
|
||||||
|
# --- Configuration ---
|
||||||
|
SERVER_URL = "http://jordan-siro.intaleqapp.com/backend/marketing_engine/social_worker.php"
|
||||||
|
BOT_TOKEN = "YOUR_SECRET_BOT_TOKEN" # Must match headers in social_worker.php
|
||||||
|
PLATFORM = "facebook" # 'facebook' or 'telegram'
|
||||||
|
CHECK_INTERVAL_SECONDS = 60 # Cooldown between checking for new tasks
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"X-Bot-Token": BOT_TOKEN
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- ADB Helper Functions ---
|
||||||
|
def run_adb(cmd):
|
||||||
|
"""Run an ADB command and return output."""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(f"adb {cmd}", shell=True, capture_output=True, text=True, timeout=15)
|
||||||
|
return result.stdout.strip()
|
||||||
|
except subprocess.TimeoutExpired:
|
||||||
|
print("[-] ADB command timed out.")
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def set_android_proxy(ip, port, username=None, password=None):
|
||||||
|
"""Dynamically set global HTTP proxy on Android device."""
|
||||||
|
if not ip or not port:
|
||||||
|
print("[+] Clearing Android proxy...")
|
||||||
|
run_adb("shell settings put global http_proxy :0")
|
||||||
|
return
|
||||||
|
|
||||||
|
print(f"[+] Routing traffic through proxy: {ip}:{port}...")
|
||||||
|
# Standard Android global proxy command
|
||||||
|
run_adb(f"shell settings put global http_proxy {ip}:{port}")
|
||||||
|
|
||||||
|
# Note: If proxy requires auth, Android standard global proxy doesn't support it directly in shell.
|
||||||
|
# In that case, you must use a proxy client app like 'Postern' or 'Drony' on the device,
|
||||||
|
# or route through a local forwarder.
|
||||||
|
time.sleep(3)
|
||||||
|
|
||||||
|
def adb_click(x, y):
|
||||||
|
"""Click on coordinates (x, y)."""
|
||||||
|
run_adb(f"shell input tap {x} {y}")
|
||||||
|
time.sleep(random.uniform(1.0, 2.5))
|
||||||
|
|
||||||
|
def adb_type_humanlike(text):
|
||||||
|
"""Simulate human typing with random delay between characters to evade ban engines."""
|
||||||
|
print(f"[+] Typing: \"{text}\"")
|
||||||
|
# Clean text to prevent shell injection
|
||||||
|
safe_text = text.replace('"', '\\"').replace('$', '\\$').replace('`', '\\`').replace(' ', '%s')
|
||||||
|
|
||||||
|
# Type characters in chunks to look natural
|
||||||
|
for char in text:
|
||||||
|
if char == ' ':
|
||||||
|
run_adb("shell input keyevent 62") # Space
|
||||||
|
else:
|
||||||
|
# We type characters, escaping special shell characters
|
||||||
|
escaped = char.replace('"', '\\"').replace('$', '\\$').replace('`', '\\`').replace("'", "\\'")
|
||||||
|
run_adb(f"shell input text '{escaped}'")
|
||||||
|
time.sleep(random.uniform(0.05, 0.25)) # Typing speed variability
|
||||||
|
|
||||||
|
time.sleep(random.uniform(1.0, 2.0))
|
||||||
|
|
||||||
|
def adb_scroll_down():
|
||||||
|
"""Perform a human-like swipe down."""
|
||||||
|
# swipe from x1 y1 to x2 y2 duration
|
||||||
|
x1, y1 = 500, 1500
|
||||||
|
x2, y2 = 500, 600
|
||||||
|
duration = random.randint(300, 800)
|
||||||
|
run_adb(f"shell input swipe {x1} {y1} {x2} {y2} {duration}")
|
||||||
|
time.sleep(random.uniform(1.5, 3.0))
|
||||||
|
|
||||||
|
def adb_open_url(url):
|
||||||
|
"""Open a URL using Android's default browser/app handler (e.g. opens deep links)."""
|
||||||
|
print(f"[+] Launching URL: {url}")
|
||||||
|
run_adb(f"shell am start -a android.intent.action.VIEW -d '{url}'")
|
||||||
|
time.sleep(random.uniform(5.0, 8.0)) # Wait for app to load
|
||||||
|
|
||||||
|
# --- Logging & Status Reporting ---
|
||||||
|
def report_status(action, params):
|
||||||
|
try:
|
||||||
|
requests.post(f"{SERVER_URL}?action={action}", data=params, headers=headers, timeout=10)
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[-] Status report connection error: {e}")
|
||||||
|
|
||||||
|
# --- Main Task Loop ---
|
||||||
|
def process_task():
|
||||||
|
print("[*] Checking for pending tasks...")
|
||||||
|
try:
|
||||||
|
res = requests.get(f"{SERVER_URL}?action=get_task&platform={PLATFORM}", headers=headers, timeout=10)
|
||||||
|
response_data = res.json()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"[-] Connection failed: {e}")
|
||||||
|
return
|
||||||
|
|
||||||
|
if response_data.get("status") != "success" or not response_data.get("data"):
|
||||||
|
print("[*] No tasks scheduled at this moment.")
|
||||||
|
return
|
||||||
|
|
||||||
|
task = response_data["data"]
|
||||||
|
|
||||||
|
task_id = task["id"]
|
||||||
|
task_type = task["type"]
|
||||||
|
target_url = task["target_url"]
|
||||||
|
comment_text = task["generated_comment"]
|
||||||
|
|
||||||
|
print(f"[+] Task Found! ID: {task_id} | Type: {task_type}")
|
||||||
|
print(f"[+] Account to use: {task.get('bot_username')}")
|
||||||
|
|
||||||
|
# 1. Shifting IP via Proxy Configuration
|
||||||
|
set_android_proxy(
|
||||||
|
task.get("proxy_ip"),
|
||||||
|
task.get("proxy_port"),
|
||||||
|
task.get("proxy_username"),
|
||||||
|
task.get("proxy_password")
|
||||||
|
)
|
||||||
|
|
||||||
|
success = False
|
||||||
|
error_msg = "Unknown execution error"
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 2. Evading Automated Scanners via Random Pre-sleep
|
||||||
|
pre_delay = random.randint(5, 15)
|
||||||
|
print(f"[+] Simulating human delay before opening app... sleeping {pre_delay}s")
|
||||||
|
time.sleep(pre_delay)
|
||||||
|
|
||||||
|
# 3. Open URL (Facebook Post/Telegram Link)
|
||||||
|
if target_url:
|
||||||
|
adb_open_url(target_url)
|
||||||
|
|
||||||
|
# 4. Execute UI actions based on task type
|
||||||
|
if task_type == "post_comment" and comment_text:
|
||||||
|
# Note: Screen coordinates (x, y) vary by device screen size.
|
||||||
|
# You must customize these coordinates based on your device profile.
|
||||||
|
print("[*] Performing UI interactions to comment...")
|
||||||
|
adb_scroll_down() # Scroll to reveal comments area
|
||||||
|
|
||||||
|
# Click on write comment box (Coordinates for Amman Drivers group screen layout)
|
||||||
|
# You can find coordinates by enabling 'Pointer Location' in Android Developer Settings.
|
||||||
|
adb_click(300, 1850)
|
||||||
|
|
||||||
|
# Evade bot detectors by typing like a real person
|
||||||
|
adb_type_humanlike(comment_text)
|
||||||
|
|
||||||
|
# Click send button (e.g. coordinate x: 1000, y: 1850)
|
||||||
|
adb_click(1010, 1850)
|
||||||
|
success = True
|
||||||
|
|
||||||
|
elif task_type == "share_link":
|
||||||
|
print("[*] Sharing deep link...")
|
||||||
|
# Click Share coordinates, type message, and click post
|
||||||
|
# Example coordinates:
|
||||||
|
adb_click(900, 1200) # Share button
|
||||||
|
adb_click(500, 1500) # Write post option
|
||||||
|
adb_type_humanlike(comment_text)
|
||||||
|
adb_click(1000, 150) # Post button
|
||||||
|
success = True
|
||||||
|
|
||||||
|
else:
|
||||||
|
error_msg = f"Task type {task_type} is not yet supported in Android ADB Client"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
error_msg = f"Automation failure: {str(e)}"
|
||||||
|
print(f"[-] Error: {error_msg}")
|
||||||
|
|
||||||
|
# 5. Clear proxy setting to keep device clean
|
||||||
|
set_android_proxy(None, None)
|
||||||
|
|
||||||
|
# 6. Report status back to Server
|
||||||
|
if success:
|
||||||
|
print("[+] Task executed successfully!")
|
||||||
|
report_status("complete_task", {"task_id": task_id, "result": "Comment posted naturally via ADB."})
|
||||||
|
else:
|
||||||
|
print(f"[-] Task failed: {error_msg}")
|
||||||
|
report_status("fail_task", {"task_id": task_id, "error_message": error_msg})
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("[*] Starting Siro Guerrilla Marketing Automation Bot...")
|
||||||
|
# Basic check to ensure ADB is connected
|
||||||
|
devices = run_adb("devices")
|
||||||
|
if "device" not in devices.split("\n")[1:]:
|
||||||
|
print("[-] Critical Error: No Android device detected via ADB! Please connect device and enable USB Debugging.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("[+] Android device connected. Starting automation loop...")
|
||||||
|
while True:
|
||||||
|
process_task()
|
||||||
|
time.sleep(CHECK_INTERVAL_SECONDS)
|
||||||
@@ -65,6 +65,10 @@ function generateCommentWithGemini($postContext, $intent) {
|
|||||||
$prompt .= "المطلوب: اكتب تعليقاً تتعاطف فيه مع المشكلة المذكورة (إن وجدت)، وانصح الزملاء بتجربة تطبيق 'سيرو' كحل واقعي وممتاز لكباتن النقل الذكي. اجعل التعليق قصيراً ومباشراً.";
|
$prompt .= "المطلوب: اكتب تعليقاً تتعاطف فيه مع المشكلة المذكورة (إن وجدت)، وانصح الزملاء بتجربة تطبيق 'سيرو' كحل واقعي وممتاز لكباتن النقل الذكي. اجعل التعليق قصيراً ومباشراً.";
|
||||||
} elseif ($intent === 'answer_question') {
|
} elseif ($intent === 'answer_question') {
|
||||||
$prompt .= "المطلوب: أجب على السؤال المطروح في المنشور بوضوح بناءً على خبرتك مع تطبيق 'سيرو'.";
|
$prompt .= "المطلوب: أجب على السؤال المطروح في المنشور بوضوح بناءً على خبرتك مع تطبيق 'سيرو'.";
|
||||||
|
} elseif ($intent === 'dialogue_skeptic') {
|
||||||
|
$prompt .= "المطلوب: اكتب تعليقاً يبدي شكاً بسيطاً أو فضولاً كزبون أو راكب عادي (مثال: هل التطبيق آمن للبنات؟ أو هل الأسعار حقيقية فعلاً؟ أو كيف كباتنهم؟)، اجعل التعليق قصيراً وسؤالاً طبيعياً وعفوياً جداً بالعامية.";
|
||||||
|
} elseif ($intent === 'dialogue_supporter') {
|
||||||
|
$prompt .= "المطلوب: أجب على الشك المذكور أو أكد التجربة الإيجابية بحماس كراكب/كابتن آخر جرب تطبيق سيرو (Siro) فعلاً ووجد فيه الأمان والخصم الجيد والأسعار الثابتة، مع كتابته بلهجة عامية دافئة وطبيعية جداً.";
|
||||||
} else {
|
} else {
|
||||||
$prompt .= "المطلوب: اكتب تعليقاً متفاعلاً بشكل عام مع المنشور بأسلوب السائقين.";
|
$prompt .= "المطلوب: اكتب تعليقاً متفاعلاً بشكل عام مع المنشور بأسلوب السائقين.";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,8 +47,7 @@ class ScheduleManager {
|
|||||||
INSERT INTO social_tasks (account_id, platform, type, target_url, prompt_context, generated_comment, scheduled_at, status)
|
INSERT INTO social_tasks (account_id, platform, type, target_url, prompt_context, generated_comment, scheduled_at, status)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')
|
VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')
|
||||||
");
|
");
|
||||||
|
$success = $stmt->execute([
|
||||||
return $stmt->execute([
|
|
||||||
$accountId,
|
$accountId,
|
||||||
$platform,
|
$platform,
|
||||||
$type,
|
$type,
|
||||||
@@ -57,6 +56,61 @@ class ScheduleManager {
|
|||||||
$generatedComment,
|
$generatedComment,
|
||||||
$scheduledAt
|
$scheduledAt
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
if ($success && ($type === 'share_link' || $type === 'post_comment')) {
|
||||||
|
// Retreive an active account to exclude as parent
|
||||||
|
$parentAccountId = $accountId;
|
||||||
|
if (!$parentAccountId) {
|
||||||
|
$stmtAcc = $this->con->prepare("SELECT id FROM social_accounts WHERE platform = ? AND status = 'active' LIMIT 1");
|
||||||
|
$stmtAcc->execute([$platform]);
|
||||||
|
$parentAccountId = $stmtAcc->fetchColumn() ?: 0;
|
||||||
|
}
|
||||||
|
$this->scheduleDialogueDrama($platform, $targetUrl, $promptContext, $parentAccountId, $delayMinutes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule supporting dialogue tasks from other accounts to create a buzz/drama.
|
||||||
|
*/
|
||||||
|
public function scheduleDialogueDrama($platform, $targetUrl, $promptContext, $parentAccountId, $baseDelayMinutes) {
|
||||||
|
// Fetch 2 other active accounts on the same platform
|
||||||
|
$stmt = $this->con->prepare("
|
||||||
|
SELECT id FROM social_accounts
|
||||||
|
WHERE platform = ? AND status = 'active' AND id != ?
|
||||||
|
ORDER BY RAND() LIMIT 2
|
||||||
|
");
|
||||||
|
$stmt->execute([$platform, $parentAccountId]);
|
||||||
|
$accounts = $stmt->fetchAll(PDO::FETCH_COLUMN);
|
||||||
|
|
||||||
|
if (count($accounts) < 1) return;
|
||||||
|
|
||||||
|
// Account 2: Skeptic/Questioner
|
||||||
|
$accountId2 = $accounts[0];
|
||||||
|
$comment2 = generateCommentWithGemini($promptContext, 'dialogue_skeptic');
|
||||||
|
|
||||||
|
$delay2 = $baseDelayMinutes + rand(3, 7); // Delay child task by rand(3, 7) minutes
|
||||||
|
$scheduledAt2 = date('Y-m-d H:i:s', strtotime("+$delay2 minutes"));
|
||||||
|
|
||||||
|
$stmtInsert = $this->con->prepare("
|
||||||
|
INSERT INTO social_tasks (account_id, platform, type, target_url, prompt_context, generated_comment, scheduled_at, status)
|
||||||
|
VALUES (?, ?, 'post_comment', ?, ?, ?, ?, 'pending')
|
||||||
|
");
|
||||||
|
$stmtInsert->execute([$accountId2, $platform, $targetUrl, $promptContext, $comment2, $scheduledAt2]);
|
||||||
|
|
||||||
|
// If we have a third account, schedule the supporter
|
||||||
|
if (count($accounts) >= 2) {
|
||||||
|
$accountId3 = $accounts[1];
|
||||||
|
// Provide context containing the first comment so supporter replies to it
|
||||||
|
$augmentedContext = $promptContext . "\n[PREVIOUS_REPLY]: " . $comment2;
|
||||||
|
$comment3 = generateCommentWithGemini($augmentedContext, 'dialogue_supporter');
|
||||||
|
|
||||||
|
$delay3 = $delay2 + rand(4, 9); // Supporter replies after the skeptic
|
||||||
|
$scheduledAt3 = date('Y-m-d H:i:s', strtotime("+$delay3 minutes"));
|
||||||
|
|
||||||
|
$stmtInsert->execute([$accountId3, $platform, $targetUrl, $promptContext, $comment3, $scheduledAt3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,10 @@ CREATE TABLE IF NOT EXISTS `social_accounts` (
|
|||||||
`total_posts` INT DEFAULT 0,
|
`total_posts` INT DEFAULT 0,
|
||||||
`total_comments` INT DEFAULT 0,
|
`total_comments` INT DEFAULT 0,
|
||||||
`total_videos` INT DEFAULT 0,
|
`total_videos` INT DEFAULT 0,
|
||||||
|
`proxy_ip` VARCHAR(100) NULL,
|
||||||
|
`proxy_port` INT NULL,
|
||||||
|
`proxy_username` VARCHAR(100) NULL,
|
||||||
|
`proxy_password` VARCHAR(100) NULL,
|
||||||
`last_active` DATETIME NULL,
|
`last_active` DATETIME NULL,
|
||||||
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
`created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||||
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
`updated_at` DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ try {
|
|||||||
|
|
||||||
// Find a pending task that is scheduled for now or earlier
|
// Find a pending task that is scheduled for now or earlier
|
||||||
$stmt = $con->prepare("
|
$stmt = $con->prepare("
|
||||||
SELECT id, type, target_url, prompt_context, generated_comment
|
SELECT id, account_id, type, target_url, prompt_context, generated_comment
|
||||||
FROM social_tasks
|
FROM social_tasks
|
||||||
WHERE status = 'pending' AND platform = ? AND (scheduled_at IS NULL OR scheduled_at <= NOW())
|
WHERE status = 'pending' AND platform = ? AND (scheduled_at IS NULL OR scheduled_at <= NOW())
|
||||||
ORDER BY created_at ASC LIMIT 1
|
ORDER BY created_at ASC LIMIT 1
|
||||||
@@ -38,11 +38,55 @@ try {
|
|||||||
$task = $stmt->fetch(PDO::FETCH_ASSOC);
|
$task = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
if ($task) {
|
if ($task) {
|
||||||
// Mark as in progress
|
require_once __DIR__ . '/account_manager.php';
|
||||||
|
$am = new AccountManager();
|
||||||
|
|
||||||
|
$accountId = $task['account_id'];
|
||||||
|
$account = null;
|
||||||
|
|
||||||
|
if ($accountId) {
|
||||||
|
// Fetch this specific account details
|
||||||
|
$stmtAcc = $con->prepare("
|
||||||
|
SELECT id, username, proxy_ip, proxy_port, proxy_username, proxy_password
|
||||||
|
FROM social_accounts WHERE id = ?
|
||||||
|
");
|
||||||
|
$stmtAcc->execute([$accountId]);
|
||||||
|
$account = $stmtAcc->fetch(PDO::FETCH_ASSOC);
|
||||||
|
} else {
|
||||||
|
// Dynamically get an available account and assign it
|
||||||
|
$account = $am->getAvailableAccount($platform, 15); // 15 min cooldown
|
||||||
|
if ($account) {
|
||||||
|
$accountId = $account['id'];
|
||||||
|
$updateTask = $con->prepare("UPDATE social_tasks SET account_id = ? WHERE id = ?");
|
||||||
|
$updateTask->execute([$accountId, $task['id']]);
|
||||||
|
$task['account_id'] = $accountId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$account) {
|
||||||
|
echo json_encode(['status' => 'error', 'message' => 'No active social account available or in cooldown']);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($account) {
|
||||||
|
$task['bot_username'] = $account['username'];
|
||||||
|
$task['proxy_ip'] = $account['proxy_ip'];
|
||||||
|
$task['proxy_port'] = $account['proxy_port'];
|
||||||
|
$task['proxy_username'] = $account['proxy_username'];
|
||||||
|
$task['proxy_password'] = $account['proxy_password'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark as in progress and update last active
|
||||||
$update = $con->prepare("UPDATE social_tasks SET status = 'in_progress' WHERE id = ?");
|
$update = $con->prepare("UPDATE social_tasks SET status = 'in_progress' WHERE id = ?");
|
||||||
$update->execute([$task['id']]);
|
$update->execute([$task['id']]);
|
||||||
|
|
||||||
echo json_encode(['status' => 'success', 'data' => $task]);
|
$am->markAccountActive($accountId);
|
||||||
|
|
||||||
|
// Return task directly in 'data' to preserve compatibility with existing Android bots
|
||||||
|
echo json_encode([
|
||||||
|
'status' => 'success',
|
||||||
|
'data' => $task
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
echo json_encode(['status' => 'success', 'message' => 'No tasks available', 'data' => null]);
|
echo json_encode(['status' => 'success', 'message' => 'No tasks available', 'data' => null]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,113 @@
|
|||||||
|
<?php
|
||||||
|
// ==============================================================================
|
||||||
|
# Siro Guerrilla Marketing Flow Verification & Integration Test Script
|
||||||
|
# ==============================================================================
|
||||||
|
# This script executes a full dry-run integration test on the marketing engine.
|
||||||
|
# It checks proxy assignments, country detection, dialect generation, and
|
||||||
|
# dialogue scheduling.
|
||||||
|
# ==============================================================================
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../../core/bootstrap.php';
|
||||||
|
require_once __DIR__ . '/schedule_manager.php';
|
||||||
|
require_once __DIR__ . '/account_manager.php';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$con = Database::get('main');
|
||||||
|
} catch (Exception $e) {
|
||||||
|
die("[-] Connection failed: " . $e->getMessage() . "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "[*] Starting Siro Integration Test...\n";
|
||||||
|
|
||||||
|
// --- 1. Set Up Mock Accounts ---
|
||||||
|
echo "[*] Setting up mock accounts in database...\n";
|
||||||
|
// Clear old test accounts if they exist
|
||||||
|
$con->query("DELETE FROM social_accounts WHERE username LIKE 'test_bot_%'");
|
||||||
|
|
||||||
|
$stmt = $con->prepare("
|
||||||
|
INSERT INTO social_accounts (platform, username, status, proxy_ip, proxy_port)
|
||||||
|
VALUES (?, ?, 'active', ?, ?)
|
||||||
|
");
|
||||||
|
$stmt->execute(['facebook', 'test_bot_sy', '194.163.173.157', 8080]);
|
||||||
|
$stmt->execute(['facebook', 'test_bot_jo', '194.163.173.200', 8080]);
|
||||||
|
$stmt->execute(['facebook', 'test_bot_eg', '194.163.173.111', 8080]);
|
||||||
|
|
||||||
|
echo "[+] 3 Mock accounts created successfully.\n";
|
||||||
|
|
||||||
|
// --- 2. Test Country Guessing & Dialogue Generation ---
|
||||||
|
$sm = new ScheduleManager();
|
||||||
|
|
||||||
|
$testCases = [
|
||||||
|
[
|
||||||
|
'platform' => 'facebook',
|
||||||
|
'url' => 'https://facebook.com/groups/yallago.syria/post/1',
|
||||||
|
'context' => "شو رأيكم بتطبيق يلاغو في دمشق؟ الأسعار صايرة خيالية!",
|
||||||
|
'expected_country' => 'SY'
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'platform' => 'facebook',
|
||||||
|
'url' => 'https://facebook.com/groups/taxif.amman/post/2',
|
||||||
|
'context' => "التاكسي إف لغى رحلتي مرتين اليوم بعمان، شو في بديل؟",
|
||||||
|
'expected_country' => 'JO'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($testCases as $index => $tc) {
|
||||||
|
echo "\n------------------------------------------------------------\n";
|
||||||
|
echo "[*] Test Case " . ($index + 1) . ": Target URL " . $tc['url'] . "\n";
|
||||||
|
|
||||||
|
// Auto guess test
|
||||||
|
$guessed = guessCountryFromContext($tc['context']);
|
||||||
|
echo "[+] Expected Country: " . $tc['expected_country'] . " | Guessed: " . $guessed . "\n";
|
||||||
|
if ($guessed === $tc['expected_country']) {
|
||||||
|
echo "[+] Country Detection: PASS\n";
|
||||||
|
} else {
|
||||||
|
echo "[-] Country Detection: FAIL\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schedule Task
|
||||||
|
// This will schedule the parent task and automatically trigger the dialogue simulator (Drama)
|
||||||
|
echo "[*] Scheduling parent task and dialog drama...\n";
|
||||||
|
$success = $sm->scheduleTask(
|
||||||
|
platform: $tc['platform'],
|
||||||
|
type: 'post_comment',
|
||||||
|
targetUrl: $tc['url'],
|
||||||
|
promptContext: $tc['context'],
|
||||||
|
accountId: null,
|
||||||
|
delayMinutes: 5
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($success) {
|
||||||
|
echo "[+] Initial task and supporting drama scheduled successfully.\n";
|
||||||
|
} else {
|
||||||
|
echo "[-] Scheduling: FAIL\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 3. Verify Scheduled Tasks in Database ---
|
||||||
|
echo "\n------------------------------------------------------------\n";
|
||||||
|
echo "[*] Querying scheduled tasks to verify dialogue database records...\n";
|
||||||
|
|
||||||
|
$stmtTasks = $con->prepare("
|
||||||
|
SELECT t.id, t.type, t.target_url, t.generated_comment, t.scheduled_at, a.username, a.proxy_ip
|
||||||
|
FROM social_tasks t
|
||||||
|
LEFT JOIN social_accounts a ON t.account_id = a.id
|
||||||
|
WHERE t.status = 'pending' AND t.target_url LIKE '%/post/%'
|
||||||
|
ORDER BY t.scheduled_at ASC
|
||||||
|
");
|
||||||
|
$stmtTasks->execute();
|
||||||
|
$tasks = $stmtTasks->fetchAll(PDO::FETCH_ASSOC);
|
||||||
|
|
||||||
|
echo "[+] Found " . count($tasks) . " pending tasks in queue:\n";
|
||||||
|
foreach ($tasks as $t) {
|
||||||
|
echo " - Account: [" . $t['username'] . " (IP: " . $t['proxy_ip'] . ")] | Type: " . $t['type'] . "\n";
|
||||||
|
echo " Scheduled: " . $t['scheduled_at'] . "\n";
|
||||||
|
echo " Generated Comment: \"" . trim($t['generated_comment']) . "\"\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- 4. Clean Up Mock Database Data ---
|
||||||
|
echo "[*] Cleaning up test data from DB...\n";
|
||||||
|
$con->query("DELETE FROM social_tasks WHERE target_url LIKE '%/post/%'");
|
||||||
|
$con->query("DELETE FROM social_accounts WHERE username LIKE 'test_bot_%'");
|
||||||
|
|
||||||
|
echo "\n[+] Siro Marketing Integration Test Completed Successfully!\n";
|
||||||
Reference in New Issue
Block a user