浏览代码

Adding a new feature to functional plugins, allowing a major cleanup of session

Kirk Trombley 5 年之前
父节点
当前提交
c787a6a041
共有 3 个文件被更改,包括 53 次插入114 次删除
  1. 11 2
      lib/rollbot/messaging.py
  2. 4 2
      lib/rollbot/plugins.py
  3. 38 110
      src/plugins/session.py

+ 11 - 2
lib/rollbot/messaging.py

@@ -162,6 +162,15 @@ class RollbotFailure(Enum):
     PERMISSIONS = auto()
     INTERNAL_ERROR = auto()
 
+    def get_debugging(self):
+        reason = getattr(self, "reason", None)
+        return {} if reason is None else { "explain": reason }
+        
+
+    def with_reason(self, reason):
+        self.reason = reason
+        return self
+
 
 _RESPONSE_TEMPLATE = """Response{
     Original Message: %s,
@@ -195,9 +204,9 @@ class RollbotResponse:
         elif self.failure == RollbotFailure.INVALID_SUBCOMMAND:
             self.failure_msg = "Sorry - the sub-command you used for %s was not valid." % self.msg.command
         elif self.failure == RollbotFailure.INVALID_ARGUMENTS:
-            self.failure_msg = "Sorry - %s cannot use those arguments!" % self.msg.command
+            self.failure_msg = "Sorry - !%s cannot use those arguments!" % self.msg.command
         elif self.failure == RollbotFailure.SERVICE_DOWN:
-            self.failure_msg = "Sorry - %s relies on a service I couldn't reach!" % self.msg.command
+            self.failure_msg = "Sorry - !%s relies on a service I couldn't reach!" % self.msg.command
         elif self.failure == RollbotFailure.PERMISSIONS:
             self.failure_msg = "Sorry - you don't have permission to use that command or sub-command in this chat!"
         elif self.failure == RollbotFailure.INTERNAL_ERROR:

+ 4 - 2
lib/rollbot/plugins.py

@@ -60,10 +60,12 @@ def as_plugin(command):
 
         def on_command_standin(self, db, msg):
             res = fn(*[c(self, db, msg) for c in converters])
-            if isinstance(res, RollbotResponse):
+            if res is None:
+                return RollbotResponse(msg, respond=False)
+            elif isinstance(res, RollbotResponse):
                 return res
             elif isinstance(res, RollbotFailure):
-                return RollbotResponse(msg, failure=res)
+                return RollbotResponse(msg, failure=res, debugging=res.get_debugging())
             else:
                 return RollbotResponse(msg, txt=str(res))
 

+ 38 - 110
src/plugins/session.py

@@ -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)
+