| from flask import Flask, request, jsonify, make_response, render_template_string, send_from_directory |
| import random |
| import string |
| import json |
|
|
| app = Flask(__name__, static_folder='dist') |
|
|
| def generate_random_id(): |
| chars = string.ascii_lowercase + string.digits |
| return ''.join(random.choices(chars, k=5)) |
|
|
| |
| @app.after_request |
| def add_cors_headers(response): |
| origin = request.headers.get('Origin') |
| if origin: |
| response.headers['Access-Control-Allow-Origin'] = origin |
| response.headers['Access-Control-Allow-Credentials'] = 'true' |
| response.headers['Access-Control-Allow-Headers'] = 'Content-Type' |
| return response |
|
|
|
|
| @app.route('/') |
| def index(): |
| id_list = request.cookies.get('ids') |
| ids = json.loads(id_list) if id_list else [] |
|
|
| html = ''' |
| <!DOCTYPE html> |
| <html lang="ja"> |
| <head> |
| <meta charset="UTF-8"> |
| <title>IDリスト</title> |
| </head> |
| <body> |
| <h1>IDリスト</h1> |
| <ul> |
| {% for id in ids %} |
| <li> |
| {{ id }} |
| <button onclick="copyToClipboard('{{ id }}')">コピー</button> |
| <form method="post" action="/delete" style="display:inline;"> |
| <input type="hidden" name="id" value="{{ id }}"> |
| <button type="submit">削除</button> |
| </form> |
| </li> |
| {% endfor %} |
| </ul> |
| |
| <form method="post" action="/add"> |
| <button type="submit">IDを追加</button> |
| </form> |
| |
| <a href="/eruda.js">/eruda.js</a> |
| <script src="/eruda.js"></script> |
| <script>eruda.init();</script> |
| |
| <hr> |
| <h2>getid のデータ</h2> |
| <pre id="id-data">ここにデータが表示されます</pre> |
| |
| <button onclick="updateServiceWorker()">getid のサービスワーカーを設定・更新</button> |
| <button onclick="loadGetID()">getid を取得</button> |
| |
| <script> |
| function copyToClipboard(text) { |
| navigator.clipboard.writeText(text).then(() => { |
| alert('コピーしました: ' + text); |
| }).catch(() => { |
| alert('コピーに失敗しました'); |
| }); |
| } |
| |
| async function updateServiceWorker() { |
| if ('serviceWorker' in navigator) { |
| try { |
| await navigator.serviceWorker.register('/service-worker.js'); |
| alert("サービスワーカーを登録しました。"); |
| } catch (e) { |
| console.error("サービスワーカーの登録に失敗しました:", e); |
| } |
| } else { |
| alert("このブラウザはサービスワーカーに対応していません。"); |
| } |
| } |
| |
| async function loadGetID() { |
| try { |
| const res = await fetch('/getid'); |
| const data = await res.json(); |
| document.getElementById('id-data').textContent = JSON.stringify(data, null, 2); |
| } catch (e) { |
| console.error("データの取得に失敗しました:", e); |
| document.getElementById('id-data').textContent = "取得に失敗しました"; |
| } |
| } |
| </script> |
| </body> |
| </html> |
| ''' |
| return render_template_string(html, ids=ids) |
|
|
| @app.route("/load.js") |
| def load_js(): |
| js_code = """ |
| (async () => { |
| const script = document.currentScript; |
| if (!script) { |
| console.error('currentScriptが取得できませんでした。'); |
| return; |
| } |
| |
| const debugMode = script.getAttribute('debug') === 'alert'; |
| const activeValue = script.getAttribute('active'); |
| if (!activeValue) { |
| console.log('active属性が見つかりません。処理を終了します。'); |
| return; |
| } |
| |
| const ids = activeValue.trim().split(/\\s+/).filter(id => /^[a-zA-Z0-9]{5}$/.test(id)); |
| if (ids.length === 0) { |
| console.warn('active属性に5桁の番号または文字列が見つかりません。処理を終了します。'); |
| return; |
| } |
| |
| try { |
| const url = 'https://soiz1-eruda3.hf.space/getid'; |
| const res = await fetch(url, { method: 'GET', credentials: 'include' }); |
| |
| if (!res.ok) { |
| const msg = `Fetchエラー: ステータス ${res.status} ${res.statusText}`; |
| console.error(msg); |
| if (debugMode) alert(msg); |
| return; |
| } |
| |
| const data = await res.json(); |
| |
| console.log('fetchレスポンス:', data); |
| if (debugMode) alert(`fetchレスポンス:\\n${JSON.stringify(data)}`); |
| |
| if (!Array.isArray(data)) { |
| const msg = 'fetchレスポンスが配列ではありません。認証失敗とみなします。'; |
| console.error(msg); |
| if (debugMode) alert(msg); |
| return; |
| } |
| |
| const hasAuthorized = ids.some(id => data.includes(id)); |
| |
| if (hasAuthorized) { |
| const msg = '認証成功: 対象IDがfetchレスポンスに含まれています。runeruda()を実行します。'; |
| console.log(msg); |
| if (debugMode) alert(msg); |
| runeruda(); |
| } else { |
| const msg = '認証失敗: 対象IDがfetchレスポンスに含まれていません。'; |
| console.warn(msg); |
| if (debugMode) alert(msg); |
| } |
| |
| } catch (err) { |
| const msg = `例外発生: ${err.message}`; |
| console.error(msg, err); |
| if (debugMode) alert(msg); |
| } |
| })(); |
| """ |
| return Response(js_code, mimetype='application/javascript') |
|
|
| @app.route('/add', methods=['POST']) |
| def add_id(): |
| id_list = request.cookies.get('ids') |
| ids = json.loads(id_list) if id_list else [] |
| new_id = generate_random_id() |
| ids.append(new_id) |
| resp = make_response('', 303) |
| resp.headers['Location'] = '/' |
| resp.set_cookie( |
| 'ids', |
| json.dumps(ids), |
| samesite='None', |
| secure=True |
| ) |
| return resp |
|
|
| @app.route('/delete', methods=['POST']) |
| def delete_id(): |
| id_to_delete = request.form.get('id') |
| id_list = request.cookies.get('ids') |
| ids = json.loads(id_list) if id_list else [] |
| if id_to_delete in ids: |
| ids.remove(id_to_delete) |
| resp = make_response('', 303) |
| resp.headers['Location'] = '/' |
| resp.set_cookie( |
| 'ids', |
| json.dumps(ids), |
| samesite='None', |
| secure=True |
| ) |
| return resp |
|
|
| @app.route('/getid') |
| def get_ids(): |
| id_list = request.cookies.get('ids') |
| ids = json.loads(id_list) if id_list else [] |
| return jsonify(ids) |
|
|
| @app.route('/service-worker.js') |
| def service_worker(): |
| response = make_response(send_from_directory('.', 'service-worker.js')) |
| response.headers['Content-Type'] = 'application/javascript' |
| return response |
|
|
| @app.route('/<path:filename>') |
| def serve_static(filename): |
| return send_from_directory(app.static_folder, filename) |
|
|
| if __name__ == '__main__': |
| app.run(host='0.0.0.0', port=7860, debug=True) |
|
|