Nyanpre commited on
Commit
0df88db
·
verified ·
1 Parent(s): 0c9855c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +228 -33
app.py CHANGED
@@ -1,158 +1,353 @@
1
  import gradio as gr
 
2
  import random
3
- import uuid
4
  from datetime import datetime, timedelta, timezone
5
 
 
 
6
  # 12名の聖職者リスト
 
7
  members = ["かほ", "さや", "こず", "るり", "めぐ", "つづ", "ぎん", "すず", "ひめ", "せら", "いず", "さち"]
8
 
 
 
9
  def get_personal_daily_oracle(device_id):
10
- # device_id が空(JS失敗時など)の場合は、その場しのぎのランダムIDを生成
11
- # これにより「全員同じ」になる事態を物理的に防ぎます
12
- if not device_id:
13
- seed_base = str(uuid.uuid4())
14
- else:
15
- seed_base = device_id
16
-
17
  jst = timezone(timedelta(hours=9))
 
18
  today_str = datetime.now(jst).strftime("%Y-%m-%d")
 
19
 
20
- # デバイスIDと日付を組み合わせてシードを固定
21
  random.seed(f"{seed_base}_{today_str}")
 
22
 
 
23
  selected = random.sample(members, 2)
 
24
  random.shuffle(selected)
 
25
  pair_name = f"{selected[0]}{selected[1]}"
 
26
 
 
27
  oracle_html = (
 
28
  f"<div id='pair-raw' style='display:none;'>{pair_name}</div>"
 
29
  f"<div style='font-size: 38px; font-weight: normal; margin-bottom: 2px;'>本日の神託</div>"
 
30
  f"<div style='font-size: 52px; font-weight: 900; letter-spacing: 2px;'>{pair_name}</div>"
 
31
  )
 
32
  peace_msg = "これにより、不毛なカップリング論争は終結しました。"
 
33
 
 
34
  return oracle_html, peace_msg, gr.update(visible=True), gr.update(visible=True)
35
 
 
 
36
  # JS: 状態チェックと復元
 
37
  js_logic = """
 
38
  function(deviceId) {
 
39
  const lastDraw = localStorage.getItem('lastOracleDate');
 
40
  const lastPair = localStorage.getItem('lastPairText');
 
41
  const today = new Date().toLocaleDateString('ja-JP');
42
 
 
 
43
  if (lastDraw === today && lastPair) {
 
44
  alert("本日の神託は既に下されています。\\n明日の更新まで、今の思想を維持しなさい。");
 
45
  return [lastPair, "これにより、不毛なカップリング論争は終結しました。", { "visible": true, "__type__": "update" }, { "visible": true, "__type__": "update" }];
 
46
  }
 
47
 
 
48
  localStorage.setItem('lastOracleDate', today);
 
49
  return [null, null, null, null];
 
50
  }
 
51
  """
52
 
 
 
53
  # JS: 結果の保存
 
54
  js_save_result = """
55
- function(oracleHtml, peaceMsg, shareBtn, instructMsg) {
 
 
56
  if (oracleHtml && oracleHtml.includes("本日の神託")) {
 
57
  localStorage.setItem('lastPairText', oracleHtml);
 
58
  }
 
59
  }
 
60
  """
61
 
 
 
62
  # JS: Bluesky投稿
 
63
  js_share_bluesky = """
 
64
  function() {
 
65
  const pairRawEl = document.getElementById('pair-raw');
 
66
  let pairName = "";
 
 
 
67
  if (pairRawEl) {
 
68
  pairName = pairRawEl.innerText;
 
69
  } else {
 
70
  const lastPair = localStorage.getItem('lastPairText') || "";
 
71
  const match = lastPair.match(/>([^<]{4,})<\\/div>$/);
 
72
  pairName = match ? match[1] : "運命";
 
73
  }
 
 
 
74
  const currentUrl = window.location.href;
 
75
  const text = `私は「${pairName}」を信仰しています。\\n\\n蓮ノ空聖書正典:${currentUrl}`;
 
76
  const intentUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
 
77
  window.open(intentUrl, '_blank');
 
78
  }
 
79
  """
80
 
 
 
81
  custom_css = """
 
82
  .gradio-container { max-width: 600px !important; text-align: center !important; }
 
 
 
 
 
83
  .center-content {
 
84
  display: flex !important;
 
85
  flex-direction: column !important;
 
86
  align-items: center !important;
 
87
  padding-top: 40px !important;
 
88
  }
89
- h1 { margin-top: 0px !important; margin-bottom: -5px !important; font-size: 32px !important; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
90
  #doctrine {
91
- font-size: 1.5em !important; line-height: 1.4 !important; font-weight: bold !important;
92
- margin-bottom: -5px !important; text-align: center !important;
 
 
 
 
 
 
 
 
 
93
  }
 
 
 
 
 
94
  #oracle-box {
95
- color: #000 !important; background: #fff !important; border: 4px solid #000 !important;
96
- padding: 25px 10px !important; line-height: 1.1 !important; min-height: 130px !important;
97
- display: flex !important; flex-direction: column !important; justify-content: center !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  margin: 0px auto -5px auto !important;
 
99
  }
 
 
 
 
 
100
  #peace-msg {
101
- font-size: 20px !important; font-weight: bold !important; color: #d63031 !important;
 
 
 
 
 
 
102
  margin: 0px auto -5px auto !important;
 
103
  }
 
 
 
 
 
104
  .action-btn {
105
- font-size: 26px !important; font-weight: bold !important; height: 70px !important;
106
- width: 320px !important; border: 2px solid #000 !important;
 
 
 
 
 
 
 
 
 
107
  }
 
 
 
108
  #draw-btn { margin: 0px auto -5px auto !important; }
109
- #share-btn { margin: 0px auto -5px auto !important; }
110
- #instruct-msg {
111
- font-size: 18px !important; font-weight: bold !important; color: #000 !important;
112
- margin: 10px auto !important; background: transparent !important; border: none !important;
113
- }
114
  """
115
 
 
 
116
  with gr.Blocks(title="蓮ノ空聖書正典", css=custom_css, theme=gr.themes.Monochrome()) as demo:
117
- # デバイスIDを保持する非表示のテキストボックス
118
- device_id_val = gr.Textbox(visible=False)
119
 
120
- # ページ読み込み時にJSでIDを取得して device_id_val にセットする
121
- demo.load(None, None, device_id_val, js="""
 
 
 
 
122
  () => {
 
123
  let id = localStorage.getItem('cp_oracle_device_id');
 
124
  if(!id) {
125
- id = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);
 
 
126
  localStorage.setItem('cp_oracle_device_id', id);
 
127
  }
 
128
  return id;
 
129
  }
 
130
  """)
131
 
 
 
132
  with gr.Column(elem_classes="center-content"):
 
133
  gr.Markdown("# ⚖️ 蓮ノ空聖書正典")
 
 
 
134
  gr.Markdown("日付が変わるまであなたの思想は<br>統一されます。", elem_id="doctrine")
 
135
 
 
136
  result_display = gr.HTML(elem_id="oracle-box", visible=False)
 
137
  peace_display = gr.Markdown(elem_id="peace-msg")
 
138
 
 
139
  draw_btn = gr.Button("神託を受ける", variant="primary", elem_id="draw-btn", elem_classes="action-btn")
 
140
  share_btn = gr.Button("信仰を広める", variant="secondary", elem_id="share-btn", elem_classes="action-btn", visible=False)
141
- instruct_msg = gr.HTML("画像を添えて<br>その導きを世界へ示しなさい。", elem_id="instruct-msg", visible=False)
 
142
 
143
  draw_btn.click(
 
144
  fn=get_personal_daily_oracle,
145
- inputs=[device_id_val],
146
- outputs=[result_display, peace_display, share_btn, instruct_msg],
 
 
 
147
  js=js_logic
 
148
  ).then(
 
149
  fn=None,
150
- inputs=[result_display, peace_display, share_btn, instruct_msg],
 
 
151
  outputs=None,
 
152
  js=js_save_result
 
153
  )
154
 
 
 
155
  share_btn.click(fn=None, inputs=None, outputs=None, js=js_share_bluesky)
156
 
 
 
157
  if __name__ == "__main__":
 
158
  demo.launch()
 
1
  import gradio as gr
2
+
3
  import random
4
+
5
  from datetime import datetime, timedelta, timezone
6
 
7
+
8
+
9
  # 12名の聖職者リスト
10
+
11
  members = ["かほ", "さや", "こず", "るり", "めぐ", "つづ", "ぎん", "すず", "ひめ", "せら", "いず", "さち"]
12
 
13
+
14
+
15
  def get_personal_daily_oracle(device_id):
16
+
17
+ seed_base = device_id if device_id else "default_fate"
18
+
 
 
 
 
19
  jst = timezone(timedelta(hours=9))
20
+
21
  today_str = datetime.now(jst).strftime("%Y-%m-%d")
22
+
23
 
24
+
25
  random.seed(f"{seed_base}_{today_str}")
26
+
27
 
28
+
29
  selected = random.sample(members, 2)
30
+
31
  random.shuffle(selected)
32
+
33
  pair_name = f"{selected[0]}{selected[1]}"
34
+
35
 
36
+
37
  oracle_html = (
38
+
39
  f"<div id='pair-raw' style='display:none;'>{pair_name}</div>"
40
+
41
  f"<div style='font-size: 38px; font-weight: normal; margin-bottom: 2px;'>本日の神託</div>"
42
+
43
  f"<div style='font-size: 52px; font-weight: 900; letter-spacing: 2px;'>{pair_name}</div>"
44
+
45
  )
46
+
47
  peace_msg = "これにより、不毛なカップリング論争は終結しました。"
48
+
49
 
50
+
51
  return oracle_html, peace_msg, gr.update(visible=True), gr.update(visible=True)
52
 
53
+
54
+
55
  # JS: 状態チェックと復元
56
+
57
  js_logic = """
58
+
59
  function(deviceId) {
60
+
61
  const lastDraw = localStorage.getItem('lastOracleDate');
62
+
63
  const lastPair = localStorage.getItem('lastPairText');
64
+
65
  const today = new Date().toLocaleDateString('ja-JP');
66
 
67
+
68
+
69
  if (lastDraw === today && lastPair) {
70
+
71
  alert("本日の神託は既に下されています。\\n明日の更新まで、今の思想を維持しなさい。");
72
+
73
  return [lastPair, "これにより、不毛なカップリング論争は終結しました。", { "visible": true, "__type__": "update" }, { "visible": true, "__type__": "update" }];
74
+
75
  }
76
+
77
 
78
+
79
  localStorage.setItem('lastOracleDate', today);
80
+
81
  return [null, null, null, null];
82
+
83
  }
84
+
85
  """
86
 
87
+
88
+
89
  # JS: 結果の保存
90
+
91
  js_save_result = """
92
+
93
+ function(oracleHtml, peaceMsg, shareBtn, resultBox) {
94
+
95
  if (oracleHtml && oracleHtml.includes("本日の神託")) {
96
+
97
  localStorage.setItem('lastPairText', oracleHtml);
98
+
99
  }
100
+
101
  }
102
+
103
  """
104
 
105
+
106
+
107
  # JS: Bluesky投稿
108
+
109
  js_share_bluesky = """
110
+
111
  function() {
112
+
113
  const pairRawEl = document.getElementById('pair-raw');
114
+
115
  let pairName = "";
116
+
117
+
118
+
119
  if (pairRawEl) {
120
+
121
  pairName = pairRawEl.innerText;
122
+
123
  } else {
124
+
125
  const lastPair = localStorage.getItem('lastPairText') || "";
126
+
127
  const match = lastPair.match(/>([^<]{4,})<\\/div>$/);
128
+
129
  pairName = match ? match[1] : "運命";
130
+
131
  }
132
+
133
+
134
+
135
  const currentUrl = window.location.href;
136
+
137
  const text = `私は「${pairName}」を信仰しています。\\n\\n蓮ノ空聖書正典:${currentUrl}`;
138
+
139
  const intentUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
140
+
141
  window.open(intentUrl, '_blank');
142
+
143
  }
144
+
145
  """
146
 
147
+
148
+
149
  custom_css = """
150
+
151
  .gradio-container { max-width: 600px !important; text-align: center !important; }
152
+
153
+
154
+
155
+ /* 1. 最上部の空白を40pxに設定 */
156
+
157
  .center-content {
158
+
159
  display: flex !important;
160
+
161
  flex-direction: column !important;
162
+
163
  align-items: center !important;
164
+
165
  padding-top: 40px !important;
166
+
167
  }
168
+
169
+
170
+
171
+ /* 2. タイトルと教義の間を-5px */
172
+
173
+ h1 {
174
+
175
+ margin-top: 0px !important;
176
+
177
+ margin-bottom: -5px !important;
178
+
179
+ font-size: 32px !important;
180
+
181
+ }
182
+
183
+
184
+
185
+ /* 3. 教義と結果の間を-5px */
186
+
187
  #doctrine {
188
+
189
+ font-size: 1.5em !important;
190
+
191
+ line-height: 1.4 !important;
192
+
193
+ font-weight: bold !important;
194
+
195
+ margin-bottom: -5px !important;
196
+
197
+ text-align: center !important;
198
+
199
  }
200
+
201
+
202
+
203
+ /* 4. 結果ボックスと終結文の間を-5px */
204
+
205
  #oracle-box {
206
+
207
+ color: #000 !important;
208
+
209
+ background: #fff !important;
210
+
211
+ border: 4px solid #000 !important;
212
+
213
+ padding: 25px 10px !important;
214
+
215
+ line-height: 1.1 !important;
216
+
217
+ min-height: 130px !important;
218
+
219
+ display: flex !important;
220
+
221
+ flex-direction: column !important;
222
+
223
+ justify-content: center !important;
224
+
225
  margin: 0px auto -5px auto !important;
226
+
227
  }
228
+
229
+
230
+
231
+ /* 5. 終結文とボタンの間を-5px */
232
+
233
  #peace-msg {
234
+
235
+ font-size: 20px !important;
236
+
237
+ font-weight: bold !important;
238
+
239
+ color: #d63031 !important;
240
+
241
  margin: 0px auto -5px auto !important;
242
+
243
  }
244
+
245
+
246
+
247
+ /* 6. ボタン同士の間を-5px */
248
+
249
  .action-btn {
250
+
251
+ font-size: 26px !important;
252
+
253
+ font-weight: bold !important;
254
+
255
+ height: 70px !important;
256
+
257
+ width: 320px !important;
258
+
259
+ border: 2px solid #000 !important;
260
+
261
  }
262
+
263
+
264
+
265
  #draw-btn { margin: 0px auto -5px auto !important; }
266
+
267
+ #share-btn { margin: 0px auto 10px auto !important; }
268
+
 
 
269
  """
270
 
271
+
272
+
273
  with gr.Blocks(title="蓮ノ空聖書正典", css=custom_css, theme=gr.themes.Monochrome()) as demo:
 
 
274
 
275
+ device_id_storage = gr.State()
276
+
277
+
278
+
279
+ demo.load(None, None, device_id_storage, js="""
280
+
281
  () => {
282
+
283
  let id = localStorage.getItem('cp_oracle_device_id');
284
+
285
  if(!id) {
286
+
287
+ id = Math.random().toString(36).substring(2, 15);
288
+
289
  localStorage.setItem('cp_oracle_device_id', id);
290
+
291
  }
292
+
293
  return id;
294
+
295
  }
296
+
297
  """)
298
 
299
+
300
+
301
  with gr.Column(elem_classes="center-content"):
302
+
303
  gr.Markdown("# ⚖️ 蓮ノ空聖書正典")
304
+
305
+
306
+
307
  gr.Markdown("日付が変わるまであなたの思想は<br>統一されます。", elem_id="doctrine")
308
+
309
 
310
+
311
  result_display = gr.HTML(elem_id="oracle-box", visible=False)
312
+
313
  peace_display = gr.Markdown(elem_id="peace-msg")
314
+
315
 
316
+
317
  draw_btn = gr.Button("神託を受ける", variant="primary", elem_id="draw-btn", elem_classes="action-btn")
318
+
319
  share_btn = gr.Button("信仰を広める", variant="secondary", elem_id="share-btn", elem_classes="action-btn", visible=False)
320
+
321
+
322
 
323
  draw_btn.click(
324
+
325
  fn=get_personal_daily_oracle,
326
+
327
+ inputs=[device_id_storage],
328
+
329
+ outputs=[result_display, peace_display, share_btn, result_display],
330
+
331
  js=js_logic
332
+
333
  ).then(
334
+
335
  fn=None,
336
+
337
+ inputs=[result_display, peace_display, share_btn, result_display],
338
+
339
  outputs=None,
340
+
341
  js=js_save_result
342
+
343
  )
344
 
345
+
346
+
347
  share_btn.click(fn=None, inputs=None, outputs=None, js=js_share_bluesky)
348
 
349
+
350
+
351
  if __name__ == "__main__":
352
+
353
  demo.launch()