awacke1 commited on
Commit
6a6053b
Β·
verified Β·
1 Parent(s): d13d130

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +163 -22
app.py CHANGED
@@ -7,6 +7,7 @@ from datetime import datetime
7
  import os
8
  import random
9
  import time
 
10
 
11
  # Fun usernames with emojis - the VIP list of quirky characters! πŸŽ‰πŸ˜œ
12
  FUN_USERNAMES = [
@@ -17,12 +18,17 @@ FUN_USERNAMES = [
17
  "MysticMoose 🦌", "GlitchGnome 🧚", "VortexViper 🐍", "ChronoChimp πŸ’"
18
  ]
19
 
20
- # Directory for chat logs - the secret vault where tales are stashed! πŸ—„οΈπŸ”’
21
  CHAT_DIR = "chat_logs"
 
22
  os.makedirs(CHAT_DIR, exist_ok=True)
 
23
 
24
- # Persistent chat file - the grand tome of all chatter! πŸ“–βœ¨
25
  CHAT_FILE = os.path.join(CHAT_DIR, "global_chat.md")
 
 
 
26
 
27
  # Node name - the app’s codename generator, sneaky and slick! πŸ•΅οΈβ€β™‚οΈπŸ’Ύ
28
  def get_node_name():
@@ -72,6 +78,82 @@ def get_user_list(chat_content):
72
  users.add(user)
73
  return sorted(list(users))
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  active_connections = {}
76
 
77
  # WebSocket handler - the bouncer at the chat rave, keeping it hopping! πŸŽ‰πŸšͺ
@@ -123,7 +205,7 @@ async def start_websocket_server(host='0.0.0.0', port=8765):
123
 
124
  # Chat interface maker - the stage builder for our chat extravaganza! 🎭🏟️
125
  def create_streamlit_interface(initial_username):
126
- """πŸ–ŒοΈ Sets up the chat stage with live updates, timers, and refresh rate flair! 🌟"""
127
  # Custom CSS for a sleek chat box and timer
128
  st.markdown("""
129
  <style>
@@ -133,7 +215,7 @@ def create_streamlit_interface(initial_username):
133
  color: #d4d4d4;
134
  padding: 10px;
135
  border-radius: 5px;
136
- height: 400px;
137
  overflow-y: auto;
138
  }
139
  .timer {
@@ -145,46 +227,97 @@ def create_streamlit_interface(initial_username):
145
  """, unsafe_allow_html=True)
146
 
147
  # Title and intro
148
- st.title(f"Chat Node: {NODE_NAME}")
149
- st.markdown("Chat live, switch names, and tweak the refresh rate! πŸŽ‰")
150
 
151
- # Session state for username and refresh rate
152
  if 'username' not in st.session_state:
153
  st.session_state.username = initial_username
154
  if 'refresh_rate' not in st.session_state:
155
- st.session_state.refresh_rate = 5 # Default 5 seconds
156
  if 'last_refresh' not in st.session_state:
157
  st.session_state.last_refresh = time.time()
 
 
 
 
158
 
159
- # Chat display
 
160
  chat_content = load_chat()
161
- st.markdown(f"<div class='chat-box'>{chat_content}</div>", unsafe_allow_html=True)
 
 
 
 
 
 
 
 
 
 
 
162
 
163
- # User switcher
164
  user_list = get_user_list(chat_content)
165
  new_username = st.selectbox("Switch User", user_list + [st.session_state.username], index=len(user_list))
166
  if new_username != st.session_state.username:
167
  st.session_state.username = new_username
168
 
169
- # Message input and send
170
  message = st.text_input("Message", placeholder="Type your epic line here! ✍️")
171
  if st.button("Send πŸš€") and message.strip():
172
  save_chat_entry(st.session_state.username, message)
173
- st.session_state.last_refresh = time.time() # Reset timer on send
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  st.rerun()
175
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
176
  # Refresh rate controls
177
  st.subheader("Set Refresh Rate ⏳")
178
- refresh_rate = st.slider(
179
- "Refresh Rate (seconds)",
180
- min_value=1,
181
- max_value=300, # 5 minutes = 300 seconds
182
- value=st.session_state.refresh_rate,
183
- step=1
184
- )
185
  st.session_state.refresh_rate = refresh_rate
186
 
187
- # Emoji buttons for quick settings
188
  col1, col2, col3 = st.columns(3)
189
  with col1:
190
  if st.button("πŸ‡ Small (1s)"):
@@ -214,6 +347,15 @@ def create_streamlit_interface(initial_username):
214
  else:
215
  st.markdown(f"<script>window.setTimeout(() => window.location.reload(), {int((st.session_state.refresh_rate - elapsed) * 1000)});</script>", unsafe_allow_html=True)
216
 
 
 
 
 
 
 
 
 
 
217
  # Main event - the ringmaster kicking off the chat circus! πŸŽͺ🀑
218
  async def main():
219
  """🎀 Drops the mic and starts the chat party - it’s showtime, folks! πŸŽ‰"""
@@ -221,7 +363,6 @@ async def main():
221
  NODE_NAME, port = get_node_name()
222
  await start_websocket_server()
223
 
224
- # Grab username from URL or roll the dice! 🎲
225
  query_params = st.query_params if hasattr(st, 'query_params') else {}
226
  initial_username = query_params.get("username", random.choice(FUN_USERNAMES)) if query_params else random.choice(FUN_USERNAMES)
227
  print(f"Welcoming {initial_username} to the chat bash!")
 
7
  import os
8
  import random
9
  import time
10
+ import hashlib
11
 
12
  # Fun usernames with emojis - the VIP list of quirky characters! πŸŽ‰πŸ˜œ
13
  FUN_USERNAMES = [
 
18
  "MysticMoose 🦌", "GlitchGnome 🧚", "VortexViper 🐍", "ChronoChimp πŸ’"
19
  ]
20
 
21
+ # Directories for chat and votes - the secret vaults where tales and tallies are stashed! πŸ—„οΈπŸ”’
22
  CHAT_DIR = "chat_logs"
23
+ VOTE_DIR = "vote_logs"
24
  os.makedirs(CHAT_DIR, exist_ok=True)
25
+ os.makedirs(VOTE_DIR, exist_ok=True)
26
 
27
+ # Persistent files - the grand tomes of chatter and votes! πŸ“–βœ¨
28
  CHAT_FILE = os.path.join(CHAT_DIR, "global_chat.md")
29
+ QUOTE_VOTES_FILE = os.path.join(VOTE_DIR, "quote_votes.md")
30
+ IMAGE_VOTES_FILE = os.path.join(VOTE_DIR, "image_votes.md")
31
+ HISTORY_FILE = os.path.join(VOTE_DIR, "vote_history.md")
32
 
33
  # Node name - the app’s codename generator, sneaky and slick! πŸ•΅οΈβ€β™‚οΈπŸ’Ύ
34
  def get_node_name():
 
78
  users.add(user)
79
  return sorted(list(users))
80
 
81
+ # Quote loader - the sage pulling wisdom from the ages! πŸ“œπŸ§™
82
+ def load_quotes(source="famous"):
83
+ """πŸ“š Grabs a stack of wise words from famous folks or custom quips! πŸ—£οΈ"""
84
+ famous_quotes = [
85
+ "The true sign of intelligence is not knowledge but imagination. – Albert Einstein",
86
+ "I have not failed. I've just found 10,000 ways that won't work. – Thomas Edison",
87
+ "Innovation distinguishes between a leader and a follower. – Steve Jobs",
88
+ "Research is what I'm doing when I don't know what I'm doing. – Wernher von Braun",
89
+ "The only way to discover the limits of the possible is to go beyond them into the impossible. – Arthur C. Clarke",
90
+ "Success is a science; if you have the conditions, you get the result. – Oscar Wilde",
91
+ "An expert is a person who has made all the mistakes that can be made in a very narrow field. – Niels Bohr",
92
+ "The important thing is to not stop questioning. Curiosity has its own reason for existing. – Albert Einstein",
93
+ "The best way to predict the future is to invent it. – Alan Kay",
94
+ "If I have seen further it is by standing on the shoulders of Giants. – Isaac Newton",
95
+ "Logic will get you from A to B. Imagination will take you everywhere. – Albert Einstein",
96
+ "Imagination is more important than knowledge. Knowledge is limited. Imagination encircles the world. – Albert Einstein",
97
+ "Science is a way of thinking much more than it is a body of knowledge. – Carl Sagan",
98
+ "We cannot solve our problems with the same thinking we used when we created them. – Albert Einstein",
99
+ "The true method of knowledge is experiment. – William Blake",
100
+ "The scientist is not a person who gives the right answers, he's one who asks the right questions. – Claude Levi-Strauss",
101
+ "It's kind of fun to do the impossible. – Walt Disney",
102
+ "Any sufficiently advanced technology is indistinguishable from magic. – Arthur C. Clarke",
103
+ "Creativity is intelligence having fun. – Albert Einstein",
104
+ "To invent, you need a good imagination and a pile of junk. – Thomas Edison"
105
+ ]
106
+ custom_quotes = [
107
+ "Every age unfolds a new lesson. Life's chapters evolve, each teaching us anew.",
108
+ "From infancy to twilight, our journey is painted in growth. Every stage shines with its own wisdom.",
109
+ "Love is the universal language, transcending boundaries and touching souls.",
110
+ "Through love, we find connection, unity, and the essence of existence."
111
+ ]
112
+ return famous_quotes if source == "famous" else custom_quotes
113
+
114
+ # Vote saver - the tally keeper counting thumbs up! πŸ‘πŸ“Š
115
+ def save_vote(file, item, user_hash):
116
+ """✍️ Tallies a vote in the grand ledger - your opinion matters! πŸ—³οΈ"""
117
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
118
+ entry = f"[{timestamp}] {user_hash} voted for {item}"
119
+ try:
120
+ with open(file, 'a') as f:
121
+ f.write(f"{entry}\n")
122
+ with open(HISTORY_FILE, 'a') as f:
123
+ f.write(f"- {timestamp} - User {user_hash} voted for {item}\n")
124
+ return True
125
+ except Exception as e:
126
+ print(f"Vote save flop: {e}")
127
+ return False
128
+
129
+ # Vote loader - the scorekeeper tallying the crowd’s cheers! πŸŽ‰πŸ…
130
+ def load_votes(file):
131
+ """πŸ“ˆ Counts the votes from the ledger - who’s winning the popularity contest? πŸ†"""
132
+ if not os.path.exists(file):
133
+ with open(file, 'w') as f:
134
+ f.write("# Vote Tally\n\nNo votes yet - get clicking! πŸ–±οΈ\n")
135
+ try:
136
+ with open(file, 'r') as f:
137
+ lines = f.read().strip().split('\n')
138
+ votes = {}
139
+ for line in lines[2:]: # Skip header
140
+ if line.strip() and 'voted for' in line:
141
+ item = line.split('voted for ')[1]
142
+ votes[item] = votes.get(item, 0) + 1
143
+ return votes
144
+ except Exception as e:
145
+ print(f"Vote load oopsie: {e}")
146
+ return {}
147
+
148
+ # User hash generator - the secret agent giving you a cool code! πŸ•΅οΈβ€β™‚οΈπŸ”‘
149
+ def generate_user_hash():
150
+ """πŸ•΅οΈ Crafts a snazzy 8-digit ID badge - you’re in the club now! 🎟️"""
151
+ if 'user_hash' not in st.session_state:
152
+ session_id = str(random.getrandbits(128))
153
+ hash_object = hashlib.md5(session_id.encode())
154
+ st.session_state['user_hash'] = hash_object.hexdigest()[:8]
155
+ return st.session_state['user_hash']
156
+
157
  active_connections = {}
158
 
159
  # WebSocket handler - the bouncer at the chat rave, keeping it hopping! πŸŽ‰πŸšͺ
 
205
 
206
  # Chat interface maker - the stage builder for our chat extravaganza! 🎭🏟️
207
  def create_streamlit_interface(initial_username):
208
+ """πŸ–ŒοΈ Sets up the chat stage with live updates, timers, voting, and refresh flair! 🌟"""
209
  # Custom CSS for a sleek chat box and timer
210
  st.markdown("""
211
  <style>
 
215
  color: #d4d4d4;
216
  padding: 10px;
217
  border-radius: 5px;
218
+ height: 300px;
219
  overflow-y: auto;
220
  }
221
  .timer {
 
227
  """, unsafe_allow_html=True)
228
 
229
  # Title and intro
230
+ st.title(f"Chat & Quote Node: {NODE_NAME}")
231
+ st.markdown("Chat, vote on messages, quotes, and images - keep the party rocking! πŸŽ‰")
232
 
233
+ # Session state for username, refresh rate, and quote index
234
  if 'username' not in st.session_state:
235
  st.session_state.username = initial_username
236
  if 'refresh_rate' not in st.session_state:
237
+ st.session_state.refresh_rate = 5
238
  if 'last_refresh' not in st.session_state:
239
  st.session_state.last_refresh = time.time()
240
+ if 'quote_index' not in st.session_state:
241
+ st.session_state.quote_index = random.randint(0, len(load_quotes("famous")) - 1)
242
+ if 'quote_source' not in st.session_state:
243
+ st.session_state.quote_source = "famous"
244
 
245
+ # Chat section
246
+ st.subheader("Chat Room πŸ’¬")
247
  chat_content = load_chat()
248
+ chat_lines = chat_content.split('\n')
249
+ for i, line in enumerate(chat_lines):
250
+ if line.strip() and ': ' in line:
251
+ col1, col2 = st.columns([5, 1])
252
+ with col1:
253
+ st.markdown(line)
254
+ with col2:
255
+ if st.button(f"πŸ‘", key=f"chat_vote_{i}"):
256
+ user_hash = generate_user_hash()
257
+ save_vote(QUOTE_VOTES_FILE, line, user_hash)
258
+ st.session_state.last_refresh = time.time()
259
+ st.rerun()
260
 
 
261
  user_list = get_user_list(chat_content)
262
  new_username = st.selectbox("Switch User", user_list + [st.session_state.username], index=len(user_list))
263
  if new_username != st.session_state.username:
264
  st.session_state.username = new_username
265
 
 
266
  message = st.text_input("Message", placeholder="Type your epic line here! ✍️")
267
  if st.button("Send πŸš€") and message.strip():
268
  save_chat_entry(st.session_state.username, message)
269
+ st.session_state.last_refresh = time.time()
270
+ st.rerun()
271
+
272
+ # Quote section
273
+ st.subheader("Quote of the Moment πŸ“")
274
+ quotes = load_quotes(st.session_state.quote_source)
275
+ quote = quotes[st.session_state.quote_index]
276
+ col1, col2 = st.columns([5, 1])
277
+ with col1:
278
+ st.markdown(quote)
279
+ with col2:
280
+ if st.button("πŸ‘ Upvote", key="quote_vote"):
281
+ user_hash = generate_user_hash()
282
+ save_vote(QUOTE_VOTES_FILE, quote, user_hash)
283
+ st.session_state.last_refresh = time.time()
284
+ st.rerun()
285
+ if time.time() - st.session_state.last_refresh > 10: # 10s quote refresh
286
+ st.session_state.quote_index = (st.session_state.quote_index + 1) % len(quotes)
287
+ st.session_state.quote_source = "custom" if st.session_state.quote_source == "famous" else "famous"
288
+ st.session_state.last_refresh = time.time()
289
  st.rerun()
290
 
291
+ # Image voting section
292
+ st.subheader("Image Voting πŸ–ΌοΈ")
293
+ image_dir = '.'
294
+ valid_extensions = ('.png', '.jpg', '.jpeg', '.gif', '.bmp', '.tiff', '.webp')
295
+ images = [f for f in os.listdir(image_dir) if f.lower().endswith(valid_extensions)]
296
+ if len(images) >= 2:
297
+ image1, image2 = random.sample(images, 2)
298
+ col1, col2 = st.columns(2)
299
+ with col1:
300
+ st.image(os.path.join(image_dir, image1))
301
+ if st.button(f"πŸ‘ Upvote {image1}", key=f"img_vote_{image1}"):
302
+ user_hash = generate_user_hash()
303
+ save_vote(IMAGE_VOTES_FILE, image1, user_hash)
304
+ st.session_state.last_refresh = time.time()
305
+ st.rerun()
306
+ with col2:
307
+ st.image(os.path.join(image_dir, image2))
308
+ if st.button(f"πŸ‘ Upvote {image2}", key=f"img_vote_{image2}"):
309
+ user_hash = generate_user_hash()
310
+ save_vote(IMAGE_VOTES_FILE, image2, user_hash)
311
+ st.session_state.last_refresh = time.time()
312
+ st.rerun()
313
+ else:
314
+ st.error("Need at least 2 images in the directory for voting!")
315
+
316
  # Refresh rate controls
317
  st.subheader("Set Refresh Rate ⏳")
318
+ refresh_rate = st.slider("Refresh Rate (seconds)", min_value=1, max_value=300, value=st.session_state.refresh_rate, step=1)
 
 
 
 
 
 
319
  st.session_state.refresh_rate = refresh_rate
320
 
 
321
  col1, col2, col3 = st.columns(3)
322
  with col1:
323
  if st.button("πŸ‡ Small (1s)"):
 
347
  else:
348
  st.markdown(f"<script>window.setTimeout(() => window.location.reload(), {int((st.session_state.refresh_rate - elapsed) * 1000)});</script>", unsafe_allow_html=True)
349
 
350
+ # Sidebar vote stats
351
+ st.sidebar.subheader("Vote Totals")
352
+ chat_votes = load_votes(QUOTE_VOTES_FILE)
353
+ image_votes = load_votes(IMAGE_VOTES_FILE)
354
+ for item, count in chat_votes.items():
355
+ st.sidebar.write(f"{item}: {count} votes")
356
+ for image, count in image_votes.items():
357
+ st.sidebar.write(f"{image}: {count} votes")
358
+
359
  # Main event - the ringmaster kicking off the chat circus! πŸŽͺ🀑
360
  async def main():
361
  """🎀 Drops the mic and starts the chat party - it’s showtime, folks! πŸŽ‰"""
 
363
  NODE_NAME, port = get_node_name()
364
  await start_websocket_server()
365
 
 
366
  query_params = st.query_params if hasattr(st, 'query_params') else {}
367
  initial_username = query_params.get("username", random.choice(FUN_USERNAMES)) if query_params else random.choice(FUN_USERNAMES)
368
  print(f"Welcoming {initial_username} to the chat bash!")