Awaiting testing

This commit is contained in:
Jacob Henry 2019-02-22 05:27:03 -05:00
parent ddb6ffac10
commit c1dbe21c77
5 changed files with 170 additions and 51 deletions

View File

@ -2,7 +2,6 @@ from dataclasses import dataclass
from typing import List, Match, Callable, TypeVar, Optional, Iterable
from fuzzywuzzy import fuzz
from slackclient import SlackClient
import house_management
import identifier
@ -311,22 +310,27 @@ async def refresh_callback(event: slack_util.Event, match: Match) -> None:
async def nag_callback(event: slack_util.Event, match: Match) -> None:
# Get the day
day = match.group(1).lower().strip()
if not await nag_jobs(day):
slack_util.get_slack().reply(event,
"No jobs found. Check that the day is spelled correctly, with no extra symbols.\n"
"It is possible that all jobs have been signed off, as well.",
in_thread=True)
# Wrapper so we can auto-call this as well
async def nag_jobs(day_of_week: str) -> bool:
# Get the assigns
assigns = await house_management.import_assignments()
# Filter to day
assigns = [assign for assign in assigns if assign is not None and assign.job.day_of_week.lower() == day]
assigns = [assign for assign in assigns if assign is not None and assign.job.day_of_week.lower() == day_of_week]
# Filter signed off
assigns = [assign for assign in assigns if assign.signer is None]
# If no jobs found, somethings up. Probably mispelled day.
# If no jobs found, somethings up. Probably mispelled day. Return failure
if not assigns:
slack_util.get_slack().reply(event, "No jobs found. Check that the day is spelled correctly, with no extra symbols.\n"
"It is possible that all jobs have been signed off, as well.",
in_thread=True)
return
return False
# Nag each
response = "Do yer jerbs! They are as follows:\n"
@ -347,7 +351,7 @@ async def nag_callback(event: slack_util.Event, match: Match) -> None:
response += "\n"
general_id = slack_util.get_slack().get_channel_by_name("#general").id
slack_util.get_slack().reply(event, response, in_thread=False, to_channel=general_id)
slack_util.get_slack().send_message(response, general_id)
signoff_hook = slack_util.ChannelHook(signoff_callback,

View File

@ -44,6 +44,9 @@ def main() -> None:
# Add boozebot
# wrap.add_passive(periodicals.ItsTenPM())
# Add automatic updating of users
wrap.add_passive(periodicals.Updatinator(wrap, 60))
# Add nagloop
wrap.add_passive(periodicals.RemindJobs())

View File

@ -4,6 +4,7 @@ from typing import Optional, List
import house_management
import identifier
import job_commands
import slack_util
@ -30,14 +31,14 @@ class ItsTenPM(slack_util.Passive):
await asyncio.sleep(60)
class RemindJobs(slack_util.Passive):
async def run(self) -> None:
while True:
# Get the end of the current day (Say, 10PM)
today_remind_time = datetime.now().replace(hour=22, minute=00, second=0)
# Get the current day of week
dow = ["Monday",
# Shared behaviour
class JobNotifier:
@staticmethod
def get_day_of_week() -> str:
"""
Gets the current day of week as a str
"""
return ["Monday",
"Tuesday",
"Wednesday",
"Thursday",
@ -45,20 +46,13 @@ class RemindJobs(slack_util.Passive):
"Saturday",
"Sunday"][datetime.now().weekday()]
# Sleep until that time
delay = seconds_until(today_remind_time)
await asyncio.sleep(delay)
# Now it is that time. Get the current jobs
assigns = await house_management.import_assignments()
# Filter to incomplete, and today
def valid_filter(a: Optional[house_management.JobAssignment]):
@staticmethod
def is_job_valid(a: Optional[house_management.JobAssignment]):
# If it doesn't exist, it a thot
if a is None:
return False
# If its not today, we shouldn't nag
if a.job.day_of_week.lower() != dow.lower():
if a.job.day_of_week.lower() != JobNotifier.get_day_of_week().lower():
return False
# If it is unassigned, we can't nag
if a.assignee is None:
@ -71,10 +65,42 @@ class RemindJobs(slack_util.Passive):
return False
return True
assigns: List[house_management.JobAssignment] = [a for a in assigns if valid_filter(a)]
class NotifyJobs(slack_util.Passive, JobNotifier):
async def run(self) -> None:
while True:
# Get the "Start" of the current day (Say, 10AM)
today_remind_time = datetime.now().replace(hour=10, minute=00, second=0)
# Sleep until that time
delay = seconds_until(today_remind_time)
await asyncio.sleep(delay)
# Now it is that time. Nag the jobs
job_commands.nag_jobs(self.get_day_of_week())
# Sleep for a bit to prevent double shots
await asyncio.sleep(10)
class RemindJobs(slack_util.Passive, JobNotifier):
async def run(self) -> None:
while True:
# Get the end of the current day (Say, 10PM)
today_remind_time = datetime.now().replace(hour=22, minute=00, second=0)
# Sleep until that time
delay = seconds_until(today_remind_time)
await asyncio.sleep(delay)
# Now it is that time. Get the current jobs
assigns = await house_management.import_assignments()
# Filter to incomplete, and today
assigns: List[house_management.JobAssignment] = [a for a in assigns if self.is_job_valid(a)]
# Now, we want to nag each person. If we don't actually know who they are, so be it.
print("Nagging!")
print("Reminding!")
for a in assigns:
# Get the relevant slack ids
assignee_ids = await identifier.lookup_brother_userids(a.assignee)
@ -92,3 +118,15 @@ class RemindJobs(slack_util.Passive):
# Take a break to ensure no double-shots
await asyncio.sleep(10)
class Updatinator(slack_util.Passive):
def __init__(self, wrapper_to_update: slack_util.ClientWrapper, interval_seconds: int):
self.wrapper_target = wrapper_to_update
self.interval = interval_seconds
async def run(self):
while True:
await asyncio.sleep(self.interval)
self.wrapper_target.update_channels()
self.wrapper_target.update_users()

View File

@ -27,7 +27,7 @@ Objects to represent things within a slack workspace
class User:
id: str
name: str
real_name: str
real_name: Optional[str]
email: Optional[str]
async def get_brother(self) -> Optional[scroll_util.Brother]:
@ -41,8 +41,6 @@ class User:
class Channel:
id: str
name: str
purpose: str
members: List[User]
"""
@ -109,7 +107,7 @@ def message_stream(slack: SlackClient) -> Generator[Event, None, None]:
# Do forever
while True:
try:
if slack.rtm_connect(with_team_state=True, auto_reconnect=True):
if slack.rtm_connect(with_team_state=False, auto_reconnect=True):
print("Waiting for messages")
while True:
sleep(0.1)
@ -171,6 +169,8 @@ class ClientWrapper(object):
# Cache users and channels
self.users: dict = {}
self.channels: dict = {}
self.update_users()
self.update_channels()
# Scheduled events handling
def add_passive(self, per: Passive) -> None:
@ -281,6 +281,83 @@ class ClientWrapper(object):
return self.api_call("chat.postMessage", **kwargs)
def update_channels(self):
"""
Queries the slack API for all current channels
"""
# Necessary because of pagination
cursor = None
# Make a new dict to use
new_dict = {}
# Iterate over results
while True:
# Set args depending on if a cursor exists
args = {"limit": 1000, "type": "public_channel,private_channel,mpim,im"}
if cursor:
args["cursor"] = cursor
channel_dicts = self.api_call("https://slack.com/api/conversations.list", **args)
# If the response is good, put its results to the dict
if channel_dicts["ok"]:
for channel_dict in channel_dicts["channels"]:
new_channel = Channel(id=channel_dict["id"],
name=channel_dict["name"])
new_dict[new_channel.id] = new_channel
# If no new channels, just give it up
if len(channel_dicts["channels"]) == 0:
break
# Otherwise, fetch the cursor
cursor = channel_dicts.get("response_metadata").get("next_cursor")
else:
print("Warning: failed to retrieve channels")
break
self.channels = new_dict
def update_users(self):
"""
Queries the slack API for all current users
"""
# Necessary because of pagination
cursor = None
while True:
# Set args depending on if a cursor exists
args = {"limit": 1000}
if cursor:
args["cursor"] = cursor
user_dicts = self.api_call("https://slack.com/api/users.list", **args)
# Make a new dict to use
new_dict = {}
# If the response is good:
if user_dicts["ok"]:
for user_dict in user_dicts["members"]:
new_user = User(id=user_dict.get("id"),
name=user_dict.get("name"),
real_name=user_dict.get("real_name"),
email=user_dict.get("profile").get("email"))
new_dict[new_user.id] = new_user
# If no new channels, just give it up
if len(user_dicts["channels"]) == 0:
break
# Otherwise, fetch the cursor
cursor = user_dicts.get("response_metadata").get("next_cursor")
else:
print("Warning: failed to retrieve channels")
break
self.users = new_dict
# Create a single instance of the client wrapper
_singleton = ClientWrapper(SLACK_API)

View File

@ -2,10 +2,7 @@ import re
import textwrap
from typing import Match
from slackclient import SlackClient
import house_management
import identifier
import slack_util
from scroll_util import Brother