Skip days stored per user

This commit is contained in:
Johnny Gear 2026-03-05 20:16:31 -06:00
parent 6140cca5bf
commit e735e46738
7 changed files with 135 additions and 18 deletions

View file

@ -180,5 +180,13 @@ class Repeat(BaseModel):
class SkipDay(BaseModel): class SkipDay(BaseModel):
date = DateField(unique=True) date = DateField(unique=True)
user = ForeignKeyField(
User,
column_name='user_id',
field='id',
null=False,
backref='skip_days'
)
class Meta: class Meta:
table_name = 'skip_day' table_name = 'skip_day'

View file

@ -108,21 +108,21 @@ def repeat_clear(id):
q = Repeat.delete() q = Repeat.delete()
q.execute() q.execute()
def skip_day_put(date): def skip_day_put(user, date):
return SkipDay.create(date=date) return SkipDay.create(user=user, date=date)
def skip_day_delete(date): def skip_day_delete(user, date):
q = SkipDay.delete().where(SkipDay.date == date) q = SkipDay.delete().where(SkipDay.user == user and SkipDay.date == date)
return q.execute() return q.execute()
def skip_days_upcoming(): def skip_days_upcoming(user):
return (SkipDay.select() return (SkipDay.select()
.where(SkipDay.date >= datetime.date.today()) .where(SkipDay.user == user and SkipDay.date >= datetime.date.today())
.order_by(SkipDay.date) .order_by(SkipDay.date)
.limit(10)) .limit(10))
def skip_day_contains(date): def skip_day_contains(user, date):
q = SkipDay.select().where(SkipDay.date == date) q = SkipDay.select().where(SkipDay.user == user and SkipDay.date == date)
return len(q) > 0 return len(q) > 0
def order_status_put(orders_pool, user, mastodon_id, created_at, due_at, text, punishment_for=None): def order_status_put(orders_pool, user, mastodon_id, created_at, due_at, text, punishment_for=None):

View file

@ -0,0 +1,52 @@
"""Peewee migrations -- 017_delete_skip_days.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
migrator.remove_model('skip_day')
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
@migrator.create_model
class SkipDay(pw.Model):
id = pw.AutoField()
date = pw.DateField(unique=True)
class Meta:
table_name = "skip_day"

View file

@ -0,0 +1,53 @@
"""Peewee migrations -- 018_add_skip_days.py.
Some examples (model - class or model name)::
> Model = migrator.orm['table_name'] # Return model in current state by name
> Model = migrator.ModelClass # Return model in current state by name
> migrator.sql(sql) # Run custom SQL
> migrator.run(func, *args, **kwargs) # Run python function with the given args
> migrator.create_model(Model) # Create a model (could be used as decorator)
> migrator.remove_model(model, cascade=True) # Remove a model
> migrator.add_fields(model, **fields) # Add fields to a model
> migrator.change_fields(model, **fields) # Change fields
> migrator.remove_fields(model, *field_names, cascade=True)
> migrator.rename_field(model, old_field_name, new_field_name)
> migrator.rename_table(model, new_table_name)
> migrator.add_index(model, *col_names, unique=False)
> migrator.add_not_null(model, *field_names)
> migrator.add_default(model, field_name, default)
> migrator.add_constraint(model, name, sql)
> migrator.drop_index(model, *col_names)
> migrator.drop_not_null(model, *field_names)
> migrator.drop_constraints(model, *constraints)
"""
from contextlib import suppress
import peewee as pw
from peewee_migrate import Migrator
with suppress(ImportError):
import playhouse.postgres_ext as pw_pext
def migrate(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your migrations here."""
@migrator.create_model
class SkipDay(pw.Model):
id = pw.AutoField()
date = pw.DateField(unique=True)
user = pw.ForeignKeyField(column_name='user_id', field='id', model=migrator.orm['user'])
class Meta:
table_name = "skip_day"
def rollback(migrator: Migrator, database: pw.Database, *, fake=False):
"""Write your rollback migrations here."""
migrator.remove_model('skip_day')

View file

@ -51,10 +51,9 @@ class OrderScheduler():
return return
# Skip stored dates # Skip stored dates
# TODO: Store these per user
today = datetime.datetime.now(tz=self.tz).strftime("%Y-%m-%d") today = datetime.datetime.now(tz=self.tz).strftime("%Y-%m-%d")
logger.info('Today %s' % today) logger.info('Today %s' % today)
if (skip_day_contains(today)): if (skip_day_contains(orders_pool.user, today)):
logger.info('Today is a skip day') logger.info('Today is a skip day')
return return

View file

@ -45,7 +45,7 @@ class DomAddCommand(TelegramCommand):
yield f"Successfully added {dom_username} to your list of doms" yield f"Successfully added {dom_username} to your list of doms"
t = Telegram(session) t = Telegram(session)
await t.message_send(f"@{sub_username} has added you as a dom. You may administer their orders at {FLASK_URL}", dom.telegram_chat_id) await t.message_send(dom.telegram_chat_id, f"@{sub_username} has added you as a dom. You may administer their orders at {FLASK_URL}")
class DomRemoveCommand(TelegramCommand): class DomRemoveCommand(TelegramCommand):
command_regex = re.compile(r"^\/dom_remove( (?P<username>@?\w+))$") command_regex = re.compile(r"^\/dom_remove( (?P<username>@?\w+))$")
@ -72,7 +72,7 @@ class DomRemoveCommand(TelegramCommand):
yield f"Successfully removed {dom_username} from your list of doms" yield f"Successfully removed {dom_username} from your list of doms"
t = Telegram(session) t = Telegram(session)
await t.message_send(f"@{sub_username} has removed you as a dom.", dom.telegram_chat_id) await t.message_send(dom.telegram_chat_id, f"@{sub_username} has removed you as a dom.")
class SkipDayAddCommand(TelegramCommand): class SkipDayAddCommand(TelegramCommand):
@ -84,8 +84,10 @@ class SkipDayAddCommand(TelegramCommand):
response = await forResponse() response = await forResponse()
user = user_get(update['message']['chat']['username'])
skip_day = datetime.date.fromisoformat(response) skip_day = datetime.date.fromisoformat(response)
skip_day_put(skip_day) skip_day_put(user, skip_day)
yield f"Skip day {response} has been added" yield f"Skip day {response} has been added"
except ValueError: except ValueError:
@ -102,8 +104,10 @@ class SkipDayDeleteCommand(TelegramCommand):
response = await forResponse() response = await forResponse()
user = user_get(update['message']['chat']['username'])
skip_day = datetime.date.fromisoformat(response) skip_day = datetime.date.fromisoformat(response)
rows = skip_day_delete(skip_day) rows = skip_day_delete(user, skip_day)
if rows > 0: if rows > 0:
yield f"Skip day {skip_day} has been deleted" yield f"Skip day {skip_day} has been deleted"
@ -116,7 +120,8 @@ class SkipDaysCommand(TelegramCommand):
command_text = "/skip_days" command_text = "/skip_days"
async def exec_inner(self, text, update, session, forResponse=None, reply=None): async def exec_inner(self, text, update, session, forResponse=None, reply=None):
dates = skip_days_upcoming() user = user_get(update['message']['chat']['username'])
dates = skip_days_upcoming(user)
yield ("Upcoming skip days -\n" + yield ("Upcoming skip days -\n" +
"\n".join([d.date.isoformat() for d in dates])) "\n".join([d.date.isoformat() for d in dates]))

View file

@ -126,14 +126,14 @@ async def handle_commands(commands=[], loop=None):
session, session,
forResponse=forResponse forResponse=forResponse
): ):
await t.message_send(reply, chat_id) await t.message_send(chat_id, reply)
except TimeoutError: except TimeoutError:
if chat_id in command_futures: if chat_id in command_futures:
del command_futures[chat_id] del command_futures[chat_id]
await t.message_send("Your command has timed out", chat_id) await t.message_send(chat_id, "Your command has timed out")
except Exception: except Exception:
await t.message_send('There was a problem with your command', chat_id) await t.message_send(chat_id, 'There was a problem with your command')
logger.exception('Problem while executing a command') logger.exception('Problem while executing a command')
task = asyncio.create_task( task = asyncio.create_task(