if recipient is None

This commit is contained in:
codey 2025-02-15 13:57:47 -05:00
parent 9d23438b13
commit 6463ace40c
9 changed files with 617 additions and 716 deletions

View File

@ -9,6 +9,7 @@ import traceback
import time import time
import importlib import importlib
import logging import logging
from typing import Optional
import discord import discord
import regex import regex
from regex import Pattern from regex import Pattern
@ -30,7 +31,7 @@ class Util:
self.timers: dict = {} # discord uid : timestamp, used for rate limiting self.timers: dict = {} # discord uid : timestamp, used for rate limiting
self.karma_cooldown: int = 15 # 15 seconds between karma updates self.karma_cooldown: int = 15 # 15 seconds between karma updates
async def get_karma(self, keyword: str) -> int|str: async def get_karma(self, keyword: str) -> int:
""" """
Get Karma for Keyword Get Karma for Keyword
Args: Args:
@ -50,15 +51,15 @@ class Util:
return resp.get('count') return resp.get('count')
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
return f"Failed-- {type(e).__name__}: {str(e)}" return False
async def get_top(self, n: int = 10) -> dict: async def get_top(self, n: int = 10) -> Optional[dict]:
""" """
Get top (n=10) Karma Get top (n=10) Karma
Args: Args:
n (int): Number of top results to return, default 10 n (int): Number of top results to return, default 10
Returns: Returns:
dict Optional[dict]
""" """
try: try:
async with ClientSession() as session: async with ClientSession() as session:
@ -74,8 +75,9 @@ class Util:
return resp return resp
except: except:
traceback.print_exc() traceback.print_exc()
return None
async def get_top_embed(self, n:int = 10) -> discord.Embed: async def get_top_embed(self, n:int = 10) -> Optional[discord.Embed]:
""" """
Get Top Karma Embed Get Top Karma Embed
Args: Args:
@ -83,11 +85,13 @@ class Util:
Returns: Returns:
discord.Embed discord.Embed
""" """
top: dict = await self.get_top(n) top: Optional[dict] = await self.get_top(n)
if not top:
return None
top_formatted: str = "" top_formatted: str = ""
for x, item in enumerate(top): for x, item in enumerate(top):
top_formatted += f"{x+1}. **{discord.utils.escape_markdown(item[0])}**: *{item[1]}*\n" top_formatted += f"{x+1}. **{discord.utils.escape_markdown(item[0])}**: *{item[1]}*\n"
top_formatted: str = top_formatted.strip() top_formatted = top_formatted.strip()
embed: discord.Embed = discord.Embed(title=f"Top {n} Karma", embed: discord.Embed = discord.Embed(title=f"Top {n} Karma",
description=top_formatted, description=top_formatted,
colour=0xff00ff) colour=0xff00ff)
@ -103,7 +107,7 @@ class Util:
flag (int) flag (int)
""" """
if not flag in [0, 1]: if not flag in [0, 1]:
return return False
reqObj: dict = { reqObj: dict = {
'granter': f"Discord: {display} ({_id})", 'granter': f"Discord: {display} ({_id})",
@ -171,6 +175,8 @@ class Karma(commands.Cog):
try: try:
top_embed = await self.util.get_top_embed(n=25) top_embed = await self.util.get_top_embed(n=25)
channel = self.bot.get_channel(self.karma_chanid) channel = self.bot.get_channel(self.karma_chanid)
if not isinstance(channel, discord.TextChannel):
return
message_to_edit = await channel.fetch_message(self.karma_msgid) message_to_edit = await channel.fetch_message(self.karma_msgid)
await message_to_edit.edit(embed=top_embed, await message_to_edit.edit(embed=top_embed,
content="## This message will automatically update periodically.") content="## This message will automatically update periodically.")
@ -184,7 +190,10 @@ class Karma(commands.Cog):
Message hook, to monitor for ++/-- Message hook, to monitor for ++/--
Also monitors for messages to #karma to autodelete, only Havoc may post in #karma! Also monitors for messages to #karma to autodelete, only Havoc may post in #karma!
""" """
if not self.bot.user: # No valid client instance
return
if not isinstance(message.channel, discord.TextChannel):
return
if message.channel.id == self.karma_chanid and not message.author.id == self.bot.user.id: if message.channel.id == self.karma_chanid and not message.author.id == self.bot.user.id:
"""Message to #karma not by Havoc, delete it""" """Message to #karma not by Havoc, delete it"""
await message.delete(reason="Messages to #karma are not allowed") await message.delete(reason="Messages to #karma are not allowed")
@ -192,12 +201,13 @@ class Karma(commands.Cog):
title="Message Deleted", title="Message Deleted",
description=f"Your message to **#{message.channel.name}** has been automatically deleted.\n**Reason**: Messages to this channel by users is not allowed." description=f"Your message to **#{message.channel.name}** has been automatically deleted.\n**Reason**: Messages to this channel by users is not allowed."
) )
return await message.author.send(embed=removal_embed) await message.author.send(embed=removal_embed)
if message.author.id == self.bot.user.id: # Bots own message if message.author.id == self.bot.user.id: # Bots own message
return return
if not message.guild:
return
if not message.guild.id in [1145182936002482196, 1228740575235149855]: # Not a valid guild for cmd if not message.guild.id in [1145182936002482196, 1228740575235149855]: # Not a valid guild for cmd
return return
@ -209,15 +219,19 @@ class Karma(commands.Cog):
logging.debug("Mention: %s", mention) logging.debug("Mention: %s", mention)
mentioned_uid: int = int(mention[1]) mentioned_uid: int = int(mention[1])
friendly_flag: int = int(mention[2]) friendly_flag: int = int(mention[2])
guild: discord.Guild = self.bot.get_guild(message.guild.id) guild: Optional[discord.Guild] = self.bot.get_guild(message.guild.id)
guild_member: discord.Member = guild.get_member(mentioned_uid) if not guild:
return
guild_member: Optional[discord.Member] = guild.get_member(mentioned_uid)
if not guild_member:
return
display: str = guild_member.display_name display: str = guild_member.display_name
message_content: str = message_content.replace(mention[0], display) message_content = message_content.replace(mention[0], display)
logging.debug("New message: %s", message_content) logging.debug("New message: %s", message_content)
except: except:
traceback.print_exc() traceback.print_exc()
message_content: str = discord.utils.escape_markdown(message_content) message_content = discord.utils.escape_markdown(message_content)
karma_regex: list[str] = regex.findall(self.karma_regex, message_content.strip()) karma_regex: list[str] = regex.findall(self.karma_regex, message_content.strip())
if not karma_regex: # Not a request to adjust karma if not karma_regex: # Not a request to adjust karma
@ -233,6 +247,8 @@ class Karma(commands.Cog):
logging.debug("Matched: %s", karma_regex) logging.debug("Matched: %s", karma_regex)
for matched_keyword in karma_regex: for matched_keyword in karma_regex:
if not isinstance(matched_keyword, tuple):
continue
if len(matched_keyword) == 4: if len(matched_keyword) == 4:
(keyword, friendly_flag, _, __) = matched_keyword (keyword, friendly_flag, _, __) = matched_keyword
else: else:
@ -242,9 +258,9 @@ class Karma(commands.Cog):
flag: int = None flag: int = None
match friendly_flag: match friendly_flag:
case "++": case "++":
flag: int = 0 flag = 0
case "--": case "--":
flag: int = 1 flag = 1
case _: case _:
logging.info("Unknown flag %s", flag) logging.info("Unknown flag %s", flag)
continue continue
@ -266,18 +282,24 @@ class Karma(commands.Cog):
"""With no arguments, top 10 karma is provided; a keyword can also be provided to lookup.""" """With no arguments, top 10 karma is provided; a keyword can also be provided to lookup."""
try: try:
if not keyword: if not keyword:
top_10_embed: discord.Embed = await self.util.get_top_embed() top_10_embed: Optional[discord.Embed] = await self.util.get_top_embed()
if not top_10_embed:
return
return await ctx.respond(embed=top_10_embed) return await ctx.respond(embed=top_10_embed)
keyword: str = discord.utils.escape_markdown(keyword) keyword = discord.utils.escape_markdown(keyword)
mentions: list[str] = regex.findall(self.mention_regex_no_flag, keyword) mentions: list[str] = regex.findall(self.mention_regex_no_flag, keyword)
for mention in mentions: for mention in mentions:
try: try:
mentioned_uid = int(mention[1]) mentioned_uid = int(mention[1])
guild = self.bot.get_guild(ctx.guild.id) guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
guild_member = guild.get_member(mentioned_uid) if not guild:
return
guild_member: Optional[discord.Member] = guild.get_member(mentioned_uid)
if not guild_member:
return
display = guild_member.display_name display = guild_member.display_name
keyword = keyword.replace(mention[0], display) keyword = keyword.replace(mention[0], display)
except: except:
@ -286,8 +308,6 @@ class Karma(commands.Cog):
score: int = await self.util.get_karma(keyword) score: int = await self.util.get_karma(keyword)
description: str = f"**{keyword}** has a karma of *{score}*" description: str = f"**{keyword}** has a karma of *{score}*"
if isinstance(score, dict) and score.get('err'):
description: str = f"*{score.get('errorText')}*"
embed: discord.Embed = discord.Embed(title=f"Karma for {keyword}", embed: discord.Embed = discord.Embed(title=f"Karma for {keyword}",
description=description) description=description)
return await ctx.respond(embed=embed) return await ctx.respond(embed=embed)

View File

@ -4,7 +4,7 @@
import traceback import traceback
import logging import logging
import os import os
from typing import Any, Optional from typing import Any, Optional, Union
import discord import discord
import aiosqlite as sqlite3 import aiosqlite as sqlite3
from discord.ext import bridge, commands from discord.ext import bridge, commands
@ -43,11 +43,15 @@ class LoveHate(commands.Cog):
""" """
try: try:
if not user: if not user:
loves: list[tuple] = await self.db.get_lovehates(user=ctx.author.display_name, loves=True) display_name = ctx.author.display_name
loves: Union[list[tuple], bool] = await self.db.get_lovehates(user=display_name,
loves=True)
if not loves: if not loves:
return await ctx.respond("You don't seem to love anything...") return await ctx.respond("You don't seem to love anything...")
out_loves: list = [] out_loves: list = []
if not isinstance(loves, list):
return
for love in loves: for love in loves:
(love,) = love (love,) = love
out_loves.append(love) out_loves.append(love)
@ -55,11 +59,11 @@ class LoveHate(commands.Cog):
out_loves_str: str = self.join_with_and(out_loves) out_loves_str: str = self.join_with_and(out_loves)
return await ctx.respond(f"{ctx.author.mention} loves {out_loves_str}") return await ctx.respond(f"{ctx.author.mention} loves {out_loves_str}")
loves: list[tuple] = await self.db.get_lovehates(user=user.strip(), loves=True) loves = await self.db.get_lovehates(user=user.strip(), loves=True)
if not loves: if not loves:
return await ctx.respond(f"{user} doesn't seem to love anything...") return await ctx.respond(f"{user} doesn't seem to love anything...")
out_loves_str: str = self.join_with_and(out_loves) out_loves_str = self.join_with_and(out_loves)
return await ctx.respond(f"{user} loves {out_loves_str}") return await ctx.respond(f"{user} loves {out_loves_str}")
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
@ -77,15 +81,27 @@ class LoveHate(commands.Cog):
""" """
try: try:
if not thing: if not thing:
thing: str = ctx.author.display_name _thing: str = ctx.author.display_name
if discord.utils.raw_mentions(thing): else:
_thing = thing
if discord.utils.raw_mentions(_thing):
# There are mentions # There are mentions
thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention thing_id: int = discord.utils.raw_mentions(_thing)[0] # First mention
thing: str = self.bot.get_guild(ctx.guild.id).get_member(thing_id).display_name guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
if not guild:
return
thing_member: Optional[discord.Member] = guild.get_member(thing_id)
if not thing_member:
return
_thing = thing_member.display_name
who_loves: list[tuple] = await self.db.get_wholovehates(thing=thing, if not _thing:
return
who_loves: Union[list, bool] = await self.db.get_wholovehates(thing=_thing,
loves=True) loves=True)
if not who_loves: if not isinstance(who_loves, list):
return await ctx.respond(f"I couldn't find anyone who loves {thing}...") return await ctx.respond(f"I couldn't find anyone who loves {thing}...")
out_wholoves: list = [] out_wholoves: list = []
@ -114,18 +130,28 @@ class LoveHate(commands.Cog):
""" """
try: try:
if not thing: if not thing:
thing: str = ctx.author.display_name _thing: str = ctx.author.display_name
if discord.utils.raw_mentions(thing): else:
_thing = thing
if discord.utils.raw_mentions(_thing):
# There are mentions # There are mentions
thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
thing: str = self.bot.get_guild(ctx.guild.id).get_member(thing_id).display_name if not guild:
return
thing_id: int = discord.utils.raw_mentions(_thing)[0] # First mention
thing_member: Optional[discord.Member] = guild.get_member(thing_id)
if not thing_member:
return
_thing = thing_member.display_name
who_hates: list[tuple] = await self.db.get_wholovehates(thing=thing, who_hates: Union[list[tuple], bool] = await self.db.get_wholovehates(thing=_thing,
hates=True) hates=True)
if not who_hates: if not who_hates:
return await ctx.respond(f"I couldn't find anyone who hates {thing}...") return await ctx.respond(f"I couldn't find anyone who hates {thing}...")
out_whohates: list = [] out_whohates: list = []
if not isinstance(who_hates, list):
return
for hater in who_hates: for hater in who_hates:
(hater,) = hater (hater,) = hater
out_whohates.append(str(hater)) out_whohates.append(str(hater))
@ -170,26 +196,24 @@ class LoveHate(commands.Cog):
""" """
try: try:
if not user: if not user:
hates: list[tuple] = await self.db.get_lovehates(user=ctx.author.display_name, display_name = ctx.author.display_name
hates: Union[list[tuple], bool] = await self.db.get_lovehates(user=display_name,
hates=True) hates=True)
if not hates: if not hates:
return await ctx.respond("You don't seem to hate anything...") return await ctx.respond("You don't seem to hate anything...")
else:
out_hates: list = [] hates = await self.db.get_lovehates(user=user.strip(), hates=True)
for hated_thing in hates: if not hates:
(hated_thing,) = hated_thing return await ctx.respond(f"{user} doesn't seem to hate anything...")
out_hates.append(str(hated_thing))
out_hates_str: str = self.join_with_and(out_hates)
return await ctx.respond(f"{ctx.author.mention} hates {out_hates_str}")
hates: list[tuple] = await self.db.get_lovehates(user=user.strip(), hates=True)
if not hates:
return await ctx.respond(f"{user} doesn't seem to hate anything...")
out_hates_str: str = self.join_with_and(hates) out_hates: list = []
if not isinstance(hates, list):
return
for hated_thing in hates:
(hated_thing,) = hated_thing
out_hates.append(str(hated_thing))
out_hates_str: str = self.join_with_and(out_hates)
return await ctx.respond(f"{user} hates {out_hates_str}") return await ctx.respond(f"{user} hates {out_hates_str}")
except Exception as e: except Exception as e:
await ctx.respond(f"Error: {str(e)}") await ctx.respond(f"Error: {str(e)}")
@ -209,7 +233,13 @@ class LoveHate(commands.Cog):
if discord.utils.raw_mentions(thing): if discord.utils.raw_mentions(thing):
# There are mentions # There are mentions
thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention
thing: str = self.bot.get_guild(ctx.guild.id).get_member(thing_id).display_name guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild)
if not guild:
return
thing_member: Optional[discord.Member] = guild.get_member(thing_id)
if not thing_member:
return
thing = thing_member.display_name
love: str = await self.db.update(ctx.author.display_name, love: str = await self.db.update(ctx.author.display_name,
thing, 1) thing, 1)
@ -232,7 +262,13 @@ class LoveHate(commands.Cog):
if discord.utils.raw_mentions(thing): if discord.utils.raw_mentions(thing):
# There are mentions # There are mentions
thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention thing_id: int = discord.utils.raw_mentions(thing)[0] # First mention
thing: str = self.bot.get_guild(ctx.guild.id).get_member(thing_id).display_name guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
if not guild:
return
thing_member: Optional[discord.Member] = guild.get_member(thing_id)
if not thing_member:
return
thing = thing_member.display_name
hate: str = await self.db.update(ctx.author.display_name, hate: str = await self.db.update(ctx.author.display_name,
thing, -1) thing, -1)
return await ctx.respond(hate) return await ctx.respond(hate)

View File

@ -8,11 +8,12 @@ import random
from typing import Optional, LiteralString from typing import Optional, LiteralString
import logging import logging
import discord import discord
from .misc_util import Util from cogs.misc_util import Util
import aiosqlite as sqlite3 import aiosqlite as sqlite3
from sh import cowsay as cow_say, fortune # pylint: disable=no-name-in-module from sh import cowsay as cow_say, fortune # pylint: disable=no-name-in-module
from discord.ext import bridge, commands, tasks from discord.ext import bridge, commands, tasks
from disc_havoc import Havoc from disc_havoc import Havoc
from constructors import MiscException
# pylint: disable=bare-except, broad-exception-caught, broad-exception-raised, global-statement # pylint: disable=bare-except, broad-exception-caught, broad-exception-raised, global-statement
# pylint: disable=too-many-lines, invalid-name # pylint: disable=too-many-lines, invalid-name
@ -64,7 +65,7 @@ class Misc(commands.Cog):
global BOT_CHANIDS global BOT_CHANIDS
BOT_CHANIDS = self.bot.BOT_CHANIDS BOT_CHANIDS = self.bot.BOT_CHANIDS
def is_spamchan() -> bool: # pylint: disable=no-method-argument def is_spamchan() -> bool: # type: ignore
"""Check if channel is spamchan""" """Check if channel is spamchan"""
def predicate(ctx): def predicate(ctx):
try: try:
@ -74,9 +75,9 @@ class Misc(commands.Cog):
except: except:
traceback.print_exc() traceback.print_exc()
return False return False
return commands.check(predicate) return commands.check(predicate) # type: ignore
def is_spamchan_or_drugs() -> bool: # pylint: disable=no-method-argument def is_spamchan_or_drugs() -> bool: # type: ignore
"""Check if channel is spamchan or drugs chan""" """Check if channel is spamchan or drugs chan"""
def predicate(ctx): def predicate(ctx):
try: try:
@ -86,10 +87,10 @@ class Misc(commands.Cog):
except: except:
traceback.print_exc() traceback.print_exc()
return False return False
return commands.check(predicate) return commands.check(predicate) # type: ignore
async def get_random_guild_member(self, online_only: Optional[bool] = False) -> str: async def get_random_guild_member(self, online_only: Optional[bool] = False) -> Optional[str]:
""" """
Get Random Guild Member Get Random Guild Member
Args: Args:
@ -97,7 +98,9 @@ class Misc(commands.Cog):
Returns: Returns:
str str
""" """
guild = self.bot.get_guild(1145182936002482196) guild: Optional[discord.Guild] = self.bot.get_guild(1145182936002482196)
if not guild:
return None
if not online_only: if not online_only:
guild_members = [str(member.display_name) for member in guild.members if not member.bot] guild_members = [str(member.display_name) for member in guild.members if not member.bot]
else: else:
@ -115,14 +118,16 @@ class Misc(commands.Cog):
None None
""" """
try: try:
stats_embed: discord.Embed = await self.util.get_stats_embed() stats_embed: Optional[discord.Embed] = await self.util.get_stats_embed()
if not stats_embed:
return
return await ctx.respond(embed=stats_embed) return await ctx.respond(embed=stats_embed)
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Error: {str(e)}") return await ctx.respond(f"Error: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def listcoffees(self, ctx) -> None: async def listcoffees(self, ctx) -> None:
""" """
List Available Coffees List Available Coffees
@ -142,8 +147,8 @@ class Misc(commands.Cog):
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Error: {str(e)}") return await ctx.respond(f"Error: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def listshoves(self, ctx) -> None: async def listshoves(self, ctx) -> None:
""" """
List Available Fates for shove command List Available Fates for shove command
@ -187,7 +192,10 @@ class Misc(commands.Cog):
'9': '9', '9': '9',
} }
with ctx.channel.typing(): with ctx.channel.typing():
(days, hours, minutes, seconds, ms, us) = self.util.get_days_to_xmas() # pylint: disable=unused-variable countdown = self.util.get_days_to_xmas()
if not isinstance(countdown, tuple) or len(countdown) < 6:
return await ctx.respond("Oops, Christmas is cancelled.") # Invalid countdown from util
(days, hours, minutes, seconds, ms, _) = countdown
now: datetime.datetime = datetime.datetime.now() now: datetime.datetime = datetime.datetime.now()
if now.month == 12 and now.day == 25: if now.month == 12 and now.day == 25:
return await ctx.respond("# IT IS CHRISTMAS!!!!!!!!\n-# keep the change, you filthy animal") return await ctx.respond("# IT IS CHRISTMAS!!!!!!!!\n-# keep the change, you filthy animal")
@ -235,19 +243,24 @@ class Misc(commands.Cog):
None None
""" """
try: try:
guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
if not guild:
return
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
else: else:
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
.get_member(recipient_id).display_name if not recipient_member:
return
recipient = recipient_member.display_name
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
with ctx.channel.typing(): with ctx.channel.typing():
insult: str = await self.util.get_insult(recipient) insult: str = await self.util.get_insult(recipient)
if insult: if insult:
@ -272,16 +285,21 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
else: else:
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
return
recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
with ctx.channel.typing(): with ctx.channel.typing():
compliment: str = await self.util.get_compliment(recipient) compliment: str = await self.util.get_compliment(recipient)
if compliment: if compliment:
@ -304,17 +322,25 @@ class Misc(commands.Cog):
""" """
try: try:
if not recipient: if not recipient:
recipient: str = ctx.author.display_name recipient = ctx.author.display_name
else: else:
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
return
recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
(choice_name, choice_category, choice_description) = await self.util.get_whisky() whisky: Optional[tuple] = await self.util.get_whisky()
if not whisky:
raise MiscException("Failed to get whisky from db")
(choice_name, choice_category, choice_description) = whisky
embed: discord.Embed = discord.Embed(title=f"Whisky for {recipient}: {choice_name}", embed: discord.Embed = discord.Embed(title=f"Whisky for {recipient}: {choice_name}",
description=choice_description.strip()) description=choice_description.strip())
embed.add_field(name="Category", value=choice_category, inline=True) embed.add_field(name="Category", value=choice_category, inline=True)
@ -339,17 +365,27 @@ class Misc(commands.Cog):
""" """
try: try:
if not recipient: if not recipient:
recipient: str = ctx.author.display_name recipient = ctx.author.display_name
else: else:
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
return
recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
(choice_name, choice_ingredients) = await self.util.get_drink() if not recipient:
return
drink: Optional[tuple] = await self.util.get_drink()
if not drink:
raise MiscException("Failed to get drink from db.")
(choice_name, choice_ingredients) = drink
await ctx.respond(f"*is mixing up **{choice_name}** for {recipient.strip()}*") await ctx.respond(f"*is mixing up **{choice_name}** for {recipient.strip()}*")
embed: discord.Embed = discord.Embed(title=f"Cocktail for {recipient}", embed: discord.Embed = discord.Embed(title=f"Cocktail for {recipient}",
description=choice_name) description=choice_name)
@ -377,20 +413,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*sprays **{recipient_normal}** with water*") await ctx.respond(f"*sprays **{recipient_normal}** with water*")
await self.util.increment_counter("water_sprays") await self.util.increment_counter("water_sprays")
@ -412,20 +452,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*passes **{recipient_normal}** a barf bag*") await ctx.respond(f"*passes **{recipient_normal}** a barf bag*")
await self.util.increment_counter("barf_bags") await self.util.increment_counter("barf_bags")
@ -448,30 +492,34 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
if recipient == "rhodes": if recipient == "rhodes":
tea: str = "a cup of Harney & Sons Hot Cinnamon Spice Tea" tea = "a cup of Harney & Sons Hot Cinnamon Spice Tea"
elif ctx.author.id == 992437729927376996 or recipient.lower() in ["kriegerin", elif ctx.author.id == 992437729927376996 or recipient.lower() in ["kriegerin",
"traurigkeit", "traurigkeit",
"krieg", "krieg",
"kriegs", "kriegs",
"cyberkrieg", "cyberkrieg",
"ck"]: "ck"]:
tea: str = "a cup of earl grey, light and sweet" tea = "a cup of earl grey, light and sweet"
response = await ctx.respond(f"*hands **{recipient_normal}** {tea}*") response = await ctx.respond(f"*hands **{recipient_normal}** {tea}*")
await self.util.increment_counter("teas") await self.util.increment_counter("teas")
try: try:
@ -483,8 +531,8 @@ class Misc(commands.Cog):
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Failed: {str(e)}") return await ctx.respond(f"Failed: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def cowsay(self, ctx, *, async def cowsay(self, ctx, *,
message: str) -> None: message: str) -> None:
""" """
@ -505,8 +553,8 @@ class Misc(commands.Cog):
return await ctx.respond(f"Failed: {str(e)}") return await ctx.respond(f"Failed: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def fortune(self, ctx, async def fortune(self, ctx,
cowfile: Optional[str] = None) -> None: cowfile: Optional[str] = None) -> None:
""" """
@ -518,7 +566,7 @@ class Misc(commands.Cog):
""" """
try: try:
if not cowfile: if not cowfile:
cowfile: str = random.choice(self.COWS).replace(".cow", "") cowfile = random.choice(self.COWS).replace(".cow", "")
if not f'{cowfile}.cow' in self.COWS: if not f'{cowfile}.cow' in self.COWS:
return await ctx.respond(f"Unknown cow {cowfile}, who dat?") return await ctx.respond(f"Unknown cow {cowfile}, who dat?")
@ -531,8 +579,8 @@ class Misc(commands.Cog):
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Failed: {str(e)}") return await ctx.respond(f"Failed: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def listcows(self, ctx) -> None: async def listcows(self, ctx) -> None:
""" """
List available .cow files (for cowsay) List available .cow files (for cowsay)
@ -544,7 +592,7 @@ class Misc(commands.Cog):
cow_list: str = "" cow_list: str = ""
try: try:
for cow in self.COWS: for cow in self.COWS:
cow: str = cow.replace(".cow", "") cow = cow.replace(".cow", "")
cow_list += f"- **{cow}**\n" cow_list += f"- **{cow}**\n"
embed: discord.Embed = discord.Embed(title="List of .cows", embed: discord.Embed = discord.Embed(title="List of .cows",
@ -568,20 +616,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*doses **{recipient_normal}** with Zyklon-B*") response = await ctx.respond(f"*doses **{recipient_normal}** with Zyklon-B*")
await self.util.increment_counter("cyanides") await self.util.increment_counter("cyanides")
@ -591,7 +643,7 @@ class Misc(commands.Cog):
except Exception as e: except Exception as e:
logging.debug("Failed to add cynaide reaction: %s", logging.debug("Failed to add cynaide reaction: %s",
str(e)) str(e))
except: except Exception as e:
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Failed: {str(e)}") return await ctx.respond(f"Failed: {str(e)}")
@ -609,20 +661,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*doses **{recipient_normal}** with school gravy*") response = await ctx.respond(f"*doses **{recipient_normal}** with school gravy*")
await self.util.increment_counter("gravies") await self.util.increment_counter("gravies")
@ -650,20 +706,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*hands **{recipient_normal}** a cold glass of water*") response = await ctx.respond(f"*hands **{recipient_normal}** a cold glass of water*")
await self.util.increment_counter("waters") await self.util.increment_counter("waters")
@ -692,20 +752,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*shoves **{recipient_normal}** {chosen_fate}*") await ctx.respond(f"*shoves **{recipient_normal}** {chosen_fate}*")
await self.util.increment_counter("shoves") await self.util.increment_counter("shoves")
@ -727,22 +791,28 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
chosen_coffee: str = self.util.get_coffee() chosen_coffee: Optional[str] = self.util.get_coffee()
if not chosen_coffee:
return
response = await ctx.respond(f"*hands **{recipient_normal}** {chosen_coffee}*") response = await ctx.respond(f"*hands **{recipient_normal}** {chosen_coffee}*")
await self.util.increment_counter("coffees") await self.util.increment_counter("coffees")
try: try:
@ -768,24 +838,31 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
else: else:
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
return
recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
chosen_cookie: dict = await self.util.get_cookie() chosen_cookie: Optional[dict] = await self.util.get_cookie()
if not chosen_cookie:
raise MiscException("Failed to get cookie from db.")
embed: discord.Embed = discord.Embed(title=f"Cookie for {recipient}", embed: discord.Embed = discord.Embed(title=f"Cookie for {recipient}",
description=f"Have a {chosen_cookie.get('name')}", description=f"Have a {chosen_cookie.get('name')}",
colour=discord.Colour.orange(), colour=discord.Colour.orange(),
image=chosen_cookie.get('image_url')) image=chosen_cookie.get('image_url'))
embed.add_field(name="Origin", embed.add_field(name="Origin",
value=chosen_cookie.get('origin')) value=chosen_cookie.get('origin', 'N/A'))
await ctx.respond(embed=embed) await ctx.respond(embed=embed)
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
@ -803,20 +880,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*hands **{recipient_normal}** 2 warm hashbrowns*") await ctx.respond(f"*hands **{recipient_normal}** 2 warm hashbrowns*")
await self.util.increment_counter("hashbrowns") await self.util.increment_counter("hashbrowns")
@ -838,20 +919,24 @@ class Misc(commands.Cog):
authorDisplay = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*serves **{recipient_normal}** a plate of ritalini* 😉") response = await ctx.respond(f"*serves **{recipient_normal}** a plate of ritalini* 😉")
await response.add_reaction(emoji="💊") await response.add_reaction(emoji="💊")
@ -875,20 +960,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*hands **{recipient_normal}** a grilled cheese*") await ctx.respond(f"*hands **{recipient_normal}** a grilled cheese*")
await self.util.increment_counter("grilled_cheeses") await self.util.increment_counter("grilled_cheeses")
@ -910,20 +999,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
await ctx.respond(f"*hands **{recipient_normal}** a hot bowl of soup*") await ctx.respond(f"*hands **{recipient_normal}** a hot bowl of soup*")
await self.util.increment_counter("soups") await self.util.increment_counter("soups")
@ -945,18 +1038,22 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
@ -981,20 +1078,24 @@ class Misc(commands.Cog):
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*hands **{recipient_normal}** a side of bacon*") response = await ctx.respond(f"*hands **{recipient_normal}** a side of bacon*")
await response.add_reaction(emoji="🥓") await response.add_reaction(emoji="🥓")
@ -1017,20 +1118,24 @@ class Misc(commands.Cog):
authorDisplay = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*sends **{recipient_normal}** to the Gallows to be hanged asynchronely*") response = await ctx.respond(f"*sends **{recipient_normal}** to the Gallows to be hanged asynchronely*")
await self.util.increment_counter("hangings") await self.util.increment_counter("hangings")
@ -1043,8 +1148,7 @@ class Misc(commands.Cog):
await ctx.respond(f"Failed: {str(e)}") await ctx.respond(f"Failed: {str(e)}")
traceback.print_exc() traceback.print_exc()
return return
@bridge.bridge_command() @bridge.bridge_command()
async def touch(self, ctx, *, async def touch(self, ctx, *,
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
@ -1056,9 +1160,12 @@ class Misc(commands.Cog):
Returns: Returns:
None None
""" """
guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
if not guild:
return
no_self_touch: str = ", don't fucking touch yourself here. You disgust me." no_self_touch: str = ", don't fucking touch yourself here. You disgust me."
if recipient is None: if not recipient:
recipient_normal: str = ctx.author.mention recipient_normal: str = ctx.author.mention
await ctx.respond(f"{recipient_normal}{no_self_touch}") await ctx.respond(f"{recipient_normal}{no_self_touch}")
try: try:
@ -1066,18 +1173,21 @@ class Misc(commands.Cog):
except Exception as e: except Exception as e:
logging.debug("Failed to add puke reactin for touch command: %s", logging.debug("Failed to add puke reactin for touch command: %s",
str(e)) str(e))
return await self.util.increment_counter("touch_denials") await self.util.increment_counter("touch_denials")
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ if not guild:
.get_member(recipient_id).display_name return
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
.get_member(recipient_id).mention if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
response = await ctx.respond(f"*touches **{recipient_normal}** for **{ctx.author.mention}** because they wouldn't touch them with a shitty stick!*") response = await ctx.respond(f"*touches **{recipient_normal}** for **{ctx.author.mention}** because they wouldn't touch them with a shitty stick!*")
await self.util.increment_counter("touches") await self.util.increment_counter("touches")
@ -1090,8 +1200,8 @@ class Misc(commands.Cog):
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Failed: {str(e)}") return await ctx.respond(f"Failed: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def qajoke(self, ctx) -> None: async def qajoke(self, ctx) -> None:
""" """
Get a joke in Q/A Form! Get a joke in Q/A Form!
@ -1101,7 +1211,10 @@ class Misc(commands.Cog):
None None
""" """
try: try:
(question, answer) = await self.util.get_qajoke() qajoke: Optional[tuple] = await self.util.get_qajoke()
if not qajoke:
return
(question, answer) = qajoke
escaped_question = discord.utils.escape_markdown(question) escaped_question = discord.utils.escape_markdown(question)
escasped_answer = discord.utils.escape_markdown(answer) escasped_answer = discord.utils.escape_markdown(answer)
embed: discord.Embed = discord.Embed(title=escaped_question, embed: discord.Embed = discord.Embed(title=escaped_question,
@ -1110,8 +1223,8 @@ class Misc(commands.Cog):
except Exception as e: except Exception as e:
await ctx.respond(f"Error: {str(e)}") await ctx.respond(f"Error: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def rjoke(self, ctx) -> None: async def rjoke(self, ctx) -> None:
""" """
Get a joke! (from r/jokes scrape) Get a joke! (from r/jokes scrape)
@ -1121,7 +1234,10 @@ class Misc(commands.Cog):
None None
""" """
try: try:
(title, body, score) = await self.util.get_rjoke() rjoke: Optional[tuple] = await self.util.get_rjoke()
if not rjoke:
raise MiscException("Failed to get rjoke from db.")
(title, body, score) = rjoke
escaped_title = discord.utils.escape_markdown(title) escaped_title = discord.utils.escape_markdown(title)
escaped_body = discord.utils.escape_markdown(body) escaped_body = discord.utils.escape_markdown(body)
embed: discord.Embed = discord.Embed(title=escaped_title, embed: discord.Embed = discord.Embed(title=escaped_title,
@ -1132,8 +1248,8 @@ class Misc(commands.Cog):
traceback.print_exc() traceback.print_exc()
return await ctx.respond(f"Error: {str(e)}") return await ctx.respond(f"Error: {str(e)}")
@bridge.bridge_command() @bridge.bridge_command() # type: ignore
@is_spamchan_or_drugs() # pylint: disable=too-many-function-args @is_spamchan_or_drugs()
async def joint(self, ctx, *, async def joint(self, ctx, *,
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
@ -1146,23 +1262,31 @@ class Misc(commands.Cog):
""" """
authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\ authorDisplay: str = ctx.author.display_name if not(ctx.author.display_name is None)\
else ctx.message.author.display_name else ctx.message.author.display_name
if recipient is None: if not recipient:
recipient: str = authorDisplay.strip() recipient = authorDisplay.strip()
recipient_normal: str = ctx.user.mention recipient_normal: str = ctx.user.mention
else: else:
recipient_normal: str = recipient recipient_normal = recipient
if discord.utils.raw_mentions(recipient): if discord.utils.raw_mentions(recipient):
# There are mentions # There are mentions
recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention recipient_id: int = discord.utils.raw_mentions(recipient)[0] # First mention
recipient: str = self.bot.get_guild(ctx.guild.id)\ guild: Optional[discord.Guild] = self.bot.get_guild(ctx.guild.id)
.get_member(recipient_id).display_name if not guild:
recipient_normal: str = self.bot.get_guild(ctx.guild.id)\ return
.get_member(recipient_id).mention recipient_member: Optional[discord.Member] = guild.get_member(recipient_id)
if not recipient_member:
return
recipient = recipient_member.display_name
recipient_normal = recipient_member.mention
else: else:
recipient: str = discord.utils.escape_mentions(recipient.strip()) recipient = discord.utils.escape_mentions(recipient.strip())
try: try:
(choice_strain, choice_desc) = await self.util.get_strain() strain: Optional[tuple] = await self.util.get_strain()
if not strain:
raise MiscException("Failed to get strain from db.")
(choice_strain, choice_desc) = strain
escaped_description = discord.utils.escape_markdown(choice_desc.strip()) escaped_description = discord.utils.escape_markdown(choice_desc.strip())
await ctx.send_followup(f"*hands **{recipient_normal}** a joint rolled up with some **{choice_strain}***", username="Joint Granter") await ctx.send_followup(f"*hands **{recipient_normal}** a joint rolled up with some **{choice_strain}***", username="Joint Granter")
embed: discord.Embed = discord.Embed(title=choice_strain, embed: discord.Embed = discord.Embed(title=choice_strain,
@ -1239,8 +1363,8 @@ class Misc(commands.Cog):
""" User Commands """ """ User Commands """
@commands.user_command(name="Give Joint") @commands.user_command(name="Give Joint") # type: ignore
@is_spamchan() # pylint: disable=too-many-function-args @is_spamchan()
async def joint_context_menu(self, ctx, member: discord.Member) -> None: async def joint_context_menu(self, ctx, member: discord.Member) -> None:
""" """
Joint Context Menu Joint Context Menu
@ -1250,7 +1374,10 @@ class Misc(commands.Cog):
Returns: Returns:
None None
""" """
(choice_strain, choice_desc) = await self.util.get_strain() strain: Optional[tuple] = await self.util.get_strain()
if not strain:
raise MiscException("Failed to get strain from db.")
(choice_strain, choice_desc) = strain
escaped_desc = discord.utils.escape_markdown(choice_desc.strip()) escaped_desc = discord.utils.escape_markdown(choice_desc.strip())
await ctx.interaction.respond(f"*hands **<@{member.id}>** a joint rolled up with some **{choice_strain}***") await ctx.interaction.respond(f"*hands **<@{member.id}>** a joint rolled up with some **{choice_strain}***")
embed: discord.Embed = discord.Embed(title=choice_strain, embed: discord.Embed = discord.Embed(title=choice_strain,
@ -1278,10 +1405,7 @@ class Misc(commands.Cog):
def cog_unload(self) -> None: def cog_unload(self) -> None:
"""Run on Cog Unload""" """Run on Cog Unload"""
try: pass
self.randstat_loop.cancel()
except Exception as e:
logging.debug("Failed to cancel randstat loop: %s", str(e))
def setup(bot) -> None: def setup(bot) -> None:
"""Run on Cog Load""" """Run on Cog Load"""

View File

@ -6,7 +6,7 @@ import traceback
import random import random
import datetime import datetime
import pytz import pytz
from typing import Optional, LiteralString from typing import Any, Optional, LiteralString, Union
import regex import regex
import aiosqlite as sqlite3 import aiosqlite as sqlite3
from aiohttp import ClientSession, ClientTimeout from aiohttp import ClientSession, ClientTimeout
@ -19,7 +19,7 @@ class Util:
self.URL_URBANDICTIONARY: str = "http://api.urbandictionary.com/v0/define" self.URL_URBANDICTIONARY: str = "http://api.urbandictionary.com/v0/define"
self.URL_INSULTAPI: str = "https://insult.mattbas.org/api/insult" self.URL_INSULTAPI: str = "https://insult.mattbas.org/api/insult"
self.COMPLIMENT_GENERATOR = ComplimentGenerator() self.COMPLIMENT_GENERATOR = ComplimentGenerator()
self.dbs: dict[str|LiteralString] = { self.dbs: dict[str, str|LiteralString] = {
'whisky': os.path.join("/usr/local/share", 'whisky': os.path.join("/usr/local/share",
"sqlite_dbs", "whiskey.db"), "sqlite_dbs", "whiskey.db"),
'drinks': os.path.join("/usr/local/share", 'drinks': os.path.join("/usr/local/share",
@ -73,50 +73,42 @@ class Util:
(mics, mils) = _t(td.microseconds, 1000) (mics, mils) = _t(td.microseconds, 1000)
return (td.days, h, m, s, mics, mils) return (td.days, h, m, s, mics, mils)
def sqlite_dict_factory(self, cursor: sqlite3.Cursor, row: sqlite3.Row) -> dict: async def get_counter(self, counter: Optional[str] = None) -> Optional[dict]:
"""
SQLite Dict Factory for Rows Returned
Args:
cursor (sqlite3.Row)
row (sqlite3.Row)
Returns:
dict
"""
fields = [column[0] for column in cursor.description]
return { key: value for key, value in zip(fields, row) }
async def get_counter(self, counter: Optional[str] = None) -> dict:
""" """
Get Counter Get Counter
Args: Args:
counter (Optional[str]) counter (Optional[str])
Returns: Returns:
dict Optional[dict]
""" """
async with sqlite3.connect(self.dbs.get('stats'), stats_db: str|LiteralString = self.dbs.get('stats', '')
if not stats_db:
return None
async with sqlite3.connect(stats_db,
timeout=3) as db_conn: timeout=3) as db_conn:
db_conn.row_factory = self.sqlite_dict_factory db_conn.row_factory = sqlite3.Row
query: str = "SELECT ? FROM stats LIMIT 1" query: str = "SELECT ? FROM stats LIMIT 1"
if not counter: if not counter:
query: str = "SELECT * FROM stats LIMIT 1" query = "SELECT * FROM stats LIMIT 1"
async with await db_conn.execute(query, (counter,) if counter else None) as db_cursor: async with await db_conn.execute(query, (counter,) if counter else None) as db_cursor:
result: dict = await db_cursor.fetchone() result = await db_cursor.fetchone()
return result return result
async def get_stats_embed(self) -> Embed: async def get_stats_embed(self) -> Optional[Embed]:
""" """
Get Stats Embed Get Stats Embed
Returns: Returns:
Embed Optional[Embed]
""" """
counters: dict = await self.get_counter() counters: Optional[dict] = await self.get_counter()
if not counters:
return None
embed: Embed = Embed(title="Stats") embed: Embed = Embed(title="Stats")
counter_message: str = "" counter_message: str = ""
counters_sorted: dict = dict(sorted(counters.items(), counters_sorted: dict = dict(sorted(counters.items(),
key=lambda item: item[1], reverse=True)) key=lambda item: item[1], reverse=True))
for counter, value in counters_sorted.items(): for counter, value in counters_sorted.items():
counter: str = regex.sub(r'_', ' ', counter = regex.sub(r'_', ' ',
counter.strip()).title() counter.strip()).title()
counter_message += f"- {value} {counter}\n" counter_message += f"- {value} {counter}\n"
embed.description = counter_message.strip() embed.description = counter_message.strip()
@ -130,7 +122,10 @@ class Util:
Returns: Returns:
bool bool
""" """
async with sqlite3.connect(self.dbs.get('stats'), stats_db: str|LiteralString = self.dbs.get('stats', '')
if not stats_db:
return False
async with sqlite3.connect(stats_db,
timeout=3) as db_conn: timeout=3) as db_conn:
async with await db_conn.execute(f"UPDATE stats SET {counter} = {counter} + 1") as db_cursor: async with await db_conn.execute(f"UPDATE stats SET {counter} = {counter} + 1") as db_cursor:
if db_cursor.rowcount < 0: if db_cursor.rowcount < 0:
@ -139,11 +134,11 @@ class Util:
await db_conn.commit() await db_conn.commit()
return True return True
async def get_ud_def(self, term: Optional[str] = None) -> tuple[str, str]: async def get_ud_def(self, term: str) -> tuple[str, str]:
""" """
Get Definition from UD Get Definition from UD
Args: Args:
term (Optional[str]) term (str)
Returns: Returns:
tuple[str, str] tuple[str, str]
""" """
@ -202,93 +197,107 @@ class Util:
return self.COMPLIMENT_GENERATOR.compliment(subject) return self.COMPLIMENT_GENERATOR.compliment(subject)
return self.COMPLIMENT_GENERATOR.compliment_in_language(subject, language) return self.COMPLIMENT_GENERATOR.compliment_in_language(subject, language)
async def get_whisky(self) -> tuple: async def get_whisky(self) -> Optional[tuple]:
""" """
Get Whisky Get Whisky
Returns: Returns:
tuple Optional[tuple]
""" """
whisky_db: str|LiteralString = self.dbs.get('whisky') whisky_db: str|LiteralString = self.dbs.get('whisky', '')
db_conn = await sqlite3.connect(database=whisky_db, timeout=2) if not whisky_db:
db_query: str = "SELECT name, category, description FROM whiskeys ORDER BY random() LIMIT 1" return None
db_cursor: sqlite3.Cursor = await db_conn.execute(db_query) async with sqlite3.connect(database=whisky_db,
db_result: tuple = await db_cursor.fetchone() timeout=2) as db_conn:
db_query: str = "SELECT name, category, description FROM whiskeys ORDER BY random() LIMIT 1"
(name, category, description) = db_result async with await db_conn.execute(db_query) as db_cursor:
name: str = regex.sub(r'(^\p{White_Space}|\r|\n)', '', db_result: Optional[Union[sqlite3.Row, tuple]] = await db_cursor.fetchone()
regex.sub(r'\p{White_Space}{2,}', ' ', if not db_result:
name.strip())) return None
category: str = regex.sub(r'(^\p{White_Space}|\r|\n)', '', (name, category, description) = db_result
regex.sub(r'\p{White_Space}{2,}', ' ', name = regex.sub(r'(^\p{White_Space}|\r|\n)', '',
category.strip()))
description: str = regex.sub(r'(^\p{White_Space}|\r|\n)', '',
regex.sub(r'\p{White_Space}{2,}', ' ', regex.sub(r'\p{White_Space}{2,}', ' ',
description.strip())) name.strip()))
return (name, category, description) category = regex.sub(r'(^\p{White_Space}|\r|\n)', '',
regex.sub(r'\p{White_Space}{2,}', ' ',
category.strip()))
description = regex.sub(r'(^\p{White_Space}|\r|\n)', '',
regex.sub(r'\p{White_Space}{2,}', ' ',
description.strip()))
return (name, category, description)
async def get_drink(self) -> tuple: async def get_drink(self) -> Optional[tuple]:
""" """
Get Drink Get Drink
Returns: Returns:
tuple Optional[tuple]
""" """
drinks_db: str|LiteralString = self.dbs.get('drinks') drinks_db: str|LiteralString = self.dbs.get('drinks', '')
db_conn = await sqlite3.connect(database=drinks_db, timeout=2) if not drinks_db:
db_query: str = "SELECT name, ingredients FROM cocktails ORDER BY random() LIMIT 1" return None
db_cursor: sqlite3.Cursor = await db_conn.execute(db_query) async with sqlite3.connect(database=drinks_db,
db_result: tuple = await db_cursor.fetchone() timeout=2) as db_conn:
db_query: str = "SELECT name, ingredients FROM cocktails ORDER BY random() LIMIT 1"
async with await db_conn.execute(db_query) as db_cursor:
db_result: tuple = await db_cursor.fetchone()
(name, ingredients) = db_result
name = regex.sub(r'(^\p{White_Space}|\r|\n)', '', regex.sub(r'\p{White_Space}{2,}', ' ', name.strip()))
ingredients = regex.sub(r'(^\p{White_Space}|\r|\n)', '', regex.sub(r'\p{White_Space}{2,}', ' ', ingredients.strip()))
ingredients = regex.sub(r'\*', '\u2731', ingredients.strip())
return (name, ingredients)
(name, ingredients) = db_result async def get_strain(self, strain: Optional[str] = None) -> Optional[tuple]:
name = regex.sub(r'(^\p{White_Space}|\r|\n)', '', regex.sub(r'\p{White_Space}{2,}', ' ', name.strip()))
ingredients = regex.sub(r'(^\p{White_Space}|\r|\n)', '', regex.sub(r'\p{White_Space}{2,}', ' ', ingredients.strip()))
ingredients = regex.sub(r'\*', '\u2731', ingredients.strip())
return (name, ingredients)
async def get_strain(self, strain: Optional[str] = None) -> tuple:
""" """
Get Strain Get Strain
Args: Args:
strain (Optional[str]) strain (Optional[str])
Returns: Returns:
tuple Optional[tuple]
""" """
strains_db: str|LiteralString = self.dbs.get('strains') strains_db: str|LiteralString = self.dbs.get('strains', '')
db_conn = await sqlite3.connect(database=strains_db, timeout=2) if not strains_db:
db_params: Optional[tuple] = None return None
if not strain: async with sqlite3.connect(database=strains_db,
db_query: str = "SELECT name, description FROM strains_w_desc ORDER BY random() LIMIT 1" timeout=2) as db_conn:
else: db_params: Optional[tuple] = None
db_query: str = "SELECT name, description FROM strains_w_desc WHERE name LIKE ?" if not strain:
db_params: tuple = (f"%{strain.strip()}%",) db_query: str = "SELECT name, description FROM strains_w_desc ORDER BY random() LIMIT 1"
else:
db_cursor: sqlite3.Cursor = await db_conn.execute(db_query, db_params) db_query = "SELECT name, description FROM strains_w_desc WHERE name LIKE ?"
db_result: tuple = await db_cursor.fetchone() db_params = (f"%{strain.strip()}%",)
async with await db_conn.execute(db_query, db_params) as db_cursor:
db_result: Optional[tuple] = await db_cursor.fetchone()
return db_result
return db_result async def get_qajoke(self) -> Optional[tuple]:
async def get_qajoke(self) -> tuple:
""" """
Get QA Joke Get QA Joke
Returns: Returns:
tuple Optional[tuple]
""" """
qajoke_db: str|LiteralString = self.dbs.get('qajoke') qajoke_db: str|LiteralString = self.dbs.get('qajoke', '')
async with sqlite3.connect(database=qajoke_db, timeout=2) as db: if not qajoke_db:
async with await db.execute('SELECT question, answer FROM jokes ORDER BY RANDOM() LIMIT 1') as cursor: return None
async with sqlite3.connect(database=qajoke_db,
timeout=2) as db_conn:
db_query: str = "SELECT question, answer FROM jokes ORDER BY RANDOM() LIMIT 1"
async with await db_conn.execute(db_query) as cursor:
(question, answer) = await cursor.fetchone() (question, answer) = await cursor.fetchone()
return (question, answer) return (question, answer)
return None return None
async def get_rjoke(self) -> tuple: async def get_rjoke(self) -> Optional[tuple]:
""" """
Get r/joke Joke Get r/joke Joke
Returns: Returns:
tuple Optional[tuple]
""" """
rjokes_db: str|LiteralString = self.dbs.get('rjokes') rjokes_db: str|LiteralString = self.dbs.get('rjokes', '')
async with sqlite3.connect(database=rjokes_db, timeout=2) as db: if not rjokes_db:
async with await db.execute('SELECT title, body, score FROM jokes WHERE score >= 100 ORDER BY RANDOM() LIMIT 1') as cursor: return None
async with sqlite3.connect(database=rjokes_db, timeout=2) as db_conn:
db_query: str = "SELECT title, body, score FROM jokes WHERE score >= 100 ORDER BY RANDOM() LIMIT 1'"
async with await db_conn.execute(db_query) as cursor:
(title, body, score) = await cursor.fetchone() (title, body, score) = await cursor.fetchone()
return (title, body, score) return (title, body, score)
return None return None
@ -307,29 +316,34 @@ class Util:
try: try:
async with await client.get(facts_api_url, async with await client.get(facts_api_url,
timeout=ClientTimeout(connect=5, sock_read=5)) as request: timeout=ClientTimeout(connect=5, sock_read=5)) as request:
json: dict = await request.json() _json: dict = await request.json()
fact: str = json.get('text') fact: str = _json.get('text', None)
if not fact: if not fact:
raise BaseException("RandFact Src 1 Failed") raise BaseException("RandFact Src 1 Failed")
return fact return fact
except: except:
async with await client.get(facts_backup_url, async with await client.get(facts_backup_url,
timeout=ClientTimeout(connect=5, sock_read=5)) as request: timeout=ClientTimeout(connect=5, sock_read=5)) as request:
json: dict = await request.json() _json = await request.json()
fact: str = json.get('fact') fact = _json.get('fact', None)
return fact return fact
except Exception as e: except Exception as e:
traceback.print_exc() traceback.print_exc()
return f"Failed to get a random fact :( [{str(e)}]" return f"Failed to get a random fact :( [{str(e)}]"
async def get_cookie(self) -> dict: async def get_cookie(self) -> Optional[dict]:
""" """
Get Cookie Get Cookie
Returns: Returns:
dict Optional[dict]
""" """
async with sqlite3.connect(self.dbs.get('cookies'), timeout=2) as db_conn: cookies_db = self.dbs.get('cookies', '')
async with await db_conn.execute("SELECT name, origin, image_url FROM cookies ORDER BY RANDOM() LIMIT 1") as db_cursor: if not cookies_db:
return None
async with sqlite3.connect(cookies_db,
timeout=2) as db_conn:
db_query: str = "SELECT name, origin, image_url FROM cookies ORDER BY RANDOM() LIMIT 1"
async with await db_conn.execute(db_query) as db_cursor:
(name, origin, image_url) = await db_cursor.fetchone() (name, origin, image_url) = await db_cursor.fetchone()
return { return {
'name': name, 'name': name,
@ -338,7 +352,7 @@ class Util:
} }
def get_coffee(self) -> str: def get_coffee(self) -> Optional[str]:
""" """
Get Coffee Get Coffee
Returns: Returns:
@ -354,16 +368,16 @@ class Util:
return randomCoffee return randomCoffee
except: except:
traceback.print_exc() traceback.print_exc()
return False return None
def get_days_to_xmas(self) -> tuple[int|float]: def get_days_to_xmas(self) -> Optional[tuple]:
""" """
Get # of Days until Xmas Get # of Days until Xmas
Returns: Returns:
tuple[int|float] Optional[tuple]
""" """
today: datetime = datetime.datetime.now(tz=pytz.UTC) today: datetime.datetime = datetime.datetime.now(tz=pytz.UTC)
xmas: datetime = datetime.datetime( xmas: datetime.datetime = datetime.datetime(
year=today.year, year=today.year,
month=12, month=12,
day=25, day=25,
@ -374,15 +388,18 @@ class Util:
return (days, hours, minutes, seconds, ms, us) return (days, hours, minutes, seconds, ms, us)
async def get_randmsg(self) -> str: async def get_randmsg(self) -> Optional[str]:
""" """
Get Random Message from randmsg.db Get Random Message from randmsg.db
Returns: Returns:
str Optional[str]
""" """
randmsg_db = self.dbs.get('randmsg') randmsg_db: str|LiteralString = self.dbs.get('randmsg', '')
if not randmsg_db:
return None
async with sqlite3.connect(database=randmsg_db, async with sqlite3.connect(database=randmsg_db,
timeout=2) as db_conn: timeout=2) as db_conn:
async with await db_conn.execute("SELECT msg FROM msgs ORDER BY RANDOM() LIMIT 1") as db_cursor: db_query: str = "SELECT msg FROM msgs ORDER BY RANDOM() LIMIT 1"
async with await db_conn.execute(db_query) as db_cursor:
(result,) = await db_cursor.fetchone() (result,) = await db_cursor.fetchone()
return result return result

View File

@ -1,321 +0,0 @@
#!/usr/bin/env python3.12
# pylint: disable=bare-except, broad-exception-caught
"""
Quote cog for Havoc
"""
import traceback
import time
import os
import datetime
import asyncio
import discord
import aiosqlite as sqlite3
from discord.ext import bridge, commands
from disc_havoc import Havoc
class DB:
"""DB Utility for Quote Cog"""
def __init__(self, bot: Havoc):
self.bot: Havoc = bot
self.db_path = os.path.join("/", "usr", "local", "share",
"sqlite_dbs", "quotes.db")
self.hp_chanid = 1157529874936909934
async def get_quote_count(self):
"""Get Quote Count"""
async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
async with await db_conn.execute("SELECT COUNT (*) FROM quotes") as db_cursor:
result = await db_cursor.fetchone()
return result[-1]
async def remove_quote(self, quote_id: int):
"""Remove Quote from DB"""
try:
async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
async with await db_conn.execute("DELETE FROM quotes WHERE id = ?", (quote_id,)) as _:
await db_conn.commit()
return True
except:
await self.bot.get_channel(self.hp_chanid).send(traceback.format_exc())
return False
async def add_quote(self, message_id: int, channel_id: int,
quoted_member_id: int,
message_time: int,
quoter_friendly: str,
quoted_friendly: str,
channel_friendly: str,
message_content: str,
):
"""Add Quote to DB"""
params = (
quoter_friendly,
int(time.time()),
quoted_friendly,
quoted_member_id,
channel_friendly,
channel_id,
message_id,
message_time,
quoter_friendly,
message_content,
)
try:
async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
# pylint: disable=line-too-long
db_conn.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])
async with await db_conn.execute("INSERT INTO quotes (added_by, added_at, quoted_user_display, quoted_user_memberid, quoted_channel_display, quoted_channel_id, quoted_message_id, quoted_message_time, added_by_friendly, quoted_message) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
params) as _: # pylint: enable=line-too-long
await db_conn.commit()
return True
except:
return traceback.format_exc()
async def fetch_quote(self, random: bool = False, quoteid: int = None, added_by: str = None, quoted_user: str = None, content: str = None):
"""Fetch Quote from DB"""
try:
query_head = "SELECT id, added_by_friendly, added_at, quoted_user_display, quoted_channel_display, quoted_message_time, quoted_message FROM quotes"
query = ""
params = None
if random:
query = f"{query_head} ORDER BY RANDOM() LIMIT 1"
elif quoteid:
query = f"{query_head} WHERE id = ? LIMIT 1"
params = (quoteid,)
elif added_by:
query = f"{query_head} WHERE added_by_friendly LIKE ? ORDER BY RANDOM() LIMIT 5"
params = (f"%{added_by}%",)
elif quoted_user:
query = f"{query_head} WHERE quoted_user_display LIKE ? ORDER BY RANDOM() LIMIT 5"
params = (f"%{quoted_user}%",)
elif content:
query = f"{query_head} WHERE quoted_message LIKE ? ORDER BY RANDOM() LIMIT 5"
params = (f"%{content}%",)
async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
db_conn.row_factory = lambda c, r: dict([(col[0], r[idx]) for idx, col in enumerate(c.description)])
async with await db_conn.execute(query, params) as db_cursor:
results = await db_cursor.fetchall()
if not results:
return {
'err': 'No results for query',
}
if random or quoteid:
chosen = results[-1]
return {
str(k): v for k,v in chosen.items()
}
else:
return [
{ str(k): v for k,v in _.items() }
for _ in results
]
except:
return traceback.format_exc()
class Quote(commands.Cog):
"""Quote Cog for Havoc"""
def __init__(self, bot: Havoc):
self.bot: Havoc = bot
self.db = DB(self.bot)
def is_homeserver(): # pylint: disable=no-method-argument
"""Check if channel/interaction is within homeserver"""
def predicate(ctx):
try:
return ctx.guild.id == 1145182936002482196
except:
traceback.print_exc()
return False
return commands.check(predicate)
@commands.message_command(name="Add Quote")
async def add_quote(self, ctx, message: discord.Message):
"""Add A Quote"""
hp_chanid = 1157529874936909934
try:
if message.author.bot:
return await ctx.respond("Quotes are for real users, not bots.", ephemeral=True)
quoter_friendly = ctx.author.display_name
quoted_message_id = message.id
quoted_channel_friendly = f'#{ctx.channel.name}'
quoted_channel_id = ctx.channel.id
message_content = message.content
message_author_friendly = message.author.display_name
message_author_id = message.author.id
message_time = int(message.created_at.timestamp())
message_escaped = discord.utils.escape_mentions(discord.utils.escape_markdown(message_content)).strip()
if len(message_escaped) < 3:
return await ctx.respond("**Error**: Message (text content) is not long enough to quote.", ephemeral=True)
if len(message_escaped) > 512:
return await ctx.respond("**Error**: Message (text content) is too long to quote.", ephemeral=True)
result = await self.db.add_quote(message_id=quoted_message_id,
channel_id=quoted_channel_id,
quoted_member_id=message_author_id,
message_time=message_time,
quoter_friendly=quoter_friendly,
quoted_friendly=message_author_friendly,
channel_friendly=quoted_channel_friendly,
message_content=message_content)
if not result:
return await ctx.respond("Failed!", ephemeral=True)
else:
return await ctx.respond("OK!", ephemeral=True)
except:
await self.bot.get_channel(hp_chanid).send(traceback.format_exc())
@bridge.bridge_command(aliases=['rand'])
@is_homeserver() # pylint: disable=too-many-function-args
async def randquote(self, ctx):
"""Get a random quote"""
try:
random_quote = await self.db.fetch_quote(random=True)
if random_quote.get('err'):
return await ctx.respond("Failed to get a quote")
quote_id = random_quote.get('id')
quoted_friendly = random_quote.get('quoted_user_display', 'Unknown')
adder_friendly = random_quote.get('added_by_friendly', 'Unknown')
message_time = datetime.datetime.fromtimestamp(random_quote.get('quoted_message_time'))
message_channel = random_quote.get('quoted_channel_display')
quote_added_at = datetime.datetime.fromtimestamp(random_quote.get('added_at'))
quote_content = random_quote.get('quoted_message')
embed = discord.Embed(
colour=discord.Colour.orange(),
title=f"Quote #{quote_id}",
)
embed.description = f"**{quoted_friendly}:** {quote_content}"
embed.add_field(name="Original Message Time", value=message_time)
embed.add_field(name="Channel", value=message_channel)
embed.add_field(name="Quote ID", value=quote_id)
embed.footer = discord.EmbedFooter(text=f"Added by {adder_friendly} {quote_added_at}")
return await ctx.respond(embed=embed)
except:
error = await ctx.respond(traceback.format_exc())
await asyncio.sleep(10)
await error.delete()
@bridge.bridge_command(aliases=['qg'])
@is_homeserver() # pylint: disable=too-many-function-args
async def quoteget(self, ctx, quoteid):
"""Get a specific quote by ID"""
try:
if not str(quoteid).strip().isnumeric():
return await ctx.respond("**Error**: Quote ID must be numeric.")
fetched_quote = await self.db.fetch_quote(quoteid=quoteid)
if fetched_quote.get('err'):
return await ctx.respond("**Error**: Quote not found")
quote_id = fetched_quote.get('id')
quoted_friendly = fetched_quote.get('quoted_user_display', 'Unknown')
adder_friendly = fetched_quote.get('added_by_friendly', 'Unknown')
message_time = datetime.datetime.fromtimestamp(fetched_quote.get('quoted_message_time'))
message_channel = fetched_quote.get('quoted_channel_display')
quote_added_at = datetime.datetime.fromtimestamp(fetched_quote.get('added_at'))
quote_content = fetched_quote.get('quoted_message')
embed = discord.Embed(
colour=discord.Colour.orange(),
title=f"Quote #{quote_id}",
)
embed.description = f"**{quoted_friendly}:** {quote_content}"
embed.add_field(name="Original Message Time", value=message_time)
embed.add_field(name="Channel", value=message_channel)
embed.add_field(name="Quote ID", value=quote_id)
embed.footer = discord.EmbedFooter(text=f"Added by {adder_friendly} {quote_added_at}")
return await ctx.respond(embed=embed)
except:
error = await ctx.respond(traceback.format_exc())
await asyncio.sleep(10)
await error.delete()
@bridge.bridge_command(aliases=['qs'])
@is_homeserver() # pylint: disable=too-many-function-args
async def quotesearch(self, ctx, *, content: str):
"""Search for a quote (by content)"""
try:
found_quotes = await self.db.fetch_quote(content=content)
if isinstance(found_quotes, dict) and found_quotes.get('err'):
return await ctx.respond(f"Quote search failed: {found_quotes.get('err')}")
embeds = []
for quote in found_quotes:
quote_id = quote.get('id')
quoted_friendly = quote.get('quoted_user_display', 'Unknown')
adder_friendly = quote.get('added_by_friendly', 'Unknown')
message_time = datetime.datetime.fromtimestamp(quote.get('quoted_message_time'))
message_channel = quote.get('quoted_channel_display')
quote_added_at = datetime.datetime.fromtimestamp(quote.get('added_at'))
quote_content = quote.get('quoted_message')
# await ctx.respond(f"**{quoted_friendly}**: {quote}")ed_friendly = quote.get('quoted_user_display', 'Unknown')
adder_friendly = quote.get('added_by_friendly', 'Unknown')
message_time = datetime.datetime.fromtimestamp(quote.get('quoted_message_time'))
message_channel = quote.get('quoted_channel_display')
quote_added_at = datetime.datetime.fromtimestamp(quote.get('added_at'))
quote = quote.get('quoted_message')
# await ctx.respond(f"**{quoted_friendly}**: {quote}")
embed = discord.Embed(
colour=discord.Colour.orange(),
title=f"Quote #{quote_id}",
)
embed.description = f"**{quoted_friendly}:** {quote_content}"
embed.add_field(name="Original Message Time", value=message_time)
embed.add_field(name="Channel", value=message_channel)
embed.add_field(name="Quote ID", value=quote_id)
embed.footer = discord.EmbedFooter(text=f"Added by {adder_friendly} {quote_added_at}")
embeds.append(embed)
return await ctx.respond(embeds=embeds)
except Exception as e:
await ctx.respond(f"Error: {type(e).__name__} - {str(e)}")
@bridge.bridge_command(aliases=['nq'])
@is_homeserver() # pylint: disable=too-many-function-args
async def nquotes(self, ctx):
"""Get # of quotes stored"""
try:
quote_count = await self.db.get_quote_count()
if not quote_count:
return await ctx.respond("**Error**: No quotes found!")
return await ctx.respond(f"I currently have **{quote_count}** quotes stored.")
except Exception as e:
await ctx.respond(f"Error: {type(e).__name__} - {str(e)}")
@bridge.bridge_command(aliases=['qr'])
@commands.is_owner()
@is_homeserver() # pylint: disable=too-many-function-args
async def quoteremove(self, ctx, quoteid):
"""Remove a quote (by id)
Owner only"""
try:
if not str(quoteid).strip().isnumeric():
return await ctx.respond("**Error**: Quote ID must be numeric.")
quoteid = int(quoteid)
remove_quote = await self.db.remove_quote(quoteid)
if not remove_quote:
return await ctx.respond("**Error**: Failed!", ephemeral=True)
return await ctx.respond("Removed!", ephemeral=True)
except Exception as e:
await ctx.respond(f"Error: {type(e).__name__} - {str(e)}")
def setup(bot):
"""Run on Cog Load"""
bot.add_cog(Quote(bot))

View File

@ -29,7 +29,7 @@ class Radio(commands.Cog):
"""Run on Bot Ready""" """Run on Bot Ready"""
await self.radio_init() await self.radio_init()
def is_radio_chan(): # pylint: disable=no-method-argument def is_radio_chan(): # type: ignore
"""Check if channel is radio chan""" """Check if channel is radio chan"""
def predicate(ctx): def predicate(ctx):
try: try:
@ -59,8 +59,12 @@ class Radio(commands.Cog):
""" """
try: try:
(radio_guild, radio_chan) = self.channels['sfm'] (radio_guild, radio_chan) = self.channels['sfm']
channel: discord.TextChannel = self.bot.get_guild(radio_guild)\ guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild)
.get_channel(radio_chan) if not guild:
return
channel = guild.get_channel(radio_chan)
if not isinstance(channel, discord.VoiceChannel):
return
if not self.bot.voice_clients: if not self.bot.voice_clients:
await channel.connect() await channel.connect()
try: try:
@ -84,24 +88,35 @@ class Radio(commands.Cog):
try: try:
(radio_guild, radio_chan) = self.channels['sfm'] (radio_guild, radio_chan) = self.channels['sfm']
try: try:
vc: discord.VoiceClient = self.bot.voice_clients[-1] vc: discord.VoiceProtocol = self.bot.voice_clients[-1]
except: except:
logging.debug("No voice client, establishing new VC connection...") logging.debug("No voice client, establishing new VC connection...")
channel = self.bot.get_guild(radio_guild)\ guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild)
.get_channel(radio_chan) if not guild:
return
channel = guild.get_channel(radio_chan)
if not isinstance(channel, discord.VoiceChannel):
return
await channel.connect() await channel.connect()
vc = self.bot.voice_clients[-1] vc = self.bot.voice_clients[-1]
if not(vc.is_playing()) or vc.is_paused():
if not vc.is_playing() or vc.is_paused(): # type: ignore
"""
Mypy does not seem aware of the is_playing, play, and is_paused methods,
but they exist.
"""
logging.info("Detected VC not playing... playing!") logging.info("Detected VC not playing... playing!")
source = discord.FFmpegOpusAudio(self.STREAM_URL, source = discord.FFmpegOpusAudio(self.STREAM_URL,
before_options="-timeout 3000000") before_options="-timeout 3000000")
vc.play(source, after=lambda e: logging.info("Error: %s", e)\
if e else None) vc.play(source, after=lambda e: logging.info("Error: %s", e) if e else None) # type: ignore
# Get Now Playing # Get Now Playing
np_track = await get_now_playing() np_track = await get_now_playing()
if np_track and not self.LAST_NP_TRACK == np_track: if np_track and not self.LAST_NP_TRACK == np_track:
self.LAST_NP_TRACK: str = np_track self.LAST_NP_TRACK = np_track
await vc.channel.set_status(f"Now playing: {np_track}") if isinstance(vc.channel, discord.VoiceChannel):
await vc.channel.set_status(f"Now playing: {np_track}")
except: except:
traceback.print_exc() traceback.print_exc()

View File

@ -13,3 +13,12 @@ LoveHate
class LoveHateException(Exception): class LoveHateException(Exception):
"""Love Hate Exception (generic)""" """Love Hate Exception (generic)"""
pass pass
"""
Misc
"""
class MiscException(Exception):
"""Misc Exception (generic)"""
pass

View File

@ -29,7 +29,6 @@ cogs_list: list[str] = [
'meme', 'meme',
'karma', 'karma',
'lovehate', 'lovehate',
'quote',
'radio', 'radio',
] ]
@ -46,6 +45,8 @@ class Havoc(bridge.Bot):
owner_ids=OWNERS, activity=bot_activity, owner_ids=OWNERS, activity=bot_activity,
help_command=commands.MinimalHelpCommand()) help_command=commands.MinimalHelpCommand())
self.BOT_CHANIDS = BOT_CHANIDS self.BOT_CHANIDS = BOT_CHANIDS
self.load_exts()
def load_exts(self, initialRun: Optional[bool] = True) -> None: def load_exts(self, initialRun: Optional[bool] = True) -> None:
""" """

View File

@ -31,13 +31,13 @@ class DB:
if hates and loves: if hates and loves:
raise LoveHateException("Both hates and loves may not be True") raise LoveHateException("Both hates and loves may not be True")
elif hates: elif hates:
flag: int = -1 flag = -1
elif loves: elif loves:
flag: int = 1 flag = 1
elif not hates and not loves: elif not hates and not loves:
raise LoveHateException("Neither loves nor hates were requested") raise LoveHateException("Neither loves nor hates were requested")
params: tuple = (thing, flag,) params = (thing, flag,)
async with sqlite3.connect(self.db_path, timeout=2) as db_conn: async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
async with await db_conn.execute(query, params) as db_cursor: async with await db_conn.execute(query, params) as db_cursor:
result: list[tuple] = await db_cursor.fetchall() result: list[tuple] = await db_cursor.fetchall()
@ -47,7 +47,7 @@ class DB:
return result return result
async def get_lovehates(self, loves: bool = False, hates: bool = False, async def get_lovehates(self, loves: bool = False, hates: bool = False,
user: str = None, thing: str = None) -> list[tuple]|bool: user: Optional[str] = None, thing: Optional[str] = None) -> list[tuple]|bool:
""" """
Get a list of either 1) what {user} loves/hates, or who loves/hates {thing}, depending on bools loves, hates Get a list of either 1) what {user} loves/hates, or who loves/hates {thing}, depending on bools loves, hates
Args: Args:
@ -70,18 +70,18 @@ class DB:
if hates and loves: if hates and loves:
raise LoveHateException("Both hates and loves may not be True") raise LoveHateException("Both hates and loves may not be True")
elif hates: elif hates:
flag: int = -1 flag = -1
elif loves: elif loves:
flag: int = 1 flag = 1
elif not hates and not loves: elif not hates and not loves:
raise LoveHateException("Neither loves nor hates were requested") raise LoveHateException("Neither loves nor hates were requested")
if user: if user:
query: str = "SELECT thing FROM lovehate WHERE display_name LIKE ? AND flag == ?" query = "SELECT thing FROM lovehate WHERE display_name LIKE ? AND flag == ?"
params: tuple = (user, flag,) params = (user, flag,)
elif thing: elif thing:
query: str = "SELECT display_name FROM lovehate WHERE thing LIKE ? AND flag == ?" query = "SELECT display_name FROM lovehate WHERE thing LIKE ? AND flag == ?"
params: tuple = (thing, flag,) params = (thing, flag,)
async with sqlite3.connect(self.db_path, timeout=2) as db_conn: async with sqlite3.connect(self.db_path, timeout=2) as db_conn:
async with await db_conn.execute(query, params) as db_cursor: async with await db_conn.execute(query, params) as db_cursor:
@ -127,21 +127,21 @@ class DB:
db_query: str = "" db_query: str = ""
params: tuple = (user, thing,) params: tuple = (user, thing,)
already_opinionated: bool = await self.check_existence(user, thing) already_opinionated: Optional[int] = await self.check_existence(user, thing)
if already_opinionated: if already_opinionated:
if flag == 0: if flag == 0:
db_query: str = "DELETE FROM lovehate WHERE display_name LIKE ? AND thing LIKE ?" db_query = "DELETE FROM lovehate WHERE display_name LIKE ? AND thing LIKE ?"
else: else:
loves_or_hates: str = "loves" loves_or_hates: str = "loves"
if already_opinionated == -1: if already_opinionated == -1:
loves_or_hates: str = "hates" loves_or_hates = "hates"
raise LoveHateException(f"But {user} already {loves_or_hates} {thing}...") raise LoveHateException(f"But {user} already {loves_or_hates} {thing}...")
else: else:
match flag: match flag:
case -1: case -1:
db_query: str = "INSERT INTO lovehate(display_name, flag, thing) VALUES(?, -1, ?)" db_query = "INSERT INTO lovehate(display_name, flag, thing) VALUES(?, -1, ?)"
case 1: case 1:
db_query: str = "INSERT INTO lovehate(display_name, flag, thing) VALUES(?, 1, ?)" db_query = "INSERT INTO lovehate(display_name, flag, thing) VALUES(?, 1, ?)"
case _: case _:
raise LoveHateException("Unknown error, default case matched") raise LoveHateException("Unknown error, default case matched")