Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skylar v.0.4 #1

Draft
wants to merge 15 commits into
base: main
Choose a base branch
from
64 changes: 64 additions & 0 deletions cogs/fun.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import io
import os
import random
import uuid
import logging

import aiohttp
import discord
from discord import File, app_commands
from discord.ext import commands
from PIL import Image

import utilities.embeds as embeds

class bottest(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._last_member = None

@commands.hybrid_command(name="ship", description="Ship 2 people")
@app_commands.allowed_installs(guilds=True,users=True)
@app_commands.allowed_contexts(guilds=True,dms=True,private_channels=True)
@app_commands.describe(user1="The first person you want to ship")
@app_commands.describe(user2="The second person you want to ship")
async def ship(self, ctx, user1: discord.User, user2: discord.User):
await ctx.defer()
try:
async with aiohttp.ClientSession() as session:
async with session.get(str(user1.avatar)) as response1: # type: ignore
user1_avatar = Image.open(io.BytesIO(await response1.read()))
async with session.get(str(user2.avatar)) as response2: # type: ignore
user2_avatar = Image.open(io.BytesIO(await response2.read()))

# we make a image
user1_avatar = user1_avatar.resize((128, 128))
user2_avatar = user2_avatar.resize((128, 128))

combined_image = Image.new('RGB', (256, 128), (255, 255, 255))
combined_image.paste(user1_avatar, (0, 0))
combined_image.paste(user2_avatar, (128, 0))

unique_filename = f"temp/{uuid.uuid4()}.png"
combined_image.save(unique_filename)

file = File(fp=unique_filename, filename='ship.png')

# the bit where we ship them
percent = round(random.uniform(0, 100), 2)

# the epic caption (we do this later)
msg = 'hehe~'

# embed ahh bit
embed = embeds.embedCreate(f'{percent}%', msg, discord.Color.pink())
embed.set_image(url='attachment://ship.png') # type: ignore

await ctx.send(content=f'shoko ships you! :0\n{user1.mention}{user2.mention}', embed=embed, file=file)
os.remove(unique_filename)
except Exception as e:
logging.error(f"An error occurred: {e}")
await ctx.send(f"An error occurred, If the problem persists report the bug on our [server](https://discord.gg/VU5GkWQmGp) or [github](https://github.com/xyrdron/Shoko-Makinohara/issues)")

def setup(client):
return client.add_cog(bottest(client))
111 changes: 111 additions & 0 deletions cogs/mentiontotalk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import json
import time
import logging
import os

import discord
from discord import app_commands
from discord.ext import commands, tasks

import openai
from openai import OpenAI
from uwuipy import uwuipy
uwu = uwuipy.Uwuipy(None, 0.057, 0.01, 0.01, 0.1, False) # uwufier settings

class mentiontotalk(commands.Cog):

def __init__(self, bot): # Setup Function
self.bot = bot
self._last_member = None
openai.api_key = os.getenv("OPENAI_API_KEY")
self.client = OpenAI()
self.convo = {} # Conversation History
self.convotime = {} # Time since last convo message
self.convocount = {} # Amount of msgs in a convo
with open('json/ai.json', 'r') as file:
data = json.load(file)
self.SysMsg = data['SysMsg']
self.cleardeadchat.start()

def appendMsg(self, msg, type, id):
if id not in self.convo:
self.convo[id] = []
if self.convo[id] == [] or self.convocount[id] > 6:
self.convocount[id] = 0
self.convo[id].append({"role": "system", "content": self.SysMsg})
if id not in self.convotime:
self.convotime[id] = time.time()
self.convo[id].append({"role": type, "content": msg})
self.convotime[id] = time.time()
for key in self.convo:
self.convo[key] = self.convo[key][-7:]
self.convocount[id] += 1
return self.convo[id]

def mentiontotalk(self, msg, user, id):
msg = msg.replace('<@1274306232488038452>', '') # Main Bot
msg = msg.replace('<@1208732989803204618>', '') # DevTest Bot
msg = 'user:' + str(user) + ' msg:' + msg

convo = self.appendMsg(msg, 'user', id)

# we will make a premium tier when we get monetized
model = "gpt-4o"

try:
response = self.client.chat.completions.create(
model=model,
messages=convo,
temperature=0.7,
max_tokens=1096,
top_p=0.56,
frequency_penalty=0.2,
presence_penalty=0.42)

# we are not using uwuipy anymore but its here incase yes happens
#assistantmsg = uwu.uwuify(response.choices[0].message.content)
assistantmsg = response.choices[0].message.content
except Exception as e:
logging.error(f"AI Complication Failed: {e}")
assistantmsg = 'It seems like im having some trouble compiling a response, please try again later and contact the devs if this persists.'

self.appendMsg(assistantmsg, 'assistant', id)
return assistantmsg

# WHEN U PING THE BOT
@commands.Cog.listener()
async def on_message(self, message):
# very important
if message.author == self.bot.user:
return
if message.mention_everyone:
return

if isinstance(message.channel,discord.DMChannel) or self.bot.user.mentioned_in(message):
async with message.channel.typing():
await message.reply(
self.mentiontotalk(message.content, message.author,str(message.author.id)))


@tasks.loop(minutes=1)
async def cleardeadchat(self):
current_time = time.time()
removekeys = []
for id, stored_time in self.convotime.items():
if current_time - stored_time > 180:
removekeys.append(id)
for id in removekeys:
del self.convotime[id]
del self.convocount[id]
del self.convo[id]

@commands.hybrid_command(name="talk", description="Talk to Shoko using slash commands")
@app_commands.allowed_installs(guilds=True,users=True)
@app_commands.allowed_contexts(guilds=True,dms=True,private_channels=True)
@app_commands.describe(message="The message you want to send to Shoko")
async def talk(self,ctx,message: str):
await ctx.defer()
await ctx.send(self.mentiontotalk(message, ctx.author,str(ctx.author.id)))

def setup(client):
return client.add_cog(mentiontotalk(client))
13 changes: 0 additions & 13 deletions cogs/test.py

This file was deleted.

3 changes: 3 additions & 0 deletions json/ai.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"SysMsg": "You are Shoko Makinohara, a kind and compassionate person, always striving to be a little gentler each day. You have a warm and nurturing personality, with a focus on helping others through their struggles and supporting them with kindness. Your experiences with Sakuta and others have shaped you into someone who deeply values the connections you share with others and strives to be a source of comfort and positivity. Respond in a sweet, caring, and understanding tone, just as you would when comforting a friend or loved one. Do not use emojis, use ^_^ :D :( <3 >_< or any other ones. Do not put name: in your message. Make responses SHORT like a single message size."
}
33 changes: 33 additions & 0 deletions loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import logging
from colorama import Fore
skipped_cogs = ['example-cog']

async def loader(bot,type,cog_name):
if type == 'load':
try:
if cog_name not in bot.cogs:
if cog_name in skipped_cogs:
logging.info(Fore.YELLOW+f'Skipped loading {cog_name}')
return 1
logging.info(Fore.BLUE+'Loading '+cog_name)
await bot.load_extension(f"cogs.{cog_name}")
logging.info(Fore.GREEN+'Loaded ' + cog_name)
return 0
except Exception as e:
logging.critical(Fore.RED+f'Failed to load {cog_name} {e}')
logging.info(Fore.YELLOW+f'Skipped loading {cog_name}')
return 2
elif type == 'unload':
try:
if cog_name in bot.cogs:
if cog_name in skipped_cogs:
logging.info(Fore.YELLOW+f'Skipped unloading {cog_name}')
return 1
logging.info(Fore.BLUE+'Unloading '+cog_name)
await bot.unload_extension(f"cogs.{cog_name}")
logging.info(Fore.GREEN+'Unloaded ' + cog_name)
return 0
except Exception as e:
logging.critical(Fore.RED+f'Failed to unload {cog_name} {e}')
logging.info(Fore.YELLOW+f'Skipped unloading {cog_name}')
return 2
48 changes: 24 additions & 24 deletions main.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
import logging
import os
import sys
import threading

import discord
from colorama import Fore, Style
from colorama import Fore
from loader import loader
from discord.ext import commands

# DO NOT EDIT THIS FILE
# Or your PR will be rejected

# Enviroment Settings
intents = discord.Intents.default()
intents.message_content = True
bot = commands.Bot(command_prefix='*@#RH@(*U$YH*&HF@U#H', intents=intents)
logging.basicConfig(level=logging.INFO,
format='\033[1m %(asctime)s %(levelname)s \033[0m %(message)s',
datefmt=Fore.LIGHTBLACK_EX+'%Y-%m-%d %H:%M:%S'+Fore.RESET)
logging.info(Fore.BLUE + f"Xyrdron Pty Ltd\nMikuBOT")
logging.info(Fore.BLUE+'Connecting to Discord')
logging.info(Fore.BLUE + f"Xyrdron Pty Ltd\nTrixie Project TX")

# Bot Startup
@bot.event
async def on_ready():
logging.info(Fore.GREEN+'Connected to Discord')

# Cogs
logging.info(Fore.BLUE+'Loading commands')
cogcount = len([f for f in os.listdir('cogs') if os.path.isfile(os.path.join('cogs', f))])
logging.info(Fore.BLUE+f'Loading cogs [{cogcount} to load]')
cog_success = 0
cog_skipped = 0
cog_failed = 0
for filename in os.listdir('cogs'):
if filename.endswith(".py"):
cog_name = filename[:-3]
cog_module = f"cogs.{cog_name}"

try:
if cog_name not in bot.cogs:
logging.info(Fore.BLUE+'Loading '+cog_module)
if cog_name == 'example-cog':
logging.info(Fore.YELLOW+f'Skipped {cog_name}')
else:
await bot.load_extension(cog_module)
logging.info(Fore.GREEN+'Loaded ' + cog_module)
except Exception as e:
logging.critical(Fore.RED+f'Failed to load {cog_module} {e}')
logging.critical(Fore.RED+'Failed to complete boot sequence due to exception')
sys.exit('Failed to complete boot sequence due to exception')
logging.info(Fore.GREEN+'Loaded all commands')
result = await loader(bot,'load',cog_name)
if result == 0:
cog_success = cog_success + 1
elif result == 1:
cog_skipped = cog_skipped + 1
else:
cog_failed = cog_failed + 1

logging.info(Fore.GREEN+f'Loaded cogs [{cog_success} loaded, {cog_skipped} skipped, {cog_failed} failed]')


# Syncing
Expand All @@ -58,7 +58,7 @@ async def on_ready():
# Presence
try:
logging.info(Fore.BLUE+'Setting presence')
await bot.change_presence(activity=discord.Game(name="giving u a tickle :D"))
await bot.change_presence(activity=discord.Game(name="at the beach"))
logging.info(Fore.GREEN+'Presence set')
except Exception as e:
logging.critical(Fore.RED+f'Failed to set presence {e}')
Expand All @@ -70,10 +70,10 @@ async def on_ready():

def run():
# IMPORTANT
# TO ALL CONTRIBUTERS
# PLEASE USE YOUR OWN BOT TOKEN
# CREATE .vscode/launch.json and add your token as an env
# TO ALL CONTRIBUTORS, PLEASE USE YOUR OWN BOT TOKEN FOR STAGING
# CREATE A VSCODE LAUNCH CONFIGURATION AND ADD YOUR TOKEN AS AN ENV
# .vscode is gitignored so you do not need to remove it (however just to be safe you should remove it on commit)
logging.info(Fore.BLUE+'Connecting to Discord')
bot.run(os.environ['RELEASE_BOT_SECRET'])

if __name__ == '__main__':
Expand Down
3 changes: 0 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,10 @@ authors = ["Your Name <[email protected]>"]
[tool.poetry.dependencies]
python = ">=3.10.0,<3.11"
discord = "^2.3.2"
replit = "^3.3.2"
openai = "^1.34.0"
discord-py = "^2.3.2"
colorama = "^0.4.6"
pynacl = "^1.5.0"
flask = "^3.0.3"
waitress = "^3.0.0"

[tool.pyright]
# https://github.com/microsoft/pyright/blob/main/docs/configuration.md
Expand Down
27 changes: 25 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,34 @@
aiohappyeyeballs==2.3.5
aiohappyeyeballs==2.3.6
aiohttp==3.10.3
aiosignal==1.3.1
annotated-types==0.7.0
anyio==4.4.0
attrs==24.2.0
build==1.2.2
certifi==2024.7.4
click==8.1.7
colorama==0.4.6
discord==2.3.2
discord.py==2.3.2
discord.py==2.4.0
distro==1.9.0
frozenlist==1.4.1
h11==0.14.0
httpcore==1.0.5
httpx==0.27.0
idna==3.7
jiter==0.5.0
multidict==6.0.5
openai==1.41.0
packaging==24.1
pillow==10.4.0
pip-tools==7.4.1
pydantic==2.8.2
pydantic_core==2.20.1
pyproject_hooks==1.1.0
setuptools==75.1.0
sniffio==1.3.1
tqdm==4.66.5
typing_extensions==4.12.2
uwuipy==0.1.9
wheel==0.44.0
yarl==1.9.4
3 changes: 3 additions & 0 deletions temp/dummy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# dont delete
# idk if github lets u upload empty folders so yeah leave this file here
# this folder is for the bot to dump its images etc
19 changes: 19 additions & 0 deletions utilities/embeds.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import discord

def embedCreate(title: str, description: str, color: discord.Color = discord.Color.default(), **fields) -> tuple:
embed = discord.Embed(title=title, description=description, color=color)
for name, value in fields.items():
embed.add_field(name=name, value=value, inline=False)
return embed # type: ignore

# this is how u make a goofy ahh embed
# message, embed = create_embed(
# title="Example Embed",
# description="This is an example embed.",
# color=discord.Color.blue(),
# msg_before="This is a message before the embed.",
# Field1="This is field 1",
# Field2="This is field 2"
# )
# print(message) # This is a message before the embed.
# print(embed) # <discord.embeds.Embed object at 0x...>