From bfca81e8ac346d7cf82c75515ccf10f14598bc01 Mon Sep 17 00:00:00 2001 From: Johnny Gear Date: Thu, 13 Nov 2025 22:03:20 -0600 Subject: [PATCH] Orders - Refactor out posting Use stored due_at --- db.py | 10 ++-- orders.py | 144 +++++++++++++++++++++++++++++++------------------- scheduling.py | 10 ++-- util.py | 7 +-- 4 files changed, 105 insertions(+), 66 deletions(-) diff --git a/db.py b/db.py index f8e6c07..c4f9007 100644 --- a/db.py +++ b/db.py @@ -23,6 +23,7 @@ TABLE_ORDER_STATUS = ''' id INTEGER PRIMARY KEY AUTOINCREMENT, mastodon_id TEXT NOT NULL, created_at TIMESTAMP NOT NULL, + due_at TIMESTAMP NOT NULL, text TEXT NOT NULL, confirmed_at TIMESTAMP, punishment_id INTEGER, @@ -90,16 +91,17 @@ class Database: c.execute(sql, [date]) return c.fetchone() is not None - def order_status_put(self, mastodon_id, created_at, text): + def order_status_put(self, mastodon_id, created_at, due_at, text): self.update( ''' INSERT INTO order_status - (mastodon_id, created_at, text) - VALUES (?, ?, ?); + (mastodon_id, created_at, due_at, text) + VALUES (?, ?, ?, ?); ''', [ mastodon_id, created_at, + due_at, text ] ) @@ -107,7 +109,7 @@ class Database: def order_status_outstanding(self): c = self.conn.cursor() sql = ''' - SELECT id, mastodon_id, created_at, confirmed_at + SELECT id, mastodon_id, created_at, due_at, confirmed_at FROM order_status WHERE confirmed_at IS NULL AND punishment_id IS NULL ''' diff --git a/orders.py b/orders.py index eeaa74b..67bcadc 100644 --- a/orders.py +++ b/orders.py @@ -7,10 +7,31 @@ from db import Database from mastodon import Mastodon from telegram import Telegram from settings import MASTODON_USERNAME, ORDER_TIMEOUT -from util import order_time +from util import timezone logger = logging.getLogger(__name__) +async def order_mastodon_post(session, orders_str, repeats, due_at): + m_post = "Here are today's orders for @%s -\n\n" % MASTODON_USERNAME + m_post += orders_str + "\n\n" + if repeats > 1: + m_post += f"These are the same orders from the last {repeats} days\n\n" + m_post += "Proof of compliance is due by " + due_at.strftime("%H:%M %p") + + m = Mastodon(session) + return await m.statusPost(m_post) + +async def order_telegram_post(session, orders_str, repeats, due_at, m_url): + t_post = "Here are your orders -\n\n" + t_post += orders_str + "\n\n" + if repeats > 1: + t_post += f"These are the same orders from the last {repeats} days\n\n" + t_post += "Proof of compliance is due by " + due_at.strftime("%H:%M %p") + "\n\n" + t_post += m_url + + t = Telegram(session) + await t.message_send(t_post) + async def order_issue(): async with make_session() as session: orders_info = generate_order() @@ -21,46 +42,84 @@ async def order_issue(): orders_str = "\n".join(orders_info['orders']) - due_by = "Proof of compliance is due by %s" % ( - (datetime.datetime.combine( - datetime.datetime.today(), - order_time() - ) + ORDER_TIMEOUT - ).strftime("%H:%M %p") - ) + created_at = datetime.datetime.now(tz=timezone()) + due_at = created_at + ORDER_TIMEOUT - m_post = "Here are today's orders for @%s -\n\n" % MASTODON_USERNAME - if "count" in orders_info and orders_info['count'] > 1: - m_post += f"These are the same orders from the last {orders_info['count']} days\n\n" - m_post += orders_str + "\n\n" - m_post += due_by + repeats_count = orders_info.get('count', 0) - m = Mastodon(session) - m_status = await m.statusPost(m_post) + m_status = await order_mastodon_post( + session, + orders_str, + repeats_count, + due_at + ) - t_post = "Here are your orders -\n\n" - t_post += orders_str + "\n\n" - t_post += due_by + "\n\n" - t_post += m_status['url'] - - t = Telegram(session) - await t.message_send(t_post) + await order_telegram_post( + session, + orders_str, + repeats_count, + due_at, + m_status['url'] + ) db = Database() db.order_status_put( m_status['id'], - m_status['created_at'], - m_post + created_at, + due_at, + orders_str ) + return due_at + +async def punishment_mastodon_post(session, punishment_str, reply_id=None): + post = "@%s has failed to post proof of compliance. Here is the punishment -\n\n" % MASTODON_USERNAME + post += punishment_str + + m = Mastodon(session) + return await m.statusPost( + post, + in_reply_to_id=reply_id + ) + +async def punishment_telegram_post(session, punishment_str, m_url): + post = "You failed to show proof of compliance. Here is your punishment -\n\n" + post += punishment_str + "\n\n" + post += m_url + + t = Telegram(session) + await t.message_send(post) + +async def punishment_issue(db, session, outstanding_order): + punishment = generate_punishment() + punishment_str = "\n".join(punishment) + + punishment_status = await punishment_mastodon_post( + session, + punishment_str, + outstanding_order['mastodon_id'], + ) + + await punishment_telegram_post( + session, + punishment_str, + punishment_status['url'] + ) + + db.punishment_status_put( + outstanding_order['id'], + punishment_status['id'], + punishment_status['created_at'], + punishment_str + ) + async def order_check(): async with make_session() as session: - m = Mastodon(session) - t = Telegram(session) db = Database() outstanding_orders = db.order_status_outstanding() for outstanding_order in outstanding_orders: + m = Mastodon(session) context = await m.statusContext(outstanding_order['mastodon_id']) confirmed_at = None @@ -72,35 +131,14 @@ async def order_check(): ): confirmed_at = d['created_at'] db.order_status_confirm(outstanding_order['id'], confirmed_at) - logger.info('Confirmed order %s' % (outstanding_order['created_at'])) + logger.info('Confirmed order %s' % (outstanding_order['id'])) break if confirmed_at is None: - logger.info('Order %s remains unconfirmed' % (outstanding_order['created_at'])) + logger.info('Order %s remains unconfirmed' % (outstanding_order['id'])) - oo_created_at = datetime.datetime.fromisoformat(outstanding_order['created_at']) - if(oo_created_at + ORDER_TIMEOUT < datetime.datetime.now(datetime.UTC)): - logger.info('Time to issue a punishment for %s' % outstanding_order['created_at']) + due_at = datetime.datetime.fromisoformat(outstanding_order['due_at']) + if(due_at < datetime.datetime.now(datetime.UTC)): + logger.info('Time to issue a punishment for %s' % outstanding_order['id']) - punishment = generate_punishment() - punishment_str = "\n".join(punishment) - - m_post = "@%s has failed to post proof of compliance. Here is the punishment -\n\n" % MASTODON_USERNAME - m_post += punishment_str - - punishment_status = await m.statusPost( - m_post, - in_reply_to_id=outstanding_order['mastodon_id'] - ) - - t_post = "You failed to show proof of compliance. Here is your punishment -\n\n" - t_post += punishment_str + "\n\n" - t_post += punishment_status['url'] - await t.message_send(t_post) - - db.punishment_status_put( - outstanding_order['id'], - punishment_status['id'], - punishment_status['created_at'], - m_post - ) + await punishment_issue(db, session, outstanding_order) diff --git a/scheduling.py b/scheduling.py index 16a994a..d3a6444 100644 --- a/scheduling.py +++ b/scheduling.py @@ -4,7 +4,7 @@ import pytz from scheduler.asyncio import Scheduler -from settings import TIMEZONE, ORDER_TIME, ORDER_TIMEOUT +from settings import TIMEZONE from orders import order_issue, order_check from db import Database from util import order_time @@ -31,7 +31,7 @@ class OrderScheduler(): outstanding_orders = db.order_status_outstanding() for oo in outstanding_orders: self.scheduler.once( - datetime.datetime.fromisoformat(oo['created_at']) + ORDER_TIMEOUT + GRACE_PERIOD, + datetime.datetime.fromisoformat(oo['due_at']) + GRACE_PERIOD, self.scheduled_check ) @@ -52,13 +52,11 @@ class OrderScheduler(): logger.info('Today is a skip day') return - await order_issue() + due_at = await order_issue() # Schedule check self.scheduler.once( - datetime.datetime.now(tz=self.tz) + - ORDER_TIMEOUT + - GRACE_PERIOD, + due_at + GRACE_PERIOD, self.scheduled_check ) diff --git a/util.py b/util.py index 61197b0..3290bd0 100644 --- a/util.py +++ b/util.py @@ -7,12 +7,13 @@ from settings import TIMEZONE, ORDER_TIME def make_session(): return aiohttp.ClientSession() -def order_time(): - tz = pytz.timezone(TIMEZONE) +def timezone(): + return pytz.timezone(TIMEZONE) +def order_time(): order_time_arr = list(map(int, ORDER_TIME.split(':'))) return datetime.time( hour=order_time_arr[0], minute=order_time_arr[1], - tzinfo=tz + tzinfo=timezone() )