diff --git a/README.md b/README.md index e66d685..791d9ec 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ## Что умеет -- показывает пользователю только его кнопку, если он привязан по `operator_user_id` +- показывает пользователю только его кнопку, если он привязан по `operator_user_id` или `operator_user_ids` - позволяет админам видеть все кнопки - после выбора персонажа предлагает статус: `open`, `backstage`, `delay`, `rest` - после выбора статуса просит фразу для публикации @@ -36,7 +36,7 @@ uv sync - `button_text` — текст на кнопке - `display_name` — имя в посте - `link` — ссылка на бота -- `operator_user_id` — Telegram user id человека, который может менять этот статус +- `operator_user_id` или `operator_user_ids` — Telegram user id человека, который может менять этот статус - `phrases` — шаблонные фразы под каждый статус ## Запуск diff --git a/config/actors.example.json b/config/actors.example.json index 4327db0..2462b03 100644 --- a/config/actors.example.json +++ b/config/actors.example.json @@ -19,7 +19,7 @@ "link": "http://t.me/astat_ovhdRPCM_bot", "pronouns": "he/him", "emoji": "🌟", - "operator_user_id": 123456789, + "operator_user_ids": [123456789, 987654321], "default_status": "backstage", "phrases": { "open": "принимает тейки.", diff --git a/config/actors.json b/config/actors.json index 4327db0..6ed308c 100644 --- a/config/actors.json +++ b/config/actors.json @@ -1,10 +1,10 @@ { - "header": "🌟🌟 🎀avigation ⠘ OVERHEARD 🌟\n⎯ шоу должно продолжаться.", - "intro_links": "rules: https://telegra.ph/example\nplot: https://telegra.ph/example\nboost: https://t.me/boost/example", - "projects_block": "🌟 RP projects: https://t.me/archive/7\n🌟 RPCM channels: https://t.me/archive/18", - "actors_title": "\"The Dearest Actors\" administration", - "legend": "🌟 исполняет роль 😻 принимает тейки\n🌟 в закулисье 😻 не принимает тейки\n🌟 антракт 😻 рест\n🌟 задержки 😻 отвечает с задержкой", - "footer": "life channel: https://t.me/lifeExample\narchive: https://t.me/archiveExample", + "header": "🌟🌟 🎀𝑎𝑣𝑖𝑔𝑎𝑡𝑖𝑜𝑛 ⠘ 𝒪𝖵𝖤𝖱𝖧𝖤𝖠𝖱𝒟 🌟\n⎯ 🤩ꫝᥱ 𝐒ℎ𝑜𝑤 𝑚ꪊ𝑠𝑡 𝑔𝑜 𝑜ꪀ.⬜", + "intro_links": " 𝘳𝘶𝘭𝘦𝘴 (https://telegra.ph/%F0%9D%96%B1%F0%9D%96%AF%F0%9D%96%A2%F0%9D%96%AC-%F0%9D%92%AA%F0%9D%96%B5%F0%9D%96%A4%F0%9D%96%B1%F0%9D%96%A7%F0%9D%96%A4%F0%9D%96%A0%F0%9D%96%B1%F0%9D%92%9F--ehto-11-23) 😻 𝗉𝐥𝐨𝗍 😻 𝖻𝗈𝗈𝗌𝗍 (https://t.me/boost/OverheardRPCM)\n 😻 𝖱𝖳 𝐩𝗈𝗌𝗍 (https://t.me/overheardinfo/3) 𝖬𝖯 𝗂𝗇𝖿𝗈 (https://telegra.ph/C%F0%9D%92%AANDITI%F0%9D%92%AANS-12-03) 𝒑𝑟𝑖𝑐𝑒 (https://telegra.ph/%F0%9D%92%AAUR-PR%E2%84%90CE--uslugi-12-03) 😻", + "projects_block": "🌟🌟🌟 𝐊аmалᦢги⠘\n🌟 𝖱𝖯 𝗉𝗋𝗈𝗃𝖾𝖼𝗍𝗌 (https://t.me/archiveOverheardRPCM/7) & 𝖱𝖯𝖢𝖬 𝖼𝗁𝖺𝗇𝗇𝖾𝗅𝗌 (https://t.me/archiveOverheardRPCM/18)", + "actors_title": " ﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋\n\"𝓣ℎ𝑒 𝔇𝑒𝑎𝑟𝑒𝑠𝑡 🎀𝑐𝑡𝑜𝑟𝑠\" 😻𝖠𝖣𝖬𝖨𝖭𝖨𝖲𝖳𝖱𝖠𝖳𝖨𝖮𝖭🌟", + "legend": "🌟исполняет роль 😻 принимает тейки\nв закулисье 😻 не принимает тейки \nантракт 😻 рест🌟", + "footer": " ﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋﹋\n 😻 🤩𝖨𝖥𝖤 𝖢𝖧𝖠𝖭𝖭𝖤𝖫 (https://t.me/lifeOverheardPRCM) & 🤩𝖱𝖢𝖧𝖨𝖵𝖤 (https://t.me/archiveOverheardRPCM) 😻", "status_labels": { "open": "исполняет роль", "backstage": "в закулисье", @@ -12,6 +12,38 @@ "rest": "антракт" }, "actors": [ + { + "key": "liebe", + "button_text": "Либэ", + "display_name": "LIEBE", + "link": "http://t.me/harurpcmoverheardbot", + "pronouns": "she/her", + "emoji": "🌟", + "operator_user_id": 5203570193, + "default_status": "backstage", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "отвечает с задержкой.", + "rest": "на антракте." + } + }, + { + "key": "motsiel", + "button_text": "Моцэ", + "display_name": "MOTSIEL", + "link": "http://t.me/OverheardRPCM_motsiel_bot", + "pronouns": "he/him", + "emoji": "🌟", + "operator_user_ids": [1378007191, 6364049891], + "default_status": "delay", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "задержки. ⭐", + "rest": "на антракте." + } + }, { "key": "astat", "button_text": "Астат", @@ -19,13 +51,29 @@ "link": "http://t.me/astat_ovhdRPCM_bot", "pronouns": "he/him", "emoji": "🌟", - "operator_user_id": 123456789, + "operator_user_id": 1021293938, "default_status": "backstage", "phrases": { "open": "принимает тейки.", "backstage": "в закулисье.", "delay": "ответит с задержкой.", - "rest": "ушел на антракт." + "rest": "на антракте." + } + }, + { + "key": "skafandr", + "button_text": "Скаф", + "display_name": "SKAFANDR", + "link": "http://t.me/Alxschfovhd_bot", + "pronouns": "he/him", + "emoji": "🌟", + "operator_user_id": 7647479588, + "default_status": "backstage", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "отвечает с задержкой.", + "rest": "на антракте." } }, { @@ -35,13 +83,61 @@ "link": "http://t.me/Marioverheard_bot", "pronouns": "she/her", "emoji": "🌟", - "operator_user_id": 987654321, + "operator_user_id": 2114793249, "default_status": "open", "phrases": { "open": "исполняет роль.", "backstage": "в закулисье.", "delay": "есть задержка.", - "rest": "антракт." + "rest": "на антракте." + } + }, + { + "key": "marcus", + "button_text": "Маркус", + "display_name": "MARCUS", + "link": "http://t.me/Marcus_OVHD_bot", + "pronouns": "he/him", + "emoji": "🌟", + "operator_user_id": 637396085, + "default_status": "backstage", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "отвечает с задержкой.", + "rest": "на антракте." + } + }, + { + "key": "leo", + "button_text": "Лео", + "display_name": "LEO", + "link": "http://t.me/LEOoverh_bot", + "pronouns": "he/him", + "emoji": "🌟", + "operator_user_id": 6730780021, + "default_status": "backstage", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "отвечает с задержкой.", + "rest": "на антракте." + } + }, + { + "key": "lein", + "button_text": "Лейн", + "display_name": "LEIN", + "link": "http://t.me/Lein_OVHD_Bot", + "pronouns": "he/him", + "emoji": "🌟", + "operator_user_id": 6751720805, + "default_status": "backstage", + "phrases": { + "open": "принимает тейки.", + "backstage": "в закулисье.", + "delay": "отвечает с задержкой.", + "rest": "на антракте." } } ] diff --git a/session_bot/bot.py b/session_bot/bot.py index 695ee0c..a488c4e 100644 --- a/session_bot/bot.py +++ b/session_bot/bot.py @@ -31,10 +31,17 @@ class SessionForm(StatesGroup): waiting_for_phrase = State() +def actor_operator_ids(actor: dict[str, Any]) -> set[int]: + if "operator_user_ids" in actor: + return {int(user_id) for user_id in actor["operator_user_ids"]} + return {int(actor["operator_user_id"])} + + def build_actor_lookup(config: dict) -> dict[int, dict[str, Any]]: lookup: dict[int, dict[str, Any]] = {} for actor in config["actors"]: - lookup[int(actor["operator_user_id"])] = actor + for user_id in actor_operator_ids(actor): + lookup[user_id] = actor return lookup @@ -45,7 +52,7 @@ def is_allowed(user_id: int, actor_lookup: dict[int, dict[str, Any]], admin_ids: def build_actor_keyboard(config: dict, user_id: int, admin_ids: set[int]) -> InlineKeyboardBuilder: keyboard = InlineKeyboardBuilder() for actor in config["actors"]: - if user_id in admin_ids or int(actor["operator_user_id"]) == user_id: + if user_id in admin_ids or user_id in actor_operator_ids(actor): keyboard.button(text=actor["button_text"], callback_data=f"actor:{actor['key']}") keyboard.adjust(2) return keyboard @@ -96,7 +103,7 @@ async def actor_handler(callback: CallbackQuery, settings, actor_lookup: dict, a await callback.answer("Персонаж не найден.", show_alert=True) return - if user_id not in settings.admin_ids and int(actor["operator_user_id"]) != user_id: + if user_id not in settings.admin_ids and user_id not in actor_operator_ids(actor): await callback.answer("Можно менять только свой статус.", show_alert=True) return @@ -127,7 +134,7 @@ async def status_handler( await callback.answer("Персонаж не найден.", show_alert=True) return - if user_id not in settings.admin_ids and int(actor["operator_user_id"]) != user_id: + if user_id not in settings.admin_ids and user_id not in actor_operator_ids(actor): await callback.answer("Можно менять только свой статус.", show_alert=True) return