Skip to content

Latest commit

 

History

History
273 lines (186 loc) · 10.5 KB

File metadata and controls

273 lines (186 loc) · 10.5 KB

معماری و فرایند سیستم

نمای سرتاسری ثبت شماره، درخواست تلگرام، دریافت SMS در اندروید، تطبیق بک‌اند، تحویل خصوصی OTP و انقضای نشست.

flowchart TB

    %% =====================================================
    %% 01 — SETUP & PHONE REGISTRATION
    %% =====================================================

    subgraph S1["01 · راه‌اندازی و ثبت شماره‌ها"]
        direction TB

        ADMIN["مدیر سامانه"]
        CONFIG["تنظیم اپ Android Receiver<br/>ثبت ۱ تا ۲ شماره تلفن"]
        READY{"Receiver آماده است؟"}
        READINESS["مجوزهای SMS<br/>اجرای پس‌زمینه<br/>آمادگی JobScheduler"]
        TEST["TEST AND SEND<br/>POST /api/test"]
        PHONE_STORE[("Phone Store<br/>شماره‌های ثبت‌شده<br/>شمارنده‌های استفاده")]

        ADMIN --> CONFIG
        CONFIG --> READY

        READY -- "خیر" --> READINESS
        READINESS --> READY

        READY -- "بله" --> TEST
        TEST --> PHONE_STORE
    end


    %% =====================================================
    %% 02 — TELEGRAM REQUEST & SESSION CREATION
    %% =====================================================

    subgraph S2["02 · درخواست تلگرام و ایجاد نشست"]
        direction TB

        USER["کاربر درخواست‌کننده"]
        START["شروع چت خصوصی با ربات<br/>پیش‌نیاز یک‌باره"]
        CODE["ارسال /code 09xxxxxxxxx<br/>در گروه فعال تلگرام"]
        WEBHOOK["Telegram Webhook<br/>POST /telegram/webhook"]
        VALIDATE["اعتبارسنجی گروه، Mode،<br/>فرمان و شماره تلفن"]

        REGISTERED{"شماره ثبت شده است؟"}
        REJECT_PHONE["رد درخواست<br/>شماره ثبت نشده است"]

        ACTIVE{"برای این شماره<br/>نشست فعال وجود دارد؟"}
        REJECT_DUP["رد درخواست تکراری<br/>نشست قبلی حفظ می‌شود"]

        PRIVATE_READY["ارسال پیام خصوصی<br/>آماده بودن نشست"]
        PRIVATE_OK{"پیام خصوصی<br/>با موفقیت ارسال شد؟"}
        START_REQUIRED["درخواست از کاربر برای<br/>Start کردن ربات"]

        CREATE["ایجاد نشست فعال"]
        SESSION_STORE[("Session Store<br/>کاربر · شماره · Session ID<br/>CreatedAt · ExpiresAt")]
        TIMER["ثبت تایمر انقضای<br/>۱۲۰ ثانیه‌ای"]
        GROUP_ACCEPT["پاسخ در گروه<br/>درخواست پذیرفته شد"]

        USER --> START
        START --> CODE
        CODE --> WEBHOOK
        WEBHOOK --> VALIDATE
        VALIDATE --> REGISTERED

        REGISTERED -- "خیر" --> REJECT_PHONE
        REGISTERED -- "بله" --> ACTIVE

        ACTIVE -- "بله" --> REJECT_DUP
        ACTIVE -- "خیر" --> PRIVATE_READY

        PRIVATE_READY --> PRIVATE_OK
        PRIVATE_OK -- "خیر" --> START_REQUIRED
        PRIVATE_OK -- "بله" --> CREATE

        CREATE --> SESSION_STORE
        CREATE --> TIMER
        CREATE --> GROUP_ACCEPT
    end


    %% شماره‌های ثبت‌شده در اعتبارسنجی درخواست استفاده می‌شوند
    PHONE_STORE --> REGISTERED


    %% =====================================================
    %% 03 — DIVAR & ANDROID SMS CAPTURE
    %% =====================================================

    subgraph S3["03 · دیوار و دریافت SMS در اندروید"]
        direction TB

        DIVAR_INPUT["کاربر همان شماره تلفن را<br/>در دیوار وارد می‌کند"]
        DIVAR["دیوار درخواست کد تأیید می‌دهد"]
        SMS["SMS تأیید دریافت می‌شود"]

        RECEIVER["Android SMS BroadcastReceiver"]
        RECOVERY["بازیابی SMSهای اخیر<br/>مسیر جایگزین برای Broadcast ازدست‌رفته"]

        PARSE{"پیام معتبر دیوار با<br/>OTP شش‌رقمی است؟"}
        IGNORE["نادیده گرفتن پیام"]

        EXTRACT["نرمال‌سازی ارقام<br/>استخراج OTP شش‌رقمی"]
        CANDIDATES["تشخیص اطلاعات SIM<br/>ساخت شماره‌های کاندید"]

        DEDUP{"Fingerprint در ۲۴ ساعت<br/>گذشته دیده شده است؟"}
        DISCARD["حذف پیام تکراری"]

        QUEUE[("صف پایدار محلی<br/>FIFO · PendingDelivery<br/>TTL برابر ۶۰ ثانیه")]

        JOB["JobScheduler<br/>نیازمند اتصال شبکه"]
        SUBMIT["ارسال OTP و شماره‌های کاندید<br/>POST /api/sms"]

        DIVAR_INPUT --> DIVAR
        DIVAR --> SMS
        SMS --> RECEIVER
        RECEIVER --> PARSE

        RECOVERY -. "مسیر جایگزین" .-> PARSE

        PARSE -- "خیر" --> IGNORE
        PARSE -- "بله" --> EXTRACT

        EXTRACT --> CANDIDATES
        CANDIDATES --> DEDUP

        DEDUP -- "بله" --> DISCARD
        DEDUP -- "خیر" --> QUEUE

        QUEUE --> JOB
        JOB --> SUBMIT
    end


    GROUP_ACCEPT --> DIVAR_INPUT


    %% =====================================================
    %% 04 — BACKEND MATCHING & SECURE DELIVERY
    %% =====================================================

    subgraph S4["04 · تطبیق در بک‌اند و تحویل امن"]
        direction TB

        AUTH["احراز درخواست اپ اندروید<br/>App Secret + App Mode"]
        AUTH_OK{"درخواست معتبر و<br/>احرازشده است؟"}

        API_REJECT["رد درخواست API<br/>آیتم در صف باقی می‌ماند"]

        CLEAN["حذف نشست‌های منقضی"]
        MATCH["تطبیق شماره‌های کاندید<br/>با نشست‌های فعال"]
        MATCH_COUNT{"تعداد نشست‌های<br/>فعال منطبق"}

        NO_SESSION["۰ تطبیق<br/>پذیرفته شده · بدون تحویل"]
        AMBIGUOUS["چند تطبیق<br/>وضعیت مبهم · نشست‌ها حفظ می‌شوند"]

        ONE_MATCH["دقیقاً یک تطبیق<br/>شناسایی درخواست‌کننده اصلی"]

        PRIVATE_OTP["ارسال خصوصی OTP<br/>از طریق تلگرام"]
        DELIVERY_OK{"تحویل خصوصی<br/>موفق بود؟"}

        RETRY["HTTP 502<br/>حفظ نشست و آیتم صف"]
        CLOSE["بستن نشست فعال<br/>لغو تایمر انقضا"]

        COUNTER["افزایش successfulDeliveries"]
        AUDIT[("Audit History<br/>رخدادهای تحویل و نشست")]

        GROUP_SUCCESS["پاسخ به پیام اصلی گروه<br/>کد دریافت و ارسال شد<br/>OTP هرگز در گروه نمایش داده نمی‌شود"]

        DONE(["OTP با موفقیت تحویل شد"])

        AUTH --> AUTH_OK

        AUTH_OK -- "خیر" --> API_REJECT
        AUTH_OK -- "بله" --> CLEAN

        CLEAN --> MATCH
        MATCH --> MATCH_COUNT

        MATCH_COUNT -- "۰" --> NO_SESSION
        MATCH_COUNT -- "چند مورد" --> AMBIGUOUS
        MATCH_COUNT -- "دقیقاً ۱" --> ONE_MATCH

        ONE_MATCH --> PRIVATE_OTP
        PRIVATE_OTP --> DELIVERY_OK

        DELIVERY_OK -- "خیر" --> RETRY
        DELIVERY_OK -- "بله" --> CLOSE

        CLOSE --> COUNTER
        CLOSE --> AUDIT
        CLOSE --> GROUP_SUCCESS
        GROUP_SUCCESS --> DONE
    end


    SUBMIT --> AUTH
    SESSION_STORE --> MATCH

    API_REJECT -. "تلاش مجدد تا زمانی که آیتم تازه است" .-> JOB
    RETRY -. "Exponential Backoff" .-> JOB

    NO_SESSION -->|"200 · پذیرفته شد"| DEQUEUE1["حذف آیتم از صف"]
    AMBIGUOUS -->|"200 · پذیرفته شد"| DEQUEUE2["حذف آیتم از صف"]
    DONE -->|"200 · تحویل موفق"| DEQUEUE3["حذف آیتم از صف"]


    %% =====================================================
    %% 05 — SESSION EXPIRATION
    %% =====================================================

    subgraph S5["05 · انقضای نشست"]
        direction TB

        DEADLINE{"پس از ۱۲۰ ثانیه<br/>نشست هنوز فعال است؟"}
        TIMER_END["بدون اقدام<br/>نشست قبلاً تکمیل شده"]
        EXPIRE["منقضی کردن نشست"]
        EXPIRE_AUDIT["ثبت رخداد انقضا"]
        NOTIFY_PRIVATE["اعلان خصوصی به درخواست‌کننده"]
        NOTIFY_GROUP["پاسخ Session Expired<br/>در گروه تلگرام"]
        EXPIRED(["نشست منقضی شد"])

        DEADLINE -- "خیر" --> TIMER_END
        DEADLINE -- "بله" --> EXPIRE

        EXPIRE --> EXPIRE_AUDIT
        EXPIRE --> NOTIFY_PRIVATE
        EXPIRE --> NOTIFY_GROUP

        NOTIFY_PRIVATE --> EXPIRED
        NOTIFY_GROUP --> EXPIRED
    end


    TIMER -. "مهلت ۱۲۰ ثانیه" .-> DEADLINE


    %% =====================================================
    %% STYLES
    %% =====================================================

    classDef actor fill:#f8fafc,stroke:#64748b,color:#0f172a,stroke-width:1.5px;
    classDef telegram fill:#eff6ff,stroke:#2563eb,color:#172554,stroke-width:1.5px;
    classDef backend fill:#f5f3ff,stroke:#7c3aed,color:#2e1065,stroke-width:1.5px;
    classDef android fill:#f0fdf4,stroke:#16a34a,color:#14532d,stroke-width:1.5px;
    classDef external fill:#fff7ed,stroke:#ea580c,color:#7c2d12,stroke-width:1.5px;
    classDef store fill:#fffbeb,stroke:#d97706,color:#78350f,stroke-width:1.8px;
    classDef decision fill:#ffffff,stroke:#475569,color:#0f172a,stroke-width:1.8px;
    classDef warning fill:#fff7ed,stroke:#ea580c,color:#7c2d12,stroke-width:1.5px;
    classDef failure fill:#fef2f2,stroke:#dc2626,color:#7f1d1d,stroke-width:1.5px;
    classDef success fill:#ecfdf5,stroke:#059669,color:#064e3b,stroke-width:2px;

    class ADMIN,USER actor;

    class START,CODE,WEBHOOK,PRIVATE_READY,GROUP_ACCEPT,PRIVATE_OTP,GROUP_SUCCESS,NOTIFY_PRIVATE,NOTIFY_GROUP telegram;

    class VALIDATE,CREATE,TIMER,AUTH,CLEAN,MATCH,ONE_MATCH,CLOSE,COUNTER,EXPIRE,EXPIRE_AUDIT backend;

    class CONFIG,READINESS,TEST,RECEIVER,RECOVERY,EXTRACT,CANDIDATES,JOB,SUBMIT android;

    class DIVAR_INPUT,DIVAR,SMS external;

    class PHONE_STORE,SESSION_STORE,QUEUE,AUDIT store;

    class READY,REGISTERED,ACTIVE,PRIVATE_OK,PARSE,DEDUP,AUTH_OK,MATCH_COUNT,DELIVERY_OK,DEADLINE decision;

    class REJECT_PHONE,REJECT_DUP,START_REQUIRED,NO_SESSION,AMBIGUOUS warning;

    class IGNORE,DISCARD,API_REJECT,RETRY failure;

    class DONE,EXPIRED success;
Loading