mirror of
https://github.com/dartdavros/chatballs.git
synced 2026-10-05 09:14:58 +03:00
Сообщения сообщества ВКонтакте принимаются через Bots Long Poll: тот же способ, что у Telegram и MAX, поэтому подключению не нужен ни публичный адрес, ни доступ извне — установка за NAT работает наравне с остальными. Позиция потока живёт в poll_marker, адрес сервера и ключ — в памяти процесса: их выдают на несколько часов, и колонка под них означала бы запись в базу на каждом цикле опроса. Ответы failed 1-3 восстанавливаются в том же цикле, иначе подключение висело бы с протухшим ключом до перезапуска воркера. Идентификатор сообщества владелец не вводит: его называет сам ключ доступа, и проверка подключения кладёт его в конфигурацию — как имя бота у Telegram и MAX. Проверка заодно смотрит настройки сообщества: без Long Poll и события о входящем сообщении приём невозможен, и об этом честнее сказать сразу, а не молчать зелёным статусом. Настройки чужого сообщества при этом не меняются. Нехватка прав у ключа объясняется словами: ВКонтакте отвечает на неё английским «no access», из которого не видно, что включить. Имя, логин и фото отправителя ВКонтакте в апдейте не присылает — их забирает один users.get на пачку сообщений, а не на каждое: на оживлённом сообществе запрос на реплику упёрся бы в частоту обращений. Телефона и кнопки «поделиться контактом» у ВКонтакте нет, поэтому просьба уходит обычным сообщением, как и почтой. Голосовые принимаются, но не отправляются: провайдер ждёт ogg/opus, а композер пишет webm. Токен уходит строкой запроса — заголовка авторизации у ВКонтакте нет. Поэтому адрес больше нигде не печатается как есть: и журнал, и поле последней ошибки подключения, которое видно в интерфейсе, проходят через маскирование секретных параметров. Проверено на живом сообществе: проверка подключения, опрос Long Poll, приём текста, голосового и фото с подстановкой имени, логина и аватара. Тесты транспорта и проверки подключения, каталоги переводов, ruff из корня, tsc и vitest по internal-ui. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
50 lines
2.6 KiB
TypeScript
50 lines
2.6 KiB
TypeScript
import { t } from "../i18n";
|
|
|
|
/* Провайдеры подключений: MAX / Telegram / ВКонтакте / Web Chat / Email.
|
|
|
|
Общий словарь для всего приложения — раньше он лежал в демо-данных диалогов,
|
|
и продуктовые экраны каналов зависели от файла с примерами.
|
|
Провайдеры различаются точкой и коротким лейблом на своих токенах
|
|
(ADR-HUB-0013), а не бренд-логотипами. */
|
|
|
|
export type ProviderKey = "EMAIL" | "MAX" | "TG" | "VK" | "WEB";
|
|
|
|
export const providerMeta: Record<ProviderKey, { label: string; short: string; color: string; bg: string }> = {
|
|
EMAIL: { label: "Email", short: "Email", color: "#d48806", bg: "#fff7e6" },
|
|
MAX: { label: "MAX", short: "MAX", color: "#6b5be0", bg: "#f2f0ff" },
|
|
TG: { label: "Telegram", short: "TG", color: "#2f8fd0", bg: "#eaf6fd" },
|
|
VK: { label: "ВКонтакте", short: "VK", color: "#0077ff", bg: "#e8f2ff" },
|
|
WEB: { label: "Web Chat", short: "Web", color: "#0f9b8e", bg: "#e8f7f4" },
|
|
};
|
|
|
|
/** Код провайдера из API → ключ словаря. */
|
|
const BY_CODE: Record<string, ProviderKey> = {
|
|
EMAIL: "EMAIL",
|
|
MAX: "MAX",
|
|
TELEGRAM: "TG",
|
|
TG: "TG",
|
|
VK: "VK",
|
|
WEB: "WEB",
|
|
WEBCHAT: "WEB",
|
|
};
|
|
|
|
export function providerKey(code: string): ProviderKey | null {
|
|
return BY_CODE[code] ?? null;
|
|
}
|
|
|
|
/* Плитка подключения (дизайн-базлайн v2, кадры K1/K5 «Контакты», G1/G3 «Агенты»):
|
|
марка в 14% на подложке карточки, глиф — цветом марки. Одна таблица на всё
|
|
приложение: список контактов, карточка контакта и раздел «Агенты». */
|
|
export const channelMap = {
|
|
EMAIL: { full: "Email", color: "#d48806", bg: "color-mix(in srgb, #fa8c16 14%, var(--surface-card))" },
|
|
MAX: { full: "MAX", color: "#5b5bd6", bg: "color-mix(in srgb, #5b5bd6 14%, var(--surface-card))" },
|
|
TG: { full: "Telegram", color: "#229ed9", bg: "color-mix(in srgb, #229ed9 14%, var(--surface-card))" },
|
|
VK: { full: "ВКонтакте", color: "#0077ff", bg: "color-mix(in srgb, #0077ff 14%, var(--surface-card))" },
|
|
WEB: { full: t("common.web_widget"), color: "#0f9b8e", bg: "color-mix(in srgb, #0f9b8e 14%, var(--surface-card))" },
|
|
} satisfies Record<ProviderKey, { full: string; color: string; bg: string }>;
|
|
|
|
export function providerLabel(code: string): string {
|
|
const key = providerKey(code);
|
|
return key ? providerMeta[key].label : code;
|
|
}
|