Skip to content

Latest commit

 

History

History
780 lines (597 loc) · 50.8 KB

File metadata and controls

780 lines (597 loc) · 50.8 KB

سند جامع فرایند سامانه MLK DVR Receiver

۱. هدف و محدوده سند

این سند رفتار فعلی سامانه را بر اساس کد موجود توضیح می‌دهد و برای تبدیل مستقیم به فلوچارت، BPMN، Sequence Diagram یا Swimlane Diagram نوشته شده است. هر جا بین رفتار مطلوب و رفتار فعلی تفاوتی وجود داشته باشد، عبارت «در پیاده‌سازی فعلی» استفاده شده است.

هدف سامانه این است که یک کاربر مجاز در گروه فعال تلگرام، برای یکی از شماره‌های ثبت‌شده درخواست کد تأیید دیوار ایجاد کند؛ گوشی دریافت‌کننده SMS کد را استخراج و به بک‌اند ارسال کند؛ و بک‌اند کد را فقط در چت خصوصی درخواست‌کننده تحویل دهد. کد نباید در گروه تلگرام نمایش داده شود.

این سند پنج حوزه را پوشش می‌دهد:

  1. آماده‌سازی و راه‌اندازی بک‌اند و ربات تلگرام؛
  2. نصب و آماده‌سازی اپ اندروید؛
  3. ثبت شماره‌ها و درخواست کد توسط کاربر؛
  4. دریافت SMS، صف محلی، ارسال، تطبیق نشست و تحویل کد؛
  5. همه حالت‌ها، شرط‌ها، خطاها، انقضاها، retryها و داده‌های ذخیره‌شده.

۲. نمای کلان سامانه

flowchart LR
    U[کاربر درخواست‌کننده] -->|دستور code در گروه| TG[گروه تلگرام فعال]
    TG -->|Webhook update| BE[بک‌اند Express]
    BE -->|پیام خصوصی آمادگی نشست| U
    U -->|ورود شماره در دیوار| DV[دیوار]
    DV -->|SMS کد تأیید| PH[گوشی دارای اپ Receiver]
    PH -->|HTTPS: POST api/sms| BE
    BE -->|تطبیق شماره با نشست فعال| SS[(Session Store)]
    BE -->|کد فقط در چت خصوصی| U
    BE -->|تأیید بدون کد| TG
    BE --> PS[(Phone Store)]
    PH --> LQ[(صف و لاگ محلی)]
Loading

اصل امنیتی اصلی

  • اپ اندروید مستقیماً به Telegram API وصل نمی‌شود و Bot Token داخل اپ نیست.
  • اپ فقط کد شش‌رقمی و یک یا دو شماره کاندید را برای بک‌اند می‌فرستد؛ متن کامل SMS و فرستنده به بک‌اند ارسال نمی‌شوند.
  • کد در گروه منتشر نمی‌شود؛ فقط پیام موفقیت یا انقضا در گروه ثبت می‌شود.
  • بک‌اند تصمیم می‌گیرد کد متعلق به کدام نشست است؛ تشخیص اسلات سیم‌کارت در اندروید فقط ترتیب کاندیدها را تغییر می‌دهد.

۳. بازیگران و Swimlaneهای پیشنهادی

برای فلوچارت نهایی، Laneها با این ترتیب پیشنهاد می‌شوند:

شناسه Lane بازیگر/جزء مسئولیت
L1 مدیر سامانه تنظیم env، استقرار بک‌اند، ثبت webhook، نصب APK و آماده‌سازی گوشی
L2 کاربر درخواست‌کننده Start کردن ربات، انتخاب شماره، ارسال /code، ورود شماره در دیوار و دریافت کد خصوصی
L3 گروه/پلتفرم تلگرام تحویل فرمان‌ها به webhook و تحویل پیام‌های ربات به گروه یا چت خصوصی
L4 بک‌اند Express اعتبارسنجی، مدیریت نشست، تطبیق SMS، audit و ارسال پیام تلگرام
L5 Phone Store ثبت شماره‌ها و نگهداری شمارنده‌های استفاده/موفقیت
L6 Session Store نگهداری نشست‌های فعال، انقضا و تاریخچه audit
L7 سرویس دیوار/شبکه اپراتور تولید و ارسال SMS کد تأیید
L8 Android OS Broadcast دریافت SMS، مجوزها، Boot event، JobScheduler و محدودیت باتری
L9 اپ Android Receiver تنظیمات، تشخیص SMS، استخراج کد، صف محلی و ارسال به بک‌اند
L10 حافظه محلی اپ SharedPreferences تنظیمات، صف pending، fingerprintهای dedup و لاگ محلی

۴. داده‌ها، مخازن و شناسه‌ها

۴.۱ تنظیمات محلی اپ

در agent_preferences ذخیره می‌شوند:

  • enabled: وضعیت ON/OFF عامل دریافت؛ مقدار اولیه false است.
  • sim_1_phone: شماره اول؛ نام فیلد تاریخی است و الزاماً به اسلات واقعی SIM 1 وابسته نیست.
  • sim_2_phone: شماره دوم و اختیاری.
  • autostart_confirmed: تأیید دستی کاربر برای فعال بودن Autostart در خانواده Xiaomi.

شماره معتبر دقیقاً باید با الگوی 09xxxxxxxxx، یعنی ۱۱ رقم و شروع با 09، تطبیق داشته باشد. حداقل یک و حداکثر دو شماره در API پذیرفته می‌شود. شماره‌های تکراری در خروجی تنظیمات محلی حذف می‌شوند.

۴.۲ صف محلی اپ

هر آیتم PendingDelivery شامل این فیلدهاست:

  • id: هش SHA-256 از sender + body + مجموعه مرتب‌شده شماره‌ها؛
  • code: کد نرمال‌شده شش‌رقمی؛
  • phones: یک یا دو شماره کاندید؛
  • createdAt: زمان دریافت SMS بر حسب millisecond epoch.

صف به صورت FIFO خوانده می‌شود و قبل از پایان Broadcast به شکل synchronous روی دیسک commit می‌شود. fingerprintهای دیده‌شده ۲۴ ساعت نگهداری می‌شوند.

۴.۳ Phone Store بک‌اند

فایل فعال بر اساس mode انتخاب می‌شود:

  • dev: فایل phones.json؛
  • product: فایل phones.product.json.

هر شماره شامل موارد زیر است:

  • timesCalled: تعداد درخواست‌های معتبر /code برای شماره ثبت‌شده؛
  • successfulDeliveries: تعداد تحویل‌های خصوصی موفق؛
  • addedAt: زمان اولین ثبت؛
  • updatedAt: زمان آخرین تغییر شمارنده.

ثبت مجدد شماره، رکورد را duplicate نمی‌کند و شمارنده‌ها را reset نمی‌کند.

۴.۴ Session Store و Audit

فایل فعال بر اساس mode انتخاب می‌شود:

  • dev: فایل sessions.json؛
  • product: فایل sessions.product.json.

کلید هر نشست فعال، خود شماره تلفن است. داده نشست:

  • sessionId: UUID؛
  • state: در رکورد فعال برابر active؛
  • requesterId: شناسه Telegram کاربر؛
  • requesterDisplayName: username یا نام نمایشی؛
  • groupChatId: گروهی که فرمان در آن ثبت شده؛
  • requestMessageId: پیام اصلی /code برای reply کردن؛
  • createdAt: زمان ایجاد؛
  • expiresAt: زمان ایجاد + ۱۲۰ ثانیه.

کلید ویژه _history آرایه append-only رخدادهاست. نوشتن فایل با فایل موقت و rename انجام می‌شود و عملیات storeها serial است تا race condition درخواست‌های هم‌زمان کنترل شود.


۵. قواعد محیط Dev و Product

  1. بک‌اند فقط یکی از modeهای dev یا product را فعال می‌کند.
  2. TELEGRAM_DEV_GROUP_ID و TELEGRAM_PRODUCT_GROUP_ID هر دو باید عدد منفی و متفاوت باشند.
  3. تنها گروه متناظر با mode، «گروه فعال» است.
  4. تمام فرمان‌های عملیاتی به جز /start و /group_id در گروه غیر فعال نادیده گرفته می‌شوند.
  5. اپ در هر درخواست X-App-Mode می‌فرستد؛ اگر با mode بک‌اند برابر نباشد، پاسخ 409 app_mode_mismatch دریافت می‌کند.
  6. داده نشست و شماره dev و product در فایل‌های جدا ذخیره می‌شود.
  7. برای تغییر محیط باید env بک‌اند تغییر کند، بک‌اند restart شود و APK با mode متناظر rebuild/reinstall شود.
  8. در پیاده‌سازی فعلی URL بک‌اند در app/build.gradle.kts روی https://mlk-dvr-receiver.darkube.ir ثابت شده است؛ Secret و Mode از Gradle property، environment یا backend/.env وارد BuildConfig می‌شوند.

۶. فاز صفر: راه‌اندازی بک‌اند

مسیر اصلی BE-BOOT

ID Lane عمل/تصمیم مسیر بعدی
BE-BOOT-01 مدیر اجرای npm start / node src/server.js BE-BOOT-02
BE-BOOT-02 بک‌اند بارگذاری env BE-BOOT-03
BE-BOOT-03 بک‌اند آیا همه متغیرهای ضروری موجودند؟ بله: 04؛ خیر: log و exit با کد ۱
BE-BOOT-04 بک‌اند آیا APP_MODE یکی از dev/product است؟ بله: 05؛ خیر: exit
BE-BOOT-05 بک‌اند آیا هر دو Group ID منفی و متفاوت‌اند؟ بله: 06؛ خیر: exit
BE-BOOT-06 بک‌اند تعیین DATA_DIR و فایل‌های mode 07
BE-BOOT-07 Session/Phone Store ساخت پوشه و خواندن JSON معتبر: 08؛ فایل مفقود/خالی/JSON خراب: بازسازی {} سپس 08
BE-BOOT-08 بک‌اند حذف نشست‌های منقضی و migration نشست legacy در transaction اولیه 09
BE-BOOT-09 بک‌اند برای هر نشست active باقی‌مانده timer انقضا را restore می‌کند 10
BE-BOOT-10 بک‌اند اعتبارسنجی PORT بین ۱ تا ۶۵۵۳۵ معتبر: 11؛ نامعتبر: exit
BE-BOOT-11 بک‌اند listen روی 0.0.0.0:PORT سرویس Ready

shutdown

  • در SIGTERM یا SIGINT فقط اولین درخواست shutdown پذیرفته می‌شود.
  • سرور پذیرش اتصال جدید را متوقف می‌کند.
  • timerهای نشست پاک و expiration handler جدا می‌شود.
  • اگر shutdown تا ۱۰ ثانیه کامل نشود، اتصال‌های باقی‌مانده force-close و process با خطا خاتمه می‌یابد.

اتصال تلگرام

  • مدیر باید webhook تلگرام را روی POST /telegram/webhook ثبت کند؛ بک‌اند آن را خودکار ثبت نمی‌کند.
  • GET /health بدون احراز هویت، 200 {"status":"ok"} برمی‌گرداند.
  • Telegram Client برای sendMessage از HTML parse mode استفاده می‌کند و timeout آن ۲۰ ثانیه است.

۷. فاز یک: نصب و آماده‌سازی اپ اندروید

۷.۱ اولین اجرا و نمایش UI

  1. اپ MainActivity را باز می‌کند.
  2. تنظیمات محلی قبلی خوانده می‌شوند؛ کلیدهای legacy مربوط به URL و Secret محلی حذف می‌شوند.
  3. شماره‌های ذخیره‌شده و وضعیت ON/OFF در UI نمایش داده می‌شوند.
  4. readiness محاسبه می‌شود:
    • مجوز RECEIVE_SMS؛
    • مجوز READ_SMS برای recovery؛
    • خارج بودن از Battery Optimization؛
    • روی Xiaomi/Redmi/Poco، تأیید Autostart.
  5. در build نوع dev، برچسب Mode: DEV نمایش داده می‌شود.

۷.۲ ذخیره شماره‌ها APP-CONFIG

ID Lane عمل/تصمیم نتیجه
APP-CONFIG-01 مدیر گوشی وارد کردن شماره اول و در صورت نیاز شماره دوم 02
APP-CONFIG-02 اپ حذف فاصله ابتدا/انتها 03
APP-CONFIG-03 اپ آیا حداقل یک شماره وارد شده و همه شماره‌های واردشده معتبرند؟ بله: ذخیره هر دو فیلد؛ خیر: عدم ذخیره مقادیر جدید
APP-CONFIG-04 اپ نمایش Toast موفق: «تنظیمات ذخیره شد»؛ ناموفق: درخواست شماره معتبر

ترتیب شماره‌ها برای تطبیق نهایی مهم نیست؛ با این حال metadata اسلات می‌تواند یکی را در ابتدای آرایه کاندید قرار دهد.

۷.۳ روشن کردن Status APP-ENABLE

  1. کاربر Switch را ON می‌کند.
  2. اپ ابتدا ورودی‌های فعلی شماره‌ها را اعتبارسنجی و ذخیره می‌کند.
  3. اگر نامعتبر باشند، Switch به OFF برمی‌گردد و فرایند متوقف می‌شود.
  4. اگر هر یک از مجوزهای RECEIVE_SMS یا READ_SMS موجود نباشد، هر دو مجوز مفقود درخواست می‌شوند.
  5. اگر RECEIVE_SMS رد شود:
    • enabled=false؛
    • Job لغو؛
    • Switch خاموش؛
    • Toast خطا.
  6. اگر RECEIVE_SMS داده شود ولی READ_SMS داده نشود، عامل می‌تواند روشن شود اما recovery پیام‌های ازدست‌رفته غیرفعال است و هشدار نمایش داده می‌شود.
  7. اپ enabled=true می‌کند و JobScheduler را با شرایط زیر ثبت می‌کند:
    • نیاز به هر نوع شبکه؛
    • persisted پس از reboot؛
    • backoff نمایی با پایه ۳۰ ثانیه.
  8. اگر Android ثبت Job را رد کند یا exception رخ دهد، اپ دوباره OFF می‌شود.
  9. در حالت موفق، log «Agent switched ON» ثبت و recovery فوری اجرا می‌شود.
  10. محدودیت باتری یا Autostart ناقص مانع ON شدن نیست؛ فقط هشدار reliability داده می‌شود.

۷.۴ خاموش کردن Status

  • enabled=false ذخیره می‌شود.
  • Job با ID ثابت 3001 لغو می‌شود.
  • log محلی ثبت می‌شود.
  • Broadcastهای بعدی SMS بدون پردازش return می‌شوند.
  • آیتم‌های موجود صف پاک نمی‌شوند، اما تا روشن شدن دوباره ارسال نخواهند شد و احتمالاً پس از ۶۰ ثانیه منقضی می‌شوند.

۷.۵ رفتار هنگام بازگشت به اپ (onResume)

  1. اگر عامل روشن باشد ولی RECEIVE_SMS revoke شده باشد، اپ خودکار OFF و Job لغو می‌شود.
  2. readiness دوباره محاسبه می‌شود.
  3. پس از بازگشت از صفحه Xiaomi Autostart، کاربر با Dialog تأیید می‌کند که Autostart را فعال کرده یا نه.
  4. اگر عامل روشن و RECEIVE_SMS موجود ولی READ_SMS مفقود باشد، در هر launch فقط یک بار مجوز recovery درخواست می‌شود.
  5. recovery پیام‌های اخیر اجرا می‌شود.
  6. آخرین logهای محلی نمایش داده می‌شوند.

۸. فاز دو: تست اتصال و ثبت شماره

۸.۱ ثبت از اپ با /api/test — مسیر TEST

ID Lane عمل/تصمیم مسیر/نتیجه
TEST-01 مدیر گوشی لمس TEST AND SEND PHONE TO GROUP 02
TEST-02 اپ اعتبارسنجی و ذخیره ۱ یا ۲ شماره نامعتبر: Toast و پایان؛ معتبر: 03
TEST-03 اپ غیرفعال کردن موقت دکمه و ارسال HTTPS POST /api/test 04
TEST-04 بک‌اند بررسی X-App-Secret با مقایسه timing-safe نامعتبر: HTTP 401؛ معتبر: 05
TEST-05 بک‌اند بررسی X-App-Mode mismatch: HTTP 409؛ معتبر: 06
TEST-06 بک‌اند بررسی body شامل ۱ تا ۲ شماره معتبر نامعتبر: HTTP 400؛ معتبر: 07
TEST-07 بک‌اند/تلگرام ارسال Receiver Test Message به گروه فعال شکست: audit + HTTP 502؛ موفق: 08
TEST-08 Phone Store ثبت شماره‌های جدید بدون reset شمارنده قبلی خطای storage: audit + HTTP 500؛ موفق: 09
TEST-09 Session Store audit با state=sent_to_group 10
TEST-10 بک‌اند پاسخ 200 {success:true} 11
TEST-11 اپ log نتیجه، فعال‌کردن دکمه و نمایش Toast پایان

نکته: انجام TEST برای روشن شدن عامل الزامی نیست، اما برای اینکه /code آن شماره پذیرفته شود، شماره باید قبلاً در Phone Store ثبت شده باشد.

۸.۲ ثبت از پیام گروه

در گروه فعال، هر پیام متنی که دقیقاً این ساختار را داشته باشد نیز شماره‌ها را ثبت می‌کند:

📱 Receiver Test Message
شماره‌های تلفن:
09901283916
#phone

یک یا دو شماره پذیرفته می‌شود. در پیاده‌سازی فعلی بک‌اند بررسی نمی‌کند که فرستنده این پیام خود ربات بوده باشد؛ هر عضو گروه فعال با قالب دقیق می‌تواند شماره ثبت کند.


۹. فاز سه: آماده‌سازی کاربر تلگرام

/start

  1. کاربر باید حداقل یک بار چت خصوصی ربات را باز و Start کند.
  2. Telegram update به webhook می‌رسد.
  3. اگر متن دقیقاً /start یا /start@BotUsername باشد، ربات در همان chat با سلام! پاسخ می‌دهد.
  4. رخداد با نوع bot_command و state replied یا telegram_failed audit می‌شود.
  5. این فرمان هم در private و هم group پاسخ داده می‌شود.

اهمیت این مرحله: Telegram اجازه نمی‌دهد Bot پیش از شروع گفت‌وگوی خصوصی توسط کاربر، پیام خصوصی آغاز کند. اگر این مرحله انجام نشده باشد، ایجاد نشست کد در مرحله ارسال پیام خصوصی شکست می‌خورد.


۱۰. فاز چهار: درخواست کد در گروه تلگرام

فرمان معتبر:

/code 09xxxxxxxxx

فرمان با suffix ربات و حروف بزرگ/کوچک نیز پذیرفته می‌شود؛ مانند /Code@BotUsername 09901283916.

مسیر کامل CODE-REQ

ID Lane عمل/تصمیم مسیر/نتیجه
CODE-REQ-01 کاربر ارسال /code PHONE 02
CODE-REQ-02 تلگرام POST update به /telegram/webhook 03
CODE-REQ-03 بک‌اند آیا update دارای message، chat.id و text است؟ خیر: 200 ignored؛ بله: 04
CODE-REQ-04 بک‌اند آیا chat نوع group/supergroup است؟ خیر: 200 ignored؛ بله: 05
CODE-REQ-05 بک‌اند آیا group همان گروه فعال mode است؟ خیر: 200 ignored؛ بله: 06
CODE-REQ-06 بک‌اند آیا متن شبیه /code است؟ خیر: 200 ignored؛ بله: 07
CODE-REQ-07 بک‌اند parse دقیق فرمان و شماره نامعتبر: audit invalid_format + reply قالب صحیح + پایان؛ معتبر: 08
CODE-REQ-08 بک‌اند آیا message.from.id موجود است؟ خیر: ignored؛ بله: 09
CODE-REQ-09 Phone Store incrementCallIfRegistered(phone) شماره موجود: افزایش timesCalled و 10؛ موجود نیست: 11A؛ خطای store: 11B
CODE-REQ-10 Session Store audit phone_scoreboard/call_incremented 12
CODE-REQ-11A بک‌اند reply «شماره در فهرست نیست» + audit phone_not_registered 200 accepted:false
CODE-REQ-11B بک‌اند reply «امکان بررسی نیست» + audit phone_registry_check_failed 200 accepted:false
CODE-REQ-12 Session Store آیا برای این شماره نشست فعال وجود دارد؟ بله: 13A؛ خیر: 13B
CODE-REQ-13A بک‌اند audit duplicate_active_session و reply هشدار 200 accepted:false؛ نشست قبلی بدون تغییر
CODE-REQ-13B بک‌اند/تلگرام ارسال پیام خصوصی «نشست آماده است» به requester شکست: 14A؛ موفق: 14B
CODE-REQ-14A بک‌اند audit private_message_failed و reply در گروه که Start را بزند 200 accepted:false؛ نشست ساخته نمی‌شود
CODE-REQ-14B Session Store ساخت نشست active با انقضای ۱۲۰ ثانیه و audit 15
CODE-REQ-15 بک‌اند ثبت timer انقضا برای phone/sessionId 16
CODE-REQ-16 بک‌اند/تلگرام reply گروه شامل شماره، درخواست‌کننده و مهلت؛ بدون کد 200 accepted:true

نکته شمارنده timesCalled

در پیاده‌سازی فعلی شمارنده قبل از بررسی duplicate بودن نشست و قبل از ارسال پیام خصوصی افزایش می‌یابد. بنابراین هر فرمان با قالب معتبر برای شماره ثبت‌شده، حتی اگر به دلیل نشست تکراری یا ناتوانی ربات در private message پذیرفته نشود، timesCalled را یک واحد زیاد می‌کند.

هم‌زمانی

Session Store عملیات را serial می‌کند. اگر دو درخواست هم‌زمان برای یک شماره برسند، فقط یکی نشست ایجاد می‌کند و دیگری duplicate_active_session می‌شود.


۱۱. فاز پنج: اقدام کاربر در دیوار و دریافت SMS

  1. پس از دریافت پیام خصوصی آمادگی نشست، کاربر شماره نمایش‌داده‌شده را در دیوار وارد می‌کند.
  2. دیوار کد تأیید را از طریق اپراتور برای همان شماره ارسال می‌کند.
  3. Android پیام SMS_RECEIVED را به SmsReceiver می‌دهد؛ این receiver در Manifest با permission BROADCAST_SMS ثبت شده است.

مسیر پردازش زنده SMS — SMS-LIVE

ID Lane عمل/تصمیم مسیر/نتیجه
SMS-LIVE-01 Android دریافت Broadcast 02
SMS-LIVE-02 اپ آیا action دقیقاً SMS_RECEIVED است؟ خیر: پایان؛ بله: 03
SMS-LIVE-03 اپ آیا enabled=true است؟ خیر: پایان بدون log؛ بله: 04
SMS-LIVE-04 اپ استخراج partهای SMS از Intent خالی: پایان؛ موجود: 05
SMS-LIVE-05 اپ اتصال body همه partها و خواندن sender از part اول 06
SMS-LIVE-06 MessageParser آیا body شامل واژه «دیوار» است و یک عدد مستقل شش‌رقمی دارد؟ خیر: پایان؛ بله: 07
SMS-LIVE-07 MessageParser نرمال‌سازی ارقام لاتین/فارسی/عربی به لاتین 08
SMS-LIVE-08 اپ آیا تنظیم شماره‌ها معتبر است؟ خیر: log و پایان؛ بله: 09
SMS-LIVE-09 resolver تلاش برای تشخیص slot/subscription از extraهای رسمی و vendor 10
SMS-LIVE-10 resolver ساخت فهرست همه شماره‌های configured؛ شماره slot تشخیص‌داده‌شده فقط اول می‌آید خالی: log و پایان؛ غیرخالی: 11
SMS-LIVE-11 صف محلی ساخت fingerprint و پاک‌سازی seenهای قدیمی‌تر از ۲۴ ساعت 12
SMS-LIVE-12 صف محلی آیا fingerprint قبلاً دیده شده است؟ بله: log duplicate و پایان؛ خیر: 13
SMS-LIVE-13 صف محلی persist آیتم pending و seen fingerprint با commit 14
SMS-LIVE-14 اپ log «queued verification code» 15
SMS-LIVE-15 Android JobScheduler schedule job نیازمند شبکه موفق یا ناموفق log می‌شود؛ پایان Broadcast

اگر هر exception در این مسیر رخ دهد، اپ آن را در LocalLog ثبت می‌کند و Broadcast را بدون crash کردن ادامه نمی‌دهد.


۱۲. مسیر جایگزین: بازیابی SMS ازدست‌رفته

Recovery فقط برای زمانی است که Broadcast receiver به دلیل محدودیت OEM، توقف اپ یا شرایط مشابه اجرا نشده، ولی SMS هنوز در Inbox است.

triggerهای recovery

  • onResume اپ؛
  • بلافاصله پس از روشن‌شدن موفق عامل؛
  • پس از grant شدن READ_SMS؛
  • پس از reboot دستگاه؛
  • پس از MY_PACKAGE_REPLACED یعنی update اپ.

شروط ورود

  • عامل ON باشد؛
  • تنظیم شماره معتبر باشد؛
  • READ_SMS داده شده باشد؛
  • در MainActivity هم‌زمان recovery دیگری در حال اجرا نباشد.

مسیر SMS-RECOVER

  1. Inbox برای پیام‌هایی با DATE >= now - 60 seconds query می‌شود؛ ترتیب قدیمی به جدید است.
  2. ابتدا projection دارای sub_id امتحان می‌شود؛ اگر provider آن را نپذیرد، query بدون آن تکرار می‌شود.
  3. هر پیام فقط وقتی قابل recovery است که زمان آن مثبت، نه در آینده و هنوز کمتر از ۶۰ ثانیه سن داشته باشد.
  4. همان MessageParser مسیر زنده روی body اعمال می‌شود.
  5. subscription ID در صورت وجود به slot تبدیل می‌شود؛ با این حال تمام شماره‌های configured به عنوان کاندید ارسال می‌شوند.
  6. همان fingerprint مسیر زنده استفاده می‌شود؛ بنابراین SMS قبلاً پردازش‌شده دوباره enqueue نمی‌شود.
  7. اگر حداقل یک پیام جدید recovery شود، JobScheduler فعال می‌شود.
  8. نبود مجوز، query ناموجود، SecurityException یا خطای عمومی با unavailable=true و log مناسب خاتمه می‌یابد.

۱۳. فاز شش: Job ارسال از اپ به بک‌اند

stateهای آیتم صف

stateDiagram-v2
    [*] --> Pending: enqueue و persist
    Pending --> ExpiredDiscarded: سن حداقل ۶۰ ثانیه
    Pending --> Paused: Agent OFF یا تنظیم/شماره نامعتبر
    Paused --> Pending: Agent دوباره ON و هنوز منقضی نشده
    Pending --> RetryWaiting: خطای شبکه، HTTP غیرموفق یا success=false
    RetryWaiting --> Pending: اجرای مجدد Job با backoff
    Pending --> Removed: پاسخ 2xx با success=true
    Removed --> [*]
    ExpiredDiscarded --> [*]
Loading

مسیر APP-SEND

  1. Job فقط وقتی شروع به کار می‌کند که preferences.enabled=true باشد؛ در غیر این صورت پایان می‌یابد.
  2. یک generation ID برای جلوگیری از ادامه اجرای قبلی ساخته می‌شود.
  3. اگر تنظیم شماره نامعتبر باشد، ارسال pause و log می‌شود؛ retry صریح درخواست نمی‌شود.
  4. اولین آیتم صف خوانده می‌شود.
  5. اگر سن آیتم حداقل ۶۰ ثانیه باشد:
    • آیتم حذف می‌شود؛
    • log انقضا ثبت می‌شود؛
    • حلقه سراغ آیتم بعدی می‌رود.
  6. شماره‌های معتبر ذخیره‌شده داخل خود آیتم انتخاب می‌شوند؛ اگر خالی باشند، شماره‌های تنظیمات فعلی fallback هستند.
  7. اگر هیچ شماره‌ای موجود نباشد، ارسال pause می‌شود.
  8. اپ درخواست POST /api/sms را با این اطلاعات می‌فرستد:
    • Header: Content-Type: application/json؛
    • Header: X-App-Secret؛
    • Header: X-App-Mode؛
    • Body: {"code":"123456","phones":["09..."]}.
  9. timeout اتصال HTTP برابر ۱۵ ثانیه و timeout خواندن ۲۰ ثانیه است؛ redirect خودکار پذیرفته نمی‌شود.
  10. فقط پاسخ HTTP 2xx که JSON آن success=true باشد موفق محسوب می‌شود.
  11. در موفقیت:
    • آیتم صف حذف می‌شود؛
    • log «Submitted» ثبت می‌شود؛
    • حلقه آیتم بعدی را بررسی می‌کند.
  12. در خطای HTTP، network، timeout، JSON نامعتبر یا success=false:
    • آیتم در صف باقی می‌ماند؛
    • retryNeeded=true؛
    • حلقه متوقف می‌شود؛
    • JobScheduler با backoff دوباره تلاش می‌کند، مشروط به اینکه آیتم هنوز منقضی نشده باشد.
  13. اگر Android اجرای Job را متوقف کند، generation تغییر می‌کند و تا وقتی عامل ON است، onStopJob=true یعنی reschedule درخواست می‌شود.

نکته بسیار مهم برای فلوچارت

پاسخ‌های no_active_session و ambiguous_active_sessions از بک‌اند HTTP 200 و success=true دارند. بنابراین اپ آن‌ها را «پذیرفته‌شده توسط بک‌اند» می‌داند و آیتم را حذف می‌کند، حتی اگر delivered=false باشد. تنها شکست تحویل خصوصی Telegram با HTTP 502 باعث باقی ماندن آیتم و retry اپ می‌شود.


۱۴. فاز هفت: پردازش POST /api/sms در بک‌اند

گیت‌های اولیه API

شرط پاسخ اثر جانبی
Secret اشتباه/غایب 401 {success:false,error:"unauthorized"} بدون audit و بدون Telegram
Mode اشتباه/غایب 409 {success:false,error:"app_mode_mismatch"} بدون audit و بدون Telegram
code غیر شش‌رقمی یا phones خارج از ۱..۲/نامعتبر 400 invalid_request بدون Telegram
JSON خراب 400 invalid_json بدون پردازش business
body بزرگ‌تر از limit اپ 413 request_too_large بدون پردازش business
خطای پیش‌بینی‌نشده 500 internal_error log سرور

قبل از منطق تطبیق، هر transaction نشست‌های منقضی را حذف و expiration handler را اجرا می‌کند.

درخت تصمیم تطبیق SMS-MATCH

flowchart TD
    A[درخواست معتبر api/sms] --> B[حذف نشست‌های منقضی]
    B --> C[شماره‌های یکتای payload که نشست فعال دارند]
    C --> D{تعداد match}
    D -->|صفر| E[Audit: no_active_session بدون ذخیره کد]
    E --> F[200 success=true delivered=false]
    D -->|بیش از یک| G[Audit: ambiguous_active_sessions بدون ذخیره کد]
    G --> H[حفظ همه نشست‌ها]
    H --> I[200 success=true delivered=false reason=ambiguous]
    D -->|دقیقاً یک| J[ارسال کد به چت خصوصی requester]
    J --> K{ارسال Telegram موفق؟}
    K -->|خیر| L[Audit: private_delivery_failed بدون ذخیره کد]
    L --> M[حفظ نشست و 502 برای retry]
    K -->|بله| N[حذف نشست و Audit: delivered]
    N --> O[لغو timer]
    O --> P[افزایش successfulDeliveries اگر شماره هنوز ثبت است]
    P --> Q[Reply موفقیت در گروه بدون کد]
    Q --> R[200 success=true delivered=true]
Loading

حالت صفر match

  • submission با state=no_active_session ثبت می‌شود.
  • کد عمداً در audit ذخیره نمی‌شود؛ فقط phones و زمان‌ها ثبت می‌شوند.
  • هیچ پیام خصوصی یا گروهی ارسال نمی‌شود.
  • پاسخ 200 {success:true, delivered:false} است.
  • اپ آیتم را حذف می‌کند.

حالت بیش از یک match

  • این حالت معمولاً وقتی رخ می‌دهد که هر دو شماره configured هم‌زمان نشست فعال دارند و metadata اسلات برای انتخاب قطعی قابل اعتماد نیست.
  • کد به هیچ کاربری ارسال نمی‌شود.
  • هر دو نشست active باقی می‌مانند.
  • audit ambiguous_active_sessions شامل phones و matchingPhones است، اما خود کد را ذخیره نمی‌کند.
  • پاسخ 200 success=true, delivered=false, reason=ambiguous_active_sessions است.
  • اپ آیتم را حذف می‌کند؛ بنابراین این submission خودکار retry نمی‌شود.

حالت دقیقاً یک match و تحویل خصوصی ناموفق

  • بک‌اند تلاش می‌کند پیام شامل شماره و کد را به requesterId بفرستد.
  • در شکست Telegram، audit private_delivery_failed شامل نتیجه و خطای Telegram ثبت می‌شود، اما خود کد را ذخیره نمی‌کند.
  • نشست active و timer آن حفظ می‌شوند.
  • پاسخ HTTP 502 با telegram_delivery_failed است.
  • اپ آیتم را حفظ و طبق backoff retry می‌کند، ولی فقط تا قبل از انقضای ۶۰ ثانیه‌ای آیتم.

حالت دقیقاً یک match و تحویل موفق

ترتیب آثار:

  1. کد در چت خصوصی درخواست‌کننده ارسال می‌شود.
  2. نشست از Session Store حذف می‌شود.
  3. دو audit با state=delivered ثبت می‌شود: یکی sms_submission و دیگری session؛ هیچ‌کدام خود کد را نگهداری نمی‌کنند.
  4. timer نشست لغو می‌شود.
  5. اگر شماره هنوز در Phone Store باشد، successfulDeliveries افزایش می‌یابد.
  6. اگر شماره در طول نشست opt-out شده باشد، دوباره ثبت نمی‌شود و فقط audit phone_not_registered ثبت می‌شود.
  7. بک‌اند در reply پیام اصلی گروه می‌نویسد: «کد دریافت و ارسال شد.»؛ خود کد در گروه نیست.
  8. شکست ارسال همین پیام گروهی فقط log می‌شود و تحویل را rollback نمی‌کند.
  9. پاسخ 200 {success:true, delivered:true} به اپ داده می‌شود.

۱۵. انقضای نشست

state machine نشست

stateDiagram-v2
    [*] --> Rejected: فرمت/شماره/Private نامعتبر
    [*] --> Active: ایجاد موفق نشست
    Active --> Active: درخواست تکراری رد می‌شود
    Active --> Delivered: یک match و ارسال خصوصی موفق
    Active --> Active: ارسال خصوصی کد ناموفق؛ قابل retry
    Active --> Active: submission مبهم؛ نشست حفظ می‌شود
    Active --> ExpiredWithoutCode: زمان جاری بزرگ‌تر یا مساوی expiresAt
    ExpiredWithoutCode --> ExpirationNotified: پیام خصوصی و گروهی هر دو موفق
    ExpiredWithoutCode --> ExpirationNotificationFailed: یکی یا هر دو اعلان ناموفق
    Delivered --> [*]
    ExpirationNotified --> [*]
    ExpirationNotificationFailed --> [*]
    Rejected --> [*]
Loading

trigger انقضا

  • timer اختصاصی نشست در زمان expiresAt؛
  • هر transaction بعدی Session Store که نشست منقضی را مشاهده کند؛
  • startup بک‌اند بعد از restart.

در لحظه دقیق ۱۲۰ ثانیه، نشست دیگر معتبر نیست (expiresAt <= now).

ترتیب انقضا

  1. نشست از مجموعه active حذف می‌شود.
  2. audit session/expired_without_code ثبت می‌شود.
  3. پیام ⏳Session expired. به private requester ارسال می‌شود.
  4. همان متن به صورت reply به پیام اصلی گروه ارسال می‌شود.
  5. audit ثانویه ثبت می‌کند:
    • expiration_notified اگر هر دو موفق باشند؛
    • expiration_notification_failed اگر یکی یا هر دو شکست بخورند، همراه نتیجه و error هر کانال.
  6. شکست notification باعث بازگشت نشست به active یا retry خودکار اعلان نمی‌شود.

۱۶. فرمان‌های جانبی ربات

۱۶.۱ /get_phone

  • فقط در گروه فعال پردازش می‌شود.
  • Phone Store فهرست یکتا را می‌خواند.
  • مرتب‌سازی:
    1. successfulDeliveries نزولی؛
    2. addedAt صعودی؛
    3. شماره به ترتیب متنی.
  • هر ردیف timesCalled و successfulDeliveries را نمایش می‌دهد.
  • اگر فهرست خالی باشد، پیام شفاف «هیچ شماره‌ای ثبت نشده» می‌دهد.
  • نتیجه ارسال پیام با replied یا telegram_failed audit می‌شود.

۱۶.۲ /opt_out 09xxxxxxxxx

  • فقط در گروه فعال پردازش می‌شود.
  • فرمت نامعتبر: reply قالب صحیح + audit invalid_format.
  • شماره موجود: رکورد و شمارنده‌های آن حذف + audit removed.
  • شماره ناموجود: reply هشدار + audit phone_not_found.
  • حذف شماره نشست فعال آن را لغو نمی‌کند.
  • اگر همان نشست بعداً کد را تحویل دهد، شمارنده موفقیت افزایش نمی‌یابد و شماره دوباره register نمی‌شود.
  • در پیاده‌سازی فعلی نقش ادمین بررسی نمی‌شود؛ هر عضوی که بتواند در گروه فعال فرمان بفرستد می‌تواند opt-out انجام دهد.

۱۶.۳ /group_id

  • در هر group یا supergroup، حتی گروه غیر فعال، پاسخ می‌دهد.
  • در private chat نادیده گرفته می‌شود.
  • پاسخ شامل ID عددی گروه و reply به پیام اصلی است.
  • رخداد audit می‌شود.

۱۶.۴ پیام‌ها و فرمان‌های ناشناخته

  • در private chat، همه چیز جز /start نادیده گرفته می‌شود.
  • در گروه غیر فعال، همه چیز جز /start و /group_id نادیده گرفته می‌شود.
  • در گروه فعال، متن ناشناخته بدون side effect با success:true, ignored:true پایان می‌یابد.

۱۷. ماتریس حالت‌های اصلی

۱۷.۱ حالت عامل اندروید

حالت ورود خروج رفتار SMS
OFF نصب اولیه، خاموش‌کردن دستی، revoke شدن RECEIVE_SMS، شکست schedule enable موفق Broadcast نادیده گرفته می‌شود؛ Job لغو است
ON_DEGRADED enable با READ_SMS مفقود یا battery/autostart ناقص تکمیل readiness یا OFF SMS زنده ممکن است کار کند؛ recovery/reliability ناقص
ON_READY enable + مجوزها + آمادگی background revoke/خاموش کردن دریافت، صف و ارسال کامل

۱۷.۲ حالت submission در بک‌اند

state کد در audit؟ نشست حفظ می‌شود؟ پیام خصوصی؟ رفتار اپ
no_active_session خیر موضوعی نیست خیر حذف صف؛ retry ندارد
ambiguous_active_sessions خیر بله، همه خیر حذف صف؛ retry ندارد
private_delivery_failed خیر بله تلاش ناموفق حفظ صف و retry
delivered خیر خیر بله حذف صف

۱۷.۳ حالت شماره ثبت‌شده

رخداد اثر
TEST موفق یا پیام قالب‌دار گروه ایجاد رکورد فقط اگر جدید باشد
/code معتبر روی شماره ثبت‌شده timesCalled + 1، حتی اگر نشست بعداً پذیرفته نشود
تحویل خصوصی موفق successfulDeliveries + 1 اگر شماره هنوز ثبت است
/opt_out حذف کامل شماره و شمارنده‌ها؛ نشست فعال دست‌نخورده
TEST مجدد پس از opt-out شماره با شمارنده‌های صفر دوباره ساخته می‌شود

۱۸. زمان‌ها و محدودیت‌های عددی

پارامتر مقدار فعلی معنی
طول نشست بک‌اند ۱۲۰ ثانیه مهلت دریافت کد از زمان ایجاد نشست
عمر آیتم pending اپ ۶۰ ثانیه بعد از آن کد stale حذف می‌شود
پنجره recovery Inbox ۶۰ ثانیه فقط SMSهای اخیر بررسی می‌شوند
پنجره dedup fingerprint ۲۴ ساعت تکرار sender/body/phones enqueue نمی‌شود
JobScheduler backoff پایه ۳۰ ثانیه، نمایی retry خطاهای transient
HTTP connect timeout اپ ۱۵ ثانیه اتصال به بک‌اند
HTTP read timeout اپ ۲۰ ثانیه انتظار پاسخ بک‌اند
Telegram send timeout بک‌اند ۲۰ ثانیه هر فراخوانی sendMessage
App API JSON limit ۱۶KB /api/test و /api/sms
Telegram webhook JSON limit ۲۵۶KB update تلگرام
LocalLog حداکثر ۵۰ رخداد UI معمولاً ۱۲ رخداد آخر را نشان می‌دهد
graceful shutdown ۱۰ ثانیه سپس force-close

نتیجه مهم: نشست ۲ دقیقه است، ولی کد در اپ فقط ۱ دقیقه قابلیت ارسال دارد. پس retry اپ نمی‌تواند تا پایان کامل نشست ادامه پیدا کند.


۱۹. مسیرهای خطا و مالک اقدام بعدی

خطا/نشانه محل رفتار خودکار اقدام انسانی احتمالی
شماره نامعتبر اپ/ربات رد درخواست اصلاح فرمت 09xxxxxxxxx
شماره ثبت نشده بک‌اند نشست ساخته نمی‌شود TEST موفق از گوشی یا ثبت قالب‌دار
کاربر Bot را Start نکرده تلگرام private setup fail؛ نشست ساخته نمی‌شود Start در چت خصوصی و درخواست مجدد
نشست تکراری بک‌اند نشست قبلی حفظ صبر تا تحویل/انقضا یا استفاده از شماره دیگر
هر دو شماره نشست فعال دارند بک‌اند کد تحویل نمی‌شود؛ هر دو نشست حفظ جلوگیری عملیاتی از هم‌زمانی یا درخواست SMS مجدد با وضعیت بدون ابهام
شبکه گوشی قطع Android Job انتظار شبکه و retry برقراری شبکه پیش از ۶۰ ثانیه
Secret غلط بک‌اند HTTP 401 و retry تا انقضای صف rebuild با Secret صحیح
Mode غلط بک‌اند HTTP 409 و retry تا انقضای صف یکسان‌سازی mode و rebuild/restart
Telegram private send fail هنگام تحویل بک‌اند + اپ نشست/صف حفظ و retry بررسی Telegram/API؛ محدود به پنجره ۶۰ ثانیه
اعلان گروه پس از تحویل fail بک‌اند تحویل rollback نمی‌شود بررسی audit/log؛ کاربر کد را خصوصی دارد
revoke شدن RECEIVE_SMS اپ خودکار OFF در onResume grant مجدد و روشن‌کردن
READ_SMS رد شده اپ فقط recovery غیرفعال grant برای مقاومت در برابر missed broadcast
Battery/Autostart ناقص Android/OEM فقط هشدار؛ امکان missed SMS تکمیل readiness
JSON store خراب بک‌اند فایل به {} بازسازی می‌شود بازیابی backup؛ نشست/شماره قبلی ممکن است از دست برود
session expire بک‌اند حذف + اعلان یک‌باره درخواست جدید

۲۰. Audit و حریم خصوصی

مواردی که ممکن است در Session history ذخیره شوند

  • شماره تلفن؛
  • Telegram user ID و نام/username؛
  • Group ID و Message ID؛
  • زمان‌های ایجاد، انقضا و تحویل؛
  • خطاهای Telegram/storage؛
  • متن فرمان نامعتبر در برخی رخدادها.

مواردی که عمداً ذخیره نمی‌شوند

  • کد OTP در هیچ state از audit ذخیره نمی‌شود؛ migration نیز کدهای legacy همه stateها را پاک می‌کند.
  • متن کامل SMS و sender از اپ به بک‌اند ارسال نمی‌شود.

ملاحظات عملیاتی فعلی

  • _history خودکار prune نمی‌شود و retention policy باید بیرون از برنامه تعریف شود.
  • فایل‌ها باید private و backupها محافظت شوند.
  • APP_SECRET داخل APK کامپایل می‌شود و در برابر استخراج از APK یک راز سخت‌افزاری محسوب نمی‌شود.
  • وب‌هوک فعلی Telegram secret-token header را اعتبارسنجی نمی‌کند.
  • فرمان‌های گروه role-based authorization ندارند؛ مرز دسترسی فعلی عضویت/توان ارسال پیام در گروه فعال است.
  • پیام قالب‌دار ثبت شماره، هویت sender را به Bot محدود نمی‌کند.

این موارد توضیح رفتار فعلی‌اند و برای threat model یا طراحی نسخه بعد باید به عنوان decision point جدا دیده شوند.


۲۱. Blueprint پیشنهادی برای رسم فلوچارت نهایی

برای جلوگیری از یک نمودار بسیار شلوغ، بهتر است خروجی به هفت نمودار مرتبط تقسیم شود:

  1. نمودار A — Deployment & Readiness: از BE-BOOT-01 تا Ready و از APP-CONFIG تا ON_READY.
  2. نمودار B — Phone Registration: کل مسیر TEST-01..11 و ثبت از پیام گروه.
  3. نمودار C — User Code Request: کل مسیر CODE-REQ-01..16.
  4. نمودار D — SMS Capture: مسیر SMS-LIVE به همراه شاخه SMS-RECOVER.
  5. نمودار E — Delivery Queue: state machine صف و مسیر APP-SEND.
  6. نمودار F — Backend Matching: درخت SMS-MATCH با شاخه‌های ۰، ۱ و ۲ match.
  7. نمودار G — Session Lifecycle: state machine نشست، timer، restart restoration و expiration notification.

قواعد اتصال بین نمودارها

  • خروجی موفق نمودار B یعنی Phone=Registered و ورودی لازم نمودار C است.
  • خروجی موفق نمودار C یعنی Session=Active و trigger اقدام کاربر در دیوار است.
  • خروجی دیوار/SMS وارد نمودار D می‌شود.
  • خروجی Queued نمودار D ورودی نمودار E است.
  • درخواست HTTP نمودار E وارد نمودار F می‌شود.
  • Delivered یا Expired نمودار F/G پایان سناریوی اصلی است.
  • ambiguous پایان submission فعلی است، نه پایان نشست‌ها.
  • private_delivery_failed یک loop بین نمودار E و F ایجاد می‌کند.

قرارداد شکل‌ها

  • دایره/Terminator: شروع و پایان؛
  • مستطیل: عمل قطعی؛
  • لوزی: شرط دو یا چند شاخه؛
  • استوانه: Phone Store، Session Store یا حافظه محلی؛
  • پاکت/Message: پیام Telegram، SMS یا HTTP؛
  • Timer event: ۶۰ ثانیه صف یا ۱۲۰ ثانیه نشست؛
  • خط‌چین: notification غیرتراکنشی که شکست آن state اصلی را rollback نمی‌کند؛
  • خط ممتد: مسیر business اصلی؛
  • Loop: فقط retry شبکه/private delivery و بازگشت Job.

۲۲. سناریوی End-to-End موفق به زبان ترتیبی

  1. مدیر بک‌اند را در mode مناسب بالا می‌آورد و webhook فعال است.
  2. مدیر اپ را نصب، یک یا دو شماره معتبر ثبت، مجوزها را صادر و Status را ON می‌کند.
  3. مدیر TEST می‌زند؛ بک‌اند پیام تست را به گروه فعال می‌فرستد و شماره‌ها در Phone Store ثبت می‌شوند.
  4. کاربر ربات را در private chat Start کرده است.
  5. کاربر در گروه فعال /code PHONE می‌فرستد.
  6. بک‌اند شماره را معتبر و ثبت‌شده تشخیص می‌دهد و timesCalled را افزایش می‌دهد.
  7. بک‌اند نبود نشست قبلی را تأیید و پیام آمادگی را خصوصی ارسال می‌کند.
  8. بک‌اند نشست active با deadline دو دقیقه می‌سازد و در گروه اعلام می‌کند.
  9. کاربر همان شماره را در دیوار وارد می‌کند.
  10. SMS حاوی «دیوار» و کد شش‌رقمی به گوشی می‌رسد.
  11. اپ کد را استخراج، شماره‌های کاندید را تعیین، duplicate را بررسی و آیتم را persist می‌کند.
  12. Job با وجود شبکه، POST /api/sms را با Secret و Mode ارسال می‌کند.
  13. بک‌اند دقیقاً یک نشست منطبق پیدا می‌کند.
  14. بک‌اند کد را به requester خصوصی می‌فرستد.
  15. پس از موفقیت Telegram، نشست حذف و audit تحویل ثبت می‌شود.
  16. successfulDeliveries شماره یک واحد افزایش می‌یابد.
  17. پیام «کد دریافت و ارسال شد» بدون کد در گروه reply می‌شود.
  18. بک‌اند success=true, delivered=true می‌دهد.
  19. اپ آیتم صف را حذف و log موفقیت ثبت می‌کند.
  20. کاربر کد خصوصی را در دیوار وارد می‌کند؛ این مرحله خارج از کنترل مستقیم سامانه حاضر است.

۲۳. مرز مسئولیت سامانه

سامانه حاضر تا «تحویل خصوصی کد به کاربر» را مدیریت می‌کند. این موارد خارج از کنترل آن‌اند:

  • اینکه دیوار درخواست شماره را قبول کند یا SMS بفرستد؛
  • تأخیر یا failure شبکه اپراتور؛
  • اینکه کاربر کد را به‌موقع و درست در دیوار وارد کند؛
  • محدودیت‌های force-stop یا OEM که Broadcast و Job را کاملاً متوقف کنند؛
  • دسترس‌پذیری Telegram و شبکه عمومی؛
  • صحت عملیاتی عضویت‌ها و مجوزهای کاربران گروه.

پایان موفق فرایند داخلی برابر است با session=delivered و پاسخ delivered=true، نه لزوماً تأیید نهایی ورود کاربر در دیوار.