|
import streamlit as st |
|
import asyncio |
|
import websockets |
|
import uuid |
|
import argparse |
|
from datetime import datetime |
|
import os |
|
import random |
|
import time |
|
import hashlib |
|
from PIL import Image |
|
import glob |
|
from urllib.parse import quote |
|
import base64 |
|
import io |
|
import streamlit.components.v1 as components |
|
|
|
|
|
icons = '๐ค๐ง ๐ฌ๐' |
|
START_ROOM = "Sector ๐" |
|
|
|
|
|
st.set_page_config( |
|
page_title="๐ค๐ง MMO Chat Brain๐๐ฌ", |
|
page_icon=icons, |
|
layout="wide", |
|
initial_sidebar_state="auto" |
|
) |
|
|
|
|
|
FUN_USERNAMES = [ |
|
"CosmicJester ๐", "PixelPanda ๐ผ", "QuantumQuack ๐ฆ", "StellarSquirrel ๐ฟ๏ธ", |
|
"GizmoGuru โ๏ธ", "NebulaNinja ๐ ", "ByteBuster ๐พ", "GalacticGopher ๐", |
|
"RocketRaccoon ๐", "EchoElf ๐ง", "PhantomFox ๐ฆ", "WittyWizard ๐ง", |
|
"LunarLlama ๐", "SolarSloth โ๏ธ", "AstroAlpaca ๐ฆ", "CyberCoyote ๐บ", |
|
"MysticMoose ๐ฆ", "GlitchGnome ๐ง", "VortexViper ๐", "ChronoChimp ๐" |
|
] |
|
|
|
|
|
CHAT_DIR = "chat_logs" |
|
VOTE_DIR = "vote_logs" |
|
STATE_FILE = "user_state.txt" |
|
os.makedirs(CHAT_DIR, exist_ok=True) |
|
os.makedirs(VOTE_DIR, exist_ok=True) |
|
|
|
CHAT_FILE = os.path.join(CHAT_DIR, "global_chat.md") |
|
QUOTE_VOTES_FILE = os.path.join(VOTE_DIR, "quote_votes.md") |
|
MEDIA_VOTES_FILE = os.path.join(VOTE_DIR, "media_votes.md") |
|
HISTORY_FILE = os.path.join(VOTE_DIR, "vote_history.md") |
|
|
|
|
|
UNICODE_DIGITS = {i: f"{i}\uFE0Fโฃ" for i in range(10)} |
|
UNICODE_FONTS = [ |
|
("Normal", lambda x: x), |
|
("Bold", lambda x: "".join(chr(ord(c) + 0x1D400 - 0x41) if 'A' <= c <= 'Z' else chr(ord(c) + 0x1D41A - 0x61) if 'a' <= c <= 'z' else c for c in x)), |
|
] |
|
|
|
server_running = False |
|
server_task = None |
|
|
|
async def get_node_name(): |
|
"""๐ - Naming Node with Code - Spins a name, oh so bold!""" |
|
action = "๐ - Naming Node with Code - Spins a name, oh so bold!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
parser = argparse.ArgumentParser(description='Start a chat node with a specific name') |
|
parser.add_argument('--node-name', type=str, default=None) |
|
parser.add_argument('--port', type=int, default=8501) |
|
args = await asyncio.to_thread(parser.parse_args) |
|
return args.node_name or f"node-{uuid.uuid4().hex[:8]}", args.port |
|
|
|
def log_action(username, action): |
|
"""Helper to log actions with deduplication""" |
|
if 'action_log' not in st.session_state: |
|
st.session_state.action_log = {} |
|
user_log = st.session_state.action_log.setdefault(username, {}) |
|
current_time = time.time() |
|
user_log = {k: v for k, v in user_log.items() if current_time - v < 10} |
|
st.session_state.action_log[username] = user_log |
|
if action not in user_log: |
|
with open(CHAT_FILE, 'a') as f: |
|
f.write(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] {username}: {action}\n") |
|
user_log[action] = current_time |
|
|
|
async def save_chat_entry(username, message): |
|
"""๐ - Chat Snap Trap - Logs your yap, no cap! โ๏ธ๐ง """ |
|
action = "๐ - Chat Snap Trap - Logs your yap, no cap! โ๏ธ๐ง " |
|
await asyncio.to_thread(log_action, username, action) |
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
entry = f"[{timestamp}] {username}: {message}" |
|
await asyncio.to_thread(lambda: open(CHAT_FILE, 'a').write(f"{entry}\n")) |
|
|
|
async def load_chat(): |
|
"""๐ - Chat Fetch Quest - Grabs the log, no jest!""" |
|
action = "๐ - Chat Fetch Quest - Grabs the log, no jest!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
if not os.path.exists(CHAT_FILE): |
|
await asyncio.to_thread(lambda: open(CHAT_FILE, 'w').write(f"# {START_ROOM} Chat\n\nWelcome to the cosmic hub - start chatting! ๐ค\n")) |
|
with open(CHAT_FILE, 'r') as f: |
|
content = await asyncio.to_thread(f.read) |
|
return content |
|
|
|
async def get_user_list(chat_content): |
|
"""๐ฅ - Crew Clue Brew - Spots whoโs who in the crew!""" |
|
action = "๐ฅ - Crew Clue Brew - Spots whoโs who in the crew!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
users = set() |
|
for line in chat_content.split('\n'): |
|
if line.strip() and ': ' in line: |
|
user = line.split(': ')[1].split(' ')[0] |
|
users.add(user) |
|
return sorted(list(users)) |
|
|
|
async def has_joined_before(client_id, chat_content): |
|
"""๐ช - Join Check Trek - Sees whoโs back, no wreck!""" |
|
action = "๐ช - Join Check Trek - Sees whoโs back, no wreck!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
return any(f"Client-{client_id} has joined" in line for line in chat_content.split('\n')) |
|
|
|
async def get_message_suggestions(chat_content, prefix): |
|
"""๐ - Suggest Jest Chest - Finds old quips, the best!""" |
|
action = "๐ - Suggest Jest Chest - Finds old quips, the best!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
lines = chat_content.split('\n') |
|
messages = [line.split(': ', 1)[1] for line in lines if ': ' in line and line.strip()] |
|
return [msg for msg in messages if msg.lower().startswith(prefix.lower())][:5] |
|
|
|
async def load_quotes(source="famous"): |
|
"""๐ - Quote Tote Note - Wise words float, we gloat!""" |
|
action = "๐ - Quote Tote Note - Wise words float, we gloat!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
famous_quotes = [ |
|
"The true sign of intelligence is not knowledge but imagination. โ Albert Einstein", |
|
] |
|
custom_quotes = [ |
|
"Every age unfolds a new lesson. Life's chapters evolve, each teaching us anew.", |
|
] |
|
return famous_quotes if source == "famous" else custom_quotes |
|
|
|
async def save_vote(file, item, user_hash, username, comment=""): |
|
"""๐ - Vote Note Float - Cheers rise, we gloat!""" |
|
action = "๐ - Vote Note Float - Cheers rise, we gloat!" |
|
await asyncio.to_thread(log_action, username, action) |
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
entry = f"[{timestamp}] {user_hash} voted for {item}" |
|
await asyncio.to_thread(lambda: open(file, 'a').write(f"{entry}\n")) |
|
await asyncio.to_thread(lambda: open(HISTORY_FILE, "a").write(f"- {timestamp} - User {user_hash} voted for {item}\n")) |
|
chat_message = f"{username} upvoted: \"{item}\"" |
|
if comment: |
|
chat_message += f" - {comment}" |
|
await save_chat_entry(username, chat_message) |
|
|
|
async def load_votes(file): |
|
"""๐ - Tally Rally Call - Counts the cheers, no stall!""" |
|
action = "๐ - Tally Rally Call - Counts the cheers, no stall!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
if not os.path.exists(file): |
|
await asyncio.to_thread(lambda: open(file, 'w').write("# Vote Tally\n\nNo votes yet - get clicking! ๐ฑ๏ธ\n")) |
|
with open(file, 'r') as f: |
|
lines = await asyncio.to_thread(f.read.strip().split, '\n')[2:] |
|
votes = {} |
|
user_votes = set() |
|
for line in lines: |
|
if line.strip() and 'voted for' in line: |
|
user_hash = line.split('] ')[1].split(' voted for ')[0] |
|
item = line.split('voted for ')[1] |
|
vote_key = f"{user_hash}-{item}" |
|
if vote_key not in user_votes: |
|
votes[item] = votes.get(item, 0) + 1 |
|
user_votes.add(vote_key) |
|
return votes |
|
|
|
async def generate_user_hash(): |
|
"""๐ - Hash Dash Bash - Crafts a code, so brash!""" |
|
action = "๐ - Hash Dash Bash - Crafts a code, so brash!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
if 'user_hash' not in st.session_state: |
|
st.session_state.user_hash = hashlib.md5(str(random.getrandbits(128)).encode()).hexdigest()[:8] |
|
return st.session_state.user_hash |
|
|
|
async def save_pasted_image(image_data): |
|
"""๐ธ - Snap Cap Trap - Saves your pic, no flap!""" |
|
action = "๐ธ - Snap Cap Trap - Saves your pic, no flap!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
filename = f"paste_{timestamp}.png" |
|
filepath = os.path.join('./', filename) |
|
if ',' in image_data: |
|
image_data = image_data.split(',')[1] |
|
img_bytes = base64.b64decode(image_data) |
|
img = Image.open(io.BytesIO(img_bytes)) |
|
await asyncio.to_thread(img.save, filepath, "PNG") |
|
return filename |
|
|
|
async def get_video_html(video_path, width="100%"): |
|
"""๐ฅ - Reel Deal Steal - Plays your flick, so real!""" |
|
action = "๐ฅ - Reel Deal Steal - Plays your flick, so real!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
video_url = f"data:video/mp4;base64,{base64.b64encode(await asyncio.to_thread(open(video_path, 'rb').read)).decode()}" |
|
return f'<video width="{width}" controls autoplay muted loop><source src="{video_url}" type="video/mp4">Your browser does not support the video tag.</video>' |
|
|
|
async def get_audio_html(audio_path, width="100%"): |
|
"""๐ถ - Tune Moon Boom - Drops a beat, so groom!""" |
|
action = "๐ถ - Tune Moon Boom - Drops a beat, so groom!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
audio_url = f"data:audio/mpeg;base64,{base64.b64encode(await asyncio.to_thread(open(audio_path, 'rb').read)).decode()}" |
|
return f'<audio controls style="width: {width};"><source src="{audio_url}" type="audio/mpeg">Your browser does not support the audio element.</audio>' |
|
|
|
active_connections = {} |
|
|
|
async def websocket_handler(websocket, path): |
|
"""๐ - Web Sock Jock - Links the chat, no block!""" |
|
action = "๐ - Web Sock Jock - Links the chat, no block!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
try: |
|
client_id = str(uuid.uuid4()) |
|
room_id = "chat" |
|
active_connections.setdefault(room_id, {})[client_id] = websocket |
|
chat_content = await load_chat() |
|
username = st.session_state.get('username', random.choice(FUN_USERNAMES)) |
|
if not await has_joined_before(client_id, chat_content): |
|
await save_chat_entry(f"Client-{client_id}", f"{username} has joined {START_ROOM}!") |
|
async for message in websocket: |
|
parts = message.split('|', 1) |
|
if len(parts) == 2: |
|
username, content = parts |
|
await save_chat_entry(username, content) |
|
await broadcast_message(f"{username}|{content}", room_id) |
|
except websockets.ConnectionClosed: |
|
pass |
|
finally: |
|
if room_id in active_connections and client_id in active_connections[room_id]: |
|
del active_connections[room_id][client_id] |
|
|
|
async def broadcast_message(message, room_id): |
|
"""๐ข - Shout Out Bout - Blasts the word, no doubt!""" |
|
action = "๐ข - Shout Out Bout - Blasts the word, no doubt!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
if room_id in active_connections: |
|
disconnected = [] |
|
for client_id, ws in active_connections[room_id].items(): |
|
try: |
|
await ws.send(message) |
|
except websockets.ConnectionClosed: |
|
disconnected.append(client_id) |
|
for client_id in disconnected: |
|
del active_connections[room_id][client_id] |
|
|
|
async def run_websocket_server(): |
|
"""๐ฅ๏ธ - Server Ferver Verve - Spins the web, with nerve!""" |
|
action = "๐ฅ๏ธ - Server Ferver Verve - Spins the web, with nerve!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
global server_running, server_task |
|
if not server_running: |
|
server = await websockets.serve(websocket_handler, '0.0.0.0', 8765) |
|
server_running = True |
|
await server.wait_closed() |
|
|
|
async def create_streamlit_interface(): |
|
"""๐จ - UI Brew Crew - Builds the view, so new!""" |
|
action = "๐จ - UI Brew Crew - Builds the view, so new!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
|
|
|
|
if 'username' in st.session_state: |
|
dynamic_title = f"๐ค๐ง MMO {st.session_state.username}๐๐ฌ" |
|
else: |
|
dynamic_title = "๐ค๐ง MMO Chat Brain๐๐ฌ" |
|
|
|
|
|
st.markdown(""" |
|
<style> |
|
.chat-box {font-family: monospace; background: #1e1e1e; color: #d4d4d4; padding: 10px; border-radius: 5px; height: 300px; overflow-y: auto;} |
|
.timer {font-size: 24px; color: #ffcc00; text-align: center; animation: pulse 1s infinite;} |
|
@keyframes pulse {0% {transform: scale(1);} 50% {transform: scale(1.1);} 100% {transform: scale(1);}} |
|
#paste-target {border: 2px dashed #ccc; padding: 20px; text-align: center; cursor: pointer;} |
|
</style> |
|
""", unsafe_allow_html=True) |
|
|
|
st.title(dynamic_title) |
|
st.markdown(f"Welcome to {START_ROOM} - chat, vote, upload, paste images, and enjoy quoting! ๐") |
|
|
|
|
|
if 'client_id' not in st.session_state: |
|
st.session_state.client_id = str(uuid.uuid4()) |
|
if 'username' not in st.session_state: |
|
chat_content = await load_chat() |
|
available_names = [name for name in FUN_USERNAMES if not any(f"{name} has joined" in line for line in chat_content.split('\n'))] |
|
st.session_state.username = random.choice(available_names) if available_names else random.choice(FUN_USERNAMES) |
|
|
|
|
|
if 'refresh_rate' not in st.session_state: |
|
st.session_state.refresh_rate = 5 |
|
if 'timer_start' not in st.session_state: |
|
st.session_state.timer_start = time.time() |
|
if 'quote_index' not in st.session_state: |
|
quotes = await load_quotes("famous") |
|
st.session_state.quote_index = random.randint(0, max(0, len(quotes) - 1)) if quotes else 0 |
|
if 'quote_source' not in st.session_state: |
|
st.session_state.quote_source = "famous" |
|
if 'pasted_image_data' not in st.session_state: |
|
st.session_state.pasted_image_data = None |
|
if 'message_text' not in st.session_state: |
|
st.session_state.message_text = "" |
|
|
|
|
|
paste_component = components.html( |
|
""" |
|
<div id="paste-target">Paste an image here (Ctrl+V)</div> |
|
<script> |
|
const pasteTarget = document.getElementById('paste-target'); |
|
pasteTarget.addEventListener('paste', (event) => { |
|
const items = (event.clipboardData || window.clipboardData).items; |
|
for (let i = 0; i < items.length; i++) { |
|
if (items[i].type.indexOf('image') !== -1) { |
|
const blob = items[i].getAsFile(); |
|
const reader = new FileReader(); |
|
reader.onload = (e) => { |
|
window.parent.postMessage({ |
|
type: 'streamlit:setComponentValue', |
|
value: e.target.result |
|
}, '*'); |
|
pasteTarget.innerHTML = '<p>Image pasted! Processing...</p>'; |
|
}; |
|
reader.readAsDataURL(blob); |
|
} |
|
} |
|
event.preventDefault(); |
|
}); |
|
</script> |
|
""", |
|
height=100 |
|
) |
|
|
|
|
|
pasted_image = st.session_state.get('pasted_image_data') |
|
if pasted_image: |
|
filename = await save_pasted_image(pasted_image) |
|
if filename: |
|
await save_chat_entry(st.session_state.username, f"Pasted image: {filename}") |
|
st.session_state.pasted_image_data = None |
|
st.rerun() |
|
|
|
|
|
st.subheader(f"{START_ROOM} Chat ๐ฌ") |
|
chat_content = await load_chat() |
|
chat_lines = chat_content.split('\n') |
|
chat_votes = await load_votes(QUOTE_VOTES_FILE) |
|
for i, line in enumerate(chat_lines): |
|
if line.strip() and ': ' in line: |
|
col1, col2, col3 = st.columns([4, 1, 1]) |
|
with col1: |
|
st.markdown(line) |
|
with col2: |
|
vote_count = chat_votes.get(line.split('. ')[1] if '. ' in line else line, 0) |
|
if st.button(f"๐ {vote_count}", key=f"chat_vote_{i}"): |
|
comment = st.session_state.message_text |
|
await save_vote(QUOTE_VOTES_FILE, line.split('. ')[1] if '. ' in line else line, await generate_user_hash(), st.session_state.username, comment) |
|
if st.session_state.pasted_image_data: |
|
filename = await save_pasted_image(st.session_state.pasted_image_data) |
|
if filename: |
|
await save_chat_entry(st.session_state.username, f"Pasted image: {filename}") |
|
st.session_state.pasted_image_data = None |
|
st.session_state.message_text = '' |
|
st.rerun() |
|
with col3: |
|
if st.button("๐ข Quote", key=f"quote_{i}"): |
|
st.session_state.quote_line = line |
|
st.rerun() |
|
|
|
|
|
if 'quote_line' in st.session_state: |
|
st.markdown(f"### Quoting: {st.session_state.quote_line}") |
|
quote_response = st.text_area("Add your response", key="quote_response") |
|
if st.button("Send Quote ๐", key="send_quote"): |
|
async def process_quote(): |
|
"""๐ข - Quote Float Boat - Echoes chat, we gloat!""" |
|
action = "๐ข - Quote Float Boat - Echoes chat, we gloat!" |
|
await asyncio.to_thread(log_action, st.session_state.username, action) |
|
markdown_response = f"### Quote Response\n- **Original**: {st.session_state.quote_line}\n- **{st.session_state.username} Replies**: {quote_response}" |
|
if st.session_state.pasted_image_data: |
|
filename = await save_pasted_image(st.session_state.pasted_image_data) |
|
if filename: |
|
markdown_response += f"\n- **Image**: " |
|
st.session_state.pasted_image_data = None |
|
await save_chat_entry(st.session_state.username, markdown_response) |
|
await process_quote() |
|
del st.session_state.quote_line |
|
st.session_state.message_text = '' |
|
st.rerun() |
|
|
|
|
|
new_username = st.selectbox("Change Name", [""] + FUN_USERNAMES, index=0) |
|
if new_username and new_username != st.session_state.username: |
|
await save_chat_entry("System ๐", f"{st.session_state.username} changed name to {new_username}") |
|
st.session_state.username = new_username |
|
st.rerun() |
|
|
|
|
|
message = st.text_input(f"Message as {st.session_state.username}", key="message_input", value=st.session_state.message_text, on_change=lambda: st.session_state.update(message_text=st.session_state.message_input)) |
|
if st.button("Send ๐", key="send_button") and message.strip(): |
|
await save_chat_entry(st.session_state.username, message) |
|
if st.session_state.pasted_image_data: |
|
filename = await save_pasted_image(st.session_state.pasted_image_data) |
|
if filename: |
|
await save_chat_entry(st.session_state.username, f"Pasted image: {filename}") |
|
st.session_state.pasted_image_data = None |
|
st.session_state.message_text = '' |
|
st.rerun() |
|
|
|
|
|
st.subheader("Media Gallery ๐จ๐ถ๐ฅ") |
|
uploaded_file = st.file_uploader("Upload Media", type=['png', 'jpg', 'mp3', 'mp4']) |
|
if uploaded_file: |
|
file_path = os.path.join('./', uploaded_file.name) |
|
await asyncio.to_thread(lambda: open(file_path, 'wb').write(uploaded_file.getbuffer())) |
|
st.success(f"Uploaded {uploaded_file.name}") |
|
|
|
media_files = glob.glob("./*.png") + glob.glob("./*.jpg") + glob.glob("./*.mp3") + glob.glob("./*.mp4") |
|
if media_files: |
|
cols = st.columns(3) |
|
media_votes = await load_votes(MEDIA_VOTES_FILE) |
|
for idx, media_file in enumerate(media_files): |
|
vote_count = media_votes.get(media_file, 0) |
|
if vote_count > 0: |
|
with cols[idx % 3]: |
|
if media_file.endswith(('.png', '.jpg')): |
|
st.image(media_file, use_container_width=True) |
|
elif media_file.endswith('.mp3'): |
|
st.markdown(await get_audio_html(media_file), unsafe_allow_html=True) |
|
elif media_file.endswith('.mp4'): |
|
st.markdown(await get_video_html(media_file), unsafe_allow_html=True) |
|
col1, col2 = st.columns(2) |
|
with col1: |
|
if st.button(f"๐ {vote_count}", key=f"media_vote_{idx}"): |
|
comment = st.session_state.message_text |
|
await save_vote(MEDIA_VOTES_FILE, media_file, await generate_user_hash(), st.session_state.username, comment) |
|
if st.session_state.pasted_image_data: |
|
filename = await save_pasted_image(st.session_state.pasted_image_data) |
|
if filename: |
|
await save_chat_entry(st.session_state.username, f"Pasted image: {filename}") |
|
st.session_state.pasted_image_data = None |
|
st.session_state.message_text = '' |
|
st.rerun() |
|
with col2: |
|
if st.button("๐๏ธ", key=f"media_delete_{idx}"): |
|
await asyncio.to_thread(os.remove, media_file) |
|
st.rerun() |
|
|
|
|
|
st.subheader("Refresh โณ") |
|
refresh_rate = st.slider("Refresh Rate", 1, 300, st.session_state.refresh_rate) |
|
st.session_state.refresh_rate = refresh_rate |
|
timer_placeholder = st.empty() |
|
for i in range(st.session_state.refresh_rate, -1, -1): |
|
font_name, font_func = random.choice(UNICODE_FONTS) |
|
countdown_str = "".join(UNICODE_DIGITS[int(d)] for d in str(i)) if i < 10 else font_func(str(i)) |
|
timer_placeholder.markdown(f"<p class='timer'>โณ {font_func('Refresh in:')} {countdown_str}</p>", unsafe_allow_html=True) |
|
await asyncio.sleep(1) |
|
st.rerun() |
|
|
|
|
|
st.sidebar.subheader("Vote Counts") |
|
chat_votes = await load_votes(QUOTE_VOTES_FILE) |
|
media_votes = await load_votes(MEDIA_VOTES_FILE) |
|
for item, count in {**chat_votes, **media_votes}.items(): |
|
if count > 0: |
|
st.sidebar.write(f"{item}: {count} votes") |
|
|
|
async def main(): |
|
"""๐ฎ - Game Fame Claim - Starts the fun, no shame!""" |
|
action = "๐ฎ - Game Fame Claim - Starts the fun, no shame!" |
|
username = st.session_state.get('username', 'System ๐') |
|
await asyncio.to_thread(log_action, username, action) |
|
global NODE_NAME, server_task |
|
NODE_NAME, port = await get_node_name() |
|
if server_task is None: |
|
server_task = asyncio.create_task(run_websocket_server()) |
|
await create_streamlit_interface() |
|
|
|
if __name__ == "__main__": |
|
asyncio.run(main()) |