async def announce_start(self, msg, *args): self.enable = True print("Enabling announcements.") await channels[self.chan].send_message(f"{bot.msg_prefix}Announcements, announcements, ANNOUNCEMENTS!") session.query(Settings).filter(Settings.key == "announcement_enabled").update({"value": True}) session.commit()
async def announce_del(self, msg, *args): try: id = args[0] id = int(id) except IndexError: print("Invalid Announcement delete value not provided") return except ValueError: print("Invalid Announcement delete ID passed, must be an integer") return except Exception as e: print(e) return announcement = self.get_announcement(id) if announcement is None: print("Invalid Announcement delete ID, 0 rows deleted.") else: session.delete(announcement) print(f"Announcement id {announcement.id} deleted.") await msg.reply(f"{bot.msg_prefix}Announcement {id=} deleted.") count = session.query(Announcements).filter(Announcements.category == announcement.id).count() if count == 0 and announcement.id != 1: await msg.reply(f"{bot.msg_prefix}Resetting category to Default") session.query(Settings).filter(Settings.key == self.current_category_setting).update({Settings.value: 1}) session.commit()
async def announce_time(self, msg, time: int = None): try: # Make sure we receive a positive number if int(time) < 1: raise ValueError self.delay = int(time) updated = session.query(Settings).filter(Settings.key == "announcement_delay").update({"value": self.delay}) if not updated: # Insert if it wasn't updated, because it didn't exist. insert = Settings(key="announcement_delay", value=self.delay) session.add(insert) session.commit() self.restart_task() await msg.reply(f"{bot.msg_prefix}New announce time is {time} seconds") except ValueError: await msg.reply(f"{bot.msg_prefix}Invalid time, please use an integer in seconds") except TypeError: await msg.reply(f"{bot.msg_prefix} Current announce time is {self.delay} seconds.") except Exception as e: print(type(e), e)
async def announce_disable(self, msg, *args): "Disables posting an announcement by ID" try: index = int(args[0]) except IndexError: await msg.reply(f"{bot.msg_prefix} Try again with an ID") return except ValueError: if args[0] == "last": result = session.query(Announcements.id).order_by(Announcements.last_sent.desc()).first() index = result.id print(f"Disabling ID {index}") else: await msg.reply(f"{bot.msg_prefix} Try again with an ID Number") return except Exception as e: print(type(e), e) return successful = session.query(Announcements).filter(Announcements.id == index).update({"enabled": False}) if successful: result = session.query(Announcements).filter(Announcements.id == index).one_or_none() print(f"Disabled announcement ID {index}") await msg.reply(f"{bot.msg_prefix}Disabled announcement ID {index}: {str(result.text)}") session.commit() else: print(f"Announcement ID {index} not found.") await msg.reply(f"{bot.msg_prefix}Announcement ID {index} not found.")
async def announce_enable(self, msg, *args): "Disables posting an announcement by ID" try: index = int(args[0]) except IndexError: await msg.reply(f"{bot.msg_prefix} Try again with an ID") return except ValueError: await msg.reply(f"{bot.msg_prefix} Try again with an ID Number") return except Exception as e: print(type(e), e) return successful = session.query(Announcements).filter(Announcements.id == index).update({"enabled": True}) if successful: print(f"Enabled announcement ID {index}") await msg.reply(f"{bot.msg_prefix}Enabled announcement ID {index}") session.commit() else: print(f"Announcement ID {index} not found.") await msg.reply(f"{bot.msg_prefix}Announcement ID {index} not found.")
async def announce_category_del(self, msg, category_id: int): """Check if any messages are still assigned to this category, and refuse to delete if so""" category_id = int(category_id) # Quick fail if trying to delete default if category_id == 1: await msg.reply(f"{bot.msg_prefix}Default category will not be deleted.") return # Grab the category category = self.get_announcements_category(category_id) if category is None: await msg.reply(f"{bot.msg_prefix} Category id {category_id} does not exist.") return # Check to see if there are announcements still assigned to this category announcement_count = session.query(Announcements).filter(Announcements.category == category_id).count() if announcement_count > 0: await msg.reply(f"{bot.msg_prefix}{category.name} is not an empty category, aborting. 🚨🚨") return session.delete(category) session.commit() await msg.reply(f"{bot.msg_prefix}{category.name} ({category.id}) has been deleted.")
async def ignore_add(self, msg: Message, pattern: str): # Check if the regex is valid, return error if not. try: re.compile(pattern) except re.error: await msg.reply(f"{bot.msg_prefix}Invalid regex pattern.") return # Will not support a space in the pattern, but that doesn't matter because usernames can't have spaces query = session.query(IgnoreList).filter( IgnoreList.pattern == pattern).one_or_none() if query is None: # Pattern didn't exist, so add it. insert = IgnoreList(pattern=pattern) session.add(insert) session.commit() session.refresh(insert) await msg.reply( f"{bot.msg_prefix}I will now ignore links from {pattern}") bot.ignore_list_patterns[insert.id] = pattern else: await msg.reply( f"{bot.msg_prefix}That pattern is already in the database.")
async def timer_loop(self): while True: # Try except to prevent loop from accidentally crashing, no known reasons to crash. try: now = datetime.now(tz=self.timezone) self.next_run = now + timedelta(seconds=self.delay) await sleep(self.delay) # This is done so the loop will continue to run and not exit out because the loop has ended # if done as a while enabled if self.enable and (self.channel_active or self.sleep_override): # Grab the currently enabled announcement category cat = session.query(Settings).filter(Settings.key == self.current_category_setting).first() category = self.get_announcements_category(cat.value) if not None else 1 if self.announcement_count >= self.announce_topic_frequency: # Send the topic instead of the announcement topic = get_topic() message_text = "Topic: " + topic self.announcement_count = 0 else: result = ( # Read the next announcement from the database session.query(Announcements) .filter(Announcements.enabled == True) # noqa E712 SQLAlchemy doesn't work with `is True` .filter(Announcements.category == category.id) .order_by(Announcements.last_sent) .first() ) # Make sure there are entries in the dictioary if result is None: # Use continue instead of return so more can be added once the bot is run continue message_text = result.text self.announcement_count += 1 # Update the last time sent of the message session.query(Announcements).filter(Announcements.id == result.id).update( {"last_sent": datetime.now(), "times_sent": result.times_sent + 1} ) session.commit() # Send the message await channels[self.chan].send_message(bot.msg_prefix + message_text) # Since we sent a message, going to clear the announcements_sleeping flag self.announcements_sleeping = False # Assuming the channel isn't active until proven otherwise self.channel_active = False elif not self.channel_active: if not self.announcements_sleeping: await channels[self.chan].send_message(bot.msg_prefix + "It's so quiet in here...") self.announcements_sleeping = True except Exception as e: print(e)
async def announce_stop(self, msg, *args): self.enable = False print("Disabling announcements.") await channels[self.chan].send_message(f"{bot.msg_prefix}Disabling announcements") session.query(Settings).filter(Settings.key == "announcement_enabled").update({"value": False}) session.commit()
async def on_channel_joined(self, channel: Channel) -> None: """Bot joined a channel""" # Call user joind for all users currently in th channel for user_name in channel.chatters.all_viewers: await self.on_user_join(user_name, channel, commit=False) # Waited to commit so only one database commit was done on the server join session.commit()
async def wig_del(self, msg: Message, id: int): """Delete a wig by ID""" id = int(id) wig: Wigs = session.query(Wigs).filter(Wigs.id == id).first() if wig is not None: session.delete(wig) session.commit() await msg.reply(f"{bot.msg_prefix}{wig.wig_name} deleted.")
async def wig_time(self, msg: Message, time: int): """Set how long the poll should run for""" time = int(time) session.query(Settings.value).filter( Settings.key == "WigPollTime").update({Settings.value: time}) session.commit() await msg.reply(f"{bot.msg_prefix}Time updated to {time}")
async def wig_add(self, msg: Message, *args): """Adds a new wig to the database""" wig_name = " ".join(map(str, args)) new_wig = Wigs(wig_name=wig_name, enabled=1) session.add(new_wig) session.commit() session.refresh(new_wig) await msg.reply(f"{bot.msg_prefix}New wig added as id {new_wig.id}.")
async def allow_user(self, msg: Message, user: str): query = ( session.query(LinksToDiscordIgnoreList).filter(LinksToDiscordIgnoreList.username == user.lower()).one_or_none() ) if query: session.delete(query) session.commit() await msg.reply(f"{bot.msg_prefix}I will now allow links from {user}") else: await msg.reply(f"{bot.msg_prefix}{user} wasn't on my ignore list.")
async def ignore_disable(self, msg: Message, id: int): id = int(id) # Library may not actually convert to an integer query = session.query(IgnoreList).filter(IgnoreList.id == id).update( {IgnoreList.enabled: False}) session.commit() if query: await msg.reply(f"{bot.msg_prefix}ID:{id} disabled.") if id in bot.ignore_list_patterns.keys(): del bot.ignore_list_patterns[id] else: await msg.reply(f"{bot.msg_prefix}Invalid ID.")
def save_topic(topic: dict): topic_json = json.dumps(topic) rows_affected = session.query(Settings).filter( Settings.key == "topic").update({"value": topic_json}) if not rows_affected: ins = Settings(key="topic", value=topic_json) session.add(ins) session.commit() return True
async def ignore_del(self, msg: Message, id: int): id = int(id) # Library may not actually convert to an integer query = session.query(IgnoreList).filter( IgnoreList.id == id).one_or_none() if query: session.delete(query) session.commit() await msg.reply( f"{bot.msg_prefix}I will no longer ignore {query.pattern}") del bot.ignore_list_patterns[id] else: await msg.reply(f"{bot.msg_prefix}ID:{id} doesn't exist.")
async def shoutout_msg(self, msg: Message, *args): message = "" for word in args: message += f"{word} " successful = session.query(Settings.value).filter(Settings.key == "shoutout_msg").update({"value": message}) if not successful: insert = Settings(key="shoutout_msg", value=message) session.add(insert) session.commit() await msg.reply(f"{bot.msg_prefix} Message updated.")
async def set_topic(self, msg, *args): topic = "" for arg in args: topic += f"{arg} " rows_affected = session.query(Settings).filter(Settings.key == "topic").update({"value": topic}) if not rows_affected: ins = Settings(key="topic", value=topic) session.add(ins) session.commit() await msg.reply(f"{bot.msg_prefix}Topic set.")
async def announce_category_add(self, msg, *args): """Add a category""" cat_name = " ".join(map(str, args)) exists = session.query(AnnouncementCategories).filter(AnnouncementCategories.name == cat_name).count() if exists: await msg.reply(f"{bot.msg_prefix}Duplicate category name") return # Insert the new category into the database new_announcement = AnnouncementCategories(name=cat_name) session.add(new_announcement) session.commit() # Refresh to pull the ID inserted as session.refresh(new_announcement) await msg.reply(f"{bot.msg_prefix}{new_announcement.name} added as id {new_announcement.id}")
def set_cooldown(self, feed: str, cooldown: int) -> None: """ Sets the MQTT cooldown Updates or inserts the value into the database Exception handling should be done in the calling function """ q = session.query(Settings.id).filter(Settings.key == f"mqtt_cooldown_{feed}").one_or_none() if q is None: # Value wasn't in the database, lets insert it. insert = Settings(key=f"mqtt_cooldown_{feed}", value=cooldown) session.add(insert) self.mqtt_cooldown[feed] = cooldown else: session.query(Settings).filter(Settings.key == f"mqtt_cooldown_{feed}").update({"value": cooldown}) self.mqtt_cooldown[feed] = cooldown session.commit()
async def on_pubsub_bits(self, raw: PubSubData, data) -> None: """Send MQTT push when a us4er redeems bits""" """ print(raw.message_dict) {'data': {'user_name': 'tisboyo', 'channel_name': 'baldengineer', 'user_id': '461713054', 'channel_id': '125957551', 'time': '2020-09-20T02:48:34.819702158Z', 'chat_message': 'cheer1', 'bits_used': 1, 'total_bits_used': 2, 'is_anonymous': False, 'context': 'cheer', 'badge_entitlement': None}, 'version': '1.0', 'message_type': 'bits_event', 'message_id': '5a2da2f4-a6b5-5d23-b7cc-839a3ea5140c' } """ # bits = await load_data("bits") # bits[datetime.now().isoformat()] = raw.message_dict # await save_data("bits", bits) user_id = raw.message_dict["data"]["user_id"] server_id = raw.message_dict["data"]["channel_id"] bits_used = raw.message_dict["data"]["bits_used"] rows_affected = (session.query(Users).filter( Users.user_id == user_id, Users.channel == server_id).update({ "cheers": Users.cheers + bits_used, "last_message": datetime.now() })) # If the user doesn't exist, insert them if not rows_affected: user_object = Users( user_id=user_id, channel=server_id, user=raw.message_dict["data"]["user_name"], message_count=1, cheers=bits_used, ) session.add(user_object) session.commit()
async def announce_add(self, msg, *args): message = "" # Build the message for arg in args: message += f"{arg} " print(f"Adding to announce: {message}", end="") announcement_object = Announcements(text=message) session.add(announcement_object) session.commit() session.refresh(announcement_object) id = announcement_object.id print(f"...done, {id=}") await msg.reply(f"{bot.msg_prefix}Added announce {id=}")
async def on_user_join(self, user_name: str, channel: Channel, commit: bool = True) -> None: """User has joined the channel""" # get_user_info is cached by the bot, so only one actual request per user is sent to the api user_id = await get_user_id(user_name) channel_id = await get_user_id(channel.name) # Don't overwrite if the user is already here, happens if they join twice if (user_name, user_id) not in self.user_joined.keys(): in_database = session.query(Users).filter(Users.user_id == user_id, Users.channel == channel_id).one_or_none() # If the user isn't in the database insert them so we can find them later if not in_database: user_object = Users(user_id=user_id, channel=channel_id, user=user_name) session.add(user_object) if commit: session.commit() self.user_joined[(user_name, user_id)] = datetime.now() print(f"{datetime.now().isoformat()}: {user_name} has joined #{channel.name}, in database: {bool(in_database)}")
async def user_exit(self, users: Union[str, frozenset], channel: Channel): now = datetime.now() # If only a single user is passed, convert it to a frozenset as if a list of users was passed if isinstance(users, str): users = frozenset([users]) for user_name in users: # Build a tuple to compare user = (user_name, await get_user_id(user_name)) # Check to make sure the user is still in the user_joined to prevent errors if user in self.user_joined.keys(): # Calculate the time in the channel for this session joined: datetime = self.user_joined[user] parted = now time_this_session = parted - joined _, user_id = user channel_id = int(await get_user_id(channel.name)) # Update the database # Adding time objects is not possible with sqlite, so using an integer to track seconds rows_affected = ( session.query(Users) .filter(Users.user_id == user_id, Users.channel == channel_id) .update({"time_in_channel": Users.time_in_channel + time_this_session.seconds}) ) if not rows_affected: user_object = Users( user_id=user_id, channel=channel_id, user=user_name, time_in_channel=time_this_session.seconds ) session.add(user_object) # Remove the user from the user_joined key, since they have exited the channel del self.user_joined[user] # Commit the changes session.commit()
async def on_raw_message(self, msg: Message) -> None: """Increment the user message counter""" # Make sure the user actually sent a message,and it's not a whisper. if not msg.is_user_message or msg.is_whisper: return user_id = msg.tags.user_id server_id = msg.tags.room_id rows_affected = (session.query(Users).filter( Users.user_id == user_id, Users.channel == server_id).update({ "message_count": Users.message_count + 1, "last_message": datetime.now() })) # If the user doesn't exist, insert them if not rows_affected: user_object = Users(user_id=user_id, channel=server_id, user=msg.author, message_count=1) session.add(user_object) # Added for #155 # If we have had a raid in the last 60 seconds, don't send anything for the new users, # even thought they got inserted into the database. if (self.last_raid + timedelta(seconds=60)) < datetime.now(): if not bot.user_ignored(msg.author): await bot.MQTT.send( first_time_chatter_topic, dumps({ "author": msg.author, "timestamp": str(datetime.now()) })) print(f"New user {msg.author} sent to MQTT.") session.commit()
async def on_raw_message(self, msg: Message) -> None: """Increment the user message counter""" # Make sure the user actually sent a message,and it's not a whisper. if not msg.is_user_message or msg.is_whisper: return user_id = msg.tags.user_id server_id = msg.tags.room_id rows_affected = ( session.query(Users) .filter(Users.user_id == user_id, Users.channel == server_id) .update({"message_count": Users.message_count + 1, "last_message": datetime.now()}) ) # If the user doesn't exist, insert them if not rows_affected: user_object = Users(user_id=user_id, channel=server_id, user=msg.author, message_count=1) session.add(user_object) session.commit()
async def lost(self, msg: Message, *args): # Check if user is on ignore list if bot.user_ignored(str(msg.author)): return # Increase both counts self.lost_count["session"] += 1 self.lost_count["total"] += 1 rows_affected = (session.query(Settings).filter( Settings.key == "lost_count").update( {"value": json.dumps(self.lost_count)})) if not rows_affected: ins = Settings(key="lost_count", value=json.dumps(self.lost_count)) session.add(ins) session.commit() await msg.reply( f"@baldengineer has lost {self.lost_count['session']} things so far today, {self.lost_count['total']} total." )
class AutoMessageStarterMod(Mod): name = "automsg" task_name = "automessage" def __init__(self): query = session.query(Settings.value).filter(Settings.key == "announcement_delay").one_or_none() self.delay = int(query[0]) if query is not None else 900 self.chan = cfg.channels[0] self.next_run = datetime.min self.timezone = pytz.timezone("America/Chicago") self.channel_active = False self.announcements_sleeping = True self.sleep_override = False self.current_category_setting = "announcement_category" self.enable = session.query(Settings.value).filter(Settings.key == "announcement_enabled").one_or_none() if self.enable is None: insert = Settings(key="announcement_enabled", value=True) session.add(insert) @property def delay(self): return self.__delay @delay.setter def delay(self, time: int): self.__delay = int(time) print(f"Announcement message delay is {self.delay} seconds") async def timer_loop(self): while True: # Try except to prevent loop from accidentally crashing, no known reasons to crash. try: now = datetime.now(tz=self.timezone) self.next_run = now + timedelta(seconds=self.delay) await sleep(self.delay) # This is done so the loop will continue to run and not exit out because the loop has ended # if done as a while enabled if self.enable and (self.channel_active or self.sleep_override): # Grab the currently enabled announcement category cat = session.query(Settings).filter(Settings.key == self.current_category_setting).first() category = self.get_announcements_category(cat.value) if not None else 1 result = ( # Read the next announcement from the database session.query(Announcements) .filter(Announcements.enabled == True) # noqa E712 SQLAlchemy doesn't work with `is True` .filter(Announcements.category == category.id) .order_by(Announcements.last_sent) .first() ) # Make sure there are entries in the dictioary if result is None: # Use continue instead of return so more can be added once the bot is run continue # Send the message await channels[self.chan].send_message(bot.msg_prefix + result.text) # Update the last time sent of the message session.query(Announcements).filter(Announcements.id == result.id).update( {"last_sent": datetime.now(), "times_sent": result.times_sent + 1} ) session.commit() # Since we sent a message, going to clear the announcements_sleeping flag self.announcements_sleeping = False # Assuming the channel isn't active until proven otherwise self.channel_active = False elif not self.channel_active: if not self.announcements_sleeping: await channels[self.chan].send_message(bot.msg_prefix + "It's so quiet in here...") self.announcements_sleeping = True except Exception as e: print(e) async def on_raw_message(self, msg: Message): """ Tracks the last time a message was sent, and if it was by the bot, consider the channel inactive. """ if msg.is_user_message: self.channel_active = True self.announcements_sleeping = False @ModCommand(name, "announce", permission="admin") async def announce(self, msg, *args): # Announce parent command pass @SubCommand(announce, "nosleep", permission="admin") async def announce_nosleep(self, msg, *args): self.sleep_override = not self.sleep_override status = "disabled" if self.sleep_override else "enabled" await msg.reply(f"{bot.msg_prefix}Announce auto-sleep status is now {status}.") @SubCommand(announce, "start", permission="admin") async def announce_start(self, msg, *args): self.enable = True print("Enabling announcements.") await channels[self.chan].send_message(f"{bot.msg_prefix}Announcements, announcements, ANNOUNCEMENTS!") session.query(Settings).filter(Settings.key == "announcement_enabled").update({"value": True}) session.commit() @SubCommand(announce, "stop", permission="admin") async def announce_stop(self, msg, *args): self.enable = False print("Disabling announcements.") await channels[self.chan].send_message(f"{bot.msg_prefix}Disabling announcements") session.query(Settings).filter(Settings.key == "announcement_enabled").update({"value": False}) session.commit() @SubCommand(announce, "time", permission="admin") async def announce_time(self, msg, time: int = None): try: # Make sure we receive a positive number if int(time) < 1: raise ValueError self.delay = int(time) updated = session.query(Settings).filter(Settings.key == "announcement_delay").update({"value": self.delay}) if not updated: # Insert if it wasn't updated, because it didn't exist. insert = Settings(key="announcement_delay", value=self.delay) session.add(insert) session.commit() self.restart_task() await msg.reply(f"{bot.msg_prefix}New announce time is {time} seconds") except ValueError: await msg.reply(f"{bot.msg_prefix}Invalid time, please use an integer in seconds") except TypeError: await msg.reply(f"{bot.msg_prefix} Current announce time is {self.delay} seconds.") except Exception as e: print(type(e), e) @SubCommand(announce, "list", permission="admin") async def announce_list(self, msg, *args): result = ( session.query(Announcements, AnnouncementCategories) .order_by(Announcements.id) .join(AnnouncementCategories) .all() ) print("Announcements".center(80, "*")) print(" Times") print(" ID : EN : Sent : Category : Text") for announcement, category in result: en = "Y" if announcement.enabled else "N" print(f"{announcement.id:3} : {en} : {announcement.times_sent:4} : {category.name[:8]:8} : {announcement.text}") print(f" https://{getenv('WEB_HOSTNAME')}/announcements ".center(80, "*")) await msg.reply(f"{bot.msg_prefix}Announcements listed in console.") @SubCommand(announce, "del", permission="admin") async def announce_del(self, msg, *args): try: id = args[0] id = int(id) except IndexError: print("Invalid Announcement delete value not provided") return except ValueError: print("Invalid Announcement delete ID passed, must be an integer") return except Exception as e: print(e) return announcement = self.get_announcement(id) if announcement is None: print("Invalid Announcement delete ID, 0 rows deleted.") else: session.delete(announcement) print(f"Announcement id {announcement.id} deleted.") await msg.reply(f"{bot.msg_prefix}Announcement {id=} deleted.") count = session.query(Announcements).filter(Announcements.category == announcement.id).count() if count == 0 and announcement.id != 1: await msg.reply(f"{bot.msg_prefix}Resetting category to Default") session.query(Settings).filter(Settings.key == self.current_category_setting).update({Settings.value: 1}) session.commit() @SubCommand(announce, "add", permission="admin") async def announce_add(self, msg, *args): message = "" # Build the message for arg in args: message += f"{arg} " print(f"Adding to announce: {message}", end="") announcement_object = Announcements(text=message) session.add(announcement_object) session.commit() session.refresh(announcement_object) id = announcement_object.id print(f"...done, {id=}") await msg.reply(f"{bot.msg_prefix}Added announce {id=}") @SubCommand(announce, "disable", permission="admin") async def announce_disable(self, msg, *args): "Disables posting an announcement by ID" try: index = int(args[0]) except IndexError: await msg.reply(f"{bot.msg_prefix} Try again with an ID") return except ValueError: if args[0] == "last": result = session.query(Announcements.id).order_by(Announcements.last_sent.desc()).first() index = result.id print(f"Disabling ID {index}") else: await msg.reply(f"{bot.msg_prefix} Try again with an ID Number") return except Exception as e: print(type(e), e) return successful = session.query(Announcements).filter(Announcements.id == index).update({"enabled": False}) if successful: result = session.query(Announcements).filter(Announcements.id == index).one_or_none() print(f"Disabled announcement ID {index}") await msg.reply(f"{bot.msg_prefix}Disabled announcement ID {index}: {str(result.text)}") session.commit() else: print(f"Announcement ID {index} not found.") await msg.reply(f"{bot.msg_prefix}Announcement ID {index} not found.") @SubCommand(announce, "enable", permission="admin") async def announce_enable(self, msg, *args): "Disables posting an announcement by ID" try: index = int(args[0]) except IndexError: await msg.reply(f"{bot.msg_prefix} Try again with an ID") return except ValueError: await msg.reply(f"{bot.msg_prefix} Try again with an ID Number") return except Exception as e: print(type(e), e) return successful = session.query(Announcements).filter(Announcements.id == index).update({"enabled": True}) if successful: print(f"Enabled announcement ID {index}") await msg.reply(f"{bot.msg_prefix}Enabled announcement ID {index}") session.commit() else: print(f"Announcement ID {index} not found.") await msg.reply(f"{bot.msg_prefix}Announcement ID {index} not found.") @SubCommand(announce, "status", permission="admin") async def announce_status(self, msg, *args): """Sends the current status of the announcements""" status = "Enabled" if self.enable else "Disabled" next_run_seconds = self.next_run - datetime.now(self.timezone) enabled = session.query(Announcements).filter(Announcements.enabled == True).count() # noqa E712 total_count = session.query(Announcements).count() # Scalar returns the first element of the first result or None cat_id = int(session.query(Settings.value).filter(Settings.key == self.current_category_setting).scalar()) category_name = session.query(AnnouncementCategories.name).filter(AnnouncementCategories.id == cat_id).scalar() announcements_in_cat = session.query(Announcements).filter(Announcements.category == cat_id).count() replies = [ f"{bot.msg_prefix}Current status is {status}", f"{bot.msg_prefix}Current delay is {self.delay} seconds. ", f"{bot.msg_prefix}Next send time will be {self.next_run.strftime('%H:%M:%S')} which is in {str(next_run_seconds)[:-7]}.", # noqa E501 f"{bot.msg_prefix}{enabled}/{total_count} of all announcements enabled.", f"{bot.msg_prefix}Current category is {category_name}, with {announcements_in_cat} announcements", ] for reply in replies: await msg.reply(reply) @SubCommand(announce, "category", permission="admin") async def announce_category(self, msg, *args): """Base command for category management""" pass @SubCommand(announce_category, "add", permission="admin") async def announce_category_add(self, msg, *args): """Add a category""" cat_name = " ".join(map(str, args)) exists = session.query(AnnouncementCategories).filter(AnnouncementCategories.name == cat_name).count() if exists: await msg.reply(f"{bot.msg_prefix}Duplicate category name") return # Insert the new category into the database new_announcement = AnnouncementCategories(name=cat_name) session.add(new_announcement) session.commit() # Refresh to pull the ID inserted as session.refresh(new_announcement) await msg.reply(f"{bot.msg_prefix}{new_announcement.name} added as id {new_announcement.id}") @SubCommand(announce_category, "del", permission="admin") async def announce_category_del(self, msg, category_id: int): """Check if any messages are still assigned to this category, and refuse to delete if so""" category_id = int(category_id) # Quick fail if trying to delete default if category_id == 1: await msg.reply(f"{bot.msg_prefix}Default category will not be deleted.") return # Grab the category category = self.get_announcements_category(category_id) if category is None: await msg.reply(f"{bot.msg_prefix} Category id {category_id} does not exist.") return # Check to see if there are announcements still assigned to this category announcement_count = session.query(Announcements).filter(Announcements.category == category_id).count() if announcement_count > 0: await msg.reply(f"{bot.msg_prefix}{category.name} is not an empty category, aborting. 🚨🚨") return session.delete(category) session.commit() await msg.reply(f"{bot.msg_prefix}{category.name} ({category.id}) has been deleted.") @SubCommand(announce_category, "list", permission="admin") async def announce_category_list(self, msg, *args): """List the available categories""" result = session.query(AnnouncementCategories).order_by(AnnouncementCategories.id).all() print("Announcement Categories".center(80, "*")) print(" ID : Category") for category in result: print(f"{category.id:3} : {category.name}") print(f" https://{getenv('WEB_HOSTNAME')}/announcements ".center(80, "*")) await msg.reply(f"{bot.msg_prefix}Categories listed in console.") @SubCommand(announce_category, "assign", permission="admin") async def announce_category_assign(self, msg, announcement_id: int, category_id: int): """ Assign a category to an Announcement Usage: !announce category assign message_id category_id """ # Cast the ID's to ints announcement_id = int(announcement_id) category_id = int(category_id) # Check to make sure the announcement category exists # Keep inside parens, otherwise this assigns True to category on a good category # instead of the category itself if (category := self.get_announcements_category(category_id)) is None: await msg.reply(f"{bot.msg_prefix}Invalid category id") return # Check to make sure the announcement itself exists if not session.query(Announcements).filter(Announcements.id == announcement_id).count(): await msg.reply(f"{bot.msg_prefix}Invalid announcement id") return # Update the announcement result = ( session.query(Announcements) .filter(Announcements.id == announcement_id) .update({Announcements.category: category_id}) ) session.commit() # Send response of results if result: await msg.reply(f"{bot.msg_prefix}Announcement id {announcement_id} updated to category {category.name}") else: await msg.reply(f"{bot.msg_prefix}Unable to update.")
if (category := self.get_announcements_category(category_id)) is None: await msg.reply(f"{bot.msg_prefix}Invalid category id.") return # TODO Change to just an update, and do a alembic revision to insert a default after #79 is complete. updated = ( session.query(Settings) .filter(Settings.key == self.current_category_setting) .update({Settings.value: category_id}) ) if not updated: # Insert the key insert = Settings(key=self.current_category_setting, value=category_id) session.add(insert) session.commit() await msg.reply(f"{bot.msg_prefix}Active announcement category is now {category.name}") def get_announcements_category(self, category_id: int) -> AnnouncementCategories or None: """ Returns an AnnouncementCategories object or None Use: if (category := self.get_announcements_category(category_id)) is None: """ category_id = int(category_id) category = session.query(AnnouncementCategories).filter(AnnouncementCategories.id == category_id).first() # Have to check if a valid category was returned # to prevent a NoneType error if an invalid one is found if category is None: category = AnnouncementCategories(id=1, name="Default")