Nyanpre commited on
Commit
3c49cd3
·
verified ·
1 Parent(s): c8fc647

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +37 -84
app.py CHANGED
@@ -4,39 +4,30 @@ from datetime import datetime, timedelta, timezone
4
  from PIL import Image, ImageDraw, ImageFont
5
  import io
6
 
 
7
  members = ["かほ", "さや", "こず", "るり", "めぐ", "つづ", "ぎん", "すず", "ひめ", "せら", "いず", "さち"]
8
 
9
- # 都度フォントを読み込む負荷を避けるため、グローバで保持
10
  try:
11
- # 適切な日本語フォントのパスを指定してください(例: NotoSansJP)
12
  font_path = "/usr/share/fonts/truetype/noto/NotoSansJP-Regular.otf"
13
- font_title = ImageFont.truetype(font_path, 32)
14
- font_pair = ImageFont.truetype(font_path, 54)
15
  except:
16
- # フォントが見つからない場合のフォールバック
17
  font_title = ImageFont.load_default()
18
  font_pair = ImageFont.load_default()
19
 
20
  def generate_oracle_image(pair_name):
21
- """
22
- ペア名から神託画像を生成し、PIL Imageオブジェクトとして返す。
23
- Pillowによる描画は非常に高速で、サーバー負荷は軽微です。
24
- """
25
- # 画像作成 (OGPを意識した1200x630サイズ、白背景)
26
- img = Image.new('RGB', (1200, 630), color=(255, 255, 255))
27
  d = ImageDraw.Draw(img)
28
-
29
- # 枠線
30
- d.rectangle([20, 20, 1180, 610], outline=(0, 0, 0), width=10)
31
-
32
- # テキスト描画(中央揃え)
33
- d.text((600, 220), "本日の神託", fill=(0, 0, 0), font=font_title, anchor="mm")
34
- d.text((600, 380), pair_name, fill=(0, 0, 0), font=font_pair, anchor="mm")
35
-
36
  return img
37
 
38
  def get_personal_daily_oracle(device_id):
39
- # IDがない場合は一時的なものを使用
40
  seed_base = device_id if device_id else str(random.random())
41
  jst = timezone(timedelta(hours=9))
42
  today_str = datetime.now(jst).strftime("%Y-%m-%d")
@@ -47,59 +38,35 @@ def get_personal_daily_oracle(device_id):
47
  random.shuffle(selected)
48
  pair_name = f"{selected[0]}{selected[1]}"
49
 
50
- oracle_html = (
51
- f"<div id='pair-raw' style='display:none;'>{pair_name}</div>"
52
- f"<div style='font-size: 38px; font-weight: normal; margin-bottom: 2px;'>本日の神託</div>"
53
- f"<div style='font-size: 52px; font-weight: 900; letter-spacing: 2px;'>{pair_name}</div>"
54
- )
55
-
56
- # 画像をその場で生成
57
  img_result = generate_oracle_image(pair_name)
58
 
59
- # [神託HTML, メッセージ, ボタン表示, 枠表示, 画像データ]
60
- return oracle_html, "これにより、不毛なカップリング論争は終結しました。", gr.update(visible=True), gr.update(visible=True), img_result
 
 
61
 
62
- # JS: 状態チェックと復元
63
  js_logic = """
64
  function(deviceId) {
65
  const lastDraw = localStorage.getItem('lastOracleDate');
66
- const lastPair = localStorage.getItem('lastPairText');
67
  const today = new Date().toLocaleDateString('ja-JP');
68
 
69
- if (lastDraw === today && lastPair) {
70
  alert("本日の神託は既に下されています。\\n明日の更新まで、今の思想を維持しなさい。");
71
- # 2回目以降は画像出力をnullにする(負荷ゼロ)
72
- return [lastPair, "れにより、不毛なカップリング論争終結しました。", { "visible": true, "__type__": "update" }, { "visible": true, "__type__": "update" }, null];
73
  }
74
-
75
  localStorage.setItem('lastOracleDate', today);
76
  return [null, null, null, null, null];
77
  }
78
  """
79
 
80
- # JS: 結果の保存
81
- js_save_result = """
82
- function(oracleHtml, peaceMsg, shareBtn, resultBox, img) {
83
- if (oracleHtml && oracleHtml.includes("本日の神託")) {
84
- localStorage.setItem('lastPairText', oracleHtml);
85
- }
86
- }
87
- """
88
-
89
- # JS: Bluesky投稿
90
  js_share_bluesky = """
91
  function() {
92
  const pairRawEl = document.getElementById('pair-raw');
93
- let pairName = "";
94
-
95
- if (pairRawEl) {
96
- pairName = pairRawEl.innerText;
97
- } else {
98
- const lastPair = localStorage.getItem('lastPairText') || "";
99
- const match = lastPair.match(/>([^<]{4,})<\\/div>$/);
100
- pairName = match ? match[1] : "運命";
101
- }
102
-
103
  const currentUrl = window.location.href;
104
  const text = `私は「${pairName}」を信仰しています。\\n\\n画像(神託の証)を保存して投稿に添付しなさい。\\n\\n蓮ノ空聖書正典:${currentUrl}`;
105
  const intentUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
@@ -110,17 +77,15 @@ function() {
110
  custom_css = """
111
  .gradio-container { max-width: 600px !important; text-align: center !important; }
112
 
113
- /* 最上部の空白 */
114
  .center-content {
115
  display: flex !important;
116
  flex-direction: column !important;
117
  align-items: center !important;
118
- padding-top: 35px !important;
119
  }
120
 
121
  h1 { margin-top: 0px !important; margin-bottom: -5px !important; font-size: 32px !important; }
122
 
123
- /* 教義 */
124
  #doctrine {
125
  font-size: 1.5em !important;
126
  line-height: 1.4 !important;
@@ -128,22 +93,16 @@ h1 { margin-top: 0px !important; margin-bottom: -5px !important; font-size: 32px
128
  margin-bottom: -5px !important;
129
  }
130
 
131
- /* 結果表示ボックス */
132
- #oracle-box {
133
- color: #000 !important;
134
- background: #fff !important;
135
- border: 4px solid #000 !important;
136
- padding: 25px 10px !important;
137
- line-height: 1.1 !important;
138
- min-height: 130px !important;
139
- display: flex !important;
140
- flex-direction: column !important;
141
- justify-content: center !important;
142
- margin: 0px auto -5px auto !important;
143
  }
144
-
145
- /* 生成された画像 */
146
- #result-img { max-width: 400px !important; margin: 10px auto -5px auto !important; border: 1px solid #ccc; }
147
 
148
  #peace-msg {
149
  font-size: 20px !important;
@@ -152,7 +111,6 @@ h1 { margin-top: 0px !important; margin-bottom: -5px !important; font-size: 32px
152
  margin: 0px auto -5px auto !important;
153
  }
154
 
155
- /* ボタン共通 */
156
  .action-btn {
157
  font-size: 26px !important;
158
  font-weight: bold !important;
@@ -183,10 +141,11 @@ with gr.Blocks(title="蓮ノ空聖書正典") as demo:
183
  gr.Markdown("# ⚖️ 蓮ノ空聖書正典")
184
  gr.Markdown("日付が変わるまであなたの思想は<br>統一されます。", elem_id="doctrine")
185
 
186
- result_display = gr.HTML(elem_id="oracle-box", visible=False)
 
187
 
188
- # 案1:画像出力(負荷軽減のため、初回描画時のみ生成)
189
- result_image = gr.Image(label="神託の証(保存して投稿に添付してください)", elem_id="result-img", visible=False, type="pil")
190
 
191
  peace_display = gr.Markdown(elem_id="peace-msg")
192
 
@@ -196,17 +155,11 @@ with gr.Blocks(title="蓮ノ空聖書正典") as demo:
196
  draw_btn.click(
197
  fn=get_personal_daily_oracle,
198
  inputs=[device_id_storage],
199
- outputs=[result_display, peace_display, share_btn, result_display, result_image],
200
  js=js_logic
201
- ).then(
202
- fn=None,
203
- inputs=[result_display, peace_display, share_btn, result_display, result_image],
204
- outputs=None,
205
- js=js_save_result
206
  )
207
 
208
  share_btn.click(fn=None, inputs=None, outputs=None, js=js_share_bluesky)
209
 
210
  if __name__ == "__main__":
211
- # Gradio最新版対応
212
  demo.launch(css=custom_css, theme=gr.themes.Monochrome())
 
4
  from PIL import Image, ImageDraw, ImageFont
5
  import io
6
 
7
+ # 12名の聖職者リスト
8
  members = ["かほ", "さや", "こず", "るり", "めぐ", "つづ", "ぎん", "すず", "ひめ", "せら", "いず", "さち"]
9
 
10
+ # フォント設定(日本語フォントがない場合はデフォトを使用)
11
  try:
 
12
  font_path = "/usr/share/fonts/truetype/noto/NotoSansJP-Regular.otf"
13
+ font_title = ImageFont.truetype(font_path, 36)
14
+ font_pair = ImageFont.truetype(font_path, 60)
15
  except:
 
16
  font_title = ImageFont.load_default()
17
  font_pair = ImageFont.load_default()
18
 
19
  def generate_oracle_image(pair_name):
20
+ # 画像作成 (1000x500, 白背景)
21
+ img = Image.new('RGB', (1000, 500), color=(255, 255, 255))
 
 
 
 
22
  d = ImageDraw.Draw(img)
23
+ # 聖典らしい太い外枠
24
+ d.rectangle([20, 20, 980, 480], outline=(0, 0, 0), width=12)
25
+ # テキスト描画
26
+ d.text((500, 160), "本日の神託", fill=(0, 0, 0), font=font_title, anchor="mm")
27
+ d.text((500, 320), pair_name, fill=(0, 0, 0), font=font_pair, anchor="mm")
 
 
 
28
  return img
29
 
30
  def get_personal_daily_oracle(device_id):
 
31
  seed_base = device_id if device_id else str(random.random())
32
  jst = timezone(timedelta(hours=9))
33
  today_str = datetime.now(jst).strftime("%Y-%m-%d")
 
38
  random.shuffle(selected)
39
  pair_name = f"{selected[0]}{selected[1]}"
40
 
41
+ # 画像生成
 
 
 
 
 
 
42
  img_result = generate_oracle_image(pair_name)
43
 
44
+ # ペア名を隠し要素として渡すためのHTML(Bluesky投稿用)
45
+ pair_raw_html = f"<div id='pair-raw' style='display:none;'>{pair_name}</div>"
46
+
47
+ return pair_raw_html, img_result, "これにより、不毛なカップリング論争は終結しました。", gr.update(visible=True), gr.update(visible=True)
48
 
49
+ # JS: 状態チェック
50
  js_logic = """
51
  function(deviceId) {
52
  const lastDraw = localStorage.getItem('lastOracleDate');
 
53
  const today = new Date().toLocaleDateString('ja-JP');
54
 
55
+ if (lastDraw === today) {
56
  alert("本日の神託は既に下されています。\\n明日の更新まで、今の思想を維持しなさい。");
57
+ // Python側の処理をスキップさせるため、入力をにするなどの制御はGradio側で行う
58
+ //こでフラグチェックのみ
59
  }
 
60
  localStorage.setItem('lastOracleDate', today);
61
  return [null, null, null, null, null];
62
  }
63
  """
64
 
65
+ # JS: Bluesky投稿(隠しHTMLからペア名を取得)
 
 
 
 
 
 
 
 
 
66
  js_share_bluesky = """
67
  function() {
68
  const pairRawEl = document.getElementById('pair-raw');
69
+ const pairName = pairRawEl ? pairRawEl.innerText : "運命";
 
 
 
 
 
 
 
 
 
70
  const currentUrl = window.location.href;
71
  const text = `私は「${pairName}」を信仰しています。\\n\\n画像(神託の証)を保存して投稿に添付しなさい。\\n\\n蓮ノ空聖書正典:${currentUrl}`;
72
  const intentUrl = `https://bsky.app/intent/compose?text=${encodeURIComponent(text)}`;
 
77
  custom_css = """
78
  .gradio-container { max-width: 600px !important; text-align: center !important; }
79
 
 
80
  .center-content {
81
  display: flex !important;
82
  flex-direction: column !important;
83
  align-items: center !important;
84
+ padding-top: 40px !important;
85
  }
86
 
87
  h1 { margin-top: 0px !important; margin-bottom: -5px !important; font-size: 32px !important; }
88
 
 
89
  #doctrine {
90
  font-size: 1.5em !important;
91
  line-height: 1.4 !important;
 
93
  margin-bottom: -5px !important;
94
  }
95
 
96
+ /* 画像表示エリアのタイル */
97
+ #result-img {
98
+ border: none !important;
99
+ margin: 0px auto -5px auto !important;
100
+ background: transparent !important;
101
+ }
102
+ #result-img img {
103
+ border: 4px solid #000 !important;
104
+ max-width: 100% !important;
 
 
 
105
  }
 
 
 
106
 
107
  #peace-msg {
108
  font-size: 20px !important;
 
111
  margin: 0px auto -5px auto !important;
112
  }
113
 
 
114
  .action-btn {
115
  font-size: 26px !important;
116
  font-weight: bold !important;
 
141
  gr.Markdown("# ⚖️ 蓮ノ空聖書正典")
142
  gr.Markdown("日付が変わるまであなたの思想は<br>統一されます。", elem_id="doctrine")
143
 
144
+ # 非表示のペア名保持用
145
+ pair_raw_display = gr.HTML(visible=False)
146
 
147
+ # 結果画像
148
+ result_image = gr.Image(label=None, elem_id="result-img", visible=False, type="pil", interactive=False)
149
 
150
  peace_display = gr.Markdown(elem_id="peace-msg")
151
 
 
155
  draw_btn.click(
156
  fn=get_personal_daily_oracle,
157
  inputs=[device_id_storage],
158
+ outputs=[pair_raw_display, result_image, peace_display, share_btn, result_image],
159
  js=js_logic
 
 
 
 
 
160
  )
161
 
162
  share_btn.click(fn=None, inputs=None, outputs=None, js=js_share_bluesky)
163
 
164
  if __name__ == "__main__":
 
165
  demo.launch(css=custom_css, theme=gr.themes.Monochrome())