Nyanpre commited on
Commit
65aa626
·
verified ·
1 Parent(s): 37f4c73

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -75
app.py CHANGED
@@ -1,84 +1,125 @@
1
- import gradio as gr
2
- import random
3
- from datetime import datetime, timedelta, timezone
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
5
- # --- 1. 定数と設定 ---
6
- GITHUB_PAGES_URL = "https://rairaff8-source.github.io/hasu-cp-ogp/"
7
- members = ["かほ", "さや", "こず", "るり", "めぐ", "つづ", "ぎん", "すず", "ひめ", "せら", "いず", "さち"]
8
 
9
- # --- 2. シェアテキスト生成ロジック ---
10
- js_get_share_text = f"""
11
- function() {{
12
- const pairRawEl = document.getElementById('pair-raw');
13
- let pairName = "";
14
- if (pairRawEl) {{
15
- pairName = pairRawEl.innerText;
16
- }} else {{
17
- const lastPair = localStorage.getItem('lastPairText') || "";
18
- const match = lastPair.match(/>([^<]{{2,}})<\\/div>$/);
19
- pairName = match ? match[1] : "運命";
20
- }}
21
- const shareUrl = "{GITHUB_PAGES_URL}" + encodeURIComponent(pairName) + ".html";
22
- return "私は「" + pairName + "」を信仰しています。\\n\\n蓮ノ空聖書正典:\\n" + shareUrl;
23
- }}
24
- """
25
 
26
- js_share_bluesky = f"function() {{ const text = ({js_get_share_text})(); window.open(`https://bsky.app/intent/compose?text=${{encodeURIComponent(text)}}`, '_blank'); }}"
27
- js_share_x = f"function() {{ const text = ({js_get_share_text})(); window.open(`https://twitter.com/intent/tweet?text=${{encodeURIComponent(text)}}`, '_blank'); }}"
 
 
 
28
 
29
- # --- 3. Python ロジック ---
30
- def get_personal_daily_oracle(device_id):
31
- seed_base = device_id if device_id else "default_fate"
32
- jst = timezone(timedelta(hours=9))
33
- today_str = datetime.now(jst).strftime("%Y-%m-%d")
34
- random.seed(f"{seed_base}_{today_str}")
35
- selected = random.sample(members, 2)
36
- random.shuffle(selected)
37
- pair_name = f"{selected[0]}{selected[1]}"
38
- oracle_html = (
39
- f"<div id='pair-raw' style='display:none;'>{pair_name}</div>"
40
- f"<div style='font-size: 38px; font-weight: normal; margin-bottom: 2px;'>本日の神託</div>"
41
- f"<div style='font-size: 52px; font-weight: 900; letter-spacing: 2px;'>{pair_name}</div>"
42
- )
43
- peace_msg = "これにより、不毛なカップリング論争は終結しました。"
44
- return oracle_html, peace_msg, gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)
45
 
46
- # --- 4. フロントエンド (Gradio UI) ---
47
- custom_css = """
48
- .gradio-container { max-width: 600px !important; text-align: center !important; }
49
- .center-content { display: flex !important; flex-direction: column !important; align-items: center !important; padding-top: 45px !important; }
50
- #oracle-box {
51
- color: #000 !important; background: #fff !important; border: 4px solid #000 !important;
52
- padding: 25px 10px !important; line-height: 1.1 !important; min-height: 130px !important;
53
- display: flex !important; flex-direction: column !important; justify-content: center !important;
54
- margin: 0px auto -5px auto !important;
55
- }
56
- .action-btn { font-size: 24px !important; font-weight: bold !important; width: 320px !important; border: 2px solid #000 !important; }
57
- """
58
 
59
- # title 以外はここでは指定せず、launch() に移動させました
60
- with gr.Blocks(title="蓮ノ空聖書正典") as demo:
61
- device_id_storage = gr.Textbox(visible=False)
62
- demo.load(None, None, device_id_storage, js="() => localStorage.getItem('cp_oracle_device_id') || '' ")
 
 
63
 
64
- with gr.Column(elem_classes="center-content"):
65
- gr.Markdown("# ⚖️ 蓮ノ空聖書正典")
66
- result_display = gr.HTML(elem_id="oracle-box", visible=False)
67
- peace_display = gr.Markdown("")
68
- draw_btn = gr.Button("神託を受ける", variant="primary", elem_classes="action-btn")
69
- share_btn_x = gr.Button("Xで信仰を広める", visible=False)
70
- share_btn_bsky = gr.Button("Blueskyで信仰を広める", visible=False)
71
 
72
- # --- Hugging Faceの app.py 125行目付近 ---
73
- draw_btn.click(
74
- fn=get_personal_daily_oracle,
75
- inputs=[device_id_storage],
76
- outputs=[result_display, peace_display, share_btn_bsky, share_btn_x, result_display],
77
- api_name="get_oracle" # ← ここにカンマとこれを追加!
78
- ) # ← 閉じカッコ
79
- share_btn_bsky.click(fn=None, js=js_share_bluesky)
80
- share_btn_x.click(fn=None, js=js_share_x)
81
 
82
- if __name__ == "__main__":
83
- # css theme はここで指定します。api_open は削除しました。
84
- demo.launch(css=custom_css, theme=gr.themes.Monochrome())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="ja">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>蓮ノ空聖書正典 (Dev)</title>
7
+ <style>
8
+ body {
9
+ background-color: white; color: black; font-family: 'Helvetica Neue', Arial, sans-serif;
10
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
11
+ min-height: 100vh; margin: 0; text-align: center;
12
+ }
13
+ .container { max-width: 600px; padding: 20px; }
14
+ h1 { font-size: 32px; margin-bottom: 0; }
15
+ .subtitle { font-size: 1.2em; font-weight: bold; margin-bottom: 30px; }
16
+ #oracle-box {
17
+ display: none; border: 4px solid black; padding: 30px; margin: 20px 0;
18
+ background: white; min-width: 300px;
19
+ }
20
+ .oracle-label { font-size: 24px; margin-bottom: 10px; }
21
+ .pair-name { font-size: 52px; font-weight: 900; letter-spacing: 2px; }
22
+ .peace-msg { color: #d63031; font-weight: bold; font-size: 1.2em; margin-top: 20px; }
23
+ .btn {
24
+ background: white; border: 2px solid black; padding: 15px 30px;
25
+ font-size: 20px; font-weight: bold; cursor: pointer; margin: 10px;
26
+ width: 280px; transition: 0.2s;
27
+ }
28
+ .btn:hover { background: #eee; }
29
+ .btn-primary { background: black; color: white; height: 70px; font-size: 24px; }
30
+ .share-area { display: none; margin-top: 20px; }
31
+ </style>
32
+ </head>
33
+ <body>
34
+ <div class="container">
35
+ <h1>⚖️ 蓮ノ空聖書正典</h1>
36
+ <p class="subtitle">日付が変わるまであなたの思想は<br>統一されます。</p>
37
 
38
+ <button id="draw-btn" class="btn btn-primary" onclick="getOracle()">神託を受ける</button>
 
 
39
 
40
+ <div id="oracle-box">
41
+ <div class="oracle-label">本日の神託</div>
42
+ <div id="pair-display" class="pair-name"></div>
43
+ <div class="peace-msg">これにより、不毛なカップリング論争は終結しました。</div>
44
+ </div>
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ <div id="share-area" class="share-area">
47
+ <button class="btn" onclick="shareSNS('bsky')">Blueskyで信仰を広める</button><br>
48
+ <button class="btn" onclick="shareSNS('x')">Xで信仰を広める</button>
49
+ </div>
50
+ </div>
51
 
52
+ <script>
53
+ const HF_URL = "https://nyanpre-cp-oracle-dev.hf.space";
54
+ const GITHUB_URL = window.location.origin + window.location.pathname.split('/').slice(0, -1).join('/') + '/';
55
+ let currentPair = "";
 
 
 
 
 
 
 
 
 
 
 
 
56
 
57
+ // この名前が HTML onclick="getOracle()" と対応します
58
+ async function getOracle() {
59
+ console.log("Starting getOracle..."); // ログ出力
60
+ const btn = document.getElementById('draw-btn');
61
+ btn.innerText = "交信中...";
62
+ btn.disabled = true;
 
 
 
 
 
 
63
 
64
+ try {
65
+ let deviceId = localStorage.getItem('cp_oracle_device_id');
66
+ if(!deviceId) {
67
+ deviceId = Math.random().toString(36).substring(2, 15);
68
+ localStorage.setItem('cp_oracle_device_id', deviceId);
69
+ }
70
 
71
+ // 1. 実行リクエスト (POST)
72
+ const response = await fetch(`${HF_URL}/call/get_oracle`, {
73
+ method: "POST",
74
+ headers: { "Content-Type": "application/json" },
75
+ body: JSON.stringify({ data: [deviceId] })
76
+ });
 
77
 
78
+ if (!response.ok) throw new Error('POST request failed');
79
+ const { event_id } = await response.json();
 
 
 
 
 
 
 
80
 
81
+ // 2. 結果取得 (GET)
82
+ const resultResponse = await fetch(`${HF_URL}/call/get_oracle/${event_id}`);
83
+ const resultText = await resultResponse.text();
84
+
85
+ const lines = resultText.split('\n');
86
+ let resultData = null;
87
+ for (const line of lines) {
88
+ if (line.startsWith('data: ')) {
89
+ resultData = JSON.parse(line.substring(6));
90
+ break;
91
+ }
92
+ }
93
+
94
+ if (!resultData) throw new Error("No data received from HF");
95
+
96
+ const htmlString = resultData[0];
97
+ const match = htmlString.match(/letter-spacing: 2px;'>([^<]+)<\/div>/);
98
+ currentPair = match ? match[1] : "運命";
99
+
100
+ document.getElementById('pair-display').innerText = currentPair;
101
+ document.getElementById('oracle-box').style.display = 'block';
102
+ document.getElementById('share-area').style.display = 'block';
103
+ btn.style.display = 'none';
104
+
105
+ } catch (e) {
106
+ console.error("Critical Error:", e);
107
+ alert("神との交信に失敗しました。詳細はコンソールを確認してください。");
108
+ btn.innerText = "神託を受ける";
109
+ btn.disabled = false;
110
+ }
111
+ }
112
+
113
+ function shareSNS(platform) {
114
+ const shareUrl = `${GITHUB_URL}${encodeURIComponent(currentPair)}.html`;
115
+ const text = `私は「${currentPair}」を信仰しています。\n\n蓮ノ空聖書正典:\n${shareUrl}`;
116
+
117
+ if (platform === 'bsky') {
118
+ window.open(`https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`, '_blank');
119
+ } else {
120
+ window.open(`https://twitter.com/intent/tweet?text=${encodeURIComponent(text)}`, '_blank');
121
+ }
122
+ }
123
+ </script>
124
+ </body>
125
+ </html>