This commit is contained in:
2026-08-16 12:02:37 -04:00
parent 268938abb1
commit fffb9c50b4
6 changed files with 66 additions and 49 deletions
+46 -39
View File
@@ -10,7 +10,7 @@ import yaml
import sqlite3
import re
import asyncio
from nio import AsyncClient, LoginResponse, RoomMessageText, SyncResponse, RoomSendResponse
from nio import AsyncClient, LoginResponse, MessageDirection, ProfileGetDisplayNameResponse, RoomMessageText, RoomMessagesResponse, RoomSendResponse, SyncResponse
from post import Post
import requests
import dbutil
@@ -64,7 +64,7 @@ class Room:
def init_db(self):
conn = dbutil.connect(self.db_path)
c = conn.cursor()
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS suggestions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user TEXT,
@@ -78,17 +78,17 @@ class Room:
)
''')
# Add is_posted column if it doesn't exist
c.execute("PRAGMA table_info(suggestions)")
_ = c.execute("PRAGMA table_info(suggestions)")
cols = [row[1] for row in c.fetchall()]
if 'is_posted' not in cols:
c.execute('ALTER TABLE suggestions ADD COLUMN is_posted INTEGER DEFAULT 0')
_ = c.execute('ALTER TABLE suggestions ADD COLUMN is_posted INTEGER DEFAULT 0')
if 'event_id' not in cols:
c.execute('ALTER TABLE suggestions ADD COLUMN event_id TEXT')
_ = c.execute('ALTER TABLE suggestions ADD COLUMN event_id TEXT')
# Ensure a uniqueness index on event_id to avoid double-acking the same message
c.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_suggestions_event_id ON suggestions(event_id)')
_ = c.execute('CREATE UNIQUE INDEX IF NOT EXISTS idx_suggestions_event_id ON suggestions(event_id)')
# New: table to log all !gettitles detections (prevents duplicates)
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS gettitles (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id TEXT,
@@ -101,7 +101,7 @@ class Room:
''')
# New: table to log all !mayhem detections (prevents duplicates)
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS mayhem (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id TEXT,
@@ -114,7 +114,7 @@ class Room:
''')
# New: table to log all !countvotes detections (prevents duplicates)
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS countvotes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id TEXT,
@@ -127,7 +127,7 @@ class Room:
''')
# New: table to log all !voteurl detections (prevents duplicates)
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS voteurl (
id INTEGER PRIMARY KEY AUTOINCREMENT,
event_id TEXT,
@@ -161,13 +161,14 @@ class Room:
return False
async def get_display_name(self, user_id):
assert self.client is not None
room = self.client.rooms.get(self.config.room_id)
if room and user_id in room.users:
member = room.users[user_id]
if hasattr(member, "display_name") and member.display_name:
return member.display_name
resp = await self.client.get_displayname(user_id)
if hasattr(resp, "displayname") and resp.displayname:
if isinstance(resp, ProfileGetDisplayNameResponse) and resp.displayname:
return resp.displayname
return user_id
@@ -219,6 +220,7 @@ class Room:
batch_size = self.config.batch_size
next_batch = None
fetched = 0
assert self.client is not None
while fetched < limit:
fetch_amount = min(batch_size, limit - fetched)
@@ -226,10 +228,10 @@ class Room:
self.config.room_id,
start=next_batch,
limit=fetch_amount,
direction="b"
direction=MessageDirection.back
)
if not hasattr(response, "chunk") or not response.chunk:
if not isinstance(response, RoomMessagesResponse) or not response.chunk:
break
for event in response.chunk:
@@ -304,7 +306,7 @@ class Room:
self.newly_inserted_posts = []
for post in self.posts:
try:
c.execute(
_ = c.execute(
"INSERT INTO suggestions (user, display_name, message, timestamp, age, is_posted, event_id) VALUES (?, ?, ?, ?, ?, ?, ?)",
post.as_tuple()
)
@@ -319,21 +321,21 @@ class Room:
room_id = self.config.room_id
conn = dbutil.connect("last_run.db")
c = conn.cursor()
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS last_run (
room_id TEXT PRIMARY KEY,
timestamp INTEGER,
datetime TEXT
)
''')
c.execute("PRAGMA table_info(last_run)")
_ = c.execute("PRAGMA table_info(last_run)")
cols = [row[1] for row in c.fetchall()]
if 'datetime' not in cols:
c.execute('ALTER TABLE last_run ADD COLUMN datetime TEXT')
_ = c.execute('ALTER TABLE last_run ADD COLUMN datetime TEXT')
now = int(_time.time())
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
c.execute('INSERT OR REPLACE INTO last_run (room_id, timestamp, datetime) VALUES (?, ?, ?)', (room_id, now, now_str))
_ = c.execute('INSERT OR REPLACE INTO last_run (room_id, timestamp, datetime) VALUES (?, ?, ?)', (room_id, now, now_str))
dbutil.commit(conn)
conn.close()
@@ -341,7 +343,7 @@ class Room:
room_id = self.config.room_id
conn = dbutil.connect("last_run.db")
c = conn.cursor()
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS last_run (
room_id TEXT PRIMARY KEY,
timestamp INTEGER,
@@ -349,11 +351,11 @@ class Room:
)
''')
c.execute("PRAGMA table_info(last_run)")
_ = c.execute("PRAGMA table_info(last_run)")
cols = [row[1] for row in c.fetchall()]
if 'datetime' not in cols:
c.execute('ALTER TABLE last_run ADD COLUMN datetime TEXT')
c.execute('SELECT timestamp FROM last_run WHERE room_id = ?', (room_id,))
_ = c.execute('ALTER TABLE last_run ADD COLUMN datetime TEXT')
_ = c.execute('SELECT timestamp FROM last_run WHERE room_id = ?', (room_id,))
row = c.fetchone()
conn.close()
if row:
@@ -366,7 +368,7 @@ class Room:
conn = dbutil.connect(self.db_path)
c = conn.cursor()
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
c.execute('''
_ = c.execute('''
INSERT OR IGNORE INTO gettitles (event_id, sender, timestamp, datetime)
VALUES (?, ?, ?, ?)
''', (event_id, sender, int(timestamp), dt_str))
@@ -381,7 +383,7 @@ class Room:
conn = dbutil.connect(self.db_path)
c = conn.cursor()
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
c.execute('''
_ = c.execute('''
INSERT OR IGNORE INTO mayhem (event_id, sender, timestamp, datetime)
VALUES (?, ?, ?, ?)
''', (event_id, sender, int(timestamp), dt_str))
@@ -396,7 +398,7 @@ class Room:
conn = dbutil.connect(self.db_path)
c = conn.cursor()
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
c.execute('''
_ = c.execute('''
INSERT OR IGNORE INTO countvotes (event_id, sender, timestamp, datetime)
VALUES (?, ?, ?, ?)
''', (event_id, sender, int(timestamp), dt_str))
@@ -411,7 +413,7 @@ class Room:
conn = dbutil.connect(self.db_path)
c = conn.cursor()
dt_str = datetime.datetime.fromtimestamp(int(timestamp)).isoformat(sep=' ', timespec='seconds')
c.execute('''
_ = c.execute('''
INSERT OR IGNORE INTO voteurl (event_id, sender, timestamp, datetime)
VALUES (?, ?, ?, ?)
''', (event_id, sender, int(timestamp), dt_str))
@@ -427,6 +429,7 @@ class Room:
next_batch = None
suggestion_votes = {}
all_events = []
assert self.client is not None
# First pass: collect all recent events (both messages and reactions)
for _ in range(15): # Look back further to catch more events
@@ -434,10 +437,10 @@ class Room:
self.config.room_id,
start=next_batch,
limit=batch_size,
direction="b"
direction=MessageDirection.back
)
if not hasattr(response, "chunk") or not response.chunk:
if not isinstance(response, RoomMessagesResponse) or not response.chunk:
break
all_events.extend(response.chunk)
@@ -522,6 +525,7 @@ class Room:
if since_ms is None:
since_ms = int(_time.time() * 1000)
assert self.client is not None
while True:
sync_response = await self.client.sync(timeout=30000)
if not isinstance(sync_response, SyncResponse):
@@ -585,6 +589,7 @@ class Room:
return result == "gettitles"
async def alert_post(self, post):
assert self.client is not None
content = {
"msgtype": "m.text",
"body": post
@@ -628,7 +633,7 @@ class Room:
if conditions:
query += " WHERE " + " AND ".join(conditions)
query += " ORDER BY timestamp ASC"
c.execute(query, tuple(params))
_ = c.execute(query, tuple(params))
rows = c.fetchall()
conn.close()
self.posts = [Post(poster=row[0], display_name=row[1], content=row[2], time=row[3], age=row[4], is_posted=bool(row[5])) for row in rows]
@@ -636,18 +641,18 @@ class Room:
def get_last_post(self):
conn = dbutil.connect("last_post.db")
c = conn.cursor()
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS last_post (
room_id TEXT PRIMARY KEY,
timestamp INTEGER,
datetime TEXT
)
''')
c.execute("PRAGMA table_info(last_post)")
_ = c.execute("PRAGMA table_info(last_post)")
cols = [row[1] for row in c.fetchall()]
if 'datetime' not in cols:
c.execute('ALTER TABLE last_post ADD COLUMN datetime TEXT')
c.execute('SELECT timestamp FROM last_post WHERE room_id = ?', (self.config.room_id,))
_ = c.execute('ALTER TABLE last_post ADD COLUMN datetime TEXT')
_ = c.execute('SELECT timestamp FROM last_post WHERE room_id = ?', (self.config.room_id,))
row = c.fetchone()
conn.close()
if row:
@@ -657,29 +662,29 @@ class Room:
def update_last_post(self):
conn = dbutil.connect("last_post.db")
c = conn.cursor()
c.execute('''
_ = c.execute('''
CREATE TABLE IF NOT EXISTS last_post (
room_id TEXT PRIMARY KEY,
timestamp INTEGER,
datetime TEXT
)
''')
c.execute("PRAGMA table_info(last_post)")
_ = c.execute("PRAGMA table_info(last_post)")
cols = [row[1] for row in c.fetchall()]
if 'datetime' not in cols:
c.execute('ALTER TABLE last_post ADD COLUMN datetime TEXT')
_ = c.execute('ALTER TABLE last_post ADD COLUMN datetime TEXT')
now = int(_time.time())
now_str = datetime.datetime.now().isoformat(sep=' ', timespec='seconds')
c.execute('INSERT OR REPLACE INTO last_post (room_id, timestamp, datetime) VALUES (?, ?, ?)',
_ = c.execute('INSERT OR REPLACE INTO last_post (room_id, timestamp, datetime) VALUES (?, ?, ?)',
(self.config.room_id, now, now_str))
dbutil.commit(conn)
conn.close()
async def post_suggestions(self):
assert self.client is not None
# Filter out already posted suggestions
unposted_posts = [post for post in self.posts if not post.is_posted]
if not unposted_posts:
await self.alert_post("No new unposted suggestions found.")
return
@@ -714,6 +719,7 @@ class Room:
async def post_suggestions_individually(self):
"""Post each unposted suggestion as its own message with a 👍 reaction for voting."""
assert self.client is not None
unposted_posts = [post for post in self.posts if not post.is_posted]
if not unposted_posts:
await self.alert_post("No new unposted suggestions found.")
@@ -791,7 +797,7 @@ class Room:
conn = dbutil.connect(self.db_path)
c = conn.cursor()
for post in posts:
c.execute(
_ = c.execute(
"UPDATE suggestions SET is_posted = 1 WHERE user = ? AND message = ? AND timestamp = ?",
(post.poster, post.content, post.time)
)
@@ -804,6 +810,7 @@ class Room:
async def acknowledge_new_suggestions(self):
"""React ✅ to newly recorded suggestions to confirm they were saved."""
assert self.client is not None
if not self.newly_inserted_posts:
return
for post in self.newly_inserted_posts: