izuemon commited on
Commit
fedb44a
·
verified ·
1 Parent(s): 73c24ae

Update news.py

Browse files
Files changed (1) hide show
  1. news.py +58 -107
news.py CHANGED
@@ -2,66 +2,76 @@ import os
2
  import time
3
  import json
4
  import requests
5
- import hashlib
6
- from datetime import datetime
7
- from bs4 import BeautifulSoup
8
- import xml.etree.ElementTree as ET
9
 
10
  # ===== Channel.io 設定 =====
11
  CHANNEL_ID = "200605"
12
- GROUP_ID = "534457"
13
 
14
- POST_URL = f"https://desk-api.channel.io/desk/channels/{CHANNEL_ID}/groups/{GROUP_ID}/messages"
 
15
 
16
  X_ACCOUNT = os.getenv("channeliotokenbot2")
17
  if not X_ACCOUNT:
18
  raise RuntimeError("環境変数 channeliotokenbot2 が設定されていません")
19
 
20
- HEADERS_POST = {
21
  "accept": "application/json",
22
  "accept-language": "ja",
23
  "content-type": "application/json",
24
  "x-account": X_ACCOUNT,
25
  }
26
 
27
- # ===== RSS =====
28
- RSS_URL = "https://www.nippon.com/ja/rss-all/"
29
-
30
- # ===== 設定 =====
31
- SENT_LOG_FILE = "sent_nippon_news.json"
32
- LAST_RUN_FILE = "last_run.json"
33
 
34
- TARGET_TIMES = {"06:30", "18:30"} # 朝・夕方
35
 
 
 
36
 
37
  # ===== Utils =====
38
- def load_sent_log():
39
- if not os.path.exists(SENT_LOG_FILE):
40
- return set()
41
- with open(SENT_LOG_FILE, "r", encoding="utf-8") as f:
42
- return set(json.load(f))
43
 
 
 
44
 
45
- def save_sent_log(sent_set):
46
- with open(SENT_LOG_FILE, "w", encoding="utf-8") as f:
47
- json.dump(list(sent_set), f, ensure_ascii=False, indent=2)
48
 
 
 
49
 
50
- def load_last_run():
51
- if not os.path.exists(LAST_RUN_FILE):
52
- return ""
53
- with open(LAST_RUN_FILE, "r", encoding="utf-8") as f:
54
- return json.load(f).get("last_run", "")
55
 
 
 
 
 
56
 
57
- def save_last_run(value):
58
- with open(LAST_RUN_FILE, "w", encoding="utf-8") as f:
59
- json.dump({"last_run": value}, f)
60
 
 
 
 
 
 
61
 
62
- def hash_link(link: str) -> str:
63
- return hashlib.sha256(link.encode("utf-8")).hexdigest()
 
 
 
 
 
64
 
 
 
65
 
66
  def send_to_channel(text):
67
  payload = {
@@ -73,115 +83,56 @@ def send_to_channel(text):
73
 
74
  res = requests.post(
75
  POST_URL,
76
- headers=HEADERS_POST,
77
  data=json.dumps(payload),
78
  timeout=30
79
  )
80
  res.raise_for_status()
81
 
82
-
83
- def fetch_rss_items():
84
- res = requests.get(RSS_URL, timeout=30)
85
- res.raise_for_status()
86
-
87
- root = ET.fromstring(res.content)
88
- channel = root.find("channel")
89
- if channel is None:
90
- return []
91
-
92
- items = []
93
- for item in channel.findall("item"):
94
- title = item.findtext("title", "").strip()
95
- link = item.findtext("link", "").strip()
96
- description_raw = item.findtext("description", "").strip()
97
-
98
- soup = BeautifulSoup(description_raw, "lxml")
99
- description = soup.get_text(strip=True)
100
-
101
- if title and link:
102
- items.append({
103
- "title": title,
104
- "link": link,
105
- "description": description,
106
- })
107
-
108
- return items
109
-
110
-
111
  # ===== Main =====
112
- def run_job():
113
- sent_log = load_sent_log()
114
- items = fetch_rss_items()
115
- new_count = 0
116
-
117
- for item in items:
118
- link_hash = hash_link(item["link"])
119
- if link_hash in sent_log:
120
- continue
121
-
122
- message = (
123
- f"<link type=\"url\" value=\"{item['link']}\">"
124
- f"{item['title']}"
125
- f"</link>\n\n"
126
- f"{item['description']}"
127
- )
128
-
129
- send_to_channel(message)
130
- sent_log.add(link_hash)
131
- new_count += 1
132
- time.sleep(1)
133
-
134
- if new_count > 0:
135
- save_sent_log(sent_log)
136
- print(f"{new_count} 件のニュースを送信しました")
137
- else:
138
- print("新しいニュースはありません")
139
-
140
-
141
  def main():
142
- processed = set()
143
 
144
  while True:
145
  try:
146
  messages = fetch_channel_messages()
147
-
148
  if not messages:
149
  time.sleep(10)
150
  continue
151
 
152
- latest = messages[-1]
153
- msg_id = latest.get("id")
154
- person_id = latest.get("personId")
155
 
156
- # すでに処理済み
157
- if msg_id in processed:
158
  time.sleep(10)
159
  continue
160
 
161
- # ★ アシスタント発言ならGPTに送らず待機
162
- if person_id == ASSISTANT_PERSON_ID:
163
  time.sleep(10)
164
  continue
165
 
166
- # GPT用メッセージ構築
167
  chat_messages = build_chat_messages(messages)
168
-
169
  if not chat_messages:
170
- processed.add(msg_id)
171
  continue
172
 
 
173
  reply = call_chat_api(chat_messages)
 
 
174
  send_to_channel(reply)
175
 
176
- processed.add(msg_id)
177
- print("送信完了")
178
 
179
  except Exception as e:
180
  print("エラー:", e)
181
 
182
  time.sleep(15)
183
 
184
-
185
-
186
  if __name__ == "__main__":
187
  main()
 
2
  import time
3
  import json
4
  import requests
 
 
 
 
5
 
6
  # ===== Channel.io 設定 =====
7
  CHANNEL_ID = "200605"
8
+ GROUP_ID = "534868"
9
 
10
+ GET_URL = f"https://desk-api.channel.io/desk/channels/{CHANNEL_ID}/groups/{GROUP_ID}/messages"
11
+ POST_URL = GET_URL
12
 
13
  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
  "content-type": "application/json",
21
  "x-account": X_ACCOUNT,
22
  }
23
 
24
+ PARAMS = {
25
+ "sortOrder": "asc",
26
+ "limit": 50,
27
+ }
 
 
28
 
29
+ ASSISTANT_PERSON_ID = "595702"
30
 
31
+ # ===== ChatGPT互換API =====
32
+ CHAT_API_URL = "https://izuemon-gpt-free-api.hf.space/v1/chat/completions"
33
 
34
  # ===== Utils =====
35
+ def fetch_channel_messages():
36
+ res = requests.get(GET_URL, headers=HEADERS, params=PARAMS, timeout=30)
37
+ res.raise_for_status()
38
+ return res.json().get("messages", [])
 
39
 
40
+ def build_chat_messages(messages):
41
+ chat_messages = []
42
 
43
+ for msg in messages:
44
+ text = msg.get("plainText")
45
+ person_id = msg.get("personId")
46
 
47
+ if not text:
48
+ continue
49
 
50
+ role = "assistant" if person_id == ASSISTANT_PERSON_ID else "user"
 
 
 
 
51
 
52
+ chat_messages.append({
53
+ "role": role,
54
+ "content": text
55
+ })
56
 
57
+ return chat_messages
 
 
58
 
59
+ def call_chat_api(chat_messages):
60
+ payload = {
61
+ "model": "gpt-3.5-turbo",
62
+ "messages": chat_messages,
63
+ }
64
 
65
+ res = requests.post(
66
+ CHAT_API_URL,
67
+ headers={"Content-Type": "application/json"},
68
+ data=json.dumps(payload),
69
+ timeout=60
70
+ )
71
+ res.raise_for_status()
72
 
73
+ data = res.json()
74
+ return data["choices"][0]["message"]["content"]
75
 
76
  def send_to_channel(text):
77
  payload = {
 
83
 
84
  res = requests.post(
85
  POST_URL,
86
+ headers=HEADERS,
87
  data=json.dumps(payload),
88
  timeout=30
89
  )
90
  res.raise_for_status()
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  # ===== Main =====
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  def main():
94
+ processed_message_ids = set()
95
 
96
  while True:
97
  try:
98
  messages = fetch_channel_messages()
 
99
  if not messages:
100
  time.sleep(10)
101
  continue
102
 
103
+ latest_msg = messages[-1]
104
+ latest_id = latest_msg.get("id")
105
+ latest_person_id = latest_msg.get("personId")
106
 
107
+ # 既に処理済みならスキップ
108
+ if latest_id in processed_message_ids:
109
  time.sleep(10)
110
  continue
111
 
112
+ # ★ 最新メッセージがアシスタントなら待機
113
+ if latest_person_id == ASSISTANT_PERSON_ID:
114
  time.sleep(10)
115
  continue
116
 
117
+ # GPTに送る会話履歴を構築
118
  chat_messages = build_chat_messages(messages)
 
119
  if not chat_messages:
120
+ processed_message_ids.add(latest_id)
121
  continue
122
 
123
+ # GPT呼び出し
124
  reply = call_chat_api(chat_messages)
125
+
126
+ # Channel.ioへ送信
127
  send_to_channel(reply)
128
 
129
+ processed_message_ids.add(latest_id)
130
+ print("GPT応答を送信しました")
131
 
132
  except Exception as e:
133
  print("エラー:", e)
134
 
135
  time.sleep(15)
136
 
 
 
137
  if __name__ == "__main__":
138
  main()