#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import time import requests from typing import List, Dict, Any, Optional # ===== 設定 ===== X_ACCOUNT = os.getenv("dmsendertoken") if not X_ACCOUNT: raise RuntimeError("環境変数 dmsendertoken が設定されていません") BASE = "https://desk-api.channel.io/desk/channels/200605" GROUP_ID = 463667 CHECK_PERSON_ID = "614601" # accountIdベースのブラックリスト BLACKLIST_ACCOUNT_IDS = ["476793", "486092", "471246"] HEADERS = { "accept": "application/json", "accept-language": "ja", "content-type": "application/json", "x-account": X_ACCOUNT, } GET_PARAMS = { "sortOrder": "desc", "limit": 34, "logFolded": "false", } WELCOME_TEMPLATE = """ こんにちは。ITRSAにようこそ。 自動でいくつかの部屋に招待しています。 使い方: 左側のメニューから、部屋(グループ)を開くことができます。 ・「あいてぃーあーるえすえい」は本部で、雑談などをする部屋です。 ・「Youtubeダウンローダー」は、URLを送ると自動でYoutubeをダウンロードしてくれる部屋です。 ・「チャッピーくん」は、ChatGPTと話せる部屋です。 ・「幹部と裁判所からの報告」はここを管理する幹部や裁判所から通知が来る部屋です。この部屋は基本的に抜けないでください。 """ INVITE_GROUPS = [ 519217, 536194, 534868, 521995, 530062, 517180, 524837 ] # ===== API ===== def get_messages() -> List[Dict[str, Any]]: url = f"{BASE}/groups/{GROUP_ID}/messages" r = requests.get(url, headers=HEADERS, params=GET_PARAMS, timeout=20) r.raise_for_status() return r.json().get("messages", []) def get_group_titles() -> Dict[int, str]: url = f"{BASE}/groups?limit=1000" response = requests.get(url, headers=HEADERS, timeout=20) response.raise_for_status() groups = response.json().get("groups", []) return { group.get("id"): group.get("title") for group in groups if "id" in group and "title" in group } def get_manager_account_id(person_id: str) -> Optional[str]: """ personId を使って managers API を取得し、 managers[0].accountId を返す """ url = f"{BASE}/managers" params = { "limit": 1, "since": person_id } r = requests.get(url, headers=HEADERS, params=params, timeout=20) r.raise_for_status() data = r.json() managers = data.get("managers", []) if not managers: return None return str(managers[0].get("accountId")) def blacklist_manager(person_id: str) -> None: """ personId を使って manager を削除 """ url = f"{BASE}/managers/{person_id}" requests.delete(url, headers=HEADERS, timeout=20).raise_for_status() payload = { "requestId": f"desk-web-{int(time.time() * 1000)}", "blocks": [ {"type": "text", "value": "さようなら。"} ] } url = f"{BASE}/groups/{GROUP_ID}/messages" requests.post(url, headers=HEADERS, json=payload, timeout=20).raise_for_status() print(f"[INFO] personId={person_id} を削除しました") def post_welcome_message() -> None: TITLES = get_group_titles() welcome_text = WELCOME_TEMPLATE.format( hq=TITLES.get(532214, "本部") ) url = f"{BASE}/groups/{GROUP_ID}/messages" payload = { "requestId": f"desk-web-{int(time.time() * 1000)}", "blocks": [ {"type": "text", "value": welcome_text} ] } requests.post(url, headers=HEADERS, json=payload, timeout=20).raise_for_status() print("[INFO] 歓迎メッセージを送信しました") def invite_person(group_id: int, person_id: str) -> None: url = f"{BASE}/groups/{group_id}/invite" params = {"managerIds": person_id} requests.post(url, headers=HEADERS, params=params, timeout=20).raise_for_status() print(f"[INFO] personId={person_id} を group {group_id} に招待しました") # ===== ロジック ===== def process(): messages = get_messages() # CHECK_PERSON_ID の最新発言時刻 latest_check_person = max( (int(m.get("createdAt", 0)) for m in messages if str(m.get("personId")) == CHECK_PERSON_ID), default=0 ) join_targets = [] for m in messages: log = m.get("log") or {} if log.get("action") != "join": continue created_at = int(m.get("createdAt", 0)) person_id = str(m.get("personId", "")) # ===== ここを追加 ===== # CHECK_PERSON_ID の最新発言より前なら無視 if created_at <= latest_check_person: continue # ===== ブラックリスト判定(accountIdベース)===== try: account_id = get_manager_account_id(person_id) except Exception as e: print(f"[ERROR] manager取得失敗 personId={person_id} : {e}") continue if account_id and account_id in BLACKLIST_ACCOUNT_IDS: try: blacklist_manager(person_id) except Exception as e: print(f"[ERROR] 削除失敗 personId={person_id} : {e}") continue # ===== 通常処理 ===== join_targets.append(person_id) if not join_targets: return join_targets = list(set(join_targets)) # 歓迎メッセージは1回だけ post_welcome_message() # 招待処理 for pid in join_targets: for gid in INVITE_GROUPS: try: invite_person(gid, pid) except Exception as e: print(f"[ERROR] 招待失敗 personId={pid} group={gid} : {e}") def main(): print("[INFO] Bot 起動(10秒間隔)") while True: try: process() except Exception as e: print(f"[ERROR] {e}") time.sleep(10) if __name__ == "__main__": main()