From 82561f050f72375a1201d85d4204d4c640505b0f Mon Sep 17 00:00:00 2001 From: crate Date: Wed, 4 Jun 2025 21:36:43 -0500 Subject: [PATCH] getting classy --- garfmain.py | 17 ++--- garfpy/__init__.py | 1 + garfpy/garfai.py | 152 +++++++++++++++++++++++---------------------- garfpy/respond.py | 32 +++++----- garfpy/wiki.py | 4 +- 5 files changed, 105 insertions(+), 101 deletions(-) diff --git a/garfmain.py b/garfmain.py index bf0e754..eb05366 100644 --- a/garfmain.py +++ b/garfmain.py @@ -6,8 +6,7 @@ import subprocess from garfpy import( logger, is_private, kroger_token, find_store, search_product, - garfpic, process_image_requests, generate_chat, - aod_message, wikisum, generate_qr, GarfbotRespond) + aod_message, wikisum, generate_qr, GarfAI, GarfbotRespond) gapikey = config.GIF_TOKEN @@ -21,14 +20,16 @@ intents.messages = True intents.message_content = True garfbot = discord.Client(intents=intents) + garf_respond = GarfbotRespond() +garfield = GarfAI() @garfbot.event async def on_ready(): try: - asyncio.create_task(process_image_requests()) garf_respond.load_responses() + asyncio.create_task(garfield.process_image_requests()) logger.info(f"Logged in as {garfbot.user.name} running {txtmodel} and {imgmodel}.") except Exception as e: logger.error(e) @@ -49,7 +50,7 @@ async def on_message(message): if lower.startswith("hey garfield") or isinstance(message.channel, discord.DMChannel): question = content[12:] if lower.startswith("hey garfield") else message.content - answer = await generate_chat(question) + answer = await garfield.generate_chat(question) logger.info(f"Chat Request - User: {user}, Server: {guild}, Prompt: {question}") await message.channel.send(answer) @@ -57,7 +58,7 @@ async def on_message(message): prompt = content[8:] logger.info(f"Image Request - User: {user}, Server: {guild}, Prompt: {prompt}") await message.channel.send(f"`Please wait... image generation queued: {prompt}`") - await garfpic(message, prompt) + await garfield.garfpic(message, prompt) # Wikipedia if lower.startswith('garfwiki '): @@ -87,7 +88,7 @@ async def on_message(message): try: logger.info(f"Ping Request - User: {user}, Server: {guild}, Target: {target}") if is_private(target): - rejection = await generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") + rejection = await garfield.generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") await message.channel.send(rejection) else: result = subprocess.run(['ping', '-c', '4', target], capture_output=True, text=True) @@ -99,7 +100,7 @@ async def on_message(message): try: logger.info(f"NSLookup Request - User: {user}, Server: {guild}, Target: {target}") if is_private(target): - rejection = await generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") + rejection = await garfield.generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") await message.channel.send(rejection) else: result = subprocess.run(['nslookup', target], capture_output=True, text=True) @@ -111,7 +112,7 @@ async def on_message(message): try: logger.info(f"Nmap Request - User: {user}, Server: {guild}, Target: {target}") if is_private(target): - rejection = await generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") + rejection = await garfield.generate_chat("Hey Garfield, explain to me why I am dumb for trying to hack your private computer network.") await message.channel.send(rejection) else: await message.channel.send(f"`Scanning {target}...`") diff --git a/garfpy/__init__.py b/garfpy/__init__.py index 353e5c8..9358eee 100644 --- a/garfpy/__init__.py +++ b/garfpy/__init__.py @@ -13,4 +13,5 @@ from .iputils import is_private from .aod import aod_message from .wiki import wikisum from .qr import generate_qr +from .garfai import GarfAI from .respond import GarfbotRespond \ No newline at end of file diff --git a/garfpy/garfai.py b/garfpy/garfai.py index 35e6f90..b9b1e42 100644 --- a/garfpy/garfai.py +++ b/garfpy/garfai.py @@ -7,83 +7,85 @@ import discord from openai import AsyncOpenAI from garfpy import logger -openaikey = config.OPENAI_TOKEN -txtmodel = config.TXT_MODEL -imgmodel = config.IMG_MODEL +class GarfAI: + def __init__(self): + self.openaikey = config.OPENAI_TOKEN + self.txtmodel = config.TXT_MODEL + self.imgmodel = config.IMG_MODEL + self.image_request_queue = asyncio.Queue() -image_request_queue = asyncio.Queue() + async def garfpic(self, message, prompt): + await self.image_request_queue.put({'message': message, 'prompt': prompt}) -async def garfpic(message, prompt): - await image_request_queue.put({'message': message, 'prompt': prompt}) + async def generate_image(self, prompt): + try: + client = AsyncOpenAI(api_key = self.openaikey) + response = await client.images.generate( + model=self.imgmodel, + prompt=prompt, + n=1, + size="1024x1024" + ) + image_url = response.data[0].url + return image_url + except openai.BadRequestError as e: + return f"`GarfBot Error: ({e.status_code}) - Your request was rejected as a result of our safety system.`" + except openai.InternalServerError as e: + logger.error(e) + return f"`GarfBot Error: ({e.status_code}) - Monday`" + except Exception as e: + logger.error(e) + return f"`GarfBot Error: Lasagna`" -async def generate_image(prompt): - try: - client = AsyncOpenAI(api_key = openaikey) - response = await client.images.generate( - model=imgmodel, - prompt=prompt, - n=1, - size="1024x1024" - ) - image_url = response.data[0].url - return image_url - except openai.BadRequestError as e: - return f"`GarfBot Error: ({e.status_code}) - Your request was rejected as a result of our safety system.`" - except openai.InternalServerError as e: - logger.error(e) - return f"`GarfBot Error: ({e.status_code}) - Monday`" - except Exception as e: - logger.error(e) - return f"`GarfBot Error: Lasagna`" + async def process_image_requests(self): + async with aiohttp.ClientSession() as session: + while True: + request = await self.image_request_queue.get() + message = request['message'] + prompt = request['prompt'] + image_url = await self.generate_image(prompt) + if "GarfBot Error" not in image_url: + logger.info("Downloading & sending image...") + async with session.get(image_url) as resp: + if resp.status == 200: + image_data = await resp.read() + ram_image = io.BytesIO(image_data) + ram_image.seek(0) + timestamp = message.created_at.strftime('%Y%m%d%H%M%S') + filename = f"{timestamp}_generated_image.png" + sendfile = discord.File(fp=ram_image, filename=filename) + try: + await message.channel.send(file=sendfile) + except Exception as e: + logger.error(e) + else: + await message.channel.send("`GarfBot Error: Odie`") + else: + await message.channel.send(image_url) + self.image_request_queue.task_done() + await asyncio.sleep(2) -async def process_image_requests(): - async with aiohttp.ClientSession() as session: - while True: - request = await image_request_queue.get() - message = request['message'] - prompt = request['prompt'] - image_url = await generate_image(prompt) - if "GarfBot Error" not in image_url: - logger.info("Downloading & sending image...") - async with session.get(image_url) as resp: - if resp.status == 200: - image_data = await resp.read() - ram_image = io.BytesIO(image_data) - ram_image.seek(0) - timestamp = message.created_at.strftime('%Y%m%d%H%M%S') - filename = f"{timestamp}_generated_image.png" - sendfile = discord.File(fp=ram_image, filename=filename) - try: - await message.channel.send(file=sendfile) - except Exception as e: - logger.error(e) - else: - await message.channel.send("`GarfBot Error: Odie`") - else: - await message.channel.send(image_url) - image_request_queue.task_done() - await asyncio.sleep(2) - -# GarfChats -async def generate_chat(question): - try: - client = AsyncOpenAI(api_key = openaikey) - response = await client.chat.completions.create( - model=txtmodel, - messages=[ - {"role": "system", "content": "Pretend you are sarcastic Garfield."}, - {"role": "user", "content": f"{question}"} - ], - max_tokens=400 - ) - answer = response.choices[0].message.content - return answer.replace("an AI language model", "a cartoon animal") - except openai.BadRequestError as e: - return f"`GarfBot Error: {e}`" - except openai.APIError as e: - logger.info(e, flush=True) - return f"`GarfBot Error: Monday`" - except Exception as e: - logger.info(e, flush=True) - return f"`GarfBot Error: Lasagna`" + # GarfChats + @staticmethod + async def generate_chat(self, question): + try: + client = AsyncOpenAI(api_key = self.openaikey) + response = await client.chat.completions.create( + model=self.txtmodel, + messages=[ + {"role": "system", "content": "Pretend you are sarcastic Garfield."}, + {"role": "user", "content": f"{question}"} + ], + max_tokens=400 + ) + answer = response.choices[0].message.content + return answer.replace("an AI language model", "a cartoon animal") + except openai.BadRequestError as e: + return f"`GarfBot Error: {e}`" + except openai.APIError as e: + logger.info(e, flush=True) + return f"`GarfBot Error: Monday`" + except Exception as e: + logger.info(e, flush=True) + return f"`GarfBot Error: Lasagna`" diff --git a/garfpy/respond.py b/garfpy/respond.py index 4a28766..a7941e0 100644 --- a/garfpy/respond.py +++ b/garfpy/respond.py @@ -7,37 +7,37 @@ import re class GarfbotRespond: def __init__(self): - self.garfbot_guild_responses = {} + self.guild_responses = {} self.responses_file = 'responses.json' def load_responses(self): if os.path.exists(self.responses_file): try: with open(self.responses_file, 'r', encoding='utf-8') as f: - self.garfbot_guild_responses = json.load(f) - self.garfbot_guild_responses = {int(k): v for k, v in self.garfbot_guild_responses.items()} - total_responses = sum(len(responses) for responses in self.garfbot_guild_responses.values()) - logger.info(f"Loaded responses for {len(self.garfbot_guild_responses)} server(s), ({total_responses} total responses)") + self.guild_responses = json.load(f) + self.guild_responses = {int(k): v for k, v in self.guild_responses.items()} + total_responses = sum(len(responses) for responses in self.guild_responses.values()) + logger.info(f"Loaded responses for {len(self.guild_responses)} server(s), ({total_responses} total responses)") except Exception as e: logger.info(f"Error loading responses: {e}") - self.garfbot_guild_responses = {} + self.guild_responses = {} else: - self.garfbot_guild_responses = {} + self.guild_responses = {} def save_responses(self): try: - save_data = {str(k): v for k, v in self.garfbot_guild_responses.items()} + save_data = {str(k): v for k, v in self.guild_responses.items()} with open(self.responses_file, 'w', encoding='utf-8') as f: json.dump(save_data, f, indent=2, ensure_ascii=False) - total_responses = sum(len(responses) for responses in self.garfbot_guild_responses.values()) - logger.info(f"Saved responses for {len(self.garfbot_guild_responses)} servers ({total_responses} total responses)") + total_responses = sum(len(responses) for responses in self.guild_responses.values()) + logger.info(f"Saved responses for {len(self.guild_responses)} servers ({total_responses} total responses)") except Exception as e: logger.info(f"Error saving responses: {e}") def get_responses(self, guild_id): - if guild_id not in self.garfbot_guild_responses: - self.garfbot_guild_responses[guild_id] = {} - return self.garfbot_guild_responses[guild_id] + if guild_id not in self.guild_responses: + self.guild_responses[guild_id] = {} + return self.guild_responses[guild_id] async def garfbot_response(self, message, content): guild_id = message.guild.id @@ -86,7 +86,7 @@ class GarfbotRespond: responses = self.get_responses(guild_id) responses[trigger] = response_text - self.garfbot_guild_responses[guild_id] = responses + self.guild_responses[guild_id] = responses self.save_responses() embed = discord.Embed( @@ -105,7 +105,7 @@ class GarfbotRespond: if trigger in responses: removed_response = responses[trigger] del responses[trigger] - self.garfbot_guild_responses[guild_id] = responses + self.guild_responses[guild_id] = responses self.save_responses() embed = discord.Embed( @@ -123,7 +123,7 @@ class GarfbotRespond: if key.lower() == trigger.lower(): removed_response = responses[key] del responses[key] - self.garfbot_guild_responses[guild_id] = responses + self.guild_responses[guild_id] = responses self.save_responses() embed = discord.Embed( diff --git a/garfpy/wiki.py b/garfpy/wiki.py index 0904bc4..d0bd570 100644 --- a/garfpy/wiki.py +++ b/garfpy/wiki.py @@ -1,10 +1,10 @@ import wikipedia -from garfpy import generate_chat +from garfpy import GarfAI async def wikisum(search_term): try: summary = wikipedia.summary(search_term) - garfsum = await generate_chat(f"Please summarize in your own words: {summary}") + garfsum = await GarfAI.generate_chat(f"Please summarize in your own words: {summary}") return garfsum