Semi-stable? Pingme works. Stability of websockets under asyncio uncertain
This commit is contained in:
parent
42f2a64967
commit
5f834e3409
|
|
@ -6,6 +6,7 @@ import slack_util
|
|||
|
||||
# Useful channels
|
||||
GENERAL = "C0CFHPNEM"
|
||||
RANDOM = "C0CFDQWUW"
|
||||
COMMAND_CENTER_ID = "GCR631LQ1"
|
||||
SLAVES_TO_THE_MACHINE_ID = "C9WUQBYNP"
|
||||
BOTZONE = "C3BF2MFKM"
|
||||
|
|
@ -26,4 +27,5 @@ async def channel_check_callback(slack: SlackClient, msg: dict, match: Match) ->
|
|||
slack_util.reply(slack, msg, response)
|
||||
|
||||
|
||||
channel_check_hook = slack_util.Hook(channel_check_callback, pattern=r"channel id\s*(.*)")
|
||||
channel_check_hook = slack_util.Hook(channel_check_callback,
|
||||
pattern=r"channel id\s*(.*)")
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ def lookup_brother_userids(brother: scroll_util.Brother) -> List[str]:
|
|||
return result
|
||||
|
||||
|
||||
identify_hook = slack_util.Hook(identify_callback, pattern=r"i am (.*)")
|
||||
identify_hook = slack_util.Hook(identify_callback, pattern=r"my scroll is (.*)")
|
||||
identify_other_hook = slack_util.Hook(identify_other_callback, pattern=r"<@(.*)>\s+has scroll\s+(.*)")
|
||||
check_hook = slack_util.Hook(check_callback, pattern=r"my scroll")
|
||||
name_hook = slack_util.Hook(name_callback, pattern=r"my name")
|
||||
check_hook = slack_util.Hook(check_callback, pattern=r"what is my scroll")
|
||||
name_hook = slack_util.Hook(name_callback, pattern=r"what is my name")
|
||||
|
|
|
|||
36
main.py
36
main.py
|
|
@ -1,5 +1,5 @@
|
|||
import asyncio
|
||||
from typing import List, Any, Match, AsyncGenerator
|
||||
from typing import List, Any, AsyncGenerator
|
||||
|
||||
from slackclient import SlackClient # Obvious
|
||||
|
||||
|
|
@ -8,6 +8,7 @@ import identifier
|
|||
import job_nagger
|
||||
import job_signoff
|
||||
import management_commands
|
||||
import periodicals
|
||||
import scroll_util
|
||||
import slack_util
|
||||
import slavestothemachine
|
||||
|
|
@ -56,16 +57,14 @@ def main() -> None:
|
|||
help_callback = management_commands.list_hooks_callback_gen(wrap.hooks)
|
||||
wrap.add_hook(slack_util.Hook(help_callback, pattern=management_commands.bot_help_pattern))
|
||||
|
||||
# Schedule?
|
||||
async def do_later(slk: SlackClient, msg: dict, match: Match):
|
||||
time = int(match.group(1))
|
||||
await asyncio.sleep(time)
|
||||
slack_util.reply(slk, msg, "hello!")
|
||||
|
||||
wrap.add_hook(slack_util.Hook(do_later, "pingme\s+(\d+)"))
|
||||
# Add boozebot
|
||||
wrap.add_passive(periodicals.ItsTenPM())
|
||||
|
||||
event_loop = asyncio.get_event_loop()
|
||||
event_loop.run_until_complete(wrap.listen())
|
||||
message_handling = wrap.respond_messages()
|
||||
passive_handling = wrap.run_passives()
|
||||
both = asyncio.gather(message_handling, passive_handling)
|
||||
event_loop.run_until_complete(both)
|
||||
|
||||
|
||||
class ClientWrapper(object):
|
||||
|
|
@ -88,10 +87,26 @@ class ClientWrapper(object):
|
|||
# Hooks go regex -> callback on (slack, msg, match)
|
||||
self.hooks: List[slack_util.Hook] = []
|
||||
|
||||
# Periodicals are just wrappers around an iterable, basically
|
||||
self.passives: List[slack_util.Passive] = []
|
||||
|
||||
# Scheduled events handling
|
||||
def add_passive(self, per: slack_util.Passive) -> None:
|
||||
self.passives.append(per)
|
||||
|
||||
async def run_passives(self) -> None:
|
||||
# Make a task to repeatedly spawn each event
|
||||
awaitables = [p.run(self.slack) for p in self.passives]
|
||||
await asyncio.gather(*awaitables)
|
||||
|
||||
# Message handling
|
||||
def add_hook(self, hook: slack_util.Hook) -> None:
|
||||
self.hooks.append(hook)
|
||||
|
||||
async def listen(self):
|
||||
async def respond_messages(self) -> None:
|
||||
"""
|
||||
Asynchronous tasks that eternally reads and responds to messages.
|
||||
"""
|
||||
async for _ in self.spool_tasks():
|
||||
print("Handling a message...!")
|
||||
|
||||
|
|
@ -108,6 +123,7 @@ class ClientWrapper(object):
|
|||
|
||||
# Strip garbage
|
||||
msg['text'] = msg['text'].strip()
|
||||
print("Recv: \"{}\"".format(msg['text']))
|
||||
|
||||
# Handle debug
|
||||
if msg['text'][:6] == "DEBUG ":
|
||||
|
|
|
|||
|
|
@ -24,4 +24,6 @@ async def reboot_callback(slack: SlackClient, msg: dict, match: Match) -> None:
|
|||
|
||||
# Make hooks
|
||||
bot_help_pattern = r"bot help" # Can't init this directly, as it relies on us knowing all other hooks. handle in main
|
||||
reboot_hook = slack_util.Hook(reboot_callback, pattern=r"reboot", channel_whitelist=[channel_util.COMMAND_CENTER_ID])
|
||||
reboot_hook = slack_util.Hook(reboot_callback,
|
||||
pattern=r"reboot",
|
||||
channel_whitelist=[channel_util.COMMAND_CENTER_ID])
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
import asyncio
|
||||
from datetime import datetime
|
||||
|
||||
from slackclient import SlackClient
|
||||
|
||||
import channel_util
|
||||
import slack_util
|
||||
|
||||
|
||||
def seconds_until(target: datetime) -> float:
|
||||
curr = datetime.now()
|
||||
delta = target - curr
|
||||
return delta.seconds
|
||||
|
||||
|
||||
class ItsTenPM(slack_util.Passive):
|
||||
async def run(self, slack: SlackClient) -> None:
|
||||
while True:
|
||||
# Get 10PM
|
||||
ten_pm = datetime.now().replace(hour=21, minute=0, second=0)
|
||||
|
||||
# Find out how long until it, then sleep that long
|
||||
delay = seconds_until(ten_pm)
|
||||
await asyncio.sleep(delay)
|
||||
|
||||
# Crow like a rooster
|
||||
slack_util.reply(slack, {}, "IT'S 10 PM!", in_thread=False, to_channel=channel_util.RANDOM)
|
||||
|
||||
# Wait a while before trying it again, to prevent duplicates
|
||||
await asyncio.sleep(60)
|
||||
|
|
@ -20,6 +20,9 @@ class Brother(object):
|
|||
self.name = name
|
||||
self.scroll = scroll
|
||||
|
||||
def __repr__(self):
|
||||
return "<Brother {}-{}>".format(self.name, self.scroll)
|
||||
|
||||
|
||||
# load the family tree
|
||||
familyfile = open("sortedfamilytree.txt", 'r')
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import asyncio
|
||||
import re
|
||||
from asyncio import Task
|
||||
from time import sleep
|
||||
from typing import Any, Optional, Generator, Match, Callable, List, Coroutine
|
||||
from typing import Any, Optional, Generator, Match, Callable, List, Coroutine, AsyncGenerator
|
||||
|
||||
from slackclient import SlackClient
|
||||
|
||||
|
|
@ -70,14 +70,20 @@ def message_stream(slack: SlackClient) -> Generator[dict, None, None]:
|
|||
"""
|
||||
# Do forever
|
||||
while True:
|
||||
if slack.rtm_connect(with_team_state=False, auto_reconnect=True):
|
||||
print("Waiting for messages")
|
||||
while True:
|
||||
sleep(1)
|
||||
update = slack.rtm_read()
|
||||
for item in update:
|
||||
if item.get('type') == 'message':
|
||||
yield item
|
||||
try:
|
||||
if slack.rtm_connect(with_team_state=False, auto_reconnect=True):
|
||||
print("Waiting for messages")
|
||||
while True:
|
||||
sleep(1)
|
||||
update = slack.rtm_read()
|
||||
for item in update:
|
||||
if item.get('type') == 'message':
|
||||
yield item
|
||||
except OSError as e:
|
||||
print("Error while reading messages:")
|
||||
print(e)
|
||||
except (ValueError, TypeError):
|
||||
print("Malformed message... Restarting connection")
|
||||
|
||||
sleep(5)
|
||||
print("Connection failed - retrying")
|
||||
|
|
@ -90,7 +96,7 @@ Callback = Callable[[SlackClient, dict, Match], MsgAction]
|
|||
class Hook(object):
|
||||
def __init__(self,
|
||||
callback: Callback,
|
||||
pattern: str = None,
|
||||
pattern: str,
|
||||
channel_whitelist: Optional[List[str]] = None,
|
||||
channel_blacklist: Optional[List[str]] = None):
|
||||
# Save all
|
||||
|
|
@ -100,9 +106,6 @@ class Hook(object):
|
|||
self.callback = callback
|
||||
|
||||
# Remedy some sensible defaults
|
||||
if self.pattern is None:
|
||||
self.pattern = ".*"
|
||||
|
||||
if self.channel_blacklist is None:
|
||||
import channel_util
|
||||
self.channel_blacklist = [channel_util.GENERAL]
|
||||
|
|
@ -135,3 +138,12 @@ class Hook(object):
|
|||
|
||||
def invoke(self, slack: SlackClient, msg: dict, match: Match):
|
||||
return self.callback(slack, msg, match)
|
||||
|
||||
|
||||
class Passive(object):
|
||||
"""
|
||||
Base class for Periodical tasks, such as reminders and stuff
|
||||
"""
|
||||
async def run(self, slack: SlackClient) -> None:
|
||||
# Run this passive routed through the specified slack client.
|
||||
raise NotImplementedError()
|
||||
|
|
|
|||
|
|
@ -89,6 +89,9 @@ async def dump_work_callback(slack: SlackClient, msg: dict, match: Match) -> Non
|
|||
|
||||
|
||||
# Make dem HOOKs
|
||||
count_work_hook = slack_util.Hook(count_work_callback, channel_whitelist=[channel_util.SLAVES_TO_THE_MACHINE_ID])
|
||||
dump_work_hook = slack_util.Hook(dump_work_callback, pattern="dump towel data",
|
||||
count_work_hook = slack_util.Hook(count_work_callback,
|
||||
pattern=".*",
|
||||
channel_whitelist=[channel_util.SLAVES_TO_THE_MACHINE_ID])
|
||||
dump_work_hook = slack_util.Hook(dump_work_callback,
|
||||
pattern="dump towel data",
|
||||
channel_whitelist=[channel_util.COMMAND_CENTER_ID])
|
||||
|
|
|
|||
Loading…
Reference in New Issue