Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a35509abd | ||
|
|
71ca3790c1 |
@@ -26,7 +26,7 @@ class AccountManager {
|
||||
// Order by last_active ascending to rotate through them (least recently used first).
|
||||
|
||||
$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
|
||||
WHERE platform = ?
|
||||
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 .= "المطلوب: اكتب تعليقاً تتعاطف فيه مع المشكلة المذكورة (إن وجدت)، وانصح الزملاء بتجربة تطبيق 'سيرو' كحل واقعي وممتاز لكباتن النقل الذكي. اجعل التعليق قصيراً ومباشراً.";
|
||||
} elseif ($intent === 'answer_question') {
|
||||
$prompt .= "المطلوب: أجب على السؤال المطروح في المنشور بوضوح بناءً على خبرتك مع تطبيق 'سيرو'.";
|
||||
} elseif ($intent === 'dialogue_skeptic') {
|
||||
$prompt .= "المطلوب: اكتب تعليقاً يبدي شكاً بسيطاً أو فضولاً كزبون أو راكب عادي (مثال: هل التطبيق آمن للبنات؟ أو هل الأسعار حقيقية فعلاً؟ أو كيف كباتنهم؟)، اجعل التعليق قصيراً وسؤالاً طبيعياً وعفوياً جداً بالعامية.";
|
||||
} elseif ($intent === 'dialogue_supporter') {
|
||||
$prompt .= "المطلوب: أجب على الشك المذكور أو أكد التجربة الإيجابية بحماس كراكب/كابتن آخر جرب تطبيق سيرو (Siro) فعلاً ووجد فيه الأمان والخصم الجيد والأسعار الثابتة، مع كتابته بلهجة عامية دافئة وطبيعية جداً.";
|
||||
} else {
|
||||
$prompt .= "المطلوب: اكتب تعليقاً متفاعلاً بشكل عام مع المنشور بأسلوب السائقين.";
|
||||
}
|
||||
|
||||
@@ -47,8 +47,7 @@ class ScheduleManager {
|
||||
INSERT INTO social_tasks (account_id, platform, type, target_url, prompt_context, generated_comment, scheduled_at, status)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, 'pending')
|
||||
");
|
||||
|
||||
return $stmt->execute([
|
||||
$success = $stmt->execute([
|
||||
$accountId,
|
||||
$platform,
|
||||
$type,
|
||||
@@ -57,6 +56,61 @@ class ScheduleManager {
|
||||
$generatedComment,
|
||||
$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_comments` 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,
|
||||
`created_at` DATETIME DEFAULT 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
|
||||
$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
|
||||
WHERE status = 'pending' AND platform = ? AND (scheduled_at IS NULL OR scheduled_at <= NOW())
|
||||
ORDER BY created_at ASC LIMIT 1
|
||||
@@ -38,11 +38,55 @@ try {
|
||||
$task = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
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->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 {
|
||||
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";
|
||||
@@ -0,0 +1,46 @@
|
||||
# خطة التسويق الفيروسي (Guerrilla Marketing & WoM) لتطبيق سيرو
|
||||
|
||||
هذه الوثيقة تحتوي على الاستراتيجيات التسويقية المجانية والذكية للوصول إلى الركاب (Passengers) وزيادة عدد الرحلات باستخدام الذكاء الاصطناعي وحسابات التواصل الاجتماعي.
|
||||
|
||||
## 1. استراتيجية "افتعال الدراما والحل" (مسرحية التعليقات) 🎭
|
||||
تعتمد على استخدام أكثر من حساب لإنشاء حوار مصطنع يلفت الانتباه ويقدم "سيرو" كبطل منقذ.
|
||||
* **السيناريو:**
|
||||
* **حساب 1 (الشاكي):** "يا جماعة تطبيقات التوصيل انجنّت! أوبر وكريم طلبوا مني 7 دنانير من السابع للجبيهة عشان في أزمة!!"
|
||||
* **حساب 2 (المنقذ):** "يا زلمة مين لسا بطلبهم؟ نزل تطبيق سيرو، نفس الرحلة ما بتطلع 4 دنانير. أسعارهم ثابتة وما عندهم ذروة تكسر الظهر."
|
||||
* **حساب 3 (الراكب المتفاجئ):** "عنجد تحكي؟ والله هسا بنزله أجربه، متنا من الدفع."
|
||||
* **الهدف:** استغلال "تأثير القطيع" (Bandwagon Effect) لدفع الركاب الذين يقرؤون التعليقات لتحميل التطبيق فوراً.
|
||||
|
||||
## 2. استراتيجية "القصة العاطفية / البطل" (لبناء الثقة المطلقة) ❤️
|
||||
الركاب يبحثون عن الأمان والثقة، وخاصة عند نسيان المقتنيات.
|
||||
* **السيناريو:** نشر قصة شكر في جروبات ضخمة (مثل طبربور، جروبات العاصمة).
|
||||
* **مثال للمنشور:** "يا جماعة بدي أشكر كابتن بتطبيق اسمه (سيرو)، نسيت محفظتي فيها كل هوياتي وبطاقتي بالسيارة، ورجعلي إياها لباب البيت ورفض يوخذ حلاوان. تطبيق محترم وكباتنهم ولاد حلال، عنجد بنصحكم فيه."
|
||||
* **الهدف:** حصد إعجابات وتعليقات إيجابية، وبناء سمعة بأن "سيرو" هو التطبيق الأكثر أماناً وأمانة.
|
||||
|
||||
## 3. اختراق التجمعات النسائية (لعب ورقة الأمان) 👱♀️
|
||||
توصيات النساء في جروباتهن (مثل صبايا الأردن) تنتشر بسرعة البرق وتُبنى على الثقة.
|
||||
* **السيناريو:** الرد أو النشر بصيغة فتاة تبحث عن الأمان.
|
||||
* **مثال للتعليق:** "بنات نصيحة، جربت تطبيق جديد اسمه سيرو، كباتنهم محترمين جداً وفي تتبع دقيق للرحلة، وأرخص من الباقي. صرت أروح عليه عالجامعة وأنا مطمنة."
|
||||
* **الهدف:** تشجيع الإناث على تبني التطبيق كخيار أول للمواصلات اليومية.
|
||||
|
||||
## 4. استهداف طلاب الجامعات (الجمهور الأكثر عدداً واستخداماً) 🎓
|
||||
الطلاب يتشاركون التطبيقات الرخيصة بسرعة، وتعتبر ميزانية المواصلات أولوية لديهم.
|
||||
* **السيناريو:** التعليق في صفحات الاعترافات الجامعية (الجامعة الأردنية، التكنو.. الخ).
|
||||
* **مثال للتعليق:** "للطلاب اللي طفرت من ورا المواصلات 😂.. جربوا سيرو، أسعارهم محروقة وما في أوقات ذروة. نصيحة قبل ما تخلص مصاريكم بنص الشهر."
|
||||
* **الهدف:** خلق قاعدة مستخدمين شبابية تعتمد على التطبيق بشكل يومي.
|
||||
|
||||
## 5. استهداف "الباحثين عن الرفاهية" (جروبات المطاعم والخروجات) 🍔
|
||||
* **السيناريو:** متابعة المنشورات التي تسأل عن المطاعم أو الفعاليات في المناطق المزدحمة (مثل اللويبدة، عبدون، البوليفارد).
|
||||
* **مثال للتعليق:** "المكان خرافي بس الأزمة والصفة هناك بتجلط! نصيحة روحوا بتطبيق سيرو، رخيص وبياخدكم من الباب للباب بدون ما تتعقدوا من أزمة السيارات."
|
||||
* **الهدف:** ربط تطبيق سيرو كحل أساسي لتجنب أزمات السير والاصطفاف خلال الخروجات الترفيهية.
|
||||
|
||||
## 6. استراتيجية "التدخل السياقي" (Hyper-Local Targeting) 📍
|
||||
استخدام البوت للدخول في السياق اليومي للجروبات بشكل طبيعي وغير مزعج:
|
||||
* إذا اشتكى شخص من غلاء الأسعار: "لأنك لسه ما جربت سيرو! أسعارنا ثابتة وما بنكسر ظهرك بوقت الذروة."
|
||||
* إذا اشتكى شخص من الإلغاء: "في سيرو الكابتن بشوف وجهتك قبل ما يقبل، فمستحيل يلغي! جربنا وانسى وجع الراس."
|
||||
|
||||
## 7. استراتيجية "التحدي والجرأة" 🥊
|
||||
* إلقاء تحديات علنية: "تحدي: إذا بتلاقي سعر أرخص من سيرو من منطقتك للدوام، بنعطيك الرحلة مجاناً! 😎 نزل التطبيق، قارن السعر بنفسك، واحكم."
|
||||
|
||||
---
|
||||
**الخلاصة:**
|
||||
هذه الاستراتيجيات تعتمد على أسلوب "التسويق المتسلل" الذي يعتمد على الإقناع غير المباشر، وتستخدم الحسابات الآلية لتوليد "شعبية وهمية إيجابية" تتحول لاحقاً إلى شعبية حقيقية صلبة بمجرد أن يختبر الركاب جودة التطبيق.
|
||||
Reference in New Issue
Block a user