izuemon commited on
Commit
a195df1
·
verified ·
1 Parent(s): ae40f42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +137 -139
app.py CHANGED
@@ -1,73 +1,167 @@
1
- from flask import Flask, request, jsonify, redirect, Response
2
  import os
 
 
3
  import requests
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
 
 
 
5
  app = Flask(__name__)
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  @app.route("/drive.com/files")
8
- def index():
9
- ip = request.remote_addr # クライアントIP取得
10
- print(f"アクセスIP: {ip}") # ログ表示
 
11
 
12
- return redirect("https://drive.google.com/")
13
 
14
  @app.route("/channel-io-managers")
15
  def get_managers():
16
- # URLパラメータ取得
17
  limit = request.args.get("limit")
18
  since = request.args.get("since")
 
19
 
20
- # パラメータがある場合だけ付ける
21
  params = {}
22
  if limit:
23
  params["limit"] = limit
24
  if since:
25
  params["since"] = since
26
-
27
- if request.args.get("channelid"):
28
- CHANNEL_ID = request.args.get("channelid")
29
- else:
30
- CHANNEL_ID = "200605"
31
-
32
- BASE_URL = f"https://desk-api.channel.io/desk/channels/{CHANNEL_ID}/managers"
33
-
34
  headers = {
35
  "accept": "application/json",
36
- "x-account": os.environ.get("channeliotokenmain") # ←環境変数 token
37
  }
38
 
39
- res = requests.get(BASE_URL, headers=headers, params=params)
40
-
41
- # APIエラー処理
42
  if res.status_code != 200:
43
  return jsonify({"error": res.text}), res.status_code
44
 
45
- json_data = res.json()
46
 
47
- # managersの部分だけ返す
48
- return jsonify(json_data.get("managers", []))
49
 
50
- @app.route("/cors-proxy")
51
- def corsproxy():
52
  url = request.args.get("url")
53
  if not url:
54
  return "url パラメータが必要です", 400
55
 
56
- if not url.startswith("http://") and not url.startswith("https://"):
57
- return "http または https のURLのみ使用できます", 400
58
 
59
  try:
60
- resp = requests.get(url, headers=request.headers, timeout=60)
 
 
 
 
 
 
61
 
62
- # 元のレスポンスヘッダを継承
63
  response = Response(resp.content, resp.status_code)
64
 
65
- # CORSヘッダを追記(上書きしない)
66
  response.headers["Access-Control-Allow-Origin"] = "*"
67
  response.headers["Access-Control-Allow-Headers"] = "*"
68
- response.headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS"
69
 
70
- # ★ Content-Typeを元のままに設定 ★
71
  if "Content-Type" in resp.headers:
72
  response.headers["Content-Type"] = resp.headers["Content-Type"]
73
 
@@ -77,114 +171,18 @@ def corsproxy():
77
  return f"エラー: {str(e)}", 500
78
 
79
 
80
-
81
- @app.route("/cors-proxy", methods=["POST","PATCH"])
82
- def corsproxy_post():
83
- url = request.args.get("url")
84
- if not url:
85
- return "url パラメータが必要です", 400
86
-
87
- if not url.startswith("http://") and not url.startswith("https://"):
88
- return "http または https のURLのみ使用できます", 400
89
-
90
- try:
91
- resp = requests.post(
92
- url,
93
- data=request.data,
94
- headers=request.headers,
95
- timeout=60
96
- )
97
-
98
- headers = {
99
- "Access-Control-Allow-Origin": "*",
100
- "Access-Control-Allow-Headers": "*",
101
- "Access-Control-Allow-Methods": "GET, POST, OPTIONS"
102
- }
103
-
104
- return Response(resp.content, resp.status_code, headers=headers)
105
-
106
- except Exception as e:
107
- return f"エラー: {str(e)}", 500
108
-
109
  if __name__ == "__main__":
110
- app.run(debug=True, host="0.0.0.0", port=7860)
111
-
112
-
113
-
114
- import os
115
- import time
116
- import requests
117
- from datetime import datetime, timezone
118
-
119
- URL = "https://desk-api.channel.io/desk/channels/200605/groups/519217/messages"
120
- PARAMS = {
121
- "sortOrder": "desc",
122
- "limit": 36,
123
- "logFolded": "false",
124
- }
125
-
126
- X_ACCOUNT = os.getenv("channeliotokenbot2")
127
- if not X_ACCOUNT:
128
- raise RuntimeError("環境変数 channeliotokenbot2 が設定されていません")
129
-
130
- HEADERS = {
131
- "accept": "application/json",
132
- "accept-language": "ja",
133
- "x-account": X_ACCOUNT,
134
- }
135
-
136
- def parse_updated_at(value):
137
- """
138
- updatedAt が
139
- - int / float : UNIX time (ms)
140
- - str : ISO8601
141
- のどちらでも処理できるようにする
142
- """
143
- if isinstance(value, (int, float)):
144
- # ミリ秒 → 秒
145
- return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
146
- elif isinstance(value, str):
147
- return datetime.fromisoformat(value.replace("Z", "+00:00"))
148
- else:
149
- return None
150
-
151
- while True:
152
- try:
153
- response = requests.get(
154
- URL,
155
- headers=HEADERS,
156
- params=PARAMS,
157
- timeout=30,
158
  )
159
- response.raise_for_status()
160
-
161
- data = response.json()
162
- messages = data.get("messages", [])
163
-
164
- latest_msg = None
165
- latest_time = None
166
 
167
- for msg in messages:
168
- plain_text = msg.get("plainText")
169
- updated_at = msg.get("updatedAt")
170
-
171
- if not plain_text or updated_at is None:
172
- continue
173
-
174
- updated_time = parse_updated_at(updated_at)
175
- if updated_time is None:
176
- continue
177
-
178
- if latest_time is None or updated_time > latest_time:
179
- latest_time = updated_time
180
- latest_msg = msg
181
-
182
- if latest_msg:
183
- print(latest_msg["plainText"])
184
- else:
185
- print("条件に合う message が見つかりませんでした")
186
-
187
- except Exception as e:
188
- print("エラー:", e)
189
-
190
- time.sleep(60)
 
 
1
  import os
2
+ import time
3
+ import threading
4
  import requests
5
+ from datetime import datetime, timezone
6
+ from flask import Flask, request, jsonify, redirect, Response
7
+
8
+ # =========================
9
+ # Channel.io 監視設定
10
+ # =========================
11
+ CHANNEL_ID = "200605"
12
+ GROUP_ID = "519217"
13
+
14
+ CHANNEL_MESSAGE_URL = (
15
+ f"https://desk-api.channel.io/desk/channels/{CHANNEL_ID}/groups/{GROUP_ID}/messages"
16
+ )
17
+
18
+ PARAMS = {
19
+ "sortOrder": "desc",
20
+ "limit": 36,
21
+ "logFolded": "false",
22
+ }
23
+
24
+ X_ACCOUNT_BOT = os.getenv("channeliotokenbot2")
25
+ if not X_ACCOUNT_BOT:
26
+ raise RuntimeError("環境変数 channeliotokenbot2 が設定されていません")
27
+
28
+ BOT_HEADERS = {
29
+ "accept": "application/json",
30
+ "accept-language": "ja",
31
+ "x-account": X_ACCOUNT_BOT,
32
+ }
33
 
34
+ # =========================
35
+ # Flask 設定
36
+ # =========================
37
  app = Flask(__name__)
38
 
39
+ # =========================
40
+ # 共通関数
41
+ # =========================
42
+ def parse_updated_at(value):
43
+ """updatedAt が int(ms) / ISO8601 の両対応"""
44
+ try:
45
+ if isinstance(value, (int, float)):
46
+ return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
47
+ if isinstance(value, str):
48
+ return datetime.fromisoformat(value.replace("Z", "+00:00"))
49
+ except Exception:
50
+ pass
51
+ return None
52
+
53
+
54
+ # =========================
55
+ # Channel.io 監視スレッド
56
+ # =========================
57
+ def watch_channel_messages():
58
+ print("▶ Channel.io message watcher started")
59
+
60
+ while True:
61
+ try:
62
+ res = requests.get(
63
+ CHANNEL_MESSAGE_URL,
64
+ headers=BOT_HEADERS,
65
+ params=PARAMS,
66
+ timeout=30,
67
+ )
68
+ res.raise_for_status()
69
+
70
+ data = res.json()
71
+ messages = data.get("messages", [])
72
+
73
+ latest_msg = None
74
+ latest_time = None
75
+
76
+ for msg in messages:
77
+ plain_text = msg.get("plainText")
78
+ updated_at = msg.get("updatedAt")
79
+
80
+ if not plain_text or updated_at is None:
81
+ continue
82
+
83
+ updated_time = parse_updated_at(updated_at)
84
+ if updated_time is None:
85
+ continue
86
+
87
+ if latest_time is None or updated_time > latest_time:
88
+ latest_time = updated_time
89
+ latest_msg = msg
90
+
91
+ if latest_msg:
92
+ print(
93
+ f"[{latest_time.isoformat()}] {latest_msg['plainText']}"
94
+ )
95
+ else:
96
+ print("条件に合う message が見つかりませんでした")
97
+
98
+ except Exception as e:
99
+ # スレッドが死なないように必ず catch
100
+ print("⚠ watcher error:", e)
101
+
102
+ time.sleep(60)
103
+
104
+
105
+ # =========================
106
+ # Flask ルーティング
107
+ # =========================
108
  @app.route("/drive.com/files")
109
+ def drive_redirect():
110
+ ip = request.remote_addr
111
+ print(f"アクセスIP: {ip}")
112
+ return redirect("https://drive.google.com/")
113
 
 
114
 
115
  @app.route("/channel-io-managers")
116
  def get_managers():
 
117
  limit = request.args.get("limit")
118
  since = request.args.get("since")
119
+ channel_id = request.args.get("channelid", CHANNEL_ID)
120
 
 
121
  params = {}
122
  if limit:
123
  params["limit"] = limit
124
  if since:
125
  params["since"] = since
126
+
127
+ url = f"https://desk-api.channel.io/desk/channels/{channel_id}/managers"
128
+
 
 
 
 
 
129
  headers = {
130
  "accept": "application/json",
131
+ "x-account": os.getenv("channeliotokenmain"),
132
  }
133
 
134
+ res = requests.get(url, headers=headers, params=params)
 
 
135
  if res.status_code != 200:
136
  return jsonify({"error": res.text}), res.status_code
137
 
138
+ return jsonify(res.json().get("managers", []))
139
 
 
 
140
 
141
+ @app.route("/cors-proxy", methods=["GET", "POST", "PATCH", "OPTIONS"])
142
+ def cors_proxy():
143
  url = request.args.get("url")
144
  if not url:
145
  return "url パラメータが必要です", 400
146
 
147
+ if not url.startswith(("http://", "https://")):
148
+ return "http / https のURLのみ使用できます", 400
149
 
150
  try:
151
+ resp = requests.request(
152
+ method=request.method,
153
+ url=url,
154
+ headers={k: v for k, v in request.headers if k.lower() != "host"},
155
+ data=request.get_data(),
156
+ timeout=60,
157
+ )
158
 
 
159
  response = Response(resp.content, resp.status_code)
160
 
 
161
  response.headers["Access-Control-Allow-Origin"] = "*"
162
  response.headers["Access-Control-Allow-Headers"] = "*"
163
+ response.headers["Access-Control-Allow-Methods"] = "GET, POST, PATCH, OPTIONS"
164
 
 
165
  if "Content-Type" in resp.headers:
166
  response.headers["Content-Type"] = resp.headers["Content-Type"]
167
 
 
171
  return f"エラー: {str(e)}", 500
172
 
173
 
174
+ # =========================
175
+ # エントリーポイント
176
+ # =========================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  if __name__ == "__main__":
178
+ # Flask debug の二重起動防止
179
+ if os.environ.get("WERKZEUG_RUN_MAIN") == "true" or not app.debug:
180
+ watcher = threading.Thread(
181
+ target=watch_channel_messages,
182
+ daemon=True,
183
+ name="ChannelWatcher",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  )
185
+ watcher.start()
 
 
 
 
 
 
186
 
187
+ print("▶ Flask server starting")
188
+ app.run(debug=True, host="0.0.0.0", port=7860)