|
@@ -1,21 +1,11 @@
|
|
|
import datetime
|
|
|
|
|
|
-from sqlalchemy import Column, Integer, String, DateTime
|
|
|
+from rollbot import RollbotFailure, as_plugin, pop_arg, as_group_singleton
|
|
|
|
|
|
-from rollbot import RollbotResponse, RollbotFailure, as_plugin, ModelBase, pop_arg
|
|
|
|
|
|
-
|
|
|
-class DnDSession(ModelBase):
|
|
|
- __tablename__ = "dnd_session"
|
|
|
- group_id = Column(String, primary_key=True)
|
|
|
- session_time = Column(DateTime)
|
|
|
-
|
|
|
-
|
|
|
-class DnDCancellationBlame(ModelBase):
|
|
|
- __tablename__ = "dnd_session_cancel_blame"
|
|
|
- group_id = Column(String, primary_key=True)
|
|
|
- name = Column(String, primary_key=True)
|
|
|
- count = Column(Integer)
|
|
|
+@as_group_singleton
|
|
|
+class DnDSessionV2:
|
|
|
+ session_time: datetime.datetime
|
|
|
|
|
|
|
|
|
WEEKDAYS = {
|
|
@@ -87,129 +77,67 @@ def parse_datetime(arg_text):
|
|
|
)
|
|
|
|
|
|
|
|
|
-
|
|
|
-def get_latest_session(db, group_id):
|
|
|
- saved = db.query(DnDSession).get(group_id)
|
|
|
- if saved is None:
|
|
|
- return
|
|
|
-
|
|
|
- if saved.session_time >= datetime.datetime.now():
|
|
|
- return saved
|
|
|
-
|
|
|
- db.delete(saved)
|
|
|
- return
|
|
|
-
|
|
|
-
|
|
|
-def get_fmt_next(db, group_id):
|
|
|
- nxt = get_latest_session(db, group_id)
|
|
|
- if nxt is None or nxt.session_time < datetime.datetime.now():
|
|
|
+def get_fmt_next(nxt):
|
|
|
+ if nxt is None or nxt.session_time is None or nxt.session_time < datetime.datetime.now():
|
|
|
return "No upcoming session found."
|
|
|
-
|
|
|
return "Next DnD session scheduled for " + nxt.session_time.strftime("%b %d, %Y, at %I:%M %p")
|
|
|
|
|
|
|
|
|
-def session_next(db, message, arg_text):
|
|
|
+def session_next(session_data, arg_text):
|
|
|
dt = parse_datetime(arg_text)
|
|
|
if dt is None:
|
|
|
- return RollbotResponse(
|
|
|
- message,
|
|
|
- failure=RollbotFailure.INVALID_ARGUMENTS,
|
|
|
- debugging={"explain": "Could not process argument as a date/time."}
|
|
|
- )
|
|
|
-
|
|
|
+ return RollbotFailure.INVALID_ARGUMENTS.with_reason("Could not process argument as a date/time.")
|
|
|
if dt < datetime.datetime.now():
|
|
|
- return RollbotResponse(
|
|
|
- message,
|
|
|
- failure=RollbotFailure.INVALID_ARGUMENTS,
|
|
|
- debugging={"explain": "Cannot schedule sessions in the past."}
|
|
|
- )
|
|
|
-
|
|
|
- nxt = get_latest_session(db, message.group_id)
|
|
|
- if nxt is not None:
|
|
|
- db.delete(nxt)
|
|
|
-
|
|
|
- db.add(DnDSession(group_id=message.group_id, session_time=dt))
|
|
|
-
|
|
|
- return RollbotResponse(message, txt=get_fmt_next(db, message.group_id))
|
|
|
+ return RollbotFailure.INVALID_ARGUMENTS.with_reason("Cannot schedule sessions in the past.")
|
|
|
+
|
|
|
+ session_data.session_time = dt
|
|
|
+ return get_fmt_next(session_data)
|
|
|
|
|
|
|
|
|
-def session_worst(db, message, arg_text):
|
|
|
- rankings = db.query(DnDCancellationBlame
|
|
|
- ).filter(DnDCancellationBlame.group_id == message.group_id
|
|
|
- ).order_by(DnDCancellationBlame.count.desc()
|
|
|
- ).all()
|
|
|
-
|
|
|
- if len(rankings) == 0:
|
|
|
- return RollbotResponse(message, txt="I don't have any records of cancelled sessions.")
|
|
|
-
|
|
|
- rankings = "\n".join(f"{i+1}: {r.name} has cancelled {r.count} session(s)" for i, r in enumerate(rankings))
|
|
|
- return RollbotResponse(message, txt="Rankings:\n"+rankings)
|
|
|
-
|
|
|
-
|
|
|
-def session_view(db, message, arg_text):
|
|
|
- return RollbotResponse(message, txt=get_fmt_next(db, message.group_id))
|
|
|
-
|
|
|
-
|
|
|
-def session_late(db, message, arg_text):
|
|
|
- nxt = get_latest_session(db, message.group_id)
|
|
|
- if nxt is None:
|
|
|
- return RollbotResponse(message, txt="No upcoming session found.")
|
|
|
+def session_late(session_data, arg_text):
|
|
|
+ if session_data.session_time is None:
|
|
|
+ return "No upcoming session found."
|
|
|
|
|
|
now = datetime.datetime.now()
|
|
|
- nxt = nxt.session_time
|
|
|
+ nxt = session_data.session_time
|
|
|
if nxt >= now:
|
|
|
- return RollbotResponse(message, txt="You're not late yet!")
|
|
|
+ return "You're not late yet!"
|
|
|
|
|
|
late = (now - nxt).total_seconds() / 60
|
|
|
- return RollbotResponse(message, txt="You're running %.2f minutes late..." % late)
|
|
|
-
|
|
|
+ return f"You're running {late:.2f} minutes late..."
|
|
|
|
|
|
-def session_cancel(db, message, arg_text):
|
|
|
- nxt = get_latest_session(db, message.group_id)
|
|
|
- if nxt is None:
|
|
|
- return RollbotResponse(message, txt="No upcoming session found.")
|
|
|
|
|
|
- db.delete(nxt)
|
|
|
-
|
|
|
- if arg_text is not None and len(arg_text) > 0:
|
|
|
- counter = db.query(DnDCancellationBlame).get((message.group_id, arg_text))
|
|
|
- if counter is not None:
|
|
|
- counter.count += 1
|
|
|
- else:
|
|
|
- db.add(DnDCancellationBlame(group_id=message.group_id, name=arg_text, count=1))
|
|
|
- return RollbotResponse(message, txt=f"Sigh, session cancelled, and it's all {arg_text}'s fault!")
|
|
|
- else:
|
|
|
- return RollbotResponse(message, txt=f"Sigh, session cancelled...")
|
|
|
+def session_cancel(session_data, arg_text):
|
|
|
+ if session_data.session_time is None:
|
|
|
+ return "No upcoming session found."
|
|
|
+
|
|
|
+ session_data.session_time = None
|
|
|
+ return "Sigh, session cancelled..."
|
|
|
|
|
|
|
|
|
SUBCOMMANDS = dict(
|
|
|
next=session_next,
|
|
|
- worst=session_worst,
|
|
|
- view=session_view,
|
|
|
+ view=lambda session_data, _: get_fmt_next(session_data),
|
|
|
late=session_late,
|
|
|
cancel=session_cancel
|
|
|
)
|
|
|
|
|
|
NEEDS_ADMIN = ("next", "cancel")
|
|
|
|
|
|
+VALID_TEXT = "Valid subcommands are: " + ", ".join(f"!{sc}" for sc in SUBCOMMANDS)
|
|
|
+
|
|
|
|
|
|
@as_plugin
|
|
|
-def session(db, message):
|
|
|
- subcommand, arg_text = pop_arg(message.raw_args)
|
|
|
-
|
|
|
- if subcommand is None:
|
|
|
- return RollbotResponse(message, failure=RollbotFailure.MISSING_SUBCOMMAND)
|
|
|
-
|
|
|
- if subcommand not in SUBCOMMANDS:
|
|
|
- return RollbotResponse(
|
|
|
- message,
|
|
|
- failure=RollbotFailure.INVALID_SUBCOMMAND,
|
|
|
- debugging={
|
|
|
- "explain": f"Must be one of: {', '.join(repr(s) for s in SUBCOMMANDS)}."
|
|
|
- }
|
|
|
- )
|
|
|
+def session(bot, subc, session_data: DnDSessionV2):
|
|
|
+ if subc is None:
|
|
|
+ return RollbotFailure.MISSING_SUBCOMMAND.with_reason(VALID_TEXT)
|
|
|
+
|
|
|
+ if subc.command not in SUBCOMMANDS:
|
|
|
+ return RollbotFailure.INVALID_SUBCOMMAND.with_reason(VALID_TEXT)
|
|
|
+
|
|
|
+ if subc.command in NEEDS_ADMIN and not subc.from_admin:
|
|
|
+ return RollbotFailure.PERMISSIONS
|
|
|
|
|
|
- if subcommand in NEEDS_ADMIN and not message.from_admin:
|
|
|
- return RollbotResponse(message, failure=RollbotFailure.PERMISSIONS)
|
|
|
+ return SUBCOMMANDS[subc.command](session_data, subc.raw_args)
|
|
|
|
|
|
- return SUBCOMMANDS[subcommand](db, message, arg_text)
|
|
|
+
|