Skip to content

Commit

Permalink
activity minor changes, RandomCats extension
Browse files Browse the repository at this point in the history
  • Loading branch information
GitGinocchio committed Dec 21, 2024
1 parent ae8341a commit 40f6e6b
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 42 deletions.
23 changes: 18 additions & 5 deletions src/commands/activity/Activity.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from nextcord.ext import commands, tasks
from nextcord import \
Status, \
ActivityType
import nextcord
import random
import time
import os

from utils.terminal import getlogger

Expand Down Expand Up @@ -57,16 +56,30 @@ async def update_activity(self):
try:
activity = nextcord.Activity(
type=ActivityType.playing,
type=nextcord.ActivityType.playing,
name=(name:=random.choice([n for n in self.commands if n != self.command] if self.command else self.commands)),
state=self.names[name]
state=self.names[name],
details="testing",
url="https://github.com/GitGinocchio/GGsBot",
assets={
"large_image": "https://github.com/GitGinocchio/GGsBot/blob/main/docs/media/banner.png?raw=true",
"large_text": "GGsBot",
"small_image": "https://github.com/GitGinocchio/GGsBot/blob/main/docs/media/circular_icon.png?raw=true",
"small_text": "GGsBot"
},
buttons=[
{ "label" : "GitHub Repository", "url" : "https://github.com/GitGinocchio/GGsBot" },
{ "label" : "Developer", "url" : "https://github.com/GitGinocchio" }
],
timestamps = { "start": int(time.time())}
)

self.command = name

#logger.info(f"Changing bot activity to: {name}")
await self.bot.change_presence(activity=activity)
except Exception as e:
logger.error(e)
logger.exception(e)


def setup(bot: commands.Bot) -> None:
Expand Down
34 changes: 3 additions & 31 deletions src/commands/games/CheapGames.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,6 @@
# allora non e' necessario inviare il messaggio

"""
updated : [
{
"name" : "",
"channels" : [],
"api" : "DEALS"
"stores" : "Steam" | etc.
"lowerPrice" : 0 | None # ritorna tutti i deal con prezzo superiore a lowerPrice
"upperPrice" : 0 | None # ritorna tutti i deal con prezzo inferiore ad upperPrice
"steamAppID" : 0 | None # guarda per determinati giochi di steam in base al loro ID
"saved" : {
gameID : publish_time
},
"on" : "hour"
},
{
"name" : "",
"channels" : [],
"api" : "GIVEAWAYS"
"type" : "game" | "loot" | "beta" | "all"
"stores" : "Steam" | etc.
"saved" : {
gameID : publish_time
},
"on" : "hour"
},
]
updates : {
name : {
"channels" : [],
Expand Down Expand Up @@ -350,7 +322,7 @@ async def update_giveaways_and_deals(self):
async def handle_server_updates(self, configuration : tuple[int, str, bool, dict[str, dict[str, dict]]], skip_time_check : bool = False) -> dict:
_, _, _, config = configuration
for update_name, update_config in config['updates'].items():
if time.localtime().tm_hour != int(update_config["on"]) and not skip_time_check: # IMPORTANT: I need to check if localtime is in UTC.
if datetime.datetime.now(datetime.UTC).hour != int(update_config["on"]) and not skip_time_check:
continue

if Api(update_config["api"]) == Api.GIVEAWAYS:
Expand Down Expand Up @@ -384,11 +356,11 @@ async def send_giveaway_update(self, update_config : dict):
games : list[dict] = await asyncget(url)

for game in games:
if (game_id:=str(game["id"])) in saved_giveaways and game["published_date"] == saved_giveaways[game_id]:
if str(game["id"]) in saved_giveaways and game["published_date"] == saved_giveaways[str(game["id"])]:
# Here we are checking if this giveaway is already registered
continue

saved_giveaways[game_id] = game["published_date"]
saved_giveaways[str(game["id"])] = game["published_date"]

for channel in giveaway_channels:
if (channel:=self.bot.get_channel(channel)) is None:
Expand Down
183 changes: 183 additions & 0 deletions src/commands/general/RandomCats.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
from nextcord import Embed,Color,Permissions
from nextcord.ext import commands

from nextcord.ext.commands import Cog
from nextcord import \
HTTPException, \
Forbidden, \
ButtonStyle, \
SelectOption, \
ChannelType, \
SlashOption, \
Interaction, \
Colour, \
Guild, \
Embed, \
File, \
slash_command
from nextcord.ui import View, Button
from enum import StrEnum
from io import BytesIO
import re

from utils.commons import safe_asyncget, asyncget

class Font(StrEnum):
AndaleMono = "Andale Mono"
Impact = "Impact"
Arial = "Arial"
ArialBlack = "Arial Black"
ComicSansMS = "Comic Sans MS"
CourierNew = "Courier New"
Georgia = "Georgia"
TimesNewRoman = "Times New Roman"
Verdana = "Verdana"
Webdings = "Webdings"

class ImageType(StrEnum):
SQUARE = "square"
MEDIUM = "medium"
SMALL = "small"
XSMALL = "xsmall"

class Filter(StrEnum):
MONO = "mono"
NEGATE = "negate"
CUSTOM = "custom"

class Fit(StrEnum):
COVER = "cover"
CONTAIN = "contain"
FILL = "fill"
INSIDE = "inside"
OUTSIDE = "outside"

class Position(StrEnum):
TOP = "top"
LEFT = "left"
RIGHT = "right"
CENTER = "center"
BOTTOM = "bottom"

LEFT_TOP = "left top"
LEFT_BOTTOM = "left bottom"

RIGHT_TOP = "right top"
RIGHT_BOTTOM = "right bottom"


class RandomCats(commands.Cog):
def __init__(self, bot : commands.Bot):
commands.Cog.__init__(self)
self.baseurl = "https://cataas.com"
self.bot = bot
self.tags = None
self.fetched_tags = False

@Cog.listener()
async def on_ready(self):
if not self.fetched_tags:
self.tags : list = await asyncget(f'{self.baseurl}/api/tags')

@slash_command(name="cats", description="Set of commands to get cat images")
async def cats(self, interaction : Interaction): pass

@cats.subcommand(name="tags",description="Get all available tags")
async def get_tags(self, interaction : Interaction):
try:
await interaction.response.defer(ephemeral=True)
assert self.tags is not None, "Tags are not loaded at the moment"


embed = Embed(
title="Available Tags",
description="You can see the available tags below",
color=Color.green()
)

view = View(timeout=3)
link = Button(style=ButtonStyle.url, label="All available tags", url=f"{self.baseurl}/api/tags")
view.add_item(link)

except AssertionError as e:
await interaction.followup.send(e, ephemeral=True, delete_after=5)
else:
await interaction.followup.send(embed=embed, view=view, ephemeral=True)

@cats.subcommand(name="randomcat",description="Get a random cat image")
@commands.cooldown(1, 60, commands.BucketType.user)
async def randomcat(self,
interaction : Interaction,
tags : str = SlashOption(description="send a random image of a cat based on tags e.g. gif,cute", default="", required=False),
text : str = SlashOption(description="Text to be displayed on the image", default=" ", required=False),
font : str = SlashOption(description="Font of the text (default: Impact)", default=Font.Impact.value, choices=Font, required=False),
fontsize : int = SlashOption(description="Size of the font (min: 10, max: 100, default: 30)", default=30, required=False, max_value=100, min_value=10),
fontcolor : str = SlashOption(description="Color of the font e.g. #fffffff or white (default: white)", default="white", required=False),
fontbackground : str = SlashOption(description="Background color of the font e.g. #fffffff or white", default=None, required=False),
type : str = SlashOption(description="Type of the image (default: square)", choices=ImageType, default=ImageType.SQUARE, required=False),
filter : str | None = SlashOption(description="Filter of the image", choices=Filter, default=None, required=False),
fit : str | None = SlashOption(description="Fit of the image", choices=Fit, default=None, required=False),
position : str = SlashOption(description="Position of the text (default: bottom)", default=Position.BOTTOM, choices=Position, required=False),
width : int | None = SlashOption(description="Width of the image (min: 100, max: 1920)", default=None, required=False, min_value=100, max_value=1920),
height : int | None = SlashOption(description="Height of the image (min: 100, max: 1080)", default=None, required=False, min_value=100, max_value=1080),
blur : int | None = SlashOption(description="Blur of the image (min: 0, max: 10, default: None)", default=None, required=False, min_value=0, max_value=10),
red : int | None = SlashOption(description="Red value of the image (min: 0, max: 255, default: 255)", default=None, required=False, min_value=0, max_value=255),
green : int | None = SlashOption(description="Green value of the image (min: 0, max: 255, default: 255)", default=None, required=False, min_value=0, max_value=255),
blue : int | None = SlashOption(description="Blue value of the image (min: 0, max: 255, default: 255)", default=None, required=False, min_value=0, max_value=255),
brightness : float | None = SlashOption(description="Brightness multiplier of the image (min: -100.0, max: 100.0, default: None)", default=None, required=False, min_value=-100, max_value=100),
saturation : float | None = SlashOption(description="Saturation multiplier of the image (min: -100.0, max: 100.0, default: None)", default=None, required=False, min_value=-100, max_value=100),
hue : int | None = SlashOption(description="Hue rotation of the image (min: -360, max: 360, default: 0)", default=None, required=False, min_value=-360, max_value=360),
lightness : int | None = SlashOption(description="Lightness addend of the image (min: -100, max: 100, default: 0)", default=None, required=False, min_value=-100, max_value=100),
spoiler : bool = SlashOption(description="Send the image as a spoiler", default=False, required=False),
ephemeral : bool = SlashOption(description="Send the image as ephemeral", default=False, required=False)
):
try:
await interaction.response.defer(ephemeral=ephemeral)

tags_pattern = r"^\S+(?:,\S+)*$" # comma separated list of strings regex
assert re.match(tags_pattern, tags), "Tags must be a comma separated list of strings"
for tag in tags.split(','): assert tag in self.tags, f"Tag \'{tag}\' is not an available tag"

params = [
f'font={font}',
f'fontSize={fontsize}',
f'fontColor={fontcolor}',
f'type={type}',
f'position={position}',
]

if filter: params.append(f'filter={filter}')
if fit: params.append(f'fit={fit}')
if width: params.append(f'width={width}')
if height: params.append(f'height={height}')
if brightness: params.append(f'brightness={brightness}')
if saturation: params.append(f'saturation={saturation}')
if red: params.append(f'red={red}')
if green: params.append(f'green={green}')
if blue: params.append(f'blue={blue}')
if hue: params.append(f'hue={hue}')
if lightness: params.append(f'lightness={lightness}')
if blur: params.append(f'blur={blur}')
if fontbackground: params.append(f'fontBackground={fontbackground}')

url = f'{self.baseurl}/cat/{tags}/says/{text.replace(' ','%20')}?{'&'.join(params)}'

print(url)

content_type, content, status, reason = await safe_asyncget(url)

assert status != 404, f"Cat not found with tags {tags} "
assert status == 200 and content_type.startswith("image/"), f"An unexpected error occurred: {reason}"

ext = content_type.split('/')[1]
filelike = BytesIO(content)
filelike.seek(0)

file = File(filelike, filename=f"cat.{ext}", description=f"Cat says {text}", spoiler=spoiler)
except AssertionError as e:
await interaction.followup.send(e, ephemeral=True, delete_after=5)
else:
await interaction.followup.send(file=file, ephemeral=ephemeral)

def setup(bot : commands.Bot):
bot.add_cog(RandomCats(bot))
4 changes: 2 additions & 2 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

def load_commands():
categories = [c for c in os.listdir('./src/commands') if c not in config['ignore_categories']]
logger.info('Loading commands...')
logger.info('Loading extensions...')
for category in categories:
#logger.info(f'Looking in commands.{category}...')
for filename in os.listdir(f'./src/commands/{category}'):
Expand All @@ -45,7 +45,7 @@ def load_commands():
except commands.ExtensionFailed as e:
logger.warning(e)
else:
logger.info(f'Imported command {F.LIGHTMAGENTA_EX}{category}.{filename[:-3]}{F.RESET}')
logger.info(f'Imported extension {F.LIGHTMAGENTA_EX}{category}.{filename[:-3]}{F.RESET}')

elif filename in config['ignore_files']:
continue
Expand Down
13 changes: 9 additions & 4 deletions src/utils/terminal.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from utils.config import config
from colorama import Fore as F
from datetime import datetime
import subprocess
import inspect
import logging
import sys
Expand All @@ -9,11 +10,10 @@

def clear():
"""call the command for clearing the terminal depending on your system"""
os.system('cls' if os.name == 'nt' else 'clear')
subprocess.run("cls" if os.name == "nt" else "clear", shell=True)

def erase():
"""Erase last terminal line (this should work on all systems)"""
print('')
sys.stdout.write('\033[F')
sys.stdout.write('\033[K')

Expand All @@ -28,7 +28,7 @@ def erase():

class CustomColorsFormatter(logging.Formatter):
def format(self, record : logging.LogRecord):
color = levels.get(record.levelname, F.WHITE)
color = levels.get(record.levelname, (logging.INFO, F.WHITE))
record.name = f"{F.LIGHTMAGENTA_EX}[{record.name}]{F.RESET}"
record.msg = f": {color[1]}{record.msg}{F.RESET}"
record.levelname = f"{color[1]}[{record.levelname}]{F.RESET}"
Expand All @@ -53,7 +53,12 @@ def format(self, record : logging.LogRecord):

def getlogger(name : str = None) -> logging.Logger:
if name is None:
name = re.match(r".*[\\/](.+?)(\.[^.]*$|$)", inspect.stack()[1].filename).group(1)
match = re.match(r".*[\\/](.+?)(\.[^.]*$|$)", inspect.stack()[1].filename)

if match:
name = match.group(1)
else:
name = "unknown"

logger = logging.getLogger(name)

Expand Down

0 comments on commit 40f6e6b

Please sign in to comment.