izuemon commited on
Commit
8ad0356
·
verified ·
1 Parent(s): bfd6376

Update join.py

Browse files
Files changed (1) hide show
  1. join.py +158 -61
join.py CHANGED
@@ -1,104 +1,201 @@
1
  #!/usr/bin/env python3
2
  # -*- coding: utf-8 -*-
3
 
 
 
 
 
 
 
 
 
4
  import os
5
  import time
 
6
  import requests
7
- from typing import List, Dict, Any
8
 
9
  # --- 設定 ---
10
  X_ACCOUNT = os.getenv("dmsendertoken")
11
  if not X_ACCOUNT:
12
  raise RuntimeError("環境変数 dmsendertoken が設定されていません。")
13
 
14
- BASE_MESSAGES = "https://desk-api.channel.io/desk/channels/200605/groups/463667/messages"
15
- INVITE_GROUPS = [519217, 536194, 534868]
16
-
17
- BOT_PERSON_ID = "599642"
18
- WELCOME_TEXT = "こんにちは。ITRSAにようこそ。自動でいくつかの部屋に招待しています。"
19
 
20
- PARAMS = {
21
- "sortOrder": "desc",
22
- "limit": 34,
23
- "logFolded": "false",
24
  }
25
-
26
- HEADERS = {
27
  "accept": "application/json",
28
  "accept-language": "ja",
29
  "content-type": "application/json",
30
  "x-account": X_ACCOUNT,
31
  }
32
 
33
- # --- API ---
34
- def post_message(text: str) -> None:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  payload = {
36
  "requestId": f"desk-web-{int(time.time() * 1000)}",
37
  "blocks": [{"type": "text", "value": text}],
38
  }
39
- r = requests.post(BASE_MESSAGES, headers=HEADERS, json=payload, timeout=30)
40
  r.raise_for_status()
41
- print("[INFO] 歓迎メッセージ送信")
42
 
43
- def invite_to_group(group_id: int, manager_id: str) -> None:
44
- url = f"https://desk-api.channel.io/desk/channels/200605/groups/{group_id}/invite"
45
- params = {"managerIds": manager_id}
46
- r = requests.post(url, headers=HEADERS, params=params, timeout=30)
47
- r.raise_for_status()
48
- print(f"[INFO] group {group_id} に {manager_id} を招待")
49
 
50
- # --- メイン処理 ---
51
- def process():
52
- r = requests.get(BASE_MESSAGES, headers=HEADERS, params=PARAMS, timeout=30)
 
53
  r.raise_for_status()
54
- messages = r.json().get("messages", [])
55
 
56
- # 最新の bot メッセージ時刻
57
- bot_created_at = None
58
- for m in messages:
59
- if str(m.get("personId")) == BOT_PERSON_ID:
60
- bot_created_at = int(m.get("createdAt") or 0)
61
- break # desc なので最初でOK
62
-
63
- join_messages: List[Dict[str, Any]] = []
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  for m in messages:
66
- created_at = int(m.get("createdAt") or 0)
67
- if bot_created_at and created_at <= bot_created_at:
68
- continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
 
70
- for log in m.get("log", []) or []:
71
- if log.get("action") == "join":
72
- join_messages.append({
73
- "createdAt": created_at,
74
- "personId": str(m.get("personId")),
75
- })
76
 
77
- if not join_messages:
78
- return
 
 
 
 
79
 
80
- # bot発言以降に join があり、botの発言がまだ無い場合のみ歓迎メッセージ
81
- if bot_created_at is None:
82
- post_message(WELCOME_TEXT)
83
 
84
- # join 全員を invite(複数可)
85
- invited = set()
86
- for jm in join_messages:
87
- pid = jm["personId"]
88
- if not pid or pid in invited:
89
  continue
90
- for gid in INVITE_GROUPS:
91
- invite_to_group(gid, pid)
92
- invited.add(pid)
93
 
94
- def main():
95
- print("[INFO] Bot 起動(10秒ごとにチェック)")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  while True:
97
  try:
98
- process()
99
  except Exception as e:
100
- print(f"[ERROR] {e}")
 
 
 
 
 
 
 
 
 
101
  time.sleep(10)
102
 
 
103
  if __name__ == "__main__":
104
- main()
 
1
  #!/usr/bin/env python3
2
  # -*- coding: utf-8 -*-
3
 
4
+ """
5
+ 10秒ごとに指定のグループのメッセージを取得し、
6
+ 各メッセージ内の log / logs の action == "join" を検出。
7
+ その join が発生したメッセージの createdAt より新しい (createdAt が大きい)
8
+ personId == 599642 のメッセージがなければ歓迎メッセージを送信し、
9
+ join を起こした人を指定のグループへ invite POST する。
10
+ """
11
+
12
  import os
13
  import time
14
+ import json
15
  import requests
16
+ from typing import List, Dict, Any, Optional, Set
17
 
18
  # --- 設定 ---
19
  X_ACCOUNT = os.getenv("dmsendertoken")
20
  if not X_ACCOUNT:
21
  raise RuntimeError("環境変数 dmsendertoken が設定されていません。")
22
 
23
+ GROUP_ID_TO_WATCH = 463667
24
+ PARAMS = {"sortOrder": "desc", "limit": 34, "logFolded": "false"}
25
+ BASE_GET = "https://desk-api.channel.io/desk/channels/200605/groups/{group_id}/messages"
26
+ BASE_POST = "https://desk-api.channel.io/desk/channels/200605/groups/{group_id}/messages"
27
+ INVITE_ENDPOINT_TEMPLATE = "https://desk-api.channel.io/desk/channels/200605/groups/{invite_group_id}/invite?managerIds={manager_id}"
28
 
29
+ HEADERS_GET = {
30
+ "accept": "application/json",
31
+ "accept-language": "ja",
32
+ "x-account": X_ACCOUNT,
33
  }
34
+ HEADERS_POST = {
 
35
  "accept": "application/json",
36
  "accept-language": "ja",
37
  "content-type": "application/json",
38
  "x-account": X_ACCOUNT,
39
  }
40
 
41
+ TARGET_PERSON_ID = "599642" # チェック対象の personId(文字列比較)
42
+ INVITE_GROUP_IDS = [519217, 536194, 534868]
43
+
44
+ WELCOME_MESSAGE_TEXT = "こんにちは。ITRSAにようこそ。自動でいくつかの部屋に招待しています。"
45
+
46
+ # --- ヘルパー ---
47
+
48
+
49
+ def fetch_messages(group_id: int) -> List[Dict[str, Any]]:
50
+ url = BASE_GET.format(group_id=group_id)
51
+ r = requests.get(url, headers=HEADERS_GET, params=PARAMS, timeout=20)
52
+ r.raise_for_status()
53
+ data = r.json()
54
+ msgs = data.get("messages", [])
55
+ if not isinstance(msgs, list):
56
+ return []
57
+ return msgs
58
+
59
+
60
+ def send_welcome_message(group_id: int, text: str) -> None:
61
+ url = BASE_POST.format(group_id=group_id)
62
  payload = {
63
  "requestId": f"desk-web-{int(time.time() * 1000)}",
64
  "blocks": [{"type": "text", "value": text}],
65
  }
66
+ r = requests.post(url, headers=HEADERS_POST, json=payload, timeout=30)
67
  r.raise_for_status()
 
68
 
 
 
 
 
 
 
69
 
70
+ def post_invite(invite_group_id: int, manager_id: str) -> None:
71
+ url = INVITE_ENDPOINT_TEMPLATE.format(invite_group_id=invite_group_id, manager_id=manager_id)
72
+ # API に特別な body が必要ならここに入れるが、指定がなかったので空 JSON を送る
73
+ r = requests.post(url, headers=HEADERS_POST, json={}, timeout=20)
74
  r.raise_for_status()
 
75
 
 
 
 
 
 
 
 
 
76
 
77
+ def extract_join_person_ids_from_message(msg: Dict[str, Any]) -> List[str]:
78
+ """
79
+ メッセージ内の log / logs を調べ、action == "join" のエントリから personId を取り出す。
80
+ log エントリ自体に personId がある場合はそれを使い、なければメッセージの personId を使う。
81
+ 戻り値は文字列の personId のリスト(重複はこの段階では除去しない)。
82
+ """
83
+ person_ids = []
84
+ # 支持されているキー名を両方確認
85
+ log_lists = []
86
+ for key in ("log", "logs"):
87
+ if key in msg and isinstance(msg[key], list):
88
+ log_lists.append(msg[key])
89
+
90
+ # もし log/ logs が無ければ return empty
91
+ if not log_lists:
92
+ return []
93
+
94
+ for logs in log_lists:
95
+ for entry in logs:
96
+ if not isinstance(entry, dict):
97
+ continue
98
+ action = entry.get("action")
99
+ if action != "join":
100
+ continue
101
+ pid = entry.get("personId") or msg.get("personId")
102
+ if pid is not None:
103
+ person_ids.append(str(pid))
104
+ return person_ids
105
+
106
+
107
+ def any_person599642_after(created_at: int, messages: List[Dict[str, Any]]) -> bool:
108
+ """
109
+ messages の中に createdAt が created_at より大きく、かつ personId == TARGET_PERSON_ID のものがあれば True
110
+ """
111
  for m in messages:
112
+ try:
113
+ ca = int(m.get("createdAt") or 0)
114
+ except Exception:
115
+ ca = 0
116
+ if ca > created_at and str(m.get("personId", "")) == TARGET_PERSON_ID:
117
+ return True
118
+ return False
119
+
120
+
121
+ def process_once(messages: List[Dict[str, Any]]) -> None:
122
+ """
123
+ 1 回分のメッセージ群を処理する。
124
+ - 各 message の log(s) 内で action == "join" を探す
125
+ - そのメッセージの createdAt 以降に personId == 599642 のメッセージが無ければ招待処理
126
+ - 同じ manager_id への招待は一回の処理実行内で重複しないようにする
127
+ - 歓迎メッセージはその条件で招待を行う最初のケースで一度だけ送る
128
+ """
129
+ if not messages:
130
+ return
131
 
132
+ invited_manager_ids: Set[str] = set()
133
+ welcome_sent = False
 
 
 
 
134
 
135
+ # messages は API から降順 (新しい順) で来るはずだが、安全のためそのまま扱う。
136
+ for msg in messages:
137
+ try:
138
+ created_at = int(msg.get("createdAt") or 0)
139
+ except Exception:
140
+ created_at = 0
141
 
142
+ join_person_ids = extract_join_person_ids_from_message(msg)
143
+ if not join_person_ids:
144
+ continue
145
 
146
+ # この join が起きたメッセージ以降に personId==599642 のメッセージがあるか確認
147
+ if any_person599642_after(created_at, messages):
148
+ # あるならこの join はスキップ(歓迎メッセージが既にある/今後来る想定のため)
 
 
149
  continue
 
 
 
150
 
151
+ # 招待対象 personId を集める(同一処理内で重複しないよう set で管理)
152
+ for manager_id in join_person_ids:
153
+ if manager_id in invited_manager_ids:
154
+ continue
155
+ # まず歓迎メッセージ(まだ送っていなければ)
156
+ if not welcome_sent:
157
+ try:
158
+ send_welcome_message(GROUP_ID_TO_WATCH, WELCOME_MESSAGE_TEXT)
159
+ print(f"[INFO] Sent welcome message to group {GROUP_ID_TO_WATCH}")
160
+ except Exception as e:
161
+ print(f"[ERROR] Failed to send welcome message: {e}")
162
+ # 歓迎送信失敗しても続行して招待は試みる
163
+ welcome_sent = True
164
+
165
+ # 各 invite グループへ POST
166
+ for invite_gid in INVITE_GROUP_IDS:
167
+ try:
168
+ post_invite(invite_gid, manager_id)
169
+ print(f"[INFO] Invited manager {manager_id} to group {invite_gid}")
170
+ except Exception as e:
171
+ print(f"[ERROR] Failed to invite manager {manager_id} to group {invite_gid}: {e}")
172
+
173
+ invited_manager_ids.add(manager_id)
174
+
175
+ if invited_manager_ids:
176
+ print(f"[INFO] Invited manager ids in this cycle: {', '.join(sorted(invited_manager_ids))}")
177
+ else:
178
+ print("[INFO] No join events required inviting in this cycle.")
179
+
180
+
181
+ def main_loop():
182
+ print("[INFO] Bot 起動。10秒ごとにチェックします。")
183
  while True:
184
  try:
185
+ messages = fetch_messages(GROUP_ID_TO_WATCH)
186
  except Exception as e:
187
+ print(f"[ERROR] メッセージ取得に失敗しました: {e}")
188
+ # エラーでも sleep して再試行
189
+ time.sleep(10)
190
+ continue
191
+
192
+ try:
193
+ process_once(messages)
194
+ except Exception as e:
195
+ print(f"[ERROR] 処理中に例外が発生しました: {e}")
196
+
197
  time.sleep(10)
198
 
199
+
200
  if __name__ == "__main__":
201
+ main_loop()