Воркспейс — каркас логік

Повний перелік логік воркспейсу — що мусить бути, щоб нічого не пропустити. Тут — що це і від чого залежить.

  • Current State: фактичні розбіжності по проектах.
  • Server Coupling: проблеми які буду пов’язані з переносом.
  • Family Blueprint: повний набір логіки одного проєкту.

Запуск

1. Логін оператора підключення сокету до нашого серверу.

  • аутентифікація оператора
  • перевірка версії програми
  • перевірка часу з світовим

2. Підключення сокету до нашого серверу - отримання списку TU.

  • підключення чи перепідключення завжди повертає актуальний список ТЮ з статусами.
  • час (зміна) роботи оператора перевіряється на цьому етапі
  • обробка індивідуальних логік проектів по логіну ТЮ буде на цьому етапі теж

3. Отримання даних з серверу для запуску та робити логік.

  • мабуть варто це реалізувати одним запитом
  • відповідно до проекту набори даних будуть і однакові і різні TO DO

4. Логін TU на сайт + сокет по ТЮ.

Логін і носій сесії для запитів різні на кожному сайті; Golden ще й має два логіни (вкладка + окреме оф-апі).

GoldenChathousePrime
Логінin-page rlogin у вкладці (id_api+pass) + окремий логін оф-апі agencyhelper (login+pass)POST /tru/login (email+pass+auth_code)POST /platform/auth/login (email+pass+referral_code) ·
Що юзаємо для запитів2× JSESSIONID: вкладки (Chromium шле сам) + оф-апі (вручну в Cookie: axios)Bearer JWT access_tokenAuthorization: Bearerкукі (Set-Cookie) у → Cookie: axios
Сокет — ключі конектуRed5 wss://…/Red5Chat: param1=id_api + param5=loginTokenChat (+2 хардкод-конст, subproto chat)Centrifuge wss://ws.chatshouse.com: окремий broadcasting-токен; канал api#<ulid>Centrifuge wss://talkytimes.com/rtm: tld-token (JWT з кукі) у хендшейку + X-Requested-With; канали broadcast/online/personal:#<id>

Golden — виняток: логін і сокет крутяться всередині реальної браузер-вкладки (Electron BrowserWindow) → кукі возяться автоматично + працює WebRTC-камера. Chathouse/Prime — headless (axios + Centrifuge), сторінка не потрібна.

  • комбінацію логінів та запусків ініціалізуючих логік треба ще переглянути, десь можна паралельно, десь тільки послідовно (зараз: Golden — TU послідовно, Prime — паралельно Promise.all, Chathouse — послідовно)

5. Запуск pre логік.

Перед основними логіками Chathouse і Prime ганяють на старті кілька підготовчих логік і показують оператору вікно з їх прогресом. У Golden цього немає.

Pre-логікаGoldenChathousePrime
Фаворити на сайті (поставити/зняти)FavoriteWorker (save/unsave)PrimeBookmarkWorker (bookmark/unbookmark)
АйсбрейкериIceWorker (чат + лист)PrimeIcesWorker (чат-групи + лист)

Фаворити на сайті. Обидва тримають на сайті позначку «фаворит» синхронізованою: кому треба — ставлять, хто вже ні — знімають. Різниця — звідки беруть «хто фаворит»:

  • Chathouse — зі статистики (RU з платним профітом за останні 7 днів). Ставить: проходить вкладку all, і кому з активних фаворитів позначки ще нема → saveDialog(save:true). Знімає: проходить вкладку saved, і хто вже не активний фаворит → saveDialog(save:false). Заодно позначає заблокованих (RU заблокував анкету).
  • Prime — статистики нема, тому все по історії листування. Ставить: де RU надіслав платне повід./лист за останні 7 днів → changeBookmark(true). Знімає (changeBookmark(false)): якщо чат-ліміти вичерпані — одразу (навіть при свіжому спілкуванні); або якщо останнє платне від RU старше 7 днів. Лічильник дій RU (за ним і визначається фаворит) оновлюється реалтайм по сокету (+1 на кожне платне повід./лист); повний скрол історії — раз на TU (перша ініціалізація), а при логіні для вже відомого фаворита скрол іде лише до останньої зафіксованої дати й доливає нові.

Реворк: сумнівно скролити діалоги й проставляти фаворитів на сайті при кожному логіні — цю логіку треба переробити.

Айсбрейкери. Раз на день на кожну TU активують випадковий айсбрейкер по кожному типу (чат + лист); що вже активовано сьогодні — не повторюють (перевірка по БД надісланих за добу).

  • Chathouse — на кожен тип бере випадковий approved і ще не активний ice → активує.
  • Prime — лист: випадковий готовий mail-ice. Чат складніше: треба ≥2 ice на кожен настрій (friendship / hot_talks / real_love), тоді зупиняє поточні й шле групу з трьох настроїв (по випадковому в кожному).

Під питанням: айсбрейкери не мусять блокувати старт — їх можна робити у фоні; тримати їх у стартовому прогресі сенсу мало.

6. Старт основних логік.

  • Сервіс підтримки ТЮ в онлайні, перевірки ТЮ з апі що вона онлайн та реконект, фіксування часу онлайн
  • Обробка дій оператора для перевірки активності та фіксування онлайну і дій оператора
  • Пошук тасків
  • Сендера
  • Оновлення фаворитів чи чатхісторі

Важливі логіки

Постійні алгоритми, що тримають роботу. Кожна мусить бути в кожному проекті. Згруповані за залежністю від партнерського API — саме вона визначає, наскільки логіку можна звести до спільної реалізації.

Тір 1 — незалежні від API

1. Обробка дій оператора

  • обчислення дій оператора по типах
  • обчислення онлайну оператора
  • кік-закриття програми при неактивності (10хв)
  • оновлення останнього онлайну в редіс

2. Синхронізація стану на бек (data-sync)

Збереження даних з локальної бази msql lite на наш сервер. Дані будуть відповідно до логік, те що уже існує:

  • результати сендерів
  • дії оператора
  • онлайн оператора
  • періоди стрімів
  • перегляди профілів
  • критичні логи

3. Інвайти для сендерів

  • створення інвайтів
  • вибір інвайтів для сендерів

4. Тімлід live-view

Реалтайм-дзеркало стану воркспейсу оператора (список TU, фаворити, таски, діалоги, стрім) → тімліду через наш сокет. Стан у нас → не залежить від сайтів, однаково всюди — просте, спільна реалізація. Залежить від: наш сокет, агрегований стан воркспейсу.

Тір 2 — слабо залежні від API

1. Тримання TU онлайн

Кожен сайт має механізм підтримки ТЮ в онлайні, треба щоб він був в кожної ТЮ імплементований незалежно

  • Golden активно пінгує + setAuthUserOnline (60с)
  • Chathouse реєструє TU у батч-пінг адмін-API
  • Prime тримає онлайн просто WS-конектом + регулярні запити

2. Перевірка онлайну TU та реконект

  • потрібне апі для перевірки чи ТЮ онлайн, зазвичай це апі з адмінки
  • якщо ТЮ онлайн - рахувати його
  • якщо ТЮ офлайн - механізм реконекту (індивідуально по проекту)

Зведення що ми маємо:

ЛогікаGolden (в Electron)ChathousePrime
Тримання онлайнуAPI ✅ · Логіка ✅API ✅ · Логіка ✅API — · Логіка ❓
Перевірка онлайну TUAPI ✅ · Логіка ✅API ✅ · Логіка ❌API ✅ · Логіка ❌
Реконект✅ детект офлайн → перезапуск TU + Red5-сокет окремо⚠️ перезапуск init, але від фейлу старту, не від перевірки⚠️ лише сокет (авто-реконект Centrifuge), без перезапуску логік

Висновок. Цільова петля — «раз на ~60с перевірити з апі онлайн кожної TU → якщо офлайн, перезапустити/переконектити». Тримання є всюди. Треба протестувати стабільність Chathouse і Prime.

Яке апі є і як працює:

  • Golden — тримання: setAuthUserOnline — на сесії самої TU (усередині її вкладки, POST на chat-сервіс), по одній. Перевірка: getOnlineLadiesапі з адмінки (agencyhelper): userId=0 = весь список онлайн-TU одним запитом; зараз Golden смикає по одній TU в циклі щохвилини.
  • Chathouse — тримання: ping-listодин батч-POST з масивом trusted_user_ids (групується по адміну). Перевірка: getLadies (GET .../trusted-user) — весь список TU одним запитом, у кожної є поле is_online (зараз код його не читає).
  • Prime — перевірка: trusted-user/collection (POST datame.cloud) — курсорна пагінація (limit+id_last), у кожної TU є is_online (зараз читається лише для синку каталогу).

3. Медіа (галерея TU)

Отримання / завантаження / видалення медіа з галереї TU. Задача на фронті однакова (вибрати й надіслати), різняться набір типів і форма апі. У Chathouse/Prime чат і лист беруть з однієї галереї (фільтр по контексту); у Goldenокремі пули. У чат зазвичай 1 файл, у лист — кілька. Chathouse ще має поле що фото було відправлене.

Чат:

GoldenChathousePrime
Типифото, відеофото, відеофото, відео, аудіо, стікери, пости
Списоквсе одразу (getMediaLibraries)все одразу (GET /media)курсор (фото/відео); аудіо — все одразу
Upload / Delete✅ / ✅✅ / ❌ (лок. «сховати»)✅ / ✅ (аудіо-delete ❌)
PaidisPaidфото✅, відео❌sent/accessed
Модераціяmoderate (поле)✅ окремі списки /media/moderation·/decline✅ статуси approved/on_moderation/declined

Лист:

GoldenChathousePrime
Типитільки фото (до 2)фото + відеофото + відео
Списоквсе одразу (attach)все одразу (GET /media)курсор (фото/відео)
Upload / Delete✅ / ✅✅ / ❌ (лок. «сховати»)✅ / ✅
PaidisPaidфото✅, відео❌ (лише режим листа paid_all)sent/accessed
МодераціяisModerate/media/moderation·/decline✅ статуси

Головна різниця — форма списку: Prime віддає фото/відео курсором (cursor+limit 40), Golden і Chathouse — все одразу. Спільний інтерфейс має вміти обидва.

Chathouse-нюанс — медіа-квота на листах: при відправці листа бек рахує частку листів із медіа за день і блокує лист без медіа, якщо оператор нижче порога (~35%), а RU з кредитами. Тобто на Chathouse відправка листа може вимагати медіа.

Тір 3 — сильно залежні від API

API диктує формування, умови й саму можливість → тут головна робота: спільний скелет, реалізація під контракт кожного сайту.

1. Таски

Три осі:

  • Механізм: сокет (реалтайм-подія) · скрол (інтервальний обхід/пагінація діалогів) · статистика (колонки подій).
  • Типи: Unanswered чат/мейл, NeedToWrite чат/мейл, OpenLimits, OpenLimits VIP, Like, Typing.
  • Скрол-логіки: що крутимо → що знаходимо → як часто → як глибоко.

Шляхи створення по типах:

ТипGoldenChathousePrime
Unanswered чатсокет + скролсокет + скролсокет + скрол
Unanswered мейлстатистикасокет + скролсокет + скрол
NeedToWrite чатскролсокет + скролскрол (×2)
NeedToWrite мейлстатистикасокет + скрол + статистика— (зводиться)
OpenLimitsскролсокет + скрол
OpenLimits VIPпланувальник (наш DB)
Likeсокетсокет + скролсокет + скрол
LikeMailскрол
Typingсокет

ActiveChat (Golden) — не окремий тип: платний чат перемикає титули-стани (ActiveChat/Finished) поверх Unanswered чат; той самий таск, інші тайтли.

Сокет-тригери (подія → логіка):

  • GoldenreceivePrivateMessage: текст 🌹 → Like, інакше → Unanswered чат. paidChatStarted/paidChatStopped → титули-стани Unanswered чат (ActiveChat/Finished).
  • ChathouseSend: платне вхідне → Unanswered чат, inmail_messageUnanswered мейл, лайк → Like. NewNotification (NEW/REPEAT; ONLINE_NOW/RECENT_PURCHASE) → тягне діалог RU: chat-ліміти → NeedToWrite чат, інакше mail-ліміти → NeedToWrite мейл, нема лімітів → скіп. TypingTyping (не в БД, гард 60с).
  • PrimeMessageSentgetDialogs[unanswered] + checkChatRestrictions: платний тип → Unanswered чат, like-тип → Like. chat_DialogCreatedgetDialogs[active]: останнє system + messagesLeftOpenLimits (VIP-дедуп). emailUnanswered мейл. Blocked → видалення всіх тасків пари.

Скрол — групи та архітектура (як буде):

Ціль: один код в Electron, різні проекти — різне апі під тими самими логіками. Архітектура: скрол-сервіс обходить діалоги певної «поверхні» (онлайн / unanswered / фаворити) → віддає потрібні діалоги в таск-сервіс, який робить таск. Поверхні групуються так:

0. Golden — списку діалогів немає. У Golden апі є лише на конкретний діалог (chatHistory / getMail по manID), а списку всіх діалогів немає взагалі. Тому скролити нема що — Golden бере свій список фаворитів (зі статистики) і по кожному окремо тягне його чат/листи. Список фаворитів заміняє Golden’у список діалогів.

1. Онлайн-діалоги (Chathouse all+is_online, Prime [active, online]). Обходимо діалоги RU, які онлайн, і шукаємо ті, де останнє повідомлення від TU (кілька хв/год тому), пара не блокована і є ліміти.

  • Chathouse: один запит віддає список онлайн-діалогів. У кожному діалозі — одне останнє повідомлення (з типом: чат це чи лист) і окремі лічильники лімітів на чат і на лист. Тобто чат і лист — не різні діалоги, це один діалог, де видно обидва ліміти; саме тіло листа, якщо треба, тягнеться окремим запитом.
  • Prime: чати і листи — різні запити (онлайн-діалоги дають чат; листи — окремо).

2. Unanswered — RU нам написав (Chathouse new, Prime unanswered + пошта inbox_unanswered). Те саме, але не онлайн, а хто нам написав — чат чи лист.

  • Chathouse: 1 запит (чат і лист в одному діалозі, як вище). Prime: 2 запити — окремо чат (unanswered) і окремо пошта (inbox_unanswered).

3. Фаворити. Як зараз — окремий прохід сайтом по збережених/закладених фаворитах (сайтова позначка «збережено»/зірочка). Є тільки в Chathouse і Prime; у Golden такого немає (група 0 вище). Що кожен робить:

  • Chathouse — вкладка saved. Щохвилини прокручує до кінця список збережених діалогів і тримає його по кожній TU. Сам таск звідси не робить — по цьому списку працює окрема логіка PostChatMail: коли RU щойно заплатив за дію в чаті по такому діалогу і минуло ≥10хв без відповіді (і немає відкритого Unanswered) — створює NeedToWrite мейл.
  • Prime — criteria bookmarked. Щохвилини прокручує закладених фаворитів, пропускає заблокованих і складає список по кожній TU (bookmarkDialogs) — це і є список фаворитів оператора; сам таск звідси не робиться. По цьому списку крутиться окремий сканер NoOnlineActiveFavorite: бере фаворита, який офлайн, останньою в діалозі писала TU (>12–16 год тому), його давно не чіпали листом і ще лишились ліміти (чат або лист) — і робить таск NeedToWrite. Це доповнення до онлайн-проходу: онлайн-фаворитів ловить [active, online] (група 1), а NoOnlineActiveFavorite — тих, хто офлайн і замовк.

Як це переробити (обговоримо).

Список активних фаворитів потрібен, по суті, лише щоб знаходити й робити таски NeedToWrite. Ідея — тримати цей список у себе і по ньому робити таски. Випадки, коли фаворит дає NeedToWrite (усі треба покрити):

  • Є куди писати (чат + ліміти). Дивимось діалог фаворита й ліміти → пишемо: онлайн з лімітами → NeedToWrite чат; офлайн, що замовк, з лімітами → NeedToWrite лист. Є всюди (Golden chatHistory, Chathouse all+is_online, Prime [active, online] + NoOnlineActiveFavorite).
  • Післячатове. Після платного чату (≥10хв, без відповіді) → NeedToWrite лист. Лише Chathouse (PostChatMail).
  • Після оплати листа. RU оплатив/прочитав наш лист → NeedToWrite лист. Golden (EmailRead/OpenAttach) і Chathouse (inmail_read), обидва зі статистики; у Prime детальної статистики нема → цього шляху нема.

Питання:

  1. Список фаворитів — статистика (Golden/Chathouse: платив за 7 днів) та Prime: ≥11 платних дій
  2. Перевірка онлайну — Golden одним запитом (список онлайн-RU), Prime батч checkMenOnline, Chathouse окремого апі нема (онлайн видно лише в списку діалогів).
  3. Дістати діалог (чат+лист) по парі TU+RU — по суті скрізь два запити (чат окремо, листи окремо): Golden chatHistory + getMail; Chathouse getDialogMessages (чат) + getInmailsChain (листи); Prime — чат і листи різними запитами. Chathouse-специфіка лише в тому, що список діалогів одразу показує обидва ліміти в одному пункті.

4. Ще два Prime-специфічні проходи:

  • criteria [active] (→ OpenLimits) — потроху (по 15 за раз, крок за кроком назад до 7 днів) проходить активні діалоги і шукає ті, де останнє повідомлення системне (знак, що ліміти щойно відкрились) і ліміти справді є → таск «відкрились ліміти».
  • criteria [] (усі діалоги) → mailTaskPrime. Це не один механізм, а три, зшиті в один скан усіх діалогів:
    1. Бутстрап фаворитів (лише перший логін TU) — глибоко читає чат-історію (не листи!) кожного діалогу, рахує платні повідомлення від RU. Єдиний спосіб Prime визначити фаворитів (статистики нема). Поріг ≥11 рахується по сумі по всіх TU (глобальний профіт RU), і саме він пускає RU в глобальний кеш «якісних», який годує автостворення чатів (CreatingChatService).
    2. Сендер — автолист нефаворитам. Спрацьовує, коли по чату ліміти вже вичерпані, а на лист ще є. Якщо RU не фаворит — лист шле автомат, без оператора: RU лайкнув → шле безумовно; RU мовчить, а TU писала останньою ≥12год → шле лише якщо RU онлайн зараз (checkMenOnline).
    3. Таск LikeMail — фаворитам. Та сама ситуація (чат вичерпаний, лист є), але RU фаворит і щойно лайкнув → замість автолиста таск оператору написати самому (unanswered2 = LikeMail). Мовчазний фаворит сюди не потрапляє — його добирають онлайн-/офлайн-проходи фаворитів.

Висновок: архітектурно — один скрол-сервіс (проходить поверхню, віддає потрібні діалоги) + таск-сервіс (з діалогу робить таск). Різниця лише в тому, як діставати діалоги: Golden — бере свій список фаворитів і питає кожного окремо; Chathouse — проходить вкладку (чат і лист в одному діалозі); Prime — проходить по criteria (чат і листи окремо). Головний невирішений вузол — фаворити + перевірка онлайну: статистика (Golden/Chathouse) проти скрол-підрахунку (Prime), і зручного апі «хто з фаворитів онлайн» немає в Chathouse.

Скрол-логіки — що крутимо і що знаходимо:

ПроєктЩо крутимо (запит)ЗнаходитьКадансГлибина
Goldenсписок онлайн-фаворитів + chatHistory по кожномуUnanswered / NeedToWrite чат60сснапшот останнього повід. (без пагінації)
Goldenсписок фаворитів (статистика) + getMail по кожномуUnanswered / NeedToWrite мейл60сснапшот останнього листа
Chathouseвкладка all + is_onlineNeedToWrite чат/мейл60сдо кінця (курсор next, поки стор. ≥50)
Chathouseвкладка newUnanswered чат/мейл, Like, OpenLimits60сдо кінця
Chathouseвкладка saved (фідер)— (годує PostChatMail)60сдо кінця
Primecriteria [active, online]NeedToWrite чат (online)120сдо кінця (limit 40)
Primecriteria unansweredUnanswered чат, Like60сдо кінця (40)
Primeпошта inbox_unansweredUnanswered мейл60с1 сторінка (15)
Primecriteria activeOpenLimits120с1 стор./тік, stateful-курсор назад до 7 днів
Primecriteria bookmarked (снапшот воркспейсу)NeedToWrite лист (офлайн-фаворит)60сдо 7 днів (limit 50)
Primecriteria [] (всі діалоги)LikeMail600сдо кінця (20) + повна історія на 1-му проході

Три патерни глибини: снапшот (Golden — не пагінує, тільки останнє повід.) · до кінця (Chathouse + більшість Prime — щотіка вся вкладка) · обмежене вікно (Prime openLimit і bookmarked — назад до 7 днів; openLimit ще й тягне курсор між тіками).

Запити по апі — скільки і як часто (те саме as-is, згруповано по запитах):

Chathouse — цикли на кожну TU:

Апі-запитЯк частоГлибинаЗвідки
getDialogs вкладка all + is_onlineщохвилинидо кінця (стор. ~50)OnlineTask
getDialogs вкладка all повнащохвилинидо кінця; з неї беруть вікно 2 годWorkspaceRunner (чат-історія)
getDialogs вкладка newщохвилинидо кінцяUnansweredTask
getDialogs вкладка savedщохвилинидо кінцяWorkspaceRunner
getInmailsChain по діалогущохвилини, тільки по кандидатах на мейл-таск; повтор по тому ж діалогу — не раніше TTL Redis-кешу (до 12 год)один діалогOnlineTask
getDialogMessages по діалогурідко, точково («післячатовий» перший лист)один діалогOnlineTask
вкладки all / savedразово на логінідо кінцяFavoriteWorker

Разом: 4 пагіновані серії getDialogs щохвилини на кожну TU + точкові листи/чат-історія по кандидатах. Вкладка all ходить двічі на хвилину (повна містить у собі онлайн-фільтровану) — перший кандидат на об’єднання.

Prime — один цикл на оператора, всередині запити по кожній TU:

Апі-запитЯк частоГлибинаЗвідки
getDialogs criteria [unanswered]щохвилинидо кінця, по 40unansweredMessageTaskPrime
getMails inbox/unansweredщохвилини (той самий тік)1 сторінка, 15unansweredMailTaskPrime
getDialogs criteria [bookmarked]щохвилинипо 50, до 7 днівPrimeWorkspaceRunner
getDialogs criteria []щохвилинипо 50, поки у вікні 4 годPrimeWorkspaceRunner (чат-історія)
getMails outboxщохвилинипо 50, до 7 днівPrimeWorkspaceRunner (мейл-історія)
getDialogs criteria [active, online]кожні 2 хвдо кінця, по 40onlineTaskPrime
getDialogs criteria [active]кожні 2 хв1 сторінка, 15; курсор живе між тіками, назад до 7 днівopenLimitTaskPrime
getDialogs criteria [] (глибокий)кожні 10 хвдо кінця, по 20; на першому проході + чат-історія по 100 до кінцяmailTaskPrime
точкові: checkChatRestrictions, checkRelations, профілі, getDialogs limit 1по кандидатах усередині проходіводиничніскрізь

Разом: 5 серій щохвилини на TU (unanswered + inbox_unanswered + bookmarked + [] 4 год + outbox), кожні 2 хв — ще дві ([active, online], [active]), кожні 10 хв — глибокий [].

Скрол — що саме крутимо (+ умови попадання в таск):

Unanswered чат.

  • Golden — список онлайн-фаворитів, по кожному chatHistory (снапшот останнього, без пагінації). Умова: останнє — від RU + чат ready-to-send.
  • Chathouse — пагінує вкладку new (курсор next, до <50). Умова: останнє — платне вхідне.
  • Prime — criteria unanswered (курсор, limit 40). Умова: останнє — платний тип + messagesLeft.

Unanswered мейл.

  • Golden — скролу нема (від статистики); getMail звіряє: останній лист від RU, <1 рік, не заблокований.
  • Chathouse — та сама вкладка new, якщо останнє = платний inmail.
  • Prime — пошта inbox_unanswered (1 стор., limit 15). Умова: lettersLeft + діалог не заблокований.

NeedToWrite чат.

  • Golden — список активних онлайн-фаворитів, chatHistory по кожному. Умова: останнє — від TU >10хв, не white-list, чат ready-to-send.
  • Chathouse — вкладка all+is_online. Умова: TU-останнє, є chat-ліміти, збережений/онлайн або >1год.
  • Prime — criteria [active,online]: TU-останнє ≥2год + messagesLeft + bookmarked. + сканер bookmarked (NoOnlineActiveFavorite): RU офлайн, останнє 12–16год, є ліміти.

NeedToWrite мейл.

  • Golden — від статистики: активний фаворит онлайн, останній лист >12год або прийшов бонус, mail ready-to-send.
  • Chathouse — вкладка all+online при mail-лімітах (решта шляхів — статистика/сокет).
  • Prime — окремого типу нема (зводиться в NeedToWrite / обробляє мейл-сендер).

OpenLimits.

  • Chathouse — вкладка new: порожній/непроявлений діалог (id=null) або «liked each other» з відкритими лімітами.
  • Prime — criteria active, stateful-курсор (1 стор./тік, limit 15, reset на 7 днях). Умова: останнє = system, є messagesLeft, не заблокований, ≤7 днів.

OpenLimits VIP.

  • Prime — не скрол: планувальник по нашому DB. Умова: леді активна + canCreateChat, є ліміти, не частіше ніж 1 VIP / 2год на TU; + ручне.

Like.

  • Chathouse — fallback у вкладці new: вхідне = лайк + ліміти.
  • Prime — criteria unanswered: останнє = like-тип + messagesLeft. LikeMail — усі діалоги ([], limit 20): like + bookmarked + lettersLeft, чат-ліміти вичерпані.

Typing — тільки сокет, скролу нема.

Статистика (є лише там, де є детальна статистика подій):

  • Golden — temp-statistics: EMAIL_SEND → Unanswered мейл; EmailRead/OpenAttach → NeedToWrite мейл (жене весь mail-блок).
  • Chathouse — Mongo-статистика: inmail_read → NeedToWrite мейл; spend-події → PostChatMail (2 з 4 mail-шляхів).
  • Primeдетальної статистики нема → статистичні шляхи неможливі. Тому mail Prime тягне сканом пошти/лімітів, а окремого NeedToWrite мейл узагалі нема.

Client-email таски (Golden UnansweredEmail) — окрема логіка, поза цим пунктом: зав’язана на зовнішні поштові акаунти леді (email-інбокс), а не на воркспейс-API сайтів. Описується окремо.

Залежить від: сесія TU, сокет, ліміти з API, фаворити, статистика (де є).

2. Сендери

Авто-надсилання інвайтів (чат/мейл) онлайн-RU, які замовкли — TU писала останньою, а RU не відповідає.

Golden — окрема, унікальна логіка (свої рушії, затримки й правила). Тут не зводимо — описується окремо.

Prime і Chathouse — по суті однакові. Спільна механіка:

  • Рушій не самостійний — його годує скан онлайн-діалогів (Prime: onlineTaskPrime ~2хв чат + mailTaskPrime ~10хв мейл; Chathouse: OnlineTask, самоперепланований). Кого слати — вирішує скан.
  • Кого бере: діалог, де останнє від TU (не збережений), старше порогу, RU онлайн і з лімітами, не заблокований і не в блек-листі.
  • Один рушій, чат-перший → мейл-фолбек: чат-інвайт, якщо минула затримка + є невідправлений чат-шаблон + чат-ліміт; інакше мейл, якщо чат-шаблонів/лімітів нема, минула мейл-затримка, є мейл-шаблон + лист-ліміт.
  • Тротлінг на пару TU+RU: історія відправок у БД (остання дата) + Redis-ключ; затримки різні (нижче).
  • Інвайти: ланцюжок шаблонів на TU (чат[]/мейл[]); бере перший, якого ще не слали цьому RU (по черзі, без рандому).
  • Первинний інвайт — без перевірки доставки: ланцюг рухається далі, лише поки RU не відповів (інакше діалог випадає зі скану) і поки попередня відправка успішна.
  • Блек-лист: пара TU+RU з isBlackList — перевірка перед самою відправкою (далі 10хв пропуск). Prime ще фільтрує глобальний блек-лист чоловіків у скані.
  • Побічне: запис в історію відправок, лічильник шаблону, лічильник автодій оператора, помітка «шаблони закінчились».

Різниці Prime vs Chathouse:

АспектPrimeChathouse
Затримка чат / мейл2год / 12год1год / 6год
Дод. досланнянема≤2 таймовані (текст/стікер/фото) з перевіркою, що попереднє дійшло
Крос-TU кап на одного RUнема≤5 TU за хвилину
Low-creditокремий мейл-шаблон для RU зі spend 0–20; фото лише при spend 20+
Мова інвайтівлише латиниця
Медіа в мейлі≤10 фото + ≤10 відеофото (крім low-credit)

Тобто уніфікований сендер = цей спільний рушій + пер-сайт параметри (затримки, медіа-ліміти, low-credit, дод. дослання).

Залежить від: інвайти (контент), API відправки, ліміти, блек-лист.

3. Фаворити + чат/мейл-історія

Дві речі разом: хто для TU постійний RU (реальний фаворит) і чим наповнити колонку фаворитів — останнє повідомлення / історія чату й листів, щоб оператор бачив свіже.

Що дає сайт (ключова різниця):

  • Prime, Chathouse — є апі фаворитів, профілів і останнього повідомлення в діалозі → простий рендер колонки фаворитів + готова чат/мейл-історія.
  • Golden — сайт не дає нічого з цього: нема апі фаворитів, профілів, останнього повідомлення, чат-історії. Тож усе тримаємо й оновлюємо в нас (фаворити — зі статистики, профілі — зберігаємо самі).

Ідеї, як звести (чернетка — обговорити):

  • Список фаворитів тримати в нас. Формуємо/оновлюємо його у себе; на логіні лише проставляємо актуальний список на апі сайту (де воно є), щоб потім зручно тягти з апі — але в самих логіках апі-версію не використовувати.
  • Останнє повідомлення в колонці рендерити в нас. Спочатку його нема; щойно прийшов лист або ми відкрили чат/лист — підставляємо в систему найсвіжіше. Так тримаємо псевдоісторію колонки без окремого апі.
  • Чат-історія Golden — зібрати штучно з історії тасків і сендера (апі чат-історії нема).

Залежить від: партнерське API фаворитів / діалогів (де є), власне сховище (де нема — Golden).

4. Створення діалогів

Проактивно завести новий платний чат з онлайн-RU, поки є вільні ліміти.

  • Prime — підсистема CreatingChat: планувальник (2хв) для кожної TU з canCreateChat і вільними лімітами бере свіжого онлайн-RU з пулу «якісних» (глобальний ≥11-пул + зовнішня агенція), звіряє онлайн (checkMenOnline) і підкидає оператору таск openLimitVip «написати першому»; сам чат відкривається, коли оператор відповість. Обмеження: ≤1 VIP / 2год на TU, дедуп, ліміти з апі (оновлення раз на добу). readyCreateChat — сигнал показати кнопку «створити чат», коли тасків нема.
  • Golden — сенсу нема;
  • Chathouse — проактивного нема; діалог виникає неявно (вгорі) при першій відправці; у списку є порожні заготовки (id=null) → таск-нагадування написати першим.

Залежить від: API створення/лімітів, список онлайн-RU, пул кандидатів.

5. Профіль RU (id, ім’я, аватар, вік)

Профіль чоловіка (id, ім’я, аватар, вік) для картки таска/діалогу й колонки фаворитів. Питання: де взяти весь профіль за раз, а де апі нема — тримати свій стор і оновлювати. Плюс критичний випадок: RU написав TU вперше, у фаворитах/на фронті профілю ще нема, а рендерити треба.

Звідки взяти весь профіль (і коли його ще нема):

  • Chathouse — у списку діалогів АБО в самій сокет-події. getDialogs несе contact (id/ім’я/аватар/вік); а коли RU пише по сокету — подія (Sendcontact, NewNotificationsender) уже містить повний профіль, тож доганяти нічого не треба (навіть новий RU рендериться з події). На вимогу — getProfile(ulid). Стор не потрібен.
  • Prime — окремий батч getManProfiles([ids]). І getDialogs, і сокет-подія дають лише id → профіль тягнеться живцем (пачкою по 50 у скані або по одному id при сокет-таску). Стор не потрібен.
  • Golden — картку наповнює зі свого стору. Стор годується харвестом онлайн-списку чоловіків із сайту (у вкладці TU, ~5хв). Профіль по id теж є — запит getMan (оф-апі) віддає повний профіль, але зараз його смикають лише для попапа профілю й бекфілу аватара при відкритті діалогу, а не для картки таска. Вузьке місце — перший контакт: нового RU може ще не бути в сторі (харвест бачить лише онлайн), а getMan для картки не викликають → профіль порожній, поки діалог не відкриють (фікс дешевий: смикнути getMan(id) при наповненні картки).

Як зараз профіль потрапляє в чат-історію / фаворитів / таски:

  • Prime — бек збагачує кожен прохід (getManProfilesinterlocutor{ім'я, аватар}); таск — через getTaskUsersgetManProfiles.
  • Chathouse — їде прямо з діалогу (contact у списку) в історію й фаворитів; таск — із того ж діалогу.
  • Golden — накладається з локального стору при рендері (manId_api → профіль зі стору); стор годується харвестом + бекфілом getMan.

Орієнтир для проектування: де можна за раз — беремо звідти (Chathouse — з діалогу, Prime — батч по id); де апі нема — тримаємо стор і оновлюємо (Golden). Уніфікація = провайдер профілю з трьома реалізаціями: (1) inline з діалогу, (2) батч по id, (3) свій стор + добір по id для промахів. Головний ризик — Golden на першому контакті (порожня картка, поки не добрали getMan).

Залежить від: API профілю RU (де є), власний стор + добір по id (Golden).

6. Ньюзфід постів (Prime)

Тільки Prime (/newsfeed). Оператор вручну створює й публікує пости від імені TU (свій текст 100–1500 + фото), пости проходять модерацію; є трекер «яка TU сьогодні ще не постила». Автопостингу нема. Зворотний бік: коли RU лайкнув/відповів на пост, це вертається таском — like_newsfeed_post → Like, reply_newsfeed_post → Unanswered (звичайний таск-пайплайн). API: platform/news-feed/post/{create,send,list,delete}. Залежить від: API ньюзфіду.

7. RU заблокував / видалив профіль

Треба знати, що RU заблокував TU (щоб зняти таски/фаворитів і не гнати сендери в порожнечу) і що RU видалив профіль.

Блокування — сигнал у кожного свій:

  • Golden — найпростіше: команда blackList (оф-апі) віддає по TU плоский список id заблокувальників; полінг ~5хв.
  • Prime: checkRelations (platform/connection/get) → blockedByInterlocutorбатчем по діалогах проходу (не по одному RU; точкові виклики лише на відкритті чату / сокеті / помилці відправки). Плюс мітка isBlocked у списку діалогів (не надійна на 100% → щопрохід досвіпують таски заблокованих) і RTM-сокет Blocked (реалтайм).
  • Chathouse: поле blocked_by_ru на діалозі (getDialogs, полінг, без сокета).

Реакція скрізь схожа: помітити фаворита blocked, видалити/закрити таски цієї пари, виключити з нових тасків і з сендера (Golden і Chathouse ще логують історію блоків у ClickHouse).

Видалення профілю — сигналу нема ніде. У всіх трьох немає ні окремого апі, ні прапорця is_deleted на профілі чоловіка, ні сокет-події, ні окремого коду помилки. Видалення можна лише здогадатись: чоловік зникає зі списків / профіль повертається порожнім / відправка падає (Prime трактує це так само, як блок).

Орієнтир для проектування: блок = свій сигнал на сайт (Golden — список id, Prime — relations + сокет, Chathouse — прапорець у діалозі) → спільна реакція (зняти таски, виключити з сендера, помітити фаворита). Видалення доведеться виводити непрямо (падіння запиту / зникнення зі списків) — окремого сигналу не буде.

TODO (обговорити): як правильно вести обидва списки — «RU заблокував TU» і зворотний «TU заблокував RU» — і як їх оновлювати (де істина: сайт чи наш стор, як синхронізувати).

Залежить від: API статусів RU (блок), непряме виведення (видалення).


Побічні логіки

Дрібні / усталені логіки, що мають просто бути. Частина — тривіальні (повністю наше апі), частина — три «душні» списки, які треба розписати детально.

Прості — повністю наше апі, дизайну майже не треба:

  • Перекладач — Electron → наше апі → наш сервер → DeepL (або AI); однаковий усюди.
  • Нотатки оператора (+ AI-нотатки) — повністю наше апі, до сайтів не прив’язані → спільний сервіс.
  • Імейли (клієнт-email канал) — зовнішні поштові акаунти TU (інбокс) → таск; повністю через наше апі/сервер. Поки лише Golden.

Тільки Golden:

  • Стрім камер TU — трансляція анкети + трекінг інтервалів трансляцій.
  • Збереження переглядів профіля — хто дивився анкету (→ ClickHouse).

Три «душні» — по порядку:

1. White-list — тільки Golden, список чат-сендера (per TU, manId_api).

  • Робить: чат-сендер (FAV-трек) авто-пише тільки тим, хто в списку; поки RU у списку — оператор вручну писати не може (бот ним володіє).
  • Наповнення: щологіну автозаповнюється неактивними фаворитами (останній контакт >7 днів), крім тих, хто вже дав дохід сьогодні; при profit ≥ 10 RU авто-виходить.
  • Керування зараз майже вимкнене: прибрати можна лише активного фаворита з малим балансом — неактивного (а список саме з них) вже не прибрати; додати — лише активного з малим балансом (profit ≥ 10 — ні). Тому сенс списку майже зник.

2. Black-lists — семантично 3 типи (Golden розмазав на 3 сховища, Chathouse/Prime — компактні поля):

  • (a) RU заблокував TU — детект блокування (див. Тір 3 #7); по такому RU не працюють сендери/таски.
  • (b) TU/оператор заблокував RU — ручний «не чіпати цього RU».
  • (c) сендер-виключення — службовий список самого сендера (авто при помилках відправки).

Назви одного концепту різні: (b) = blockedByTU (Golden) = isBlackList (Chathouse/Prime).

  • Chathouse: (b) isBlackList на фаворита (оператор) → сендер не шле; (a) авто-blocked (окреме поле, для UI/детекту). Глобального нема.
  • Prime: (b) isBlackList → гейтить сендер; (a) авто-blocked — пишеться, але для гейту не читається (блок при таску бере живий checkRelations); + глобальний prime_men_black_list (по RU, наповнюється руками) — його юзають усі таск-ранери (скіпають цих RU).
  • Golden — 3 окремі сховища: (b) blockedByTU — гейтить майже все (створення тасків, чат-сендер FAV, мейл-сендер FAV, інтервали); (a) golden_block_list (синк 5хв) — гейтить сендер + закриває мейл/чат-таски; (c) мейл-сендер має власні 2 списки (FAV/NEW, авто при помилці). Чат-сендер персистентного (c) не має (лише тимчасові стопи); глобального нема.

Орієнтир для проектування: звести все до 3 типів на пару TU+RU (a/b/c) + опційно глобальний по RU (як Prime, адмін-інструмент) — не плодити окремий список на кожен сендер. Назви уніфікувати.

3. Фрілоадери — «безкоштовний» RU, на якого шкода зусиль. Тільки Chathouse і Prime; у Golden концепту нема. Назва одна, а критерій і вплив різні:

  • Chathouse — «платить лише бонусами». Ставиться: усі платежі RU — тільки безкоштовні кредити, реальних грошей не було (з 2025-03-21); глобально по RU (isFreeProfit), перерахунок щотижня/щодня. Знімається: щойно заплатив реальні гроші — одразу. Впливає: виключає з мейл-тасків (NeedToWriteMail, PostChatMail) + UI-бейдж; сендер не чіпає. Суть: не писати листи тому, хто платить лише бонусами.
  • Prime — «мало платив» (profit < 11). Ставиться: похідне від GlobalMan.profit (сумарна к-сть платних повід./листів по всіх TU); фрілоадер ⇔ profit < 11 (той самий поріг, що й «фаворит»); не зберігається — рахується на льоту. Знімається: автоматично при profit ≥ 11. Впливає: лише UI-бейдж, тасків/сендера не гейтить. (Відсів по грошах у Prime робить інверсія: profit ≥ 11 = «якісний» → лише таких бере авто-створення чатів.) Суть: мітка «чатиться, але не платить».

Головна різниця: Chathouse дивиться на вид оплати (бонуси vs гроші) і ріже мейл-таски; Prime — на кількість платних (< 11) і це лише мітка. Одна назва — різний критерій і різний вплив; при уніфікації визначити єдино: що таке «фрілоадер» і що він гейтить.

Уже описані окремо, тут не дублюємо: айсбрейкери й перевірка версії/часу — у «Запуску»; стартовий чек-ліст статусів.


Відкриті рішення

  • Перенос усього у Electron — Server Coupling (реле сесії → повністю клієнт).
  • Тримання TU онлайн — єдина стратегія чи per-API.
  • Data-sync — мінімальний спільний контракт на всі проекти.
  • Панель заробітку оператора (денна сума на фронт) — чи тримаємо в уніфікованому воркспейсі, чи це аналітика збоку.

Зв’язки