Spaces:
Building
Building
File size: 3,971 Bytes
9e6af01 3a12425 9e6af01 5187cb9 3a12425 5187cb9 3a12425 5187cb9 3a12425 5187cb9 3a12425 5187cb9 3a12425 5187cb9 3a12425 5187cb9 3a12425 5187cb9 9e6af01 3a12425 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
from flask import Flask, render_template, Response
from sonatoki.ilo import Ilo
from sonatoki.Configs import PrefConfig
from atproto import FirehoseSubscribeReposClient, parse_subscribe_repos_message
from atproto import CAR, models
import json
import re
import emoji
import queue
import threading
from werkzeug.serving import run_simple
app = Flask(__name__)
message_queue = queue.Queue()
# Your existing code for Ilo and JSONExtra remains the same
ilo = Ilo(**PrefConfig)
class JSONExtra(json.JSONEncoder):
def default(self, obj):
try:
return json.JSONEncoder.default(self, obj)
except:
return repr(obj)
def clean_text(text: str) -> str:
text = emoji.replace_emoji(text, replace='')
text = re.sub(r'https?://\S+', '', text)
text = re.sub(r'[^A-Za-z\s]', '', text)
text = text.strip()
return text
def process_firehose():
client = FirehoseSubscribeReposClient()
def on_message_handler(message):
commit = parse_subscribe_repos_message(message)
if not isinstance(commit, models.ComAtprotoSyncSubscribeRepos.Commit):
return
car = CAR.from_bytes(commit.blocks)
for op in commit.ops:
if op.action in ["create"] and op.cid:
raw = car.blocks.get(op.cid)
cooked = models.get_or_create(raw, strict=False)
if not cooked:
continue
if cooked.py_type == "app.bsky.feed.post":
cleaned_text = clean_text(raw.get("text", ""))
if not cleaned_text or len(cleaned_text.split()) < 3:
continue
if not ilo.is_toki_pona(cleaned_text.lower()):
continue
url = f'https://bsky.app/profile/{commit.repo}/post/{op.path.split("/")[1]}'
message_queue.put({'text': raw.get("text", ""), 'url': url})
client.start(on_message_handler)
def generate_sse():
while True:
message = message_queue.get()
yield f"data: {json.dumps(message)}\n\n"
@app.route('/')
def index():
return """<!DOCTYPE html>
<html>
<head>
<title>Toki Pona Live Stream</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
background-color: #f5f5f5;
}
.message {
background: white;
padding: 15px;
margin: 10px 0;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
a {
color: #0066cc;
text-decoration: none;
}
h1 {
text-align: center;
}
</style>
</head>
<body>
<h1>Toki Pona Live Stream</h1>
<div id="messages"></div>
<script>
const evtSource = new EventSource("/stream");
const messages = document.getElementById('messages');
evtSource.onmessage = function(event) {
const data = JSON.parse(event.data);
const messageDiv = document.createElement('div');
messageDiv.className = 'message';
messageDiv.innerHTML = `
<p>${data.text}</p>
<a href="${data.url}" target="_blank">View on Bluesky</a>
`;
messages.insertBefore(messageDiv, messages.firstChild);
if (messages.children.length > 50) {
messages.removeChild(messages.lastChild);
}
};
</script>
</body>
</html>"""
@app.route('/stream')
def stream():
return Response(generate_sse(), mimetype='text/event-stream')
if __name__ == '__main__':
# Start the firehose processing in a separate thread
threading.Thread(target=process_firehose, daemon=True).start()
# Use run_simple instead of app.run
run_simple('localhost', 7860, app, use_reloader=True, use_debugger=True) |