benjamin5607 commited on
Commit
3ebf811
ยท
verified ยท
1 Parent(s): 4b6ad52

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -13
app.py CHANGED
@@ -3,11 +3,14 @@ import streamlit.components.v1 as components
3
  import json
4
  import base64
5
  import os
 
 
 
6
 
7
  # ==========================================
8
- # [ํ•„์ˆ˜] Groq API ํ‚ค (gsk_...)
9
  # ==========================================
10
- GROQ_API_KEY = "gsk_..." # <-- ์—ฌ๊ธฐ์— ๋ณธ์ธ ํ‚ค ์ž…๋ ฅ!
11
 
12
  # 1. ํŽ˜์ด์ง€ ์„ค์ •
13
  st.set_page_config(page_title="Drunken Plane", page_icon="โœˆ๏ธ", layout="wide")
@@ -20,14 +23,47 @@ st.markdown("""
20
  </style>
21
  """, unsafe_allow_html=True)
22
 
23
- # 2. ๋ฐ์ดํ„ฐ ๋ฐ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ
 
 
 
 
 
 
 
24
  try:
25
- with open('places.json', 'r', encoding='utf-8-sig') as f:
26
- PLACE_DB = json.load(f)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  except Exception as e:
 
 
28
  PLACE_DB = {}
29
- st.error(f"๐Ÿšจ DB ๋กœ๋“œ ์‹คํŒจ: {e}")
30
 
 
31
  emily_base64 = ""
32
  if os.path.exists('emily.jpg'):
33
  try:
@@ -38,7 +74,7 @@ if os.path.exists('emily.jpg'):
38
  db_json_raw = json.dumps(PLACE_DB, ensure_ascii=False)
39
  db_base64 = base64.b64encode(db_json_raw.encode('utf-8')).decode('utf-8')
40
 
41
- # 3. HTML/JS/CSS (์„ค๋ช… ํ…์ŠคํŠธ Fallback ๋กœ์ง ์ˆ˜์ •๋จ)
42
  html_code = f"""
43
  <!DOCTYPE html>
44
  <html>
@@ -436,8 +472,8 @@ html_code = f"""
436
  "<div class='pc-cat'>" + translatedCat + "</div>" +
437
  "<div class='pc-desc'>" + desc + "</div>" +
438
  "<div class='card-actions'>" +
439
- "<button class='btn-action btn-ai' onclick=\\"openDetail('" + sN + "', '" + sC + "')\\">" + t.aiBtn + "</button>" +
440
- "<button class='btn-action btn-map' onclick=\\"window.open('" + mapLink + "', '_blank')\\">" + t.mapLinkBtn + "</button></div>";
441
  list.appendChild(card);
442
  }});
443
  }}
@@ -604,7 +640,7 @@ html_code = f"""
604
  if(loadingMsg) loadingMsg.remove();
605
 
606
  let finalMsg = res;
607
- const match = res.match(/\\[(.*?)\\]/);
608
  if(match) {{
609
  const pName = match[1];
610
  const found = nearbyPlaces.find(p => p.name.includes(pName));
@@ -643,8 +679,8 @@ html_code = f"""
643
 
644
  const popupContent = "<div style='text-align:center'><b>" + p.name + "</b><br>" +
645
  "<div style='display:flex; gap:5px; margin-top:5px; justify-content:center;'>" +
646
- "<button onclick=\\"openDetailFromMap('" + sN + "', '" + sC + "')\\" style='background:#d4af37; border:none; border-radius:4px; padding:4px 8px; font-size:11px; cursor:pointer;'>๐Ÿค– REVIEW</button>" +
647
- "<button onclick=\\"window.open('" + mapUrl + "', '_blank')\\" style='background:#333; color:white; border:1px solid #555; border-radius:4px; padding:4px 8px; font-size:11px; cursor:pointer;'>๐Ÿ—บ๏ธ MAP</button>" +
648
  "</div></div>";
649
  L.marker([p.lat, p.lon]).bindPopup(popupContent).addTo(worldMap);
650
  }}
@@ -701,7 +737,7 @@ html_code = f"""
701
  const targetLang = TRANSLATIONS[currentLang].ai;
702
  const detailMessages = [
703
  {{ role: "system", content: "Act as Emily. Write a DETAILED, structured travel report." }},
704
- {{ role: "user", content: "Write a report for '" + n + "' in '" + c + "'. Include sections: 'Vibe & Atmosphere', 'Must Try Drinks/Food', 'Secret Tip'. Use Markdown. IMPORTANT: Write this report IN " + targetLang + " ONLY." }}
705
  ];
706
 
707
  const res = await callGroq(detailMessages);
 
3
  import json
4
  import base64
5
  import os
6
+ import pandas as pd
7
+ import requests
8
+ import io
9
 
10
  # ==========================================
11
+ # [ํ•„์ˆ˜] Groq API ํ‚ค
12
  # ==========================================
13
+ GROQ_API_KEY = "gsk_..." # <-- ์—ฌ๊ธฐ์— ๋ณธ์ธ ํ‚ค ์ž…๋ ฅ! (ํ˜น์€ Secrets์—์„œ ๊ฐ€์ ธ์™€๋„ ๋จ)
14
 
15
  # 1. ํŽ˜์ด์ง€ ์„ค์ •
16
  st.set_page_config(page_title="Drunken Plane", page_icon="โœˆ๏ธ", layout="wide")
 
23
  </style>
24
  """, unsafe_allow_html=True)
25
 
26
+ # ==========================================
27
+ # 2. ๋ฐ์ดํ„ฐ ๋กœ๋“œ (๊ตฌ๊ธ€ ์‹œํŠธ ์—ฐ๋™)
28
+ # ==========================================
29
+ PLACE_DB = {}
30
+
31
+ # (1) ์‹œํฌ๋ฆฟ์—์„œ ๊ตฌ๊ธ€ ์‹œํŠธ ๋งํฌ ๊ฐ€์ ธ์˜ค๊ธฐ
32
+ SHEET_URL = os.environ.get("PRIVATE_SHEET_URL")
33
+
34
  try:
35
+ if SHEET_URL:
36
+ # ๊ตฌ๊ธ€ ์‹œํŠธ(CSV) ๋‹ค์šด๋กœ๋“œ
37
+ response = requests.get(SHEET_URL)
38
+ response.raise_for_status()
39
+
40
+ # CSV๋ฅผ ๋ฐ์ดํ„ฐํ”„๋ ˆ์ž„์œผ๋กœ ๋ณ€ํ™˜
41
+ df = pd.read_csv(io.StringIO(response.text))
42
+
43
+ # ๋ฐ์ดํ„ฐ๋ฅผ ๊ตญ๊ฐ€๋ณ„๋กœ ๊ทธ๋ฃนํ™”ํ•˜์—ฌ JSON ๊ตฌ์กฐ(PLACE_DB)๋กœ ๋ณ€ํ™˜
44
+ # ๊ตฌ์กฐ: { "CountryName": [ {place_info}, {place_info}... ] }
45
+ if 'Country' in df.columns:
46
+ for country, group in df.groupby('Country'):
47
+ # NaN ๊ฐ’(๋นˆ์นธ)์€ ๋นˆ ๋ฌธ์ž์—ด๋กœ ์ฒ˜๋ฆฌ (์—๋Ÿฌ ๋ฐฉ์ง€)
48
+ cleaned_group = group.fillna("").to_dict(orient='records')
49
+ PLACE_DB[country] = cleaned_group
50
+ else:
51
+ st.error("๐Ÿšจ CSV ํŒŒ์ผ์— 'Country' ์ปฌ๋Ÿผ์ด ์—†์Šต๋‹ˆ๋‹ค.")
52
+
53
+ else:
54
+ # ์‹œํฌ๋ฆฟ์ด ์—†์œผ๋ฉด ๋กœ์ปฌ ํŒŒ์ผ ์‹œ๋„ (๋ฐฑ์—…์šฉ)
55
+ if os.path.exists('places.json'):
56
+ with open('places.json', 'r', encoding='utf-8-sig') as f:
57
+ PLACE_DB = json.load(f)
58
+ else:
59
+ st.warning("โš ๏ธ ๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. (Secrets ์„ค์ • ํ•„์š”)")
60
+
61
  except Exception as e:
62
+ st.error(f"๐Ÿšจ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {e}")
63
+ # ์‹คํŒจ ์‹œ ๋นˆ DB๋ผ๋„ ์ƒ์„ฑํ•ด์„œ ์•ฑ์ด ๊บผ์ง€๋Š” ๊ฑด ๋ฐฉ์ง€
64
  PLACE_DB = {}
 
65
 
66
+ # 3. ์ด๋ฏธ์ง€ ๋ฐ ๋ฐ์ดํ„ฐ ์ธ์ฝ”๋”ฉ
67
  emily_base64 = ""
68
  if os.path.exists('emily.jpg'):
69
  try:
 
74
  db_json_raw = json.dumps(PLACE_DB, ensure_ascii=False)
75
  db_base64 = base64.b64encode(db_json_raw.encode('utf-8')).decode('utf-8')
76
 
77
+ # 4. HTML/JS/CSS (๊ธฐ์กด ์ฝ”๋“œ 100% ์œ ์ง€)
78
  html_code = f"""
79
  <!DOCTYPE html>
80
  <html>
 
472
  "<div class='pc-cat'>" + translatedCat + "</div>" +
473
  "<div class='pc-desc'>" + desc + "</div>" +
474
  "<div class='card-actions'>" +
475
+ "<button class='btn-action btn-ai' onclick=\"openDetail('" + sN + "', '" + sC + "')\">" + t.aiBtn + "</button>" +
476
+ "<button class='btn-action btn-map' onclick=\"window.open('" + mapLink + "', '_blank')\">" + t.mapLinkBtn + "</button></div>";
477
  list.appendChild(card);
478
  }});
479
  }}
 
640
  if(loadingMsg) loadingMsg.remove();
641
 
642
  let finalMsg = res;
643
+ const match = res.match(/\[(.*?)\]/);
644
  if(match) {{
645
  const pName = match[1];
646
  const found = nearbyPlaces.find(p => p.name.includes(pName));
 
679
 
680
  const popupContent = "<div style='text-align:center'><b>" + p.name + "</b><br>" +
681
  "<div style='display:flex; gap:5px; margin-top:5px; justify-content:center;'>" +
682
+ "<button onclick=\"openDetailFromMap('" + sN + "', '" + sC + "')\" style='background:#d4af37; border:none; border-radius:4px; padding:4px 8px; font-size:11px; cursor:pointer;'>๐Ÿค– REVIEW</button>" +
683
+ "<button onclick=\"window.open('" + mapUrl + "', '_blank')\" style='background:#333; color:white; border:1px solid #555; border-radius:4px; padding:4px 8px; font-size:11px; cursor:pointer;'>๐Ÿ—บ๏ธ MAP</button>" +
684
  "</div></div>";
685
  L.marker([p.lat, p.lon]).bindPopup(popupContent).addTo(worldMap);
686
  }}
 
737
  const targetLang = TRANSLATIONS[currentLang].ai;
738
  const detailMessages = [
739
  {{ role: "system", content: "Act as Emily. Write a DETAILED, structured travel report." }},
740
+ {{ role: "user", content: "Write a report for '" + n + "' in '" + c + "'. Include sections: 'Vibe & Atmosphere', 'Must Try Drinks/Food', 'Secret Tip'. Use Markdown. IMPORTANT: Write this report IN " + targetLang + " ONLY. " }}
741
  ];
742
 
743
  const res = await callGroq(detailMessages);