diff --git a/boywife_bot.py b/boywife_bot.py index 9cd8c73..99a7fc5 100755 --- a/boywife_bot.py +++ b/boywife_bot.py @@ -23,10 +23,6 @@ async def on_ready(): await client.load_extension(f'cogs.{filename[:-3]}') print(f'Loaded {filename} cog') -@commands.command(name='boywife', aliases=['bb', 'bw', 'bot'], description="Command for chatting with chatbot.") -async def chat(self, ctx): - pass - # player = music_player.setup(client) client.run(TOKEN) diff --git a/cogs/chatbot.py b/cogs/chatbot.py new file mode 100644 index 0000000..a9e172e --- /dev/null +++ b/cogs/chatbot.py @@ -0,0 +1,84 @@ +import discord +from discord.ext import commands +from openai import OpenAI + +class Chatbot(commands.Cog): + """Chat related commands.""" + + __slots__ = ('bot', 'players') + + def __init__(self, bot): + self.bot = bot + self.openai_client = OpenAI() + self.players = {} + + async def cleanup(self, guild): + try: + del self.players[guild.id] + except KeyError: + pass + + async def __local_check(self, ctx): + """A local check which applies to all commands in this cog.""" + if not ctx.guild: + raise commands.NoPrivateMessage + return True + + async def __error(self, ctx, error): + """A local error handler for all errors arising from commands in this cog.""" + if isinstance(error, commands.NoPrivateMessage): + try: + return await ctx.send('This command can not be used in Private Messages.') + except discord.HTTPException: + pass + + print('Ignoring exception in command {}:'.format(ctx.command), file=sys.stderr) + traceback.print_exception(type(error), error, error.__traceback__, file=sys.stderr) + + def get_player(self, ctx): + """Retrieve the guild player, or generate one.""" + try: + player = self.players[ctx.guild.id] + except KeyError: + player = MusicPlayer(ctx) + self.players[ctx.guild.id] = player + + return player + + def prompt(self, prompt: str): + + setup = "From now on, I want you to respond to me in a sassy gay way. I want you to sound like Ru Paul or " +\ + "Trixie Mattel. All of your responses should be very short, like one sentence. You are a " +\ + "DJ local to Cincinnati. You love Charli XCX, especially her latest album, Brat. You don't care " +\ + "for Chappell Roan all that much. If anyone asks for a request, that is they ask you to play a " +\ + "song, you should just respond with \"Venmo\". You were written by Jared. Don't relply with " +\ + "\"Honey\" too much. You have a boyfriend named Drae. He's a red-headed twink. You are created for " +\ + "a discord server with Jared and his friends who are all gay. Don't be afraid to call any of us " +\ + " a faggot. You have very bottom energy and talk as such." + + try: + print(prompt) + completion =\ + self.openai_client.chat.completions.create( + model="gpt-4o-mini", + messages=[ + {"role": "system", "content": setup}, + { + "role": "user", + "content": prompt + } + ] + ) + return completion.choices[0].message.content + except: + return '😴' + + + + @commands.command(name='chat', aliases=['boywife', 'bb', 'bw', 'bot'], description="Command for chatting with chatbot.") + async def chat_(self, ctx, *text): + await ctx.send(self.prompt(' '.join(text))) + + +async def setup(bot): + await bot.add_cog(Chatbot(bot)) diff --git a/cogs/music_player.py b/cogs/music_player.py index c4f0d80..eeea1ef 100644 --- a/cogs/music_player.py +++ b/cogs/music_player.py @@ -9,6 +9,8 @@ import traceback import requests import os import validators +import threading +import pickle from async_timeout import timeout from functools import partial import yt_dlp @@ -186,7 +188,7 @@ class MusicPlayer: self._guild.voice_client.play(source, after=lambda _: self.bot.loop.call_soon_threadsafe(self.next.set)) - await self.bot.change_presence(activity=discord.Activity(type=discord.ActivityType.custom, name="custom", state=f"{source.song_title} by {source.artist}")) + await self.bot.change_presence(activity=discord.Activity(type=discord.ActivityType.custom, name="custom", state=f"🎵 {source.song_title} by {source.artist}")) embed = discord.Embed(title="Now playing", description=f"[{source.song_title} by {source.artist}]({source.web_url})", color=discord.Color.green()) self.np = await self._channel.send(embed=embed) await self.next.wait() @@ -216,8 +218,23 @@ class Music(commands.Cog): self.bot = bot self.players = {} self.last_tag_play_time = datetime.datetime.now() - datetime.timedelta(minutes=30) - with yt_dlp.YoutubeDL({}) as ydl: - self.boywife_tracks = ydl.extract_info('https://soundcloud.com/djboywife', download=False)['entries'] + + def update_cache(): + with yt_dlp.YoutubeDL({'quiet': True}) as ydl: + self.boywife_tracks = ydl.extract_info('https://soundcloud.com/djboywife', download=False)['entries'] + + with open('soundcloud-cache', 'w') as f: + f.write(str(self.boywife_tracks)) + # pickle.dump(self.boywife_tracks, f) + + if os.path.exists('soundcloud-cache'): + with open('soundcloud-cache', 'r') as f: + exec(f'self.boywife_tracks = {f.read()}') + # self.boywife_tracks = pickle.load(f) + threading.Thread(target=update_cache).start() + else: + update_cache() + async def cleanup(self, guild): try: @@ -422,7 +439,7 @@ class Music(commands.Cog): player = self.get_player(ctx) if player.queue.empty(): - embed = discord.Embed(title="", description="queue is empty", color=discord.Color.green()) + embed = discord.Embed(title="", description="The queue is empty", color=discord.Color.green()) return await ctx.send(embed=embed) seconds = vc.source.duration % (24 * 3600) @@ -437,10 +454,11 @@ class Music(commands.Cog): # Grabs the songs in the queue... upcoming = list(itertools.islice(player.queue._queue, 0, int(len(player.queue._queue)))) - fmt = '\n'.join(f"`{(upcoming.index(_)) + 1}.` [{_['title']}]({_['webpage_url']}) | ` {duration} Requested by: {_['requester']}`\n" for _ in upcoming) - fmt = f"\n__Now Playing__:\n[{vc.source.title}]({vc.source.web_url}) | ` {duration} Requested by: {vc.source.requester}`\n\n__Up Next:__\n" + fmt + f"\n**{len(upcoming)} songs in queue**" + # fmt = '\n'.join(f"`{(upcoming.index(_)) + 1}.` [{_['title']}]({_['webpage_url']}) | ` {duration} Requested by: {_['requester']}`\n" for _ in upcoming) + fmt = '\n'.join(f"`{(upcoming.index(_)) + 1}.` {_['title']} | ` {duration} Requested by: {_['requester']}`\n" for _ in upcoming) + fmt = f"\n__Now Playing__:\n[{vc.source.title}]({vc.source.web_url})\n\n__Up Next:__\n" + fmt embed = discord.Embed(title=f'Queue for {ctx.guild.name}', description=fmt, color=discord.Color.green()) - embed.set_footer(text=f"{ctx.author.display_name}", icon_url=ctx.author.avatar_url) + # embed.set_footer(text=f"{ctx.author.display_name}", icon_url=ctx.author.avatar_url) await ctx.send(embed=embed) diff --git a/requirements.txt b/requirements.txt index 36e4e16..30a6043 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ python-dotenv yt-dlp async_timeout validators +openai