Skip to content

Commit

Permalink
run ssort
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviasculley committed Oct 3, 2023
1 parent 4b8dc2d commit 2e205ea
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 163 deletions.
204 changes: 102 additions & 102 deletions src/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,74 +35,59 @@
APP_HANDLER = AsyncSlackRequestHandler(APP)


async def periodically_check_api():
"""Periodically check the api every hour
This function runs in a thread, meaning that it needs to create it's own
database connection. This is OK however, since it only runs once an hour
"""
print("Checking api every hour")
while True:
try:
await check_api()
except Exception: # pylint: disable=broad-except
print(traceback.format_exc())
os._exit(1)
await asyncio.sleep(60 * 60) # 60 minutes x 60 seconds
async def post_or_update_messages(week, blocks, text):
"""Posts or updates a message in a slack channel for a week"""
channels = await database.get_slack_channel_ids()
messages = await database.get_messages(week)

# used to lookup the message id and message for a particular
# channel
message_details = {
message["slack_channel_id"]: {
"timestamp": message["message_timestamp"],
"message": message["message"],
}
for message in messages
}

@APP.command("/add_channel")
async def add_channel(ack, say, logger, command):
"""Handle adding a slack channel to the bot"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
try:
await database.add_channel(command["channel_id"])
await ack("Added channel to slack events bot 👍")
except sqlite3.IntegrityError:
await ack("slack events bot has already been activated for this channel")
# used to quickly lookup if a message has been posted for a
# particular channel
posted_channels_set = set(message["slack_channel_id"] for message in messages)

for slack_channel_id in channels:
if (
slack_channel_id in posted_channels_set
and text == message_details[slack_channel_id]["message"]
):
print(
f"Week of {week.strftime('%B %-d')} in {slack_channel_id} "
"hasn't changed, not updating"
)

@APP.command("/remove_channel")
async def remove_channel(ack, say, logger, command):
"""Handle removing a slack channel from the bot"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
try:
await database.remove_channel(command["channel_id"])
await ack("Removed channel from slack events bot 👍")
except sqlite3.IntegrityError:
await ack("slack events bot is not activated for this channel")
elif slack_channel_id in posted_channels_set:
print(f"updating week {week.strftime('%B %-d')} " f"in {slack_channel_id}")

timestamp = message_details[slack_channel_id]["timestamp"]
slack_response = await APP.client.chat_update(
ts=timestamp, channel=slack_channel_id, blocks=blocks, text=text
)

@APP.command("/check_api")
async def trigger_check_api(ack, say, logger, command):
"""Handle manually rechecking the api for updates"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
await ack("Checking api for events 👍")
await check_api()
await database.update_message(week, text, timestamp, slack_channel_id)

else:
print(f"posting week {week.strftime('%B %-d')} " f"in {slack_channel_id}")

async def check_api():
"""Check the api for updates and update any existing messages"""
async with aiohttp.ClientSession() as session:
async with session.get("https://events.openupstate.org/api/gtc") as resp:
# get timezone aware today
today = datetime.date.today()
today = datetime.datetime(
today.year, today.month, today.day, tzinfo=pytz.utc
slack_response = await APP.client.chat_postMessage(
channel=slack_channel_id,
blocks=blocks,
text=text,
unfurl_links=False,
unfurl_media=False,
)

# keep current week's post up to date
await parse_events_for_week(today, resp)

# potentially post next week 5 days early
probe_date = today + datetime.timedelta(days=5)
await parse_events_for_week(probe_date, resp)
await database.create_message(
week, text, slack_response["ts"], slack_channel_id
)


async def parse_events_for_week(probe_date, resp):
Expand Down Expand Up @@ -147,59 +132,74 @@ async def parse_events_for_week(probe_date, resp):
await post_or_update_messages(week_start, blocks, text)


async def post_or_update_messages(week, blocks, text):
"""Posts or updates a message in a slack channel for a week"""
channels = await database.get_slack_channel_ids()
messages = await database.get_messages(week)
async def check_api():
"""Check the api for updates and update any existing messages"""
async with aiohttp.ClientSession() as session:
async with session.get("https://events.openupstate.org/api/gtc") as resp:
# get timezone aware today
today = datetime.date.today()
today = datetime.datetime(
today.year, today.month, today.day, tzinfo=pytz.utc
)

# used to lookup the message id and message for a particular
# channel
message_details = {
message["slack_channel_id"]: {
"timestamp": message["message_timestamp"],
"message": message["message"],
}
for message in messages
}
# keep current week's post up to date
await parse_events_for_week(today, resp)

# used to quickly lookup if a message has been posted for a
# particular channel
posted_channels_set = set(message["slack_channel_id"] for message in messages)
# potentially post next week 5 days early
probe_date = today + datetime.timedelta(days=5)
await parse_events_for_week(probe_date, resp)

for slack_channel_id in channels:
if (
slack_channel_id in posted_channels_set
and text == message_details[slack_channel_id]["message"]
):
print(
f"Week of {week.strftime('%B %-d')} in {slack_channel_id} "
"hasn't changed, not updating"
)

elif slack_channel_id in posted_channels_set:
print(f"updating week {week.strftime('%B %-d')} " f"in {slack_channel_id}")
async def periodically_check_api():
"""Periodically check the api every hour
timestamp = message_details[slack_channel_id]["timestamp"]
slack_response = await APP.client.chat_update(
ts=timestamp, channel=slack_channel_id, blocks=blocks, text=text
)
This function runs in a thread, meaning that it needs to create it's own
database connection. This is OK however, since it only runs once an hour
"""
print("Checking api every hour")
while True:
try:
await check_api()
except Exception: # pylint: disable=broad-except
print(traceback.format_exc())
os._exit(1)
await asyncio.sleep(60 * 60) # 60 minutes x 60 seconds

await database.update_message(week, text, timestamp, slack_channel_id)

else:
print(f"posting week {week.strftime('%B %-d')} " f"in {slack_channel_id}")
@APP.command("/add_channel")
async def add_channel(ack, say, logger, command):
"""Handle adding a slack channel to the bot"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
try:
await database.add_channel(command["channel_id"])
await ack("Added channel to slack events bot 👍")
except sqlite3.IntegrityError:
await ack("slack events bot has already been activated for this channel")

slack_response = await APP.client.chat_postMessage(
channel=slack_channel_id,
blocks=blocks,
text=text,
unfurl_links=False,
unfurl_media=False,
)

await database.create_message(
week, text, slack_response["ts"], slack_channel_id
)
@APP.command("/remove_channel")
async def remove_channel(ack, say, logger, command):
"""Handle removing a slack channel from the bot"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
try:
await database.remove_channel(command["channel_id"])
await ack("Removed channel from slack events bot 👍")
except sqlite3.IntegrityError:
await ack("slack events bot is not activated for this channel")


@APP.command("/check_api")
async def trigger_check_api(ack, say, logger, command):
"""Handle manually rechecking the api for updates"""
del say
logger.info(f"{command['command']} from {command['channel_id']}")
if command["channel_id"] is not None:
await ack("Checking api for events 👍")
await check_api()


API = FastAPI()
Expand Down
122 changes: 61 additions & 61 deletions src/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,67 @@
from dateutil import parser


def parse_location(event_json):
"""Parse location string from event json"""
if event_json["venue"] is None:
return None

if None not in (
event_json["venue"]["name"],
event_json["venue"]["address"],
event_json["venue"]["city"],
event_json["venue"]["state"],
event_json["venue"]["zip"],
):
return (
f"{event_json['venue']['name']} at "
f"{event_json['venue']['address']} {event_json['venue']['city']}, "
f"{event_json['venue']['state']} {event_json['venue']['zip']}"
)

if event_json["venue"]["lat"] is not None and event_json["venue"]["lat"]:
return f"lat/long: {event_json['venue']['lat']}, {event_json['venue']['lat']}"

return f"{event_json['venue']['name']}"


def truncate_string(string, length=250):
"""Truncate string and add ellipses if it's too long"""
return string[:length] + (string[length:] and "...")


def get_location_url(location):
"""Return google maps link for location or plaintext"""
if location is None:
return "No location"

return (
"<https://www.google.com/maps/search/?api=1&query="
f"{urllib.parse.quote(location)}|{location}>"
)


def print_status(status):
"""Prints status with emojis :D"""
if status == "upcoming":
return "Upcoming ✅"

if status == "past":
return "Past ✔"

if status == "cancelled":
return "Cancelled ❌"

return status.title()


def print_datetime(time):
"""Print datetime in local timezone as string"""
return time.astimezone(pytz.timezone(os.environ.get("TZ"))).strftime(
"%B %-d, %Y %I:%M %p %Z"
)


class Event:
"""Event records all the data from an event, and has methods to generate the
message from an event
Expand Down Expand Up @@ -79,64 +140,3 @@ def generate_text(self):
f"Location: {self.location}\n"
f"Time: {print_datetime(self.time)}"
)


def parse_location(event_json):
"""Parse location string from event json"""
if event_json["venue"] is None:
return None

if None not in (
event_json["venue"]["name"],
event_json["venue"]["address"],
event_json["venue"]["city"],
event_json["venue"]["state"],
event_json["venue"]["zip"],
):
return (
f"{event_json['venue']['name']} at "
f"{event_json['venue']['address']} {event_json['venue']['city']}, "
f"{event_json['venue']['state']} {event_json['venue']['zip']}"
)

if event_json["venue"]["lat"] is not None and event_json["venue"]["lat"]:
return f"lat/long: {event_json['venue']['lat']}, {event_json['venue']['lat']}"

return f"{event_json['venue']['name']}"


def truncate_string(string, length=250):
"""Truncate string and add ellipses if it's too long"""
return string[:length] + (string[length:] and "...")


def get_location_url(location):
"""Return google maps link for location or plaintext"""
if location is None:
return "No location"

return (
"<https://www.google.com/maps/search/?api=1&query="
f"{urllib.parse.quote(location)}|{location}>"
)


def print_status(status):
"""Prints status with emojis :D"""
if status == "upcoming":
return "Upcoming ✅"

if status == "past":
return "Past ✔"

if status == "cancelled":
return "Cancelled ❌"

return status.title()


def print_datetime(time):
"""Print datetime in local timezone as string"""
return time.astimezone(pytz.timezone(os.environ.get("TZ"))).strftime(
"%B %-d, %Y %I:%M %p %Z"
)

0 comments on commit 2e205ea

Please sign in to comment.