This commit is contained in:
codey 2025-02-16 20:07:02 -05:00
parent bb59b5a457
commit 9df3b37619
17 changed files with 196 additions and 56 deletions

View File

@ -1,3 +1,5 @@
![](https://codey.lol/havoc-fv.jpg) ![](https://codey.lol/havoc-fv.jpg)
# Discord-Havoc Rewrite (Pycord) # Discord-Havoc Rewrite (Pycord)
## [Wiki](/wiki)

View File

@ -17,8 +17,6 @@ from aiohttp import ClientSession, ClientTimeout
from discord.ext import bridge, commands, tasks from discord.ext import bridge, commands, tasks
from disc_havoc import Havoc from disc_havoc import Havoc
class Util: class Util:
"""Karma Utility""" """Karma Utility"""
def __init__(self, bot: Havoc): def __init__(self, bot: Havoc):
@ -34,10 +32,11 @@ class Util:
async def get_karma(self, keyword: str) -> int: async def get_karma(self, keyword: str) -> int:
""" """
Get Karma for Keyword Get Karma for Keyword
Args: Args:
keyword (str) keyword (str)
Returns: Returns:
int|str int
""" """
try: try:
async with ClientSession() as session: async with ClientSession() as session:
@ -56,10 +55,11 @@ class Util:
async def get_top(self, n: int = 10) -> Optional[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:
Optional[dict] Optional[dict]
""" """
try: try:
async with ClientSession() as session: async with ClientSession() as session:
@ -80,10 +80,11 @@ class Util:
async def get_top_embed(self, n:int = 10) -> Optional[discord.Embed]: async def get_top_embed(self, n:int = 10) -> Optional[discord.Embed]:
""" """
Get Top Karma Embed Get Top Karma Embed
Args: Args:
n (int): Number of top results to return, default 10 n (int): Number of top results to return, default 10
Returns: Returns:
discord.Embed Optional[discord.Embed]
""" """
top: Optional[dict] = await self.get_top(n) top: Optional[dict] = await self.get_top(n)
if not top: if not top:
@ -101,11 +102,14 @@ class Util:
""" """
Update Karma for Keyword Update Karma for Keyword
Args: Args:
display (str): Display name of the user who requested the update display (str): Display name of the user who requested the update
_id (int): Discord UID of the user who requested the update _id (int): Discord UID of the user who requested the update
keyword (str): Keyword to update keyword (str): Keyword to update
flag (int) flag (int)
""" Returns:
bool
"""
if not flag in [0, 1]: if not flag in [0, 1]:
return False return False
@ -134,6 +138,7 @@ class Util:
async def check_cooldown(self, user_id: int) -> bool: async def check_cooldown(self, user_id: int) -> bool:
""" """
Check if member has met cooldown period prior to adjusting karma Check if member has met cooldown period prior to adjusting karma
Args: Args:
user_id (int): The Discord UID to check user_id (int): The Discord UID to check
Returns: Returns:

View File

@ -21,10 +21,11 @@ class LoveHate(commands.Cog):
def join_with_and(self, items: list) -> str: def join_with_and(self, items: list) -> str:
""" """
Join list with and added before last item Join list with and added before last item
Args: Args:
items (list) items (list)
Returns: Returns:
str str
""" """
if len(items) > 1: if len(items) > 1:
return ', '.join(items[:-1]) + ' and ' + items[-1] return ', '.join(items[:-1]) + ' and ' + items[-1]
@ -35,11 +36,12 @@ class LoveHate(commands.Cog):
async def loves(self, ctx, user: Optional[str] = None) -> None: async def loves(self, ctx, user: Optional[str] = None) -> None:
""" """
If keyword isn't provided, returns the things YOU love; specify a user to find what THEY love. If keyword isn't provided, returns the things YOU love; specify a user to find what THEY love.
Args: Args:
ctx (Any) ctx (Any)
user (Optional[str]) user (Optional[str])
Returns: Returns:
None None
""" """
try: try:
if not user: if not user:
@ -73,6 +75,7 @@ class LoveHate(commands.Cog):
async def wholoves(self, ctx, *, thing: Optional[str] = None) -> None: async def wholoves(self, ctx, *, thing: Optional[str] = None) -> None:
""" """
Check who loves <thing> Check who loves <thing>
Args: Args:
ctx (Any) ctx (Any)
thing (Optional[str]) thing (Optional[str])
@ -122,6 +125,7 @@ class LoveHate(commands.Cog):
async def whohates(self, ctx, *, thing: Optional[str] = None) -> None: async def whohates(self, ctx, *, thing: Optional[str] = None) -> None:
""" """
Check who hates <thing> Check who hates <thing>
Args: Args:
ctx (Any) ctx (Any)
thing (Optional[str]) thing (Optional[str])
@ -170,6 +174,7 @@ class LoveHate(commands.Cog):
async def dontcare(self, ctx, thing: str) -> None: async def dontcare(self, ctx, thing: str) -> None:
""" """
Make me forget your opinion on <thing> Make me forget your opinion on <thing>
Args: Args:
ctx (Any) ctx (Any)
thing (str) thing (str)
@ -188,11 +193,12 @@ class LoveHate(commands.Cog):
async def hates(self, ctx, user: Optional[str] = None) -> None: async def hates(self, ctx, user: Optional[str] = None) -> None:
""" """
If keyword isn't provided, returns the things YOU hate; specify a user to find what THEY hate. If keyword isn't provided, returns the things YOU hate; specify a user to find what THEY hate.
Args: Args:
ctx (Any) ctx (Any)
user (Optional[str]) user (Optional[str])
Returns: Returns:
None None
""" """
try: try:
if not user: if not user:
@ -223,6 +229,7 @@ class LoveHate(commands.Cog):
async def love(self, ctx, *, thing: str) -> None: async def love(self, ctx, *, thing: str) -> None:
""" """
Love <thing> Love <thing>
Args: Args:
ctx (Any) ctx (Any)
thing (str) thing (str)
@ -252,6 +259,7 @@ class LoveHate(commands.Cog):
async def hate(self, ctx, *, thing: str) -> None: async def hate(self, ctx, *, thing: str) -> None:
""" """
Hate <thing> Hate <thing>
Args: Args:
ctx (Any) ctx (Any)
thing (str) thing (str)

View File

@ -90,9 +90,11 @@ class MemeModal(discord.ui.Modal):
await interaction.response.send_message("ERR: Text is limited to 80 characters for each the top and bottom lines.") await interaction.response.send_message("ERR: Text is limited to 80 characters for each the top and bottom lines.")
return return
meme_link: str = await self.meme_generator.create_meme(top_line=meme_top_line, meme_link: Optional[str] = await self.meme_generator.create_meme(top_line=meme_top_line,
bottom_line=meme_bottom_line, meme=selected_meme) bottom_line=meme_bottom_line, meme=selected_meme)
if not meme_link:
await interaction.response.send_message("Failed!")
return
embed: discord.Embed = discord.Embed(title="Generated Meme") embed: discord.Embed = discord.Embed(title="Generated Meme")
embed.set_image(url=meme_link) embed.set_image(url=meme_link)
embed.add_field(name="Meme", value=selected_meme, inline=True) embed.add_field(name="Meme", value=selected_meme, inline=True)
@ -159,6 +161,7 @@ class Meme(commands.Cog):
async def do_autos(self, only_comics: Optional[bool] = False) -> None: async def do_autos(self, only_comics: Optional[bool] = False) -> None:
""" """
Run Auto Posters Run Auto Posters
Args: Args:
only_comics (Optional[bool]): default False only_comics (Optional[bool]): default False
Returns: Returns:

View File

@ -93,6 +93,7 @@ class Misc(commands.Cog):
async def get_random_guild_member(self, online_only: Optional[bool] = False) -> Optional[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:
online_only (Optional[bool]) online_only (Optional[bool])
Returns: Returns:
@ -112,6 +113,7 @@ class Misc(commands.Cog):
async def stats(self, ctx) -> None: async def stats(self, ctx) -> None:
""" """
Get Stats Get Stats
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -131,6 +133,7 @@ class Misc(commands.Cog):
async def listcoffees(self, ctx) -> None: async def listcoffees(self, ctx) -> None:
""" """
List Available Coffees List Available Coffees
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -152,10 +155,11 @@ class Misc(commands.Cog):
async def listshoves(self, ctx) -> None: async def listshoves(self, ctx) -> None:
""" """
List Available Fates for shove command List Available Fates for shove command
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
None None
""" """
fates: str = "" fates: str = ""
try: try:
@ -173,10 +177,11 @@ class Misc(commands.Cog):
async def xmas(self, ctx) -> None: async def xmas(self, ctx) -> None:
""" """
Countdown til xmas! Countdown til xmas!
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
None None
""" """
try: try:
emojis: dict = { emojis: dict = {
@ -217,6 +222,7 @@ class Misc(commands.Cog):
async def randfact(self, ctx) -> None: async def randfact(self, ctx) -> None:
""" """
Get a random (useless) fact! Get a random (useless) fact!
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -236,6 +242,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Insult Someone (or yourself) Insult Someone (or yourself)
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -275,6 +282,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Compliment someone (or yourself) Compliment someone (or yourself)
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -314,6 +322,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Get a whisky for yourself or a friend! Get a whisky for yourself or a friend!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -357,6 +366,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Get a cocktail for yourself or a friend! Get a cocktail for yourself or a friend!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -404,6 +414,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Spray someone with water! Spray someone with water!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -443,6 +454,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Pass someone (or yourself) a barf bag! Pass someone (or yourself) a barf bag!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -482,6 +494,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Tea! Tea!
Args: Args:
recipient (Optional[str]) recipient (Optional[str])
Returns: Returns:
@ -537,6 +550,7 @@ class Misc(commands.Cog):
message: str) -> None: message: str) -> None:
""" """
Cowsay! Cowsay!
Args: Args:
ctx (Any) ctx (Any)
message (str) message (str)
@ -559,10 +573,11 @@ class Misc(commands.Cog):
cowfile: Optional[str] = None) -> None: cowfile: Optional[str] = None) -> None:
""" """
Fortune | Cowsay! Fortune | Cowsay!
Args: Args:
cowfile (Optional[str]) cowfile (Optional[str])
Returns: Returns:
None None
""" """
try: try:
if not cowfile: if not cowfile:
@ -584,6 +599,7 @@ class Misc(commands.Cog):
async def listcows(self, ctx) -> None: async def listcows(self, ctx) -> None:
""" """
List available .cow files (for cowsay) List available .cow files (for cowsay)
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -607,6 +623,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Cyanide! Cyanide!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -652,6 +669,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
School gravy! (It's deadly) School gravy! (It's deadly)
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -697,6 +715,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Cold water! Drink up. Cold water! Drink up.
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -741,6 +760,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Shove someone! (Or yourself) Shove someone! (Or yourself)
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -782,6 +802,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Coffee! Coffee!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -829,6 +850,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Cookies! Cookies!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -873,9 +895,12 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Hashbrowns! Hashbrowns!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
Returns:
None
""" """
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
@ -910,6 +935,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Ritalini! Ritalini!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -951,6 +977,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Grilled Cheese! Grilled Cheese!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -990,6 +1017,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Soup! Soup!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1029,6 +1057,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Muffins! Muffins!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1069,6 +1098,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Bacon! Bacon!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1109,6 +1139,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Hang someone! Hang someone!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1154,6 +1185,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Touch someone! Touch someone!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1205,6 +1237,7 @@ class Misc(commands.Cog):
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!
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -1228,10 +1261,11 @@ class Misc(commands.Cog):
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)
Args: Args:
ctx (Any) ctx (Any)
Returns; Returns;
None None
""" """
try: try:
rjoke: Optional[tuple] = await self.util.get_rjoke() rjoke: Optional[tuple] = await self.util.get_rjoke()
@ -1254,6 +1288,7 @@ class Misc(commands.Cog):
recipient: Optional[str] = None) -> None: recipient: Optional[str] = None) -> None:
""" """
Joints! Joints!
Args: Args:
ctx (Any) ctx (Any)
recipient (Optional[str]) recipient (Optional[str])
@ -1301,6 +1336,7 @@ class Misc(commands.Cog):
async def isitfriday(self, ctx) -> None: async def isitfriday(self, ctx) -> None:
""" """
IS IT FRIDAY!? IS IT FRIDAY!?
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
@ -1321,10 +1357,11 @@ class Misc(commands.Cog):
async def isitflyday(self, ctx) -> None: async def isitflyday(self, ctx) -> None:
""" """
IS IT FLYDAY!? IS IT FLYDAY!?
Args: Args:
ctx (Any) ctx (Any)
Returns: Returns:
None None
""" """
try: try:
today: datetime.datetime = datetime.datetime.today() today: datetime.datetime = datetime.datetime.today()
@ -1343,11 +1380,12 @@ class Misc(commands.Cog):
term: str) -> None: term: str) -> None:
""" """
Not sure what that term means? UD prolly knows. Not sure what that term means? UD prolly knows.
Args: Args:
ctx (Any) ctx (Any)
term (str) term (str)
Returns: Returns:
None None
""" """
try: try:
with ctx.channel.typing(): with ctx.channel.typing():
@ -1368,6 +1406,7 @@ class Misc(commands.Cog):
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
Args: Args:
ctx (Any) ctx (Any)
member (discord.Member) member (discord.Member)
@ -1389,11 +1428,12 @@ class Misc(commands.Cog):
async def coffee_context_menu(self, ctx, member: discord.Member) -> None: async def coffee_context_menu(self, ctx, member: discord.Member) -> None:
""" """
Coffee Context Menu Coffee Context Menu
Args: Args:
ctx (Any) ctx (Any)
member (discord.Member) member (discord.Member)
Returns: Returns:
None None
""" """
chosen_coffee = self.util.get_coffee() chosen_coffee = self.util.get_coffee()
response = await ctx.interaction.respond(f"*hands <@{member.id}> {chosen_coffee}*") response = await ctx.interaction.respond(f"*hands <@{member.id}> {chosen_coffee}*")

View File

@ -58,10 +58,12 @@ class Util:
def tdTuple(self, td:datetime.timedelta) -> tuple: def tdTuple(self, td:datetime.timedelta) -> tuple:
""" """
Create TimeDelta Tuple Create TimeDelta Tuple
Args: Args:
td (datetime.timedelta) td (datetime.timedelta)
Returns: Returns:
tuple tuple
""" """
def _t(t, n): def _t(t, n):
if t < n: if t < n:
@ -76,10 +78,12 @@ class Util:
async def get_counter(self, counter: Optional[str] = None) -> Optional[dict]: async def get_counter(self, counter: Optional[str] = None) -> Optional[dict]:
""" """
Get Counter Get Counter
Args: Args:
counter (Optional[str]) counter (Optional[str])
Returns: Returns:
Optional[dict] Optional[dict]
""" """
stats_db: str|LiteralString = self.dbs.get('stats', '') stats_db: str|LiteralString = self.dbs.get('stats', '')
if not stats_db: if not stats_db:
@ -97,8 +101,10 @@ class Util:
async def get_stats_embed(self) -> Optional[Embed]: async def get_stats_embed(self) -> Optional[Embed]:
""" """
Get Stats Embed Get Stats Embed
Returns: Returns:
Optional[Embed] Optional[Embed]
""" """
counters: Optional[dict] = await self.get_counter() counters: Optional[dict] = await self.get_counter()
if not counters: if not counters:
@ -117,10 +123,12 @@ class Util:
async def increment_counter(self, counter: str) -> bool: async def increment_counter(self, counter: str) -> bool:
""" """
Increment Counter Increment Counter
Args: Args:
counter (str) counter (str)
Returns: Returns:
bool bool
""" """
stats_db: str|LiteralString = self.dbs.get('stats', '') stats_db: str|LiteralString = self.dbs.get('stats', '')
if not stats_db: if not stats_db:
@ -137,10 +145,12 @@ class Util:
async def get_ud_def(self, term: str) -> 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 (str) term (str)
Returns: Returns:
tuple[str, str] tuple[str, str]
""" """
try: try:
async with ClientSession() as session: async with ClientSession() as session:
@ -172,10 +182,12 @@ class Util:
async def get_insult(self, recipient: str) -> str: async def get_insult(self, recipient: str) -> str:
""" """
Get Insult Get Insult
Args: Args:
recipient (str) recipient (str)
Returns: Returns:
str str
""" """
async with ClientSession() as session: async with ClientSession() as session:
async with await session.get(f"{self.URL_INSULTAPI}?who={recipient}") as request: async with await session.get(f"{self.URL_INSULTAPI}?who={recipient}") as request:
@ -187,11 +199,13 @@ class Util:
language: Optional[str] = None) -> str: language: Optional[str] = None) -> str:
""" """
Get Compliment Get Compliment
Args: Args:
subject (str) subject (str)
language (Optional[str]) language (Optional[str])
Returns: Returns:
str str
""" """
if not language: if not language:
return self.COMPLIMENT_GENERATOR.compliment(subject) return self.COMPLIMENT_GENERATOR.compliment(subject)
@ -200,8 +214,10 @@ class Util:
async def get_whisky(self) -> Optional[tuple]: async def get_whisky(self) -> Optional[tuple]:
""" """
Get Whisky Get Whisky
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
whisky_db: str|LiteralString = self.dbs.get('whisky', '') whisky_db: str|LiteralString = self.dbs.get('whisky', '')
if not whisky_db: if not whisky_db:
@ -228,8 +244,10 @@ class Util:
async def get_drink(self) -> Optional[tuple]: async def get_drink(self) -> Optional[tuple]:
""" """
Get Drink Get Drink
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
drinks_db: str|LiteralString = self.dbs.get('drinks', '') drinks_db: str|LiteralString = self.dbs.get('drinks', '')
if not drinks_db: if not drinks_db:
@ -249,10 +267,12 @@ class Util:
async def get_strain(self, strain: Optional[str] = None) -> Optional[tuple]: async def get_strain(self, strain: Optional[str] = None) -> Optional[tuple]:
""" """
Get Strain Get Strain
Args: Args:
strain (Optional[str]) strain (Optional[str])
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
strains_db: str|LiteralString = self.dbs.get('strains', '') strains_db: str|LiteralString = self.dbs.get('strains', '')
if not strains_db: if not strains_db:
@ -272,8 +292,10 @@ class Util:
async def get_qajoke(self) -> Optional[tuple]: async def get_qajoke(self) -> Optional[tuple]:
""" """
Get QA Joke Get QA Joke
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
qajoke_db: str|LiteralString = self.dbs.get('qajoke', '') qajoke_db: str|LiteralString = self.dbs.get('qajoke', '')
if not qajoke_db: if not qajoke_db:
@ -289,8 +311,10 @@ class Util:
async def get_rjoke(self) -> Optional[tuple]: async def get_rjoke(self) -> Optional[tuple]:
""" """
Get r/joke Joke Get r/joke Joke
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
rjokes_db: str|LiteralString = self.dbs.get('rjokes', '') rjokes_db: str|LiteralString = self.dbs.get('rjokes', '')
if not rjokes_db: if not rjokes_db:
@ -306,8 +330,10 @@ class Util:
async def get_random_fact(self) -> str: async def get_random_fact(self) -> str:
""" """
Get Random Fact Get Random Fact
Returns: Returns:
str str
""" """
try: try:
facts_api_url: str = "https://uselessfacts.jsph.pl/api/v2/facts/random" facts_api_url: str = "https://uselessfacts.jsph.pl/api/v2/facts/random"
@ -334,8 +360,10 @@ class Util:
async def get_cookie(self) -> Optional[dict]: async def get_cookie(self) -> Optional[dict]:
""" """
Get Cookie Get Cookie
Returns: Returns:
Optional[dict] Optional[dict]
""" """
cookies_db = self.dbs.get('cookies', '') cookies_db = self.dbs.get('cookies', '')
if not cookies_db: if not cookies_db:
@ -355,8 +383,10 @@ class Util:
def get_coffee(self) -> Optional[str]: def get_coffee(self) -> Optional[str]:
""" """
Get Coffee Get Coffee
Returns: Returns:
str str
""" """
try: try:
randomCoffee: str = random.choice(self.COFFEES) randomCoffee: str = random.choice(self.COFFEES)
@ -373,8 +403,10 @@ class Util:
def get_days_to_xmas(self) -> Optional[tuple]: def get_days_to_xmas(self) -> Optional[tuple]:
""" """
Get # of Days until Xmas Get # of Days until Xmas
Returns: Returns:
Optional[tuple] Optional[tuple]
""" """
today: datetime.datetime = datetime.datetime.now(tz=pytz.UTC) today: datetime.datetime = datetime.datetime.now(tz=pytz.UTC)
xmas: datetime.datetime = datetime.datetime( xmas: datetime.datetime = datetime.datetime(
@ -391,8 +423,10 @@ class Util:
async def get_randmsg(self) -> Optional[str]: async def get_randmsg(self) -> Optional[str]:
""" """
Get Random Message from randmsg.db Get Random Message from randmsg.db
Returns: Returns:
Optional[str] Optional[str]
""" """
randmsg_db: str|LiteralString = self.dbs.get('randmsg', '') randmsg_db: str|LiteralString = self.dbs.get('randmsg', '')
if not randmsg_db: if not randmsg_db:

View File

@ -23,6 +23,7 @@ class Owner(commands.Cog):
async def temperature(self, ctx, temp: Optional[int|str] = None) -> None: async def temperature(self, ctx, temp: Optional[int|str] = None) -> None:
""" """
Set Temperature Set Temperature
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
temperature (Optional[int|str]): New temperature temperature (Optional[int|str]): New temperature
@ -50,6 +51,7 @@ class Owner(commands.Cog):
async def reload(self, ctx) -> None: async def reload(self, ctx) -> None:
""" """
Reload Cogs Reload Cogs
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
Returns: Returns:
@ -66,6 +68,7 @@ class Owner(commands.Cog):
parameters: str) -> None: parameters: str) -> None:
""" """
Make me say something in a channel Make me say something in a channel
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
parameters (str): Channel <space> Message parameters (str): Channel <space> Message
@ -92,6 +95,7 @@ class Owner(commands.Cog):
status: Optional[str] = None) -> None: status: Optional[str] = None) -> None:
""" """
Change bots status Change bots status
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
status (Optional[str]): The new status to set status (Optional[str]): The new status to set
@ -111,6 +115,7 @@ class Owner(commands.Cog):
async def purge(self, ctx, message: discord.Message) -> None: async def purge(self, ctx, message: discord.Message) -> None:
""" """
Purge Messages Purge Messages
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
message (discord.Message): Discord message message (discord.Message): Discord message
@ -137,6 +142,7 @@ class Owner(commands.Cog):
async def movememe(self, ctx, message: discord.Message) -> None: async def movememe(self, ctx, message: discord.Message) -> None:
""" """
Move to Memes Move to Memes
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
message (discord.Message): Discord message message (discord.Message): Discord message
@ -173,6 +179,7 @@ class Owner(commands.Cog):
async def movedrugs(self, ctx, message: discord.Message) -> None: async def movedrugs(self, ctx, message: discord.Message) -> None:
""" """
Move to Drugs Move to Drugs
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
message (discord.Message): Discord message message (discord.Message): Discord message
@ -210,6 +217,7 @@ class Owner(commands.Cog):
async def movefunhouse(self, ctx, message: discord.Message) -> None: async def movefunhouse(self, ctx, message: discord.Message) -> None:
""" """
Move to fun-house Move to fun-house
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
message (discord.Message): Discord message message (discord.Message): Discord message
@ -245,6 +253,7 @@ class Owner(commands.Cog):
async def einsperren(self, ctx, member: discord.Member) -> None: async def einsperren(self, ctx, member: discord.Member) -> None:
""" """
Einsperren! Einsperren!
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
member (discord.Member): Discord member member (discord.Member): Discord member

View File

@ -44,6 +44,7 @@ class Radio(commands.Cog):
async def reinitradio(self, ctx) -> None: async def reinitradio(self, ctx) -> None:
""" """
Reinitialize serious.FM Reinitialize serious.FM
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
Returns: Returns:
@ -54,9 +55,7 @@ class Radio(commands.Cog):
await ctx.respond("Done!", ephemeral=True) await ctx.respond("Done!", ephemeral=True)
async def radio_init(self) -> None: async def radio_init(self) -> None:
""" """Init Radio"""
Init Radio
"""
try: try:
(radio_guild, radio_chan) = self.channels['sfm'] (radio_guild, radio_chan) = self.channels['sfm']
guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild) guild: Optional[discord.Guild] = self.bot.get_guild(radio_guild)

View File

@ -42,6 +42,7 @@ class Sing(commands.Cog):
song: Optional[str] = None) -> None: song: Optional[str] = None) -> None:
""" """
Search for lyrics, format is artist : song. Also reads activity. Search for lyrics, format is artist : song. Also reads activity.
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
song (Optional[str]): Song to search song (Optional[str]): Song to search
@ -120,6 +121,7 @@ class Sing(commands.Cog):
async def sing_context_menu(self, ctx, member: discord.Member) -> None: async def sing_context_menu(self, ctx, member: discord.Member) -> None:
""" """
Sing Context Menu Command Sing Context Menu Command
Args: Args:
ctx (Any): Discord context ctx (Any): Discord context
member (discord.Member): Discord member member (discord.Member): Discord member

View File

@ -51,10 +51,12 @@ class Havoc(bridge.Bot):
def load_exts(self, initialRun: Optional[bool] = True) -> None: def load_exts(self, initialRun: Optional[bool] = True) -> None:
""" """
Load Cogs/Extensions Load Cogs/Extensions
Args: Args:
initialRun (Optional[bool]) default: True initialRun (Optional[bool]) default: True
Returns: Returns:
None""" None
"""
load_method = self.load_extension if initialRun\ load_method = self.load_extension if initialRun\
else self.reload_extension else self.reload_extension

View File

@ -29,6 +29,7 @@ class CatboxAsync:
def generateRandomFileName(self, fileExt: Optional[str] = None) -> str: def generateRandomFileName(self, fileExt: Optional[str] = None) -> str:
""" """
Generate random file name Generate random file name
Args: Args:
fileExt (Optional[str]): File extension to use for naming fileExt (Optional[str]): File extension to use for naming
Returns: Returns:
@ -41,6 +42,7 @@ class CatboxAsync:
async def upload(self, file: str) -> Optional[str]: async def upload(self, file: str) -> Optional[str]:
""" """
Upload file to catbox Upload file to catbox
Args: Args:
file (str): Path of file to be uploaded file (str): Path of file to be uploaded
Returns: Returns:

View File

@ -11,6 +11,7 @@ async def get_channel_by_name(bot: discord.Bot, channel: str,
guild: int | None = None) -> Optional[Any]: # Optional[Any] used as pycord channel types can be ambigious guild: int | None = None) -> Optional[Any]: # Optional[Any] used as pycord channel types can be ambigious
""" """
Get Channel by Name Get Channel by Name
Args: Args:
bot (discord.Bot) bot (discord.Bot)
channel (str) channel (str)
@ -37,6 +38,7 @@ async def send_message(bot: discord.Bot, channel: str,
""" """
Send Message to the provided channel. If guild is provided, will limit to channels within that guild to ensure the correct Send Message to the provided channel. If guild is provided, will limit to channels within that guild to ensure the correct
channel is selected. Useful in the event a channel exists in more than one guild that the bot resides in. channel is selected. Useful in the event a channel exists in more than one guild that the bot resides in.
Args: Args:
bot (discord.Bot) bot (discord.Bot)
channel (str) channel (str)

View File

@ -35,12 +35,15 @@ class JesusMemeGenerator():
meme="Jesus-Talking-To-Cool-Dude") -> Optional[str]: meme="Jesus-Talking-To-Cool-Dude") -> Optional[str]:
""" """
Create Meme Create Meme
Args: Args:
top_line (str): Top line of meme top_line (str): Top line of meme
bottom_line (str): Bottom line of meme bottom_line (str): Bottom line of meme
meme (str): The meme to use, defaults to Jesus-Talking-To-Cool-Dude meme (str): The meme to use, defaults to Jesus-Talking-To-Cool-Dude
Returns: Returns:
Optional[str] Optional[str]
""" """
try: try:
if not top_line or not bottom_line: if not top_line or not bottom_line:

View File

@ -30,6 +30,7 @@ class LitterboxAsync:
def generateRandomFileName(self, fileExt: Optional[str] = None) -> str: def generateRandomFileName(self, fileExt: Optional[str] = None) -> str:
""" """
Generate Random Filename Generate Random Filename
Args: Args:
fileExt (Optional[str]): File extension to use for naming fileExt (Optional[str]): File extension to use for naming
Returns: Returns:
@ -44,6 +45,7 @@ class LitterboxAsync:
time='1h') -> Optional[str]: time='1h') -> Optional[str]:
""" """
Upload File to Litterbox Upload File to Litterbox
Args: Args:
file (Union[str, bytes, BufferedReader]): File to upload (accepts either filepath or io.BufferedReader) file (Union[str, bytes, BufferedReader]): File to upload (accepts either filepath or io.BufferedReader)
time (str): Expiration time, default: 1h time (str): Expiration time, default: 1h

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python3.12 #!/usr/bin/env python3.12
import os import os
import logging import logging
from typing import Optional, LiteralString from typing import LiteralString, Optional, Union
import aiosqlite as sqlite3 import aiosqlite as sqlite3
from constructors import LoveHateException from constructors import LoveHateException
@ -47,16 +47,18 @@ 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: Optional[str] = None, thing: Optional[str] = None) -> list[tuple]|bool: user: Optional[str] = None, thing: Optional[str] = None) -> Union[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:
loves (bool): Are we looking for loves? loves (bool): Are we looking for loves?
hates (bool): ...OR are we looking for hates? hates (bool): ...OR are we looking for hates?
user (Optional[str]): the user to query against user (Optional[str]): the user to query against
thing (Optional[str]): ... OR the thing to query against thing (Optional[str]): ... OR the thing to query against
Returns: Returns:
list[tuple]|bool Union[list[tuple], bool]
""" """
query: str = "" query: str = ""
@ -94,6 +96,7 @@ class DB:
async def check_existence(self, user: str, thing: str) -> Optional[int]: async def check_existence(self, user: str, thing: str) -> Optional[int]:
""" """
Determine whether a user is opinionated on a <thing> Determine whether a user is opinionated on a <thing>
Args: Args:
user (str): The user to check user (str): The user to check
thing (str): The thing to check if the user has an opinion on thing (str): The thing to check if the user has an opinion on
@ -114,6 +117,7 @@ class DB:
async def update(self, user: str, thing: str, flag: int) -> str: async def update(self, user: str, thing: str, flag: int) -> str:
""" """
Updates the lovehate database, and returns an appropriate response Updates the lovehate database, and returns an appropriate response
Args: Args:
user (str): The user to update user (str): The user to update
thing (str): The thing the user loves/hates/doesn't care about anymore thing (str): The thing the user loves/hates/doesn't care about anymore

View File

@ -7,6 +7,12 @@ from aiohttp import ClientSession, ClientTimeout
"""Radio Utils""" """Radio Utils"""
async def get_now_playing() -> Optional[str]: async def get_now_playing() -> Optional[str]:
"""
Get radio now playing
Returns:
str
"""
np_url: str = "https://api.codey.lol/radio/np" np_url: str = "https://api.codey.lol/radio/np"
try: try:
async with ClientSession() as session: async with ClientSession() as session:

View File

@ -4,23 +4,26 @@ import regex
import aiohttp import aiohttp
import textwrap import textwrap
import traceback import traceback
from typing import Optional
from discord import Activity from discord import Activity
from typing import Optional, Union
class Utility: class Utility:
"""Sing Utility""" """Sing Utility"""
def __init__(self): def __init__(self) -> None:
self.api_url: str = "http://127.0.0.1:52111/lyric/search" self.api_url: str = "http://127.0.0.1:52111/lyric/search"
self.api_src: str = "DISC-HAVOC" self.api_src: str = "DISC-HAVOC"
def parse_song_input(self, song: Optional[str] = None, def parse_song_input(self, song: Optional[str] = None,
activity: Optional[Activity] = None) -> bool|tuple: activity: Optional[Activity] = None) -> Union[bool, tuple]:
"""Parse Song (Sing Command) Input """
Parse Song (Sing Command) Input
Args: Args:
song (Optional[str]): Song to search song (Optional[str]): Song to search
activity (Optional[discord.Activity]): Discord activity, used to attempt lookup if no song is provided activity (Optional[discord.Activity]): Discord activity, used to attempt lookup if no song is provided
Returns: Returns:
bool|tuple Union[bool, tuple]
""" """
logging.debug("Activity? %s", activity) logging.debug("Activity? %s", activity)
try: try:
@ -28,58 +31,70 @@ class Utility:
# pylint: disable=superfluous-parens # pylint: disable=superfluous-parens
return False return False
# pylint: enable=superfluous-parens # pylint: enable=superfluous-parens
if not song and activity: if not song and isinstance(activity, Activity):
if not activity.name:
return False # No valid activity found
match activity.name.lower(): match activity.name.lower():
case "codey toons" | "cider" | "sonixd": case "codey toons" | "cider" | "sonixd":
search_artist: str = " ".join(str(activity.state)\ search_artist: str = " ".join(str(activity.state)\
.strip().split(" ")[1:]) .strip().split(" ")[1:])
search_artist: str = regex.sub(r"(\s{0,})(\[(spotify|tidal|sonixd|browser|yt music)])$", "", search_artist = regex.sub(r"(\s{0,})(\[(spotify|tidal|sonixd|browser|yt music)])$", "",
search_artist.strip(), flags=regex.IGNORECASE) search_artist.strip(), flags=regex.IGNORECASE)
search_song: str = str(activity.details) search_song = str(activity.details)
song: str = f"{search_artist} : {search_song}" song = f"{search_artist} : {search_song}"
case "tidal hi-fi": case "tidal hi-fi":
search_artist: str = str(activity.state) search_artist = str(activity.state)
search_song: str = str(activity.details) search_song = str(activity.details)
song: str = f"{search_artist} : {search_song}" song = f"{search_artist} : {search_song}"
case "spotify": case "spotify":
search_artist: str = str(activity.title) if not activity.title or not activity.artist: # type: ignore
search_song: str = str(activity.artist) """
song: str = f"{search_artist} : {search_song}" Attributes exist, but mypy does not recognize them. Ignored.
"""
return False
search_artist = str(activity.title) # type: ignore
search_song = str(activity.artist) # type: ignore
song = f"{search_artist} : {search_song}"
case "serious.fm" | "cocks.fm" | "something": case "serious.fm" | "cocks.fm" | "something":
if not activity.details: if not activity.details:
song: str = str(activity.state) song = str(activity.state)
else: else:
search_artist: str = str(activity.state) search_artist = str(activity.state)
search_song: str = str(activity.details) search_song = str(activity.details)
song: str = f"{search_artist} : {search_song}" song = f"{search_artist} : {search_song}"
case _: case _:
return False # Unsupported activity detected return False # Unsupported activity detected
search_split_by: str = ":" if not(song) or len(song.split(":")) > 1\ search_split_by: str = ":" if not(song) or len(song.split(":")) > 1\
else "-" # Support either : or - to separate artist/track else "-" # Support either : or - to separate artist/track
search_artist: str = song.split(search_split_by)[0].strip() if not song:
search_song: str = "".join(song.split(search_split_by)[1:]).strip() return False
search_artist = song.split(search_split_by)[0].strip()
search_song = "".join(song.split(search_split_by)[1:]).strip()
search_subsearch: Optional[str] = None search_subsearch: Optional[str] = None
if search_split_by == ":" and len(song.split(":")) > 2: # Support sub-search if : is used (per instructions) if search_split_by == ":" and len(song.split(":")) > 2: # Support sub-search if : is used (per instructions)
search_song: str = song.split(search_split_by)[1].strip() # Reduce search_song to only the 2nd split of : [the rest is meant to be lyric text] search_song = song.split(search_split_by)[1].strip() # Reduce search_song to only the 2nd split of : [the rest is meant to be lyric text]
search_subsearch: str = "".join(song.split(search_split_by)[2:]) # Lyric text from split index 2 and beyond search_subsearch = "".join(song.split(search_split_by)[2:]) # Lyric text from split index 2 and beyond
return (search_artist, search_song, search_subsearch) return (search_artist, search_song, search_subsearch)
except: except:
traceback.print_exc() traceback.print_exc()
return False return False
async def lyric_search(self, artist: str, song: str, async def lyric_search(self, artist: str, song: str,
sub: Optional[str] = None) -> list[str]: sub: Optional[str] = None) -> Optional[list]:
""" """
Lyric Search Lyric Search
Args: Args:
artist (str): Artist to search artist (str): Artist to search
song (str): Song to search song (str): Song to search
sub (Optional[str]): Lyrics for subsearch sub (Optional[str]): Lyrics for subsearch
Returns:
Optional[list]
""" """
try: try:
if not artist or not song: if not artist or not song:
return ["FAIL! Artist/Song not provided"] return [("FAIL! Artist/Song not provided",)]
search_obj: dict = { search_obj: dict = {
'a': artist.strip(), 'a': artist.strip(),
@ -103,7 +118,7 @@ class Utility:
request.raise_for_status() request.raise_for_status()
response: dict = await request.json() response: dict = await request.json()
if response.get('err'): if response.get('err'):
return [f"ERR: {response.get('errorText')}"] return [(f"ERR: {response.get('errorText')}",)]
out_lyrics = regex.sub(r'<br>', '\u200B\n', response.get('lyrics')) out_lyrics = regex.sub(r'<br>', '\u200B\n', response.get('lyrics'))
response_obj: dict = { response_obj: dict = {
@ -111,11 +126,13 @@ class Utility:
'song': response.get('song'), 'song': response.get('song'),
'lyrics': out_lyrics, 'lyrics': out_lyrics,
'src': response.get('src'), 'src': response.get('src'),
'confidence': float(response.get('confidence')), 'confidence': float(response.get('confidence', 0.0)),
'time': float(response.get('time')), 'time': float(response.get('time', -1.0)),
} }
lyrics = response_obj.get('lyrics') lyrics = response_obj.get('lyrics')
if not lyrics:
return None
response_obj['lyrics'] = textwrap.wrap(text=lyrics.strip(), response_obj['lyrics'] = textwrap.wrap(text=lyrics.strip(),
width=4000, drop_whitespace=False, width=4000, drop_whitespace=False,
replace_whitespace=False, break_long_words=True, replace_whitespace=False, break_long_words=True,
@ -128,7 +145,7 @@ class Utility:
return [ return [
( (
response_obj.get('artist'), response_obj.get('song'), response_obj.get('src'), response_obj.get('artist'), response_obj.get('song'), response_obj.get('src'),
f"{int(response_obj.get('confidence'))}%", f"{int(response_obj.get('confidence', -1.0))}%",
f"{response_obj.get('time', -666.0):.4f}s", f"{response_obj.get('time', -666.0):.4f}s",
), ),
response_obj.get('lyrics'), response_obj.get('lyrics'),