izuemon commited on
Commit
3f49d8c
·
verified ·
1 Parent(s): dbb692e

Update watcher.py

Browse files
Files changed (1) hide show
  1. watcher.py +112 -15
watcher.py CHANGED
@@ -1,9 +1,14 @@
1
  import os
 
2
  import time
 
3
  import requests
4
  from datetime import datetime, timezone
5
 
6
- URL = "https://desk-api.channel.io/desk/channels/200605/groups/519217/messages"
 
 
 
7
  PARAMS = {
8
  "sortOrder": "desc",
9
  "limit": 36,
@@ -14,12 +19,23 @@ X_ACCOUNT = os.getenv("channeliotokenbot2")
14
  if not X_ACCOUNT:
15
  raise RuntimeError("環境変数 channeliotokenbot2 が設定されていません")
16
 
17
- HEADERS = {
 
 
 
 
 
 
18
  "accept": "application/json",
19
  "accept-language": "ja",
 
20
  "x-account": X_ACCOUNT,
21
  }
22
 
 
 
 
 
23
  def parse_updated_at(value):
24
  if isinstance(value, (int, float)):
25
  return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
@@ -27,19 +43,78 @@ def parse_updated_at(value):
27
  return datetime.fromisoformat(value.replace("Z", "+00:00"))
28
  return None
29
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
30
  def main():
31
  while True:
32
  try:
33
- response = requests.get(
34
- URL,
35
- headers=HEADERS,
36
  params=PARAMS,
37
  timeout=30,
38
  )
39
- response.raise_for_status()
40
 
41
- data = response.json()
42
- messages = data.get("messages", [])
43
 
44
  latest_msg = None
45
  latest_time = None
@@ -51,18 +126,40 @@ def main():
51
  if not plain_text or updated_at is None:
52
  continue
53
 
54
- updated_time = parse_updated_at(updated_at)
55
- if not updated_time:
56
  continue
57
 
58
- if latest_time is None or updated_time > latest_time:
59
- latest_time = updated_time
60
  latest_msg = msg
61
 
62
- if latest_msg:
63
- print(latest_msg["plainText"])
64
- else:
65
  print("条件に合う message が見つかりませんでした")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
  except Exception as e:
68
  print("エラー:", e)
 
1
  import os
2
+ import re
3
  import time
4
+ import json
5
  import requests
6
  from datetime import datetime, timezone
7
 
8
+ # ===== Channel.io 設定 =====
9
+ GET_URL = "https://desk-api.channel.io/desk/channels/200605/groups/519217/messages"
10
+ POST_URL = GET_URL
11
+
12
  PARAMS = {
13
  "sortOrder": "desc",
14
  "limit": 36,
 
19
  if not X_ACCOUNT:
20
  raise RuntimeError("環境変数 channeliotokenbot2 が設定されていません")
21
 
22
+ HEADERS_GET = {
23
+ "accept": "application/json",
24
+ "accept-language": "ja",
25
+ "x-account": X_ACCOUNT,
26
+ }
27
+
28
+ HEADERS_POST = {
29
  "accept": "application/json",
30
  "accept-language": "ja",
31
+ "content-type": "application/json",
32
  "x-account": X_ACCOUNT,
33
  }
34
 
35
+ # ===== Vidfly API =====
36
+ VIDFLY_API = "https://api.vidfly.ai/api/media/youtube/download?url="
37
+
38
+ # ===== Utils =====
39
  def parse_updated_at(value):
40
  if isinstance(value, (int, float)):
41
  return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
 
43
  return datetime.fromisoformat(value.replace("Z", "+00:00"))
44
  return None
45
 
46
+ def extract_youtube_id(text):
47
+ """
48
+ 対応例:
49
+ https://www.youtube.com/watch?v=ID
50
+ https://youtu.be/ID
51
+ """
52
+ patterns = [
53
+ r"v=([A-Za-z0-9_-]{11})",
54
+ r"youtu\.be/([A-Za-z0-9_-]{11})",
55
+ ]
56
+ for p in patterns:
57
+ m = re.search(p, text)
58
+ if m:
59
+ return m.group(1)
60
+ return None
61
+
62
+ def build_links(items):
63
+ lines = []
64
+ for item in items:
65
+ url = item.get("url")
66
+ ext = item.get("ext")
67
+ height = item.get("height")
68
+ media_type = item.get("type")
69
+
70
+ if not url or not ext or not height:
71
+ continue
72
+
73
+ label_type = "動画" if ext in ("mp4", "webm") else "音声"
74
+ audio_suffix = " (音声付き)" if media_type == "video_with_audio" else ""
75
+
76
+ line = f'<link type="url" value="{url}">{label_type}{audio_suffix} {height}p</link>'
77
+ lines.append(line)
78
+
79
+ return "\n".join(lines)
80
+
81
+ def send_to_channel(text):
82
+ payload = {
83
+ "requestId": f"desk-web-{int(time.time() * 1000)}",
84
+ "blocks": [
85
+ {
86
+ "type": "text",
87
+ "value": text
88
+ }
89
+ ],
90
+ "buttons": None,
91
+ "form": None,
92
+ "webPage": None,
93
+ "files": None,
94
+ "customPayload": None
95
+ }
96
+
97
+ res = requests.post(
98
+ POST_URL,
99
+ headers=HEADERS_POST,
100
+ data=json.dumps(payload),
101
+ timeout=30
102
+ )
103
+ res.raise_for_status()
104
+
105
+ # ===== Main =====
106
  def main():
107
  while True:
108
  try:
109
+ res = requests.get(
110
+ GET_URL,
111
+ headers=HEADERS_GET,
112
  params=PARAMS,
113
  timeout=30,
114
  )
115
+ res.raise_for_status()
116
 
117
+ messages = res.json().get("messages", [])
 
118
 
119
  latest_msg = None
120
  latest_time = None
 
126
  if not plain_text or updated_at is None:
127
  continue
128
 
129
+ t = parse_updated_at(updated_at)
130
+ if not t:
131
  continue
132
 
133
+ if latest_time is None or t > latest_time:
134
+ latest_time = t
135
  latest_msg = msg
136
 
137
+ if not latest_msg:
 
 
138
  print("条件に合う message が見つかりませんでした")
139
+ time.sleep(10)
140
+ continue
141
+
142
+ text = latest_msg["plainText"]
143
+ youtube_id = extract_youtube_id(text)
144
+
145
+ if not youtube_id:
146
+ print("YouTube ID が見つかりません")
147
+ time.sleep(10)
148
+ continue
149
+
150
+ youtube_url = f"https://www.youtube.com/watch?v={youtube_id}"
151
+ vidfly_res = requests.get(VIDFLY_API + youtube_url, timeout=30)
152
+ vidfly_res.raise_for_status()
153
+
154
+ items = vidfly_res.json().get("data", {}).get("items", [])
155
+ if not items:
156
+ print("Vidfly の items が空です")
157
+ time.sleep(10)
158
+ continue
159
+
160
+ message_text = build_links(items)
161
+ send_to_channel(message_text)
162
+ print("送信完了")
163
 
164
  except Exception as e:
165
  print("エラー:", e)