From 97f90e38143a9e47de778399995fa599a22d241a Mon Sep 17 00:00:00 2001 From: crate Date: Sat, 7 Jun 2025 17:52:20 -0500 Subject: [PATCH] switch to commands bot --- garfmain.py | 121 ++++++++++++++++++++++++++++++---------------- garfpy/iputils.py | 102 +++++++++++++++++--------------------- garfpy/qr.py | 4 +- garfpy/weather.py | 30 ++++++------ 4 files changed, 140 insertions(+), 117 deletions(-) diff --git a/garfmain.py b/garfmain.py index feea18d..4eeaa13 100644 --- a/garfmain.py +++ b/garfmain.py @@ -1,6 +1,7 @@ import config import asyncio import discord +from discord.ext import commands from garfpy import ( help, @@ -24,7 +25,8 @@ intents = discord.Intents.default() intents.members = True intents.messages = True intents.message_content = True -garfbot = discord.Client(intents=intents) + +garfbot = commands.Bot(command_prefix=["garfbot ", "garf", "$"], intents=intents) garf_respond = GarfbotRespond() garfield = GarfAI() @@ -39,12 +41,82 @@ async def on_ready(): garf_respond.load_responses() asyncio.create_task(garfield.process_image_requests()) logger.info( - f"Logged in as {garfbot.user.name} running {txtmodel} and {imgmodel}." + f"Logged in as {garfbot.user.name} running {txtmodel} and {imgmodel}." # type: ignore ) except Exception as e: logger.error(e) +@garfbot.command(name="ping") +async def ping(ctx, *, target): + """Ping a target""" + logger.info( + f"Ping Request - User: {ctx.author.name}, Server: {ctx.guild.name}, Target: {target}" + ) + await iputils.ping(ctx, target) + + +@garfbot.command(name="dns") +async def dns(ctx, *, target): + """DNS lookup for a target""" + logger.info( + f"NSLookup Request - User: {ctx.author.name}, Server: {ctx.guild.name}, Target: {target}" + ) + await iputils.dns(ctx, target) + + +@garfbot.command(name="hack") +async def hack(ctx, *, target): + """Nmap scan a target""" + logger.info( + f"Nmap Request - User: {ctx.author.name}, Server: {ctx.guild.name}, Target: {target}" + ) + await iputils.scan(ctx, target) + + +@garfbot.command(name="qr") +async def garfbot_qr(ctx, *, text): + logger.info( + f"QR Code Request - User: {ctx.author.name}, Server: {ctx.guild.name}, Text: {text}" + ) + if len(text) > 1000: + await ctx.send("❌ Text too long! Maximum 1000 characters.") + else: + try: + qr_code = await generate_qr(text) + sendfile = discord.File(fp=qr_code, filename="qrcode.png") + await ctx.send(file=sendfile) + except Exception as e: + logger.error(e) + await ctx.send(e) + + +@garfbot.command(name="wiki") +async def garfbot_wiki(ctx, *, query): + summary = await garfield.wikisum(query) + await ctx.send(summary) + + +@garfbot.command(name="shop") +async def garfbot_shop(ctx, *, query): + try: + response = kroger.garfshop(query) + await ctx.send(response) + except Exception as e: + await ctx.send(f"`GarfBot Error: {str(e)}`") + + +@garfbot.command(name="weather") +async def garfbot_weather(ctx, *, location): + embed = await weather.weather(location) + await ctx.send(embed=embed) + + +# @garfbot.command(name="help") +# async def garfbot_help(ctx): +# await help(ctx) + + @garfbot.event async def on_message(message): if message.author == garfbot.user: @@ -56,41 +128,8 @@ async def on_message(message): guild_id = message.guild.id guild_name = message.guild.name if message.guild else "Direct Message" - # IP utils - if message.guild and lower.startswith(("garfping ", "garfdns ", "garfhack ")): - await iputils.scan(message, user_name, guild_name, lower) - - # Wikipedia - if lower.startswith("garfwiki "): - query = message.content[9:] - summary = await garfield.wikisum(query) - await message.channel.send(summary) - - # QR codes - if lower.startswith("garfqr "): - text = message.content[7:] - if len(text) > 1000: - await message.channel.send("❌ Text too long! Maximum 1000 characters.") - else: - try: - qr_code = await generate_qr(text) - sendfile = discord.File(fp=qr_code, filename="qrcode.png") - await message.channel.send(file=sendfile) - except Exception as e: - logger.error(e) - await message.channel.send(e) - - # Kroger Shopping - if lower.startswith("garfshop "): - try: - query = message.content[9:] - response = kroger.garfshop(query) - await message.channel.send(response) - except Exception as e: - await message.channel.send(f"`GarfBot Error: {str(e)}`") - # Chats & pics - elif lower.startswith("hey garfield") or isinstance( + if lower.startswith("hey garfield") or isinstance( message.channel, discord.DMChannel ): prompt = content[12:] if lower.startswith("hey garfield") else message.content @@ -100,7 +139,7 @@ async def on_message(message): ) await message.channel.send(answer) - elif lower.startswith("garfpic "): + if lower.startswith("garfpic "): prompt = content[8:] logger.info( f"Image Request - User: {user_name}, Server: {guild_name}, Prompt: {prompt}" @@ -110,12 +149,6 @@ async def on_message(message): ) await garfield.garfpic(message, prompt) - # Weather - elif lower.startswith("garfbot weather "): - location = lower[16:] - embed = await weather.weather(location) - await message.channel.send(embed=embed) - # GarfBot help elif lower.strip() == "garfbot help": await help(message) @@ -137,6 +170,8 @@ async def on_message(message): await message.channel.send(response) break + await garfbot.process_commands(message) + # Run GarfBot async def garfbot_connect(): diff --git a/garfpy/iputils.py b/garfpy/iputils.py index 6a301d4..59b7201 100644 --- a/garfpy/iputils.py +++ b/garfpy/iputils.py @@ -1,7 +1,6 @@ import discord import ipaddress import subprocess -from garfpy import logger class IPUtils: @@ -23,63 +22,52 @@ class IPUtils: return True return False - async def scan(self, message, user, guild, query): - split = query.split() - target = split[-1] + async def ping(self, ctx, target): if self.is_private(target): return + try: + await ctx.send(f"`Pinging {target}...`") + result = subprocess.run( + ["ping", "-c", "4", target], capture_output=True, text=True + ) + embed = discord.Embed( + title=f"Ping result: {target}", + color=discord.Color.light_gray(), + description=f"```{result.stdout}```", + ) + await ctx.send(embed=embed) + except Exception as e: + await ctx.send(f"`GarfBot Error: {str(e)}`") - if query.startswith("garfping "): - try: - logger.info( - f"Ping Request - User: {user}, Server: {guild}, Target: {target}" - ) - await message.channel.send(f"`Pinging {target}...`") - result = subprocess.run( - ["ping", "-c", "4", target], capture_output=True, text=True - ) - embed = discord.Embed( - title=f"Ping result: {target}", - color=0x4D4D4D, - description=f"```{result.stdout}```", - ) - await message.channel.send(embed=embed) - except Exception as e: - await message.channel.send(f"`GarfBot Error: {str(e)}`") + async def dns(self, ctx, target): + if self.is_private(target): + return + try: + await ctx.send(f"`Requesting {target}...`") + result = subprocess.run( + ["nslookup", target], capture_output=True, text=True + ) + embed = discord.Embed( + title=f"NSLookup result: {target}", + color=discord.Color.light_gray(), + description=f"```{result.stdout}```", + ) + await ctx.send(embed=embed) + except Exception as e: + await ctx.send(f"`GarfBot Error: {str(e)}`") - if query.startswith("garfdns "): - try: - logger.info( - f"NSLookup Request - User: {user}, Server: {guild}, Target: {target}" - ) - await message.channel.send(f"`Requesting {target}...`") - result = subprocess.run( - ["nslookup", target], capture_output=True, text=True - ) - embed = discord.Embed( - title=f"NSLookup result: {target}", - color=0x4D4D4D, - description=f"```{result.stdout}```", - ) - await message.channel.send(embed=embed) - except Exception as e: - await message.channel.send(f"`GarfBot Error: {str(e)}`") - - if query.startswith("garfhack "): - try: - logger.info( - f"Nmap Request - User: {user}, Server: {guild}, Target: {target}" - ) - await message.channel.send(f"`Scanning {target}...`") - result = subprocess.run( - ["nmap", "-Pn", "-O", "-v", target], capture_output=True, text=True - ) - embed = discord.Embed( - title=f"Nmap scan result: {target}", - color=0x4D4D4D, - description=f"```{result.stdout}```", - ) - embed.set_footer(text="https://nmap.org/") - await message.channel.send(embed=embed) - except Exception as e: - await message.channel.send(f"`GarfBot Error: {str(e)}`") + async def scan(self, ctx, target): + try: + await ctx.send(f"`Scanning {target}...`") + result = subprocess.run( + ["nmap", "-Pn", "-O", "-v", target], capture_output=True, text=True + ) + embed = discord.Embed( + title=f"Nmap scan result: {target}", + color=discord.Color.light_gray(), + description=f"```{result.stdout}```", + ) + embed.set_footer(text="https://nmap.org/") + await ctx.send(embed=embed) + except Exception as e: + await ctx.send(f"`GarfBot Error: {str(e)}`") diff --git a/garfpy/qr.py b/garfpy/qr.py index 0ac4b48..0779241 100644 --- a/garfpy/qr.py +++ b/garfpy/qr.py @@ -47,7 +47,7 @@ async def generate_qr(text): qr = qrcode.QRCode( version=version, - error_correction=qrcode.constants.ERROR_CORRECT_L, + error_correction=qrcode.constants.ERROR_CORRECT_L, # type: ignore box_size=box_size, border=4, ) @@ -58,7 +58,7 @@ async def generate_qr(text): qr_image = qr.make_image(fill_color="black", back_color="white") img_buffer = BytesIO() - qr_image.save(img_buffer, format="PNG") + qr_image.save(img_buffer, format="PNG") # type: ignore img_buffer.seek(0) return img_buffer diff --git a/garfpy/weather.py b/garfpy/weather.py index 0ae585d..afb87bb 100644 --- a/garfpy/weather.py +++ b/garfpy/weather.py @@ -18,13 +18,13 @@ class WeatherAPI: else: return {"zip": location} - parts = location.split() + params = location.split() - if len(parts) == 1: - return {"q": f"{parts[0]},US"} + if len(params) == 1: + return {"q": f"{params[0]},US"} - elif len(parts) == 2: - city, second = parts + elif len(params) == 2: + city, second = params if len(second) == 2 and second.upper() not in [ "AK", @@ -88,26 +88,26 @@ class WeatherAPI: else: return {"q": f"{city},{second},US"} - elif len(parts) == 3: - city, state, country = parts + elif len(params) == 3: + city, state, country = params return {"q": f"{city},{state},{country.upper()}"} else: - if len(parts[-1]) == 2: - city_parts = parts[:-1] - country = parts[-1] + if len(params[-1]) == 2: + city_parts = params[:-1] + country = params[-1] city_name = " ".join(city_parts) return {"q": f"{city_name},{country.upper()}"} - elif len(parts) >= 2 and len(parts[-1]) == 2 and len(parts[-2]) <= 2: - city_parts = parts[:-2] - state = parts[-2] - country = parts[-1] + elif len(params) >= 2 and len(params[-1]) == 2 and len(params[-2]) <= 2: + city_parts = params[:-2] + state = params[-2] + country = params[-1] city_name = " ".join(city_parts) return {"q": f"{city_name},{state},{country.upper()}"} else: - city_name = " ".join(parts) + city_name = " ".join(params) return {"q": f"{city_name},US"} async def get_weather(self, location, units="metric"):