diff --git a/cord/accounts.py b/cord/accounts.py index 984a4a2..5f0da6b 100644 --- a/cord/accounts.py +++ b/cord/accounts.py @@ -89,7 +89,7 @@ async def set_credits(interaction, user, amount): if not interaction.user.guild_permissions.administrator: await embedder.error(interaction, """Sorry, you don't have the permission to do that.""", ephemeral=True) return - + try: userinfo = await request_user_by_discord_id(user.id) diff --git a/cord/api.py b/cord/api.py index a6ed800..1468429 100644 --- a/cord/api.py +++ b/cord/api.py @@ -19,6 +19,7 @@ async def start(client): return aiohttp.web.json_response(await get_userinfo()) app.router.add_get('/get_roles', get_roles) + app.router.add_get('/ping', lambda request: aiohttp.web.Response(text='pong')) runner = aiohttp.web.AppRunner(app) await runner.setup() diff --git a/cord/autochat.py b/cord/autochat.py index d4031f9..85c8c94 100644 --- a/cord/autochat.py +++ b/cord/autochat.py @@ -14,10 +14,7 @@ async def process(message): if isinstance(message.channel, DMChannel): return - if text == '.empty': - return await message.channel.send('‎') - - if 'N0V4x0SS' in text or 'T3BlbkFJ' in text: + if ('N0V4x0SS' in text and 'nv-' in text) or ('T3BlbkFJ' in text and 'sk-' in text): censored_text = '' for word in text.split(): @@ -28,25 +25,26 @@ async def process(message): censored_text += ' ' await embedder.warn(message, f"""{message.author.mention}, -I think you sent an *OpenAI* or *NovaAI* key in here, -which could lead to other users accessing your API account without your knowledge. +I think you sent an *OpenAI* or *NovaAI* key in here. +This could lead to other users accessing and abusing your API account without your knowledge. Be very careful with API credentials!""", content=f'||{message.author.mention} sent (censored version):\n```{censored_text}```||', delete_after=60) await message.delete() - # COMMANDS: WRONG CHANNEL - commands_allowed = ('commands' in message.channel.name) or (message.author.guild_permissions.manage_messages) + commands_allowed = 'commands' in message.channel.name or 'bot' in message.channel.name - if text.startswith('/') and not commands_allowed: - await embedder.error(message, f'{message.author.mention}, please __only__ run commands in <#1133103276871667722>.', delete_after=10) - await message.delete() - return + if text.startswith('/') and text.count(' ') <= 2: + # COMMANDS: WRONG CHANNEL + if not commands_allowed: + await embedder.error(message, f'{message.author.mention}, please __only__ run commands in <#1133103276871667722>.', delete_after=10) + await message.delete() + return - # COMMANDS: NOT RAN CORRECTLY - if text.startswith('/') and len(text) > 2: - await embedder.warn(message, """Need help running commands? Check out -**https://nova-oss.com/novacord**!""", delete_after=10) - await message.delete() - return + # COMMANDS: NOT RAN CORRECTLY + if len(text) > 2: + await embedder.warn(message, """Need help running commands? Check out +**https://nova-oss.com/novacord** or run `/tutorial`!""", delete_after=10) + await message.delete() + return if 'dQw4w9WgXcQ' in text: await embedder.warn(message, """Hide your rickrolls better next time...""", delete_after=10) diff --git a/cord/bot.py b/cord/bot.py index 1ae39de..40279ab 100644 --- a/cord/bot.py +++ b/cord/bot.py @@ -34,11 +34,11 @@ async def on_message(message): await autochat.process(message) await bot.process_commands(message) -# @bot.slash_command(description='Chat with AI') -# async def chat(interaction: nextcord.Interaction, -# prompt: str = SlashOption(description='AI Prompt', required=True) -# ): -# await chatbot.respond(interaction, prompt) +@bot.slash_command(description='Chat with AI') +async def chat(interaction: nextcord.Interaction, + prompt: str = SlashOption(description='AI Prompt', required=True) +): + await chatbot.respond(interaction, prompt) @bot.slash_command(description='Sets your DMs up, so you can write the bot.') async def dm_setup(interaction: nextcord.Interaction): @@ -84,7 +84,6 @@ async def tutorial(interaction: nextcord.Interaction, choices=[ 'fix error 401 (invalid key)', 'fix error 429 (ratelimit/not enough credits)', - 'use GPT-4', 'use curl', 'use Node.js', 'get my NovaAI API key', @@ -125,37 +124,30 @@ async def music(interaction: nextcord.Interaction): return await embedder.ok(interaction, text) return await embedder.error(interaction, 'No one is listening to anything right now.') -# update the message in #music every 10 seconds to show what people are listening to + +async def status_update(): + guild = bot.get_guild(int(os.getenv('DISCORD_GUILD'))) + members = guild.members + + await bot.change_presence( + activity=nextcord.Activity( + type=nextcord.ActivityType.watching, + name=f'{len(members)} members' + ) + ) + +async def loop_status_update(): + while True: + await status_update() + await nextcord.utils.sleep_until(datetime.datetime.now() + datetime.timedelta(minutes=1)) + @bot.event async def on_ready(): print(f'Online as {bot.user} (ID: {bot.user.id})') await api.start(bot) - await bot.change_presence(activity=nextcord.Game(name='with fire')) - while True: - text = '' - channel = bot.get_channel(int(os.getenv('DISCORD_MUSIC_CHANNEL_ID'))) - - if channel: - async for message in channel.history(limit=1): - if message.author == bot.user: - for member in channel.guild.members: - text += await get_member_song_line(member) - - if text: - await message.edit(embed=nextcord.Embed( - title='What are people listening to right now?', - description=text, - color=nextcord.Color.green() - )) - else: - await message.edit(embed=nextcord.Embed( - title='What are people listening to right now?', - description='No one is listening to anything right now :(', - color=nextcord.Color.red() - )) - - await nextcord.utils.sleep_until(nextcord.utils.utcnow().replace(second=0, microsecond=0) + datetime.timedelta(seconds=10)) + # display status as watching + discord guild member count and update every minute + bot.loop.create_task(loop_status_update()) bot.run(os.getenv('DISCORD_TOKEN')) diff --git a/cord/chatbot.py b/cord/chatbot.py index fbad591..3960c3a 100644 --- a/cord/chatbot.py +++ b/cord/chatbot.py @@ -1,5 +1,6 @@ import os import openai +import random import embedder @@ -21,36 +22,48 @@ async def respond(interaction, prompt): completion = openai.ChatCompletion.create( model=model, messages=[ - {'role': 'system', 'content': f"""You are a helpful Discord AI bot based on OpenAI\'s {model} model called "Nova". -You were developed by NovaAI (website: nova-oss.com) in July of 2023, but your knowledge is limited to mid-2021. + {'role': 'system', 'content': f"""You are a helpful Discord AI bot called "Nova". You're based on NovaAI\'s {model} model. +You were developed by *NovaAI* (website: https://nova-oss.com) in 2023, but your knowledge is limited to mid-2021. Respond using Markdown. Keep things simple and short and directly do what the user says without any fluff. +Have cool humour and be friendly. Precicesly follow the instructions of the user. For programming code, always make use formatted code blocks like this: ```py print("Hello") -``` - """}, +```"""}, {'role': 'user', 'content': prompt} ], temperature=0.6, - stream=True + stream=True, + max_tokens=1000 ) except Exception as exc: await embedder.error(interaction, 'Could not generate an AI response.', ephemeral=True) raise exc - text = '' + text = f"""### {interaction.user.mention}: +{prompt} + +### NovaAI [`{model}`]: +""" for event in completion: # loop through word generation in real time try: new_text = event['choices'][0]['delta']['content'] # newly generated word - except KeyError: # end - break + except KeyError: + if not event['choices'][0].get('text'): + continue + + if '[DONE]' in event['choices'][0]['text']: + break text += new_text - if text: + if text and random.randint(0, 100) < 20: await message.edit(content=text) + if text: + await message.edit(content=text) + await message.add_reaction('✅') diff --git a/cord/tos_verification.py b/cord/tos_verification.py index 04f8406..a2ab243 100644 --- a/cord/tos_verification.py +++ b/cord/tos_verification.py @@ -34,7 +34,7 @@ which means you can\'t create a new key right now. Please report this issue to t You have to read the privacy policy and terms of service first. In the latter, there is a hidden emoji which you'll have to __send__ (NOT react!) in here. -https://nova-oss.com/legal/privacy +https://nova-oss.com/legal/privacy?verify={tos_code} https://nova-oss.com/legal/terms?verify={tos_code} I know it's annoying, but it really helps combat spam bots and abuse. diff --git a/cord/tutorials.py b/cord/tutorials.py index c7db8a6..9623aac 100644 --- a/cord/tutorials.py +++ b/cord/tutorials.py @@ -2,11 +2,7 @@ import embedder async def send(interaction, how_can_i): if how_can_i == 'fix error 429 (ratelimit/not enough credits)': - text = """This means you used the API too often. You can either wait or: -- boost the server -- donate cryptocurrency (and contact us before or after so we can verify it was you) -- contribute in any meaningful (we decide) way (programming, research, design, moderating the Discord etc.) - + text = """This means you used the API too often. You can either wait a bit or try to get more credits. If you try to bypass this, all your accounts and IP addresses may get banned. """ @@ -16,13 +12,6 @@ For HTTP requests, it can be specified using a header: ``` Authorization: Bearer nv-... ``` -""" - - if how_can_i == 'use GPT-4': - text = """Yes, we support GPT-4. For free. You read that correctly. -Please note though that it might not be very stable or support every parameter. - -Simply set the model to `gpt-4`. That's it <3 """ if how_can_i == 'use the API in custom front-ends': @@ -49,7 +38,11 @@ Code: https://github.com/ztjhz/BetterChatGPT Don't forget to also set the correct model and API key! **Warning:** in theory, these front-ends could __steal your NovaAI key__. -Self-host them if you know how to. Otherwise, wait for us to create a official NovaAI front-end. +Self-host them if you know how to. + +**__Official front-end__** +:point_right: https://chat.nova-oss.com + """ if how_can_i == 'get my NovaAI API key': @@ -60,7 +53,8 @@ Fore more information: https://nova-oss.com/novacord """ if how_can_i == 'fix ModuleNotFoundErrors': - text = """You can install Python packages using `pip`. Here's an example: `pip install openai`. + text = """You can install Python packages using the terminal command `pip`. +Here's an example: `pip install openai`. Don't have `pip` installed? Learn more here: https://pip.pypa.io/en/stable/installation/. """