2023-07-09 00:57:11 -07:00
import discord
2023-07-10 10:38:28 -07:00
from discord . ext import commands , tasks
2023-07-09 00:57:11 -07:00
from discord . utils import get
import shutil
import json
import random
import time
import os
import io
import base64
import asyncio
import sys
import subprocess
import math
from PIL import Image , PngImagePlugin
from dotenv import load_dotenv
import matplotlib . pyplot as plt
import aiohttp
2023-07-09 13:07:09 -07:00
import aioftp
2023-12-27 20:48:57 -08:00
import asyncssh
2023-07-09 00:57:11 -07:00
2023-07-13 01:10:28 -07:00
#Stable Diffusion
2023-07-16 22:52:43 -07:00
#Set this env variable to http://host:port or "disabled"
2023-07-13 01:10:28 -07:00
#os.getenv('stablediffusion_url')
2023-07-09 00:57:11 -07:00
#env vars START
load_dotenv ( )
imgflip_username = os . getenv ( ' imgflip_username ' )
imgflip_password = os . getenv ( ' imgflip_password ' )
discord_token = os . getenv ( ' discord_token ' )
ftp_server = os . getenv ( ' ftp_server ' )
ftp_username = os . getenv ( ' ftp_username ' )
ftp_password = os . getenv ( ' ftp_password ' )
ftp_public_html = os . getenv ( ' ftp_public_html ' )
#env vars END
2024-01-17 18:09:45 -08:00
#discord setup START
2023-07-09 00:57:11 -07:00
intents = discord . Intents . default ( )
intents . message_content = True
bot = commands . Bot ( command_prefix = ' ! ' , intents = intents )
2024-01-17 18:09:45 -08:00
#discord setup END
2023-07-09 00:57:11 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Moderate " ,
help = " This currently tool works by replacing the filename on the ftp server with a black image. The description will remain the same and may need to be altered. " ,
brief = " Moderation Tools "
)
2023-07-12 15:10:02 -07:00
async def moderate ( ctx , filename ) :
2023-12-27 22:37:30 -08:00
await upload_sftp ( " blank_image.png " , ( os . getenv ( ' ftp_public_html ' ) + ' ai-images/ ' ) , filename )
2023-07-12 19:13:19 -07:00
output = " Image " + filename + " replaced "
await ctx . send ( output )
2023-07-12 15:10:02 -07:00
2023-07-09 00:57:11 -07:00
async def upload_ftp ( local_filename , server_folder , server_filename ) :
2023-07-09 18:02:15 -07:00
client = aioftp . Client ( )
await client . connect ( ftp_server )
await client . login ( ftp_username , ftp_password )
await client . change_directory ( server_folder )
await client . upload ( local_filename , server_folder + server_filename , write_into = True )
await client . quit ( )
2023-12-27 20:48:57 -08:00
async def upload_sftp ( local_filename , server_folder , server_filename ) :
remotepath = server_folder + server_filename
async with asyncssh . connect ( ftp_server , username = ftp_username , password = ftp_password ) as conn :
async with conn . start_sftp_client ( ) as sftp :
await sftp . put ( local_filename , remotepath = remotepath )
2023-07-09 18:02:15 -07:00
2023-07-11 17:04:28 -07:00
async def handle_error ( error ) :
print ( error )
current_time = time . strftime ( " % Y- % m- %d % H: % M: % S " , time . localtime ( ) )
2023-07-16 16:35:40 -07:00
log_line = current_time + ' : ' + str ( error ) + ' \n '
2023-07-11 17:04:28 -07:00
with open ( " databases/error_log.txt " , ' a ' ) as f :
f . write ( log_line )
return error
2023-07-09 00:57:11 -07:00
async def upload_ftp_ai_images ( filename , prompt ) :
2023-07-09 16:06:45 -07:00
html_file = " phixxy.com/ai-images/index.html "
2023-07-09 00:57:11 -07:00
html_insert = ''' <!--REPLACE THIS COMMENT-->
< div >
2023-07-09 14:58:57 -07:00
< img src = " <!--filename--> " loading = " lazy " >
2023-07-09 00:57:11 -07:00
< p class = " image-description " > < ! - - description - - > < / p >
< / div > '''
img_list = [ ]
2023-12-27 22:37:30 -08:00
server_folder = ( os . getenv ( ' ftp_public_html ' ) + ' ai-images/ ' )
2023-12-27 20:48:57 -08:00
new_filename = str ( time . time_ns ( ) ) + " .png "
await upload_sftp ( filename , server_folder , new_filename )
2023-12-27 22:05:14 -08:00
print ( " Uploaded " , new_filename )
2023-07-09 18:02:15 -07:00
with open ( html_file , ' r ' ) as f :
html_data = f . read ( )
2023-12-27 20:48:57 -08:00
html_insert = html_insert . replace ( " <!--filename--> " , new_filename )
2023-07-09 18:02:15 -07:00
html_insert = html_insert . replace ( " <!--description--> " , prompt )
html_data = html_data . replace ( " <!--REPLACE THIS COMMENT--> " , html_insert )
with open ( html_file , " w " ) as f :
f . writelines ( html_data )
2023-12-27 20:48:57 -08:00
await upload_sftp ( html_file , server_folder , " index.html " )
2023-07-09 00:57:11 -07:00
def create_channel_config ( filepath ) :
config_dict = {
" personality " : " average " ,
" channel_topic " : " casual " ,
" chat_enabled " : False ,
" commands_enabled " : True ,
" chat_history_len " : 5 ,
" look_at_images " : False ,
" react_to_msgs " : False ,
" ftp_enabled " : False
}
with open ( filepath , " w " ) as f :
json . dump ( config_dict , f )
print ( " Wrote config variables to file. " )
async def get_channel_config ( channel_id ) :
2023-07-09 16:06:45 -07:00
filepath = " channels/config/ {0} .json " . format ( str ( channel_id ) )
2023-07-09 00:57:11 -07:00
if not os . path . exists ( filepath ) :
create_channel_config ( filepath )
with open ( filepath , " r " ) as f :
config_dict = json . loads ( f . readline ( ) )
return config_dict
async def answer_question ( topic , model = " gpt-3.5-turbo " ) :
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : model ,
" messages " : [ { " role " : " user " , " content " : topic } ]
}
url = " https://api.openai.com/v1/chat/completions "
try :
2023-07-19 22:05:56 -07:00
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
response = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ]
return response
2023-07-09 00:57:11 -07:00
except Exception as error :
2023-07-11 17:04:28 -07:00
return await handle_error ( error )
2024-01-17 18:27:17 -08:00
2023-07-09 00:57:11 -07:00
def edit_channel_config ( channel_id , key , value ) :
2023-07-09 16:06:45 -07:00
config_file = " channels/config/ " + str ( channel_id ) + " .json "
2023-07-09 00:57:11 -07:00
with open ( config_file , ' r ' ) as f :
config_data = json . load ( f )
config_data [ key ] = value
with open ( config_file , " w " ) as f :
json . dump ( config_data , f )
async def react_to_msg ( ctx , react ) :
2023-07-25 17:49:30 -07:00
def is_emoji ( string ) :
if len ( string ) == 1 :
# Range of Unicode codepoints for emojis
2023-08-19 12:40:46 -07:00
if 0x1F300 < = ord ( string ) < = 0x1F6FF :
2023-07-25 17:49:30 -07:00
return True
return False
2023-07-25 17:20:14 -07:00
if react :
2023-07-09 00:57:11 -07:00
if not random . randint ( 0 , 10 ) and ctx . author . id != 1097302679836971038 :
2023-07-11 18:10:44 -07:00
system_msg = " Send only an emoji as a discord reaction to the following chat message "
message = ctx . content [ 0 ]
2023-07-09 00:57:11 -07:00
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : " gpt-3.5-turbo " ,
2023-07-11 18:10:44 -07:00
" messages " : [ { " role " : " system " , " content " : system_msg } , { " role " : " user " , " content " : message } ]
2023-07-09 00:57:11 -07:00
}
url = " https://api.openai.com/v1/chat/completions "
2023-07-25 17:49:30 -07:00
2023-07-09 00:57:11 -07:00
try :
2023-07-19 22:05:56 -07:00
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
2023-07-25 17:49:30 -07:00
reaction = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ] . strip ( )
if is_emoji ( reaction ) :
await ctx . add_reaction ( reaction )
else :
await ctx . add_reaction ( " 😓 " )
2023-07-09 00:57:11 -07:00
except Exception as error :
print ( " Some error happened while trying to react to a message " )
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
async def log_chat_and_get_history ( ctx , logfile , channel_vars ) :
2024-01-17 18:27:17 -08:00
#metadata = await look_at(ctx, channel_vars["look_at_images"])
log_line = ' '
2023-07-09 00:57:11 -07:00
log_line + = ctx . content
log_line = ctx . author . name + " : " + log_line + " \n "
chat_history = " "
print ( " Logging: " + log_line , end = " " )
with open ( logfile , " a " , encoding = " utf-8 " ) as f :
f . write ( log_line )
with open ( logfile , " r " , encoding = " utf-8 " ) as f :
for line in ( f . readlines ( ) [ - int ( channel_vars [ " chat_history_len " ] ) : ] ) :
chat_history + = line
return chat_history
async def chat_response ( ctx , channel_vars , chat_history_string ) :
async with ctx . channel . typing ( ) :
await asyncio . sleep ( 1 )
prompt = f " You are a { channel_vars [ ' personality ' ] } chat bot named Sparkytron 3000 created by @phixxy.com. Your personality should be { channel_vars [ ' personality ' ] } . You are currently in a { channel_vars [ ' channel_topic ' ] } chatroom. The message history is: { chat_history_string } "
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : " gpt-3.5-turbo " ,
" messages " : [ { " role " : " user " , " content " : prompt } ]
}
url = " https://api.openai.com/v1/chat/completions "
2023-07-17 23:06:04 -07:00
try :
2023-07-19 22:05:56 -07:00
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
response = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ]
if " Sparkytron 3000: " in response [ 0 : 17 ] :
response = response . replace ( " Sparkytron 3000: " , " " )
max_len = 1999
if len ( response ) > max_len :
messages = [ response [ y - max_len : y ] for y in range ( max_len , len ( response ) + max_len , max_len ) ]
else :
messages = [ response ]
for message in messages :
await ctx . channel . send ( message )
2023-07-09 00:57:11 -07:00
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
2023-07-09 01:57:35 -07:00
async def folder_setup ( ) :
2023-07-10 22:01:25 -07:00
folder_names = [ " tmp " , " channels " , " users " , " channels/config " , " channels/logs " , " databases " , " databases/currency " , " databases/currency/players " ]
2023-07-09 01:57:35 -07:00
for folder_name in folder_names :
if not os . path . exists ( folder_name ) :
os . mkdir ( folder_name )
2023-07-09 16:06:45 -07:00
async def delete_all_files ( path ) :
for filename in os . listdir ( path ) :
if os . path . isdir ( path + filename ) :
shutil . rmtree ( path + filename )
elif os . path . isfile ( path + filename ) :
os . remove ( path + filename )
2023-07-10 17:44:15 -07:00
2023-12-28 15:19:43 -08:00
async def delete_derp_files ( server_folder ) :
async with asyncssh . connect ( ftp_server , username = ftp_username , password = ftp_password ) as conn :
async with conn . start_sftp_client ( ) as sftp :
for filename in ( await sftp . listdir ( server_folder ) ) :
2023-12-28 17:05:26 -08:00
if filename == ' . ' or filename == ' .. ' or filename == ' style.css ' or filename == ' myScript.js ' :
pass
else :
2023-12-28 15:19:43 -08:00
try :
print ( " Deleting " , filename )
await sftp . remove ( server_folder + filename )
except :
print ( " Couldn ' t delete " , filename )
2023-07-10 10:38:28 -07:00
2023-07-10 17:44:15 -07:00
@tasks.loop ( seconds = 1 ) # Run the task every second
2023-07-10 10:38:28 -07:00
async def task_loop ( ) :
current_time = time . localtime ( )
2023-07-10 17:44:15 -07:00
#Run daily tasks
2023-07-11 11:54:40 -07:00
if current_time . tm_hour == 17 and current_time . tm_min == 0 and current_time . tm_sec == 0 :
2023-07-10 17:44:15 -07:00
bot_stuff = bot . get_channel ( 544408659174883328 )
2023-07-10 17:08:39 -07:00
output = ' The following tasks failed: \n ``` '
2023-07-10 11:23:05 -07:00
failed_tasks = [ ]
await bot_stuff . send ( " <@242018983241318410> The current time is 5pm. Running daily tasks! " )
2023-07-10 10:38:28 -07:00
try :
2023-07-16 22:52:43 -07:00
await generate_blog ( bot_stuff )
2023-07-10 10:38:28 -07:00
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-10 17:08:39 -07:00
failed_tasks . append ( " Blogpost " )
2023-07-10 11:23:05 -07:00
try :
await delete_all_files ( " tmp/ " )
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-10 17:08:39 -07:00
failed_tasks . append ( " Delete tmp/ " )
2023-12-28 15:19:43 -08:00
try :
await delete_derp_files ( " /home/debian/websites/derp.phixxy.com/files/ " )
except Exception as error :
await handle_error ( error )
failed_tasks . append ( " Delete derp files " )
2023-07-10 11:23:05 -07:00
if failed_tasks != [ ] :
for failed_task in failed_tasks :
2023-07-10 17:08:39 -07:00
output + = failed_task + ' \n '
output + = ' ``` '
await bot_stuff . send ( output )
2023-07-10 11:23:05 -07:00
else :
await bot_stuff . send ( " All daily tasks successfully ran! " )
2023-07-16 21:36:42 -07:00
2023-07-19 15:02:50 -07:00
async def create_session ( ) :
2023-07-25 17:13:23 -07:00
return aiohttp . ClientSession ( )
2023-07-19 15:02:50 -07:00
async def close_session ( http_session ) :
await http_session . close ( )
@bot.event
async def on_connect ( ) :
bot . http_session = await create_session ( )
2023-07-21 23:25:55 -07:00
@bot.event
async def on_resumed ( ) :
bot . http_session = await create_session ( )
2023-07-19 15:02:50 -07:00
@bot.event
async def on_disconnect ( ) :
await close_session ( bot . http_session )
2023-07-09 00:57:11 -07:00
@bot.event
async def on_ready ( ) :
2024-01-17 18:09:45 -08:00
# Import plugins from plugins folder
for plugin_file in os . listdir ( ' plugins/ ' ) :
if plugin_file != ' __init__.py ' and plugin_file [ - 3 : ] == ' .py ' :
await bot . load_extension ( f ' plugins. { plugin_file [ : - 3 ] } ' )
2023-07-09 00:57:11 -07:00
print ( ' We have logged in as {0.user} ' . format ( bot ) )
#stuff to do if first run
2023-07-09 01:57:35 -07:00
await folder_setup ( )
2023-07-09 16:06:45 -07:00
await delete_all_files ( " tmp/ " )
2023-07-10 10:38:28 -07:00
task_loop . start ( )
2023-07-10 17:44:15 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Update " ,
help = " This will update sparkytron to the most recent version on github. Only privileged users can run this command! Usage: !update " ,
2023-07-17 11:36:34 -07:00
brief = " Runs git pull " ,
hidden = True
2023-07-16 22:52:43 -07:00
)
2023-07-10 17:44:15 -07:00
async def update ( ctx ) :
if ctx . author . id == 242018983241318410 :
2023-07-10 18:04:46 -07:00
output = subprocess . run ( [ " git " , " pull " ] , capture_output = True )
if output . stderr :
2023-12-28 14:26:38 -08:00
await ctx . send ( " Update Attempted " )
2023-07-10 18:04:46 -07:00
await ctx . send ( output . stderr . decode ( ' utf-8 ' ) )
else :
await ctx . send ( output . stdout . decode ( ' utf-8 ' ) )
2023-07-10 17:44:15 -07:00
else :
await ctx . send ( " You don ' t have permission to do this. " )
2023-07-09 00:57:11 -07:00
2023-07-25 17:35:43 -07:00
@bot.command (
description = " Errors " ,
help = " Shows the last errors that were logged. " ,
brief = " Display Errors "
)
async def errors ( ctx , amount = " 5 " ) :
output = " "
amount = int ( amount )
try :
with open ( " databases/error_log.txt " , ' r ' ) as f :
for line in ( f . readlines ( ) [ - amount : ] ) :
output + = line
await ctx . send ( output )
except Exception as error :
await handle_error ( error )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " RSGP " ,
help = " Uses probably outdated information to calculate how much rsgp is worth in usd. Usage: !rsgp (amount) " ,
brief = " Runescape gold to usd "
)
2023-07-09 00:57:11 -07:00
async def rsgp ( ctx , amount ) :
2023-07-19 23:04:05 -07:00
output = " "
cost_per_bil = 25.50 #1b rsgp to usd
cost_per_bil_os = 210
gold_per_bond = 70000000
gold_per_bond_os = 7000000
cost_per_bond = 8 #dollars usd
bondcost = ( int ( amount ) / gold_per_bond ) * cost_per_bond
rwtcost = ( int ( amount ) * cost_per_bil / 1000000000 )
dollar_gp = ( int ( amount ) * 1000000000 ) / cost_per_bil
osbondcost = ( int ( amount ) / gold_per_bond_os ) * cost_per_bond
osrwtcost = ( int ( amount ) * cost_per_bil_os / 1000000000 )
osdollar_gp = ( int ( amount ) * 1000000000 ) / cost_per_bil_os
2023-07-19 23:16:20 -07:00
output + = str ( amount ) + ' rs3 gp would cost: $ ' + str ( round ( rwtcost , 2 ) ) + " (RWT) \n "
2023-07-25 17:23:17 -07:00
output + = str ( amount ) + ' osrs gp would cost: $ ' + str ( round ( osrwtcost , 2 ) ) + " (RWT) \n "
2023-07-19 23:16:20 -07:00
output + = str ( amount ) + ' rs3 gp would cost: $ ' + str ( round ( bondcost , 2 ) ) + " (Bonds) \n "
2023-07-25 17:23:17 -07:00
output + = str ( amount ) + ' osrs gp would cost: $ ' + str ( round ( osbondcost , 2 ) ) + " (Bonds) \n "
2023-07-19 23:16:20 -07:00
output + = str ( amount ) + ' dollars spent on rs3 gp would be: ' + str ( round ( dollar_gp , 2 ) ) + " (RS3 GP) \n "
2023-07-25 17:23:17 -07:00
output + = str ( amount ) + ' dollars spent on osrs gp would be: ' + str ( round ( osdollar_gp , 2 ) ) + " (OSRS GP) \n "
2023-07-09 00:57:11 -07:00
await ctx . send ( output )
2023-07-10 17:17:28 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Blog " ,
help = " Adds your topic to the list of possible future blog topics. Usage: !suggest_blog (topic) " ,
brief = " Suggest a blog topic "
)
async def blog ( ctx , * args ) :
2023-07-10 17:17:28 -07:00
message = ' ' . join ( args )
if ' \n ' in message :
await ctx . send ( " Send only one topic at a time. " )
return
else :
blogpost_file = " databases/blog_topics.txt "
with open ( blogpost_file , ' a ' ) as f :
2023-07-17 23:47:00 -07:00
f . writelines ( message + ' \n ' )
2023-07-10 22:01:25 -07:00
await ctx . send ( " Saved suggestion! " )
2023-09-18 23:31:22 -07:00
@bot.command (
description = " Negative Prompt " ,
help = " Changes the negative prompt for imagine across all channels " ,
brief = " Change the negative prompt for imagine "
)
async def negative_prompt ( ctx , * args ) :
message = ' ' . join ( args )
2023-09-18 23:48:27 -07:00
if not message :
message = " easynegative, badhandv4, verybadimagenegative_v1.3 "
2023-09-18 23:31:22 -07:00
neg_prompt_file = " databases/negative_prompt.txt "
with open ( neg_prompt_file , ' w ' ) as f :
f . writelines ( message )
2023-09-18 23:34:55 -07:00
await ctx . send ( " Changed negative prompt to " + message )
2023-07-09 00:57:11 -07:00
2023-07-17 23:33:58 -07:00
@bot.command ( )
2023-07-16 22:52:43 -07:00
async def generate_blog ( ctx ) :
2023-07-09 00:57:11 -07:00
start_time = time . time ( )
2023-07-10 17:08:39 -07:00
topic = ' '
2023-07-09 16:30:06 -07:00
filename = " phixxy.com/ai-blog/index.html "
2023-07-09 00:57:11 -07:00
with open ( filename , ' r ' , encoding = " utf-8 " ) as f :
html_data = f . read ( )
current_time = time . time ( )
current_struct_time = time . localtime ( current_time )
date = time . strftime ( " % B %d , % Y " , current_struct_time )
if date in html_data :
await ctx . send ( " I already wrote a blog post today! " )
return
2023-07-10 17:08:39 -07:00
blogpost_file = " databases/blog_topics.txt "
2023-12-27 22:37:30 -08:00
#blog_subscribers = ["276197608735637505","242018983241318410"]
2023-07-10 17:08:39 -07:00
if os . path . isfile ( blogpost_file ) :
with open ( blogpost_file , ' r ' ) as f :
blogpost_topics = f . read ( )
2023-07-11 11:54:40 -07:00
f . seek ( 0 )
topic = f . readline ( )
2023-07-13 22:23:17 -07:00
blogpost_topics = blogpost_topics . replace ( topic , ' ' )
with open ( blogpost_file , ' w ' ) as f :
2023-07-10 17:08:39 -07:00
f . write ( blogpost_topics )
if topic != ' ' :
await ctx . send ( " Writing blogpost " )
else :
await ctx . send ( " No topic given for blogpost, generating one. " )
2023-07-12 02:55:31 -07:00
topic = await answer_question ( " Give me one topic for an absurd blogpost. " )
2023-07-09 00:57:11 -07:00
post_div = ''' <!--replace this with a post-->
< div class = " post " >
< h2 class = " post-title " > < ! - - POST_TITLE - - > < / h2 >
< p class = " post-date " > < ! - - POST_DATE - - > < / p >
< div class = " post-content " >
< ! - - POST_CONTENT - - >
< / div >
< / div > '''
title_prompt = ' generate an absurd essay title about ' + topic
title = await answer_question ( title_prompt , model = " gpt-3.5-turbo " )
prompt = ' Write a satirical essay with a serious tone titled: " ' + title + ' " . Do not label parts of the essay. '
content = await answer_question ( prompt , model = " gpt-4 " )
if title in content [ : len ( title ) ] :
content = content . replace ( title , ' ' , 1 )
content = f " <p> { content } </p> "
content = content . replace ( ' \n \n ' , " </p><p> " )
content = content . replace ( " <p></p> " , ' ' )
post_div = post_div . replace ( " <!--POST_TITLE--> " , title )
post_div = post_div . replace ( " <!--POST_DATE--> " , date )
post_div = post_div . replace ( " <!--POST_CONTENT--> " , content )
html_data = html_data . replace ( " <!--replace this with a post--> " , post_div )
with open ( filename , ' w ' , encoding = " utf-8 " ) as f :
f . write ( html_data )
2023-12-27 22:37:30 -08:00
await upload_sftp ( filename , ( os . getenv ( ' ftp_public_html ' ) + ' ai-blog/ ' ) , " index.html " )
2023-07-09 00:57:11 -07:00
run_time = time . time ( ) - start_time
print ( " It took " + str ( run_time ) + " seconds to generate the blog post! " )
2023-12-27 22:58:58 -08:00
output = " Blog Updated! ( " + str ( run_time ) + " seconds) https://ai.phixxy.com/ai-blog "
2023-12-27 22:37:30 -08:00
#output += '\nNotifying subscribers: '
#for subscriber in blog_subscribers:
# output += '<@' + subscriber + '> '
2023-07-10 10:38:28 -07:00
await ctx . send ( output )
2023-07-09 00:57:11 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Question " ,
help = " Ask a raw chatgpt question. Usage: !question (question) " ,
brief = " Get an answer "
)
2023-07-09 00:57:11 -07:00
async def question ( ctx ) :
question = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
answer = await answer_question ( question )
chunks = [ answer [ i : i + 1999 ] for i in range ( 0 , len ( answer ) , 1999 ) ]
for chunk in chunks :
await ctx . send ( chunk )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Question GPT4 " ,
help = " Ask GPT4 a question. Usage: !question_gpt4 (question) " ,
brief = " Get an answer "
)
2023-07-09 00:57:11 -07:00
async def question_gpt4 ( ctx ) :
question = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
2024-01-02 21:40:58 -08:00
answer = await answer_question ( question , " gpt-4-vision-preview " )
chunks = [ answer [ i : i + 1999 ] for i in range ( 0 , len ( answer ) , 1999 ) ]
for chunk in chunks :
await ctx . send ( chunk )
@bot.command (
description = " Image GPT4 " ,
help = " Ask GPT4 a question about an image. Usage: !question_gpt4 (link) (question) " ,
brief = " Get an answer "
)
2024-01-02 21:48:40 -08:00
async def looker ( ctx ) :
2024-01-02 21:40:58 -08:00
image_link = ctx . message . content . split ( " " , maxsplit = 2 ) [ 1 ]
question = ctx . message . content . split ( " " , maxsplit = 2 ) [ 2 ]
headers = {
' Content-Type ' : ' application/json ' ,
' Authorization ' : f ' Bearer { os . getenv ( " openai.api_key " ) } ' ,
}
data = {
" model " : " gpt-4-vision-preview " ,
2024-01-02 21:48:40 -08:00
" messages " : [ { " role " : " user " , " content " : [ { " type " : " text " , " text " : question } , { " type " : " image_url " , " image_url " : { " url " : image_link } } ] } ] ,
" max_tokens " : 500
2024-01-02 21:40:58 -08:00
}
url = " https://api.openai.com/v1/chat/completions "
2024-01-02 21:48:40 -08:00
try :
async with bot . http_session . post ( url , headers = headers , json = data ) as resp :
response_data = await resp . json ( )
print ( response_data )
answer = response_data [ ' choices ' ] [ 0 ] [ ' message ' ] [ ' content ' ]
2024-01-02 21:40:58 -08:00
2024-01-02 21:48:40 -08:00
except Exception as error :
return await handle_error ( error )
2024-01-02 21:40:58 -08:00
2023-07-09 00:57:11 -07:00
chunks = [ answer [ i : i + 1999 ] for i in range ( 0 , len ( answer ) , 1999 ) ]
for chunk in chunks :
await ctx . send ( chunk )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Highscores " ,
help = " Shows a bar graph of users in this channel and how many messages they have sent. " ,
brief = " Display chat highscores "
)
2023-07-09 00:57:11 -07:00
async def highscores ( ctx , limit = 0 ) :
filename = str ( ctx . channel . id ) + " .log "
2023-07-09 16:06:45 -07:00
with open ( " channels/logs/ " + filename , ' r ' , encoding = " utf-8 " ) as logfile :
2023-07-09 00:57:11 -07:00
data = logfile . readlines ( )
logfile . close ( )
def is_username ( user ) :
for character in user :
if character . isupper ( ) :
return False
if not ( character . isalpha ( ) or character . isdigit ( ) or character == ' . ' or character == ' _ ' ) :
return False
return True
user_message_counts = { }
for line in data :
try :
user = line [ 0 : line . find ( ' : ' ) ]
if is_username ( user ) :
if user not in user_message_counts and user != " " and len ( user ) < = 32 :
user_message_counts [ user ] = 1
else :
user_message_counts [ user ] + = 1
2023-07-11 17:04:28 -07:00
except Exception as error :
await handle_error ( error )
2023-07-09 00:57:11 -07:00
def remove_dict_keys_if_less_than_x ( dictionary , x ) :
for key in dictionary :
if dictionary [ key ] < = x :
dictionary . pop ( key )
return remove_dict_keys_if_less_than_x ( dictionary , x )
return dictionary
print ( user_message_counts )
remove_dict_keys_if_less_than_x ( user_message_counts , limit )
keys = list ( user_message_counts . keys ( ) )
values = list ( user_message_counts . values ( ) )
fig , ax = plt . subplots ( )
bar_container = ax . barh ( keys , values )
ax . set_xlabel ( " Message Count " )
ax . set_ylabel ( " Username " )
ax . set_title ( " Messages Sent in " + ctx . channel . name )
ax . bar_label ( bar_container , label_type = ' center ' )
plt . savefig ( str ( ctx . channel . id ) + ' _hiscores.png ' , dpi = 1000 , bbox_inches = " tight " )
with open ( str ( ctx . channel . id ) + ' _hiscores.png ' , " rb " ) as fh :
f = discord . File ( fh , filename = str ( ctx . channel . id ) + ' _hiscores.png ' )
await ctx . send ( file = f )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Highscores Server " ,
help = " Shows a bar graph of users across all servers I am in and how many messages they have sent. " ,
brief = " Display chat highscores "
)
2023-07-09 00:57:11 -07:00
async def highscores_server ( ctx , limit = 0 ) :
user_message_counts = { }
data = [ ]
2023-07-09 16:06:45 -07:00
for filename in os . listdir ( " channels/logs/ " ) :
with open ( " channels/logs/ " + filename , ' r ' , encoding = " utf-8 " ) as logfile :
2023-07-09 00:57:11 -07:00
data + = logfile . readlines ( )
logfile . close ( )
def is_username ( user ) :
for character in user :
if character . isupper ( ) :
return False
if not ( character . isalpha ( ) or character . isdigit ( ) or character == ' . ' or character == ' _ ' ) :
return False
return True
user_message_counts = { }
for line in data :
try :
user = line [ 0 : line . find ( ' : ' ) ]
if is_username ( user ) :
if user not in user_message_counts and user != " " and len ( user ) < = 32 :
user_message_counts [ user ] = 1
else :
user_message_counts [ user ] + = 1
2023-07-11 17:04:28 -07:00
except Exception as error :
await handle_error ( error )
2023-07-09 00:57:11 -07:00
def remove_dict_keys_if_less_than_x ( dictionary , x ) :
for key in dictionary :
if dictionary [ key ] < = x :
dictionary . pop ( key )
return remove_dict_keys_if_less_than_x ( dictionary , x )
return dictionary
print ( user_message_counts )
print ( " printed " )
user_message_counts = remove_dict_keys_if_less_than_x ( user_message_counts , limit )
keys = list ( user_message_counts . keys ( ) )
values = list ( user_message_counts . values ( ) )
fig , ax = plt . subplots ( )
bar_container = ax . barh ( keys , values )
ax . set_xlabel ( " Message Count " )
ax . set_ylabel ( " Username " )
ax . set_title ( " Messages Sent in all channels I can see " )
ax . bar_label ( bar_container , label_type = ' center ' )
plt . savefig ( str ( ctx . channel . id ) + ' _hiscores.png ' , dpi = 1000 , bbox_inches = " tight " )
with open ( str ( ctx . channel . id ) + ' _hiscores.png ' , " rb " ) as fh :
f = discord . File ( fh , filename = str ( ctx . channel . id ) + ' _hiscores.png ' )
await ctx . send ( file = f )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Website " ,
help = " Generates a website using gpt 3.5. Usage: !website (topic) " ,
brief = " Generate a website "
)
2023-07-09 00:57:11 -07:00
async def website ( ctx ) :
2023-07-09 12:05:19 -07:00
async def delete_local_pngs ( local_folder ) :
for filename in os . listdir ( local_folder ) :
if " .png " in filename :
os . remove ( local_folder + filename )
2023-12-27 20:48:57 -08:00
2023-12-27 22:58:58 -08:00
async def delete_ftp_pngs ( server_folder ) :
2023-12-27 20:48:57 -08:00
async with asyncssh . connect ( ftp_server , username = ftp_username , password = ftp_password ) as conn :
async with conn . start_sftp_client ( ) as sftp :
for filename in ( await sftp . listdir ( server_folder ) ) :
2023-12-27 23:10:14 -08:00
if ' .png ' in filename :
try :
print ( " Deleting " , filename )
await sftp . remove ( server_folder + filename )
except :
print ( " Couldn ' t delete " , filename )
2023-07-09 13:07:09 -07:00
2023-07-09 12:05:19 -07:00
async def extract_image_tags ( code ) :
count = code . count ( " <img " )
tags = [ ]
for x in range ( 0 , count ) :
index1 = code . find ( " <img " )
index2 = code [ index1 : ] . find ( " > " ) + index1 + 1
img_tag = code [ index1 : index2 ]
tags . append ( img_tag )
code = code [ index2 : ]
return tags
async def extract_image_alt_text ( tags ) :
alt_texts = [ ]
for tag in tags :
index1 = tag . find ( " alt " ) + 5
index2 = tag [ index1 : ] . find ( " \" " ) + index1
alt_text = tag [ index1 : index2 ]
alt_texts . append ( alt_text )
return alt_texts
async def generate_images ( local_folder , image_list ) :
2023-07-13 01:10:28 -07:00
url = os . getenv ( ' stablediffusion_url ' )
2023-07-13 01:24:27 -07:00
if url == " disabled " :
return
2023-07-09 12:05:19 -07:00
file_list = [ ]
2023-07-19 22:05:56 -07:00
for image in image_list :
filename = image . replace ( " " , " " ) . lower ( ) + " .png "
payload = { " prompt " : image , " steps " : 25 }
response = await bot . http_session . post ( url = f ' { url } /sdapi/v1/txt2img ' , json = payload )
r = await response . json ( )
for i in r [ ' images ' ] :
image = Image . open ( io . BytesIO ( base64 . b64decode ( i . split ( " , " , 1 ) [ 0 ] ) ) )
png_payload = { " image " : " data:image/png;base64, " + i }
response2 = await bot . http_session . post ( url = f ' { url } /sdapi/v1/png-info ' , json = png_payload )
pnginfo = PngImagePlugin . PngInfo ( )
json_response = await response2 . json ( )
pnginfo . add_text ( " parameters " , json_response . get ( " info " ) )
image . save ( local_folder + filename , pnginfo = pnginfo )
file_list . append ( filename )
2023-07-09 12:05:19 -07:00
return file_list
async def add_image_filenames ( code , file_list ) :
for filename in file_list :
code = code . replace ( " src= \" \" " , " src= \" " + filename + " \" " , 1 )
return code
2023-07-09 13:07:09 -07:00
async def upload_html_and_imgs ( local_folder , server_folder ) :
2023-12-27 23:21:24 -08:00
2023-07-09 13:07:09 -07:00
for filename in os . listdir ( local_folder ) :
if " .png " in filename :
2023-12-28 00:35:09 -08:00
await upload_sftp ( local_folder + filename , ( os . getenv ( ' ftp_public_html ' ) + ' ai-webpage/ ' ) , filename )
2023-07-09 13:07:09 -07:00
#explicitly upload html files last!
for filename in os . listdir ( local_folder ) :
if " .html " in filename :
2023-12-28 00:35:09 -08:00
await upload_sftp ( local_folder + filename , ( os . getenv ( ' ftp_public_html ' ) + ' ai-webpage/ ' ) , filename )
2023-07-09 12:05:19 -07:00
2023-07-09 01:39:20 -07:00
2023-12-27 22:37:30 -08:00
server_folder = ftp_public_html + ' ai-webpage/ '
server_archive_folder = ftp_public_html + " webpage-archive/ "
2023-07-09 12:05:19 -07:00
local_archive_folder = " websites/ "
2023-07-09 16:06:45 -07:00
local_folder = " tmp/webpage/ "
2023-07-09 12:05:19 -07:00
working_file = local_folder + " index.html "
2023-07-09 16:06:45 -07:00
if not os . path . exists ( local_folder ) :
os . mkdir ( local_folder )
2023-07-09 00:57:11 -07:00
try :
2023-12-27 22:58:58 -08:00
await ctx . send ( " Please wait, this will take a long time! You will be able to view the website here: https://ai.phixxy.com/ai-webpage/ " )
2023-07-09 12:05:19 -07:00
with open ( working_file , " w " ) as f :
2023-07-09 00:57:11 -07:00
f . write ( " <!DOCTYPE html><html><head><script>setTimeout(function() { location.reload();}, 10000);</script><title>Generating Website</title><style>body { font-size: 24px;text-align: center;margin-top: 100px;}</style></head><body><p>This webpage is currently being generated. The page will refresh once it is complete. Please be patient.</p></body></html> " )
2023-12-27 20:48:57 -08:00
await upload_sftp ( working_file , server_folder , " index.html " )
2023-07-09 00:57:11 -07:00
topic = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
2023-07-09 01:39:20 -07:00
prompt = " Generate a webpage using html and inline css. The webpage topic should be " + topic + " . Feel free to add image tags with alt text. Leave the image source blank. The images will be added later. "
2023-07-09 12:05:19 -07:00
code = await answer_question ( prompt )
await delete_local_pngs ( local_folder )
await delete_ftp_pngs ( server_folder )
tags = await extract_image_tags ( code )
alt_texts = await extract_image_alt_text ( tags )
file_list = await generate_images ( local_folder , alt_texts )
code = await add_image_filenames ( code , file_list )
with open ( working_file , ' w ' ) as f :
f . write ( code )
f . close ( )
2023-07-09 13:07:09 -07:00
await upload_html_and_imgs ( local_folder , server_folder )
2023-07-09 12:05:19 -07:00
2023-12-27 22:58:58 -08:00
await ctx . send ( " Finished https://ai.phixxy.com/ai-webpage/ " )
2023-07-16 21:36:42 -07:00
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
await ctx . send ( " Failed, Try again. " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Feature " ,
help = " Suggest a feature. Usage: !feature (feature) " ,
brief = " Suggest a feature "
)
2023-07-09 00:57:11 -07:00
async def feature ( ctx ) :
try :
feature = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
with open ( " features.txt " , ' a ' ) as f :
f . writelines ( ' \n ' + feature )
await ctx . send ( " Added " + feature )
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2023-07-09 00:57:11 -07:00
with open ( " features.txt " , ' r ' ) as f :
features = f . read ( )
await ctx . send ( features )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Chat " ,
help = " Enable or disable bot chat in this channel. Usage !chat (enable|disable) " ,
brief = " Enable or disable bot chat "
)
2023-07-09 00:57:11 -07:00
async def chat ( ctx , message ) :
if " enable " in message :
edit_channel_config ( ctx . channel . id , " chat_enabled " , True )
await ctx . send ( " Chat Enabled " )
elif " disable " in message :
edit_channel_config ( ctx . channel . id , " chat_enabled " , False )
await ctx . send ( " Chat Disabled " )
else :
await ctx . send ( " Usage: !chat (enable|disable) " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Reactions " ,
help = " Enable or disable bot reactions in this channel. Usage !reactions (enable|disable) " ,
brief = " Enable or disable bot reactions "
)
2023-07-09 00:57:11 -07:00
async def reactions ( ctx , message ) :
if " enable " in message :
edit_channel_config ( ctx . channel . id , " react_to_msgs " , True )
await ctx . send ( " Reactions Enabled " )
elif " disable " in message :
edit_channel_config ( ctx . channel . id , " react_to_msgs " , False )
await ctx . send ( " Reactions Disabled " )
else :
await ctx . send ( " Usage: !reactions (enable|disable) " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " View Images " ,
help = " Enable or disable bot viewing images in this channel. Usage !viewimages (enable|disable) " ,
brief = " Enable or disable bot viewing images "
)
2023-07-09 00:57:11 -07:00
async def viewimages ( ctx , message ) :
if " enable " in message :
edit_channel_config ( ctx . channel . id , " look_at_images " , True )
await ctx . send ( " Viewing Enabled " )
elif " disable " in message :
edit_channel_config ( ctx . channel . id , " look_at_images " , False )
await ctx . send ( " Viewing Disabled " )
else :
await ctx . send ( " Usage: !viewimages (enable|disable) " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Commands " ,
help = " Enable or disable bot commands in this channel. Usage !enable_commands (enable|disable) " ,
brief = " Enable or disable bot commands "
)
2023-07-09 16:30:06 -07:00
async def enable_commands ( ctx , message ) :
if " disable " in message or " false " in message :
2023-07-09 00:57:11 -07:00
edit_channel_config ( ctx . channel . id , " commands_enabled " , False )
await ctx . send ( " Commands Disabled " )
else :
2023-07-09 16:30:06 -07:00
edit_channel_config ( ctx . channel . id , " commands_enabled " , True )
await ctx . send ( " Commands Enabled " )
2023-07-09 00:57:11 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Topic " ,
help = " Set the channel topic for the bot. Usage: !topic (topic) " ,
brief = " Set channel topic "
)
2023-07-09 00:57:11 -07:00
async def topic ( ctx , channel_topic ) :
edit_channel_config ( ctx . channel . id , " channel_topic " , channel_topic )
await ctx . send ( " Topic changed to " + channel_topic )
2024-01-03 08:51:26 -08:00
''' @bot.command(
2023-07-16 22:52:43 -07:00
description = " Python " ,
help = " Run some python code. Imports are disabled but random is imported for you. Usage !python (codeblock) " ,
brief = " Run some python code "
)
2023-07-09 00:57:11 -07:00
async def python ( ctx ) :
try :
code = ctx . message . content
print ( code . find ( " ``` " ) , code . rfind ( " ``` " ) )
code = code [ code . find ( " ``` " ) + 3 : code . rfind ( " ``` " ) ] #Finds the code in codeblocks
if " import " in code :
await ctx . send ( " Imports not allowed " )
return 0
if " ``` " in code :
code = code . replace ( " ``` " , " " )
code = " import random \n import math \n " + code
if len ( code ) == 0 :
await ctx . send ( ' Please provide some code to run ' )
else :
2023-07-09 16:06:45 -07:00
folder_path = " tmp/python_temp_scripts/ "
2023-07-09 00:57:11 -07:00
if not os . path . exists ( folder_path ) :
os . makedirs ( folder_path )
2023-07-09 16:06:45 -07:00
unique_num = str ( len ( os . listdir ( folder_path ) ) )
filename = f " { folder_path } { unique_num } .py "
2023-07-09 00:57:11 -07:00
with open ( filename , " w " ) as f :
f . write ( code )
try :
try :
response = subprocess . run ( [ " python " , filename ] , timeout = 10 , capture_output = True , check = True )
except subprocess . TimeoutExpired :
await ctx . send ( " Code took too long to run! " )
return 0
print ( " response " , response . stdout . decode ( ' utf-8 ' ) )
if response . stdout . decode ( ' utf-8 ' ) == " " :
await ctx . send ( " No Output " )
return 0
await ctx . send ( response . stdout . decode ( ' utf-8 ' ) )
except subprocess . CalledProcessError as error :
await ctx . send ( error . stderr . decode ( ' utf-8 ' ) )
except Exception as error :
2023-07-11 17:04:28 -07:00
await handle_error ( error )
2024-01-03 08:51:26 -08:00
await ctx . send ( " Usage: !python (codeblock) " ) '''
2023-07-09 00:57:11 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " FTP " ,
help = " Enable or disable bot FTP to phixxy.com in this channel. Usage !ftp (enable|disable) " ,
brief = " Enable or disable uploading to web "
)
2023-07-09 00:57:11 -07:00
async def ftp ( ctx , message ) :
if " enable " in message :
edit_channel_config ( ctx . channel . id , " ftp_enabled " , True )
await ctx . send ( " FTP Enabled " )
elif " disable " in message :
edit_channel_config ( ctx . channel . id , " ftp_enabled " , False )
await ctx . send ( " FTP Disabled " )
else :
await ctx . send ( " Usage: !ftp (enable|disable) " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Personality " ,
help = " Set the personality of the bot. Usage: !personality (personality) " ,
brief = " Set the personality "
)
2023-07-09 00:57:11 -07:00
async def personality ( ctx ) :
personality_type = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
edit_channel_config ( ctx . channel . id , " personality " , personality_type )
await ctx . send ( " Personality changed to " + personality_type )
2023-11-01 10:00:17 -07:00
2024-01-03 08:44:00 -08:00
''' @bot.command(
2023-11-01 10:00:17 -07:00
description = " Secret Santa Register " ,
help = " Register for secret santa! " ,
brief = " Register for secret santa! "
)
async def ss_register ( ctx ) :
try :
email = ctx . message . content . split ( " " , maxsplit = 1 ) [ 1 ]
print ( ctx . author . name , email )
with open ( " santa.txt " , ' a ' ) as f :
f . writelines ( ctx . author . name + ' ; ' + email + ' , ' )
await ctx . send ( ctx . author . name + " registered for secret santa! " )
except :
2024-01-03 08:44:00 -08:00
await ctx . send ( " Usage: !ss_register (email address) " ) '''
2023-07-09 00:57:11 -07:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Poll " ,
help = ' Create a poll with up to 9 options. Usage: !poll " Put question here " " option 1 " " option 2 " ' ,
brief = " Enable or disable bot reactions "
)
2023-07-09 00:57:11 -07:00
async def poll ( ctx , question , * options : str ) :
if len ( options ) > 9 :
await ctx . send ( " Error: You cannot have more than 9 options " )
return
embed = discord . Embed ( title = question , colour = discord . Colour ( 0x283593 ) )
for i , option in enumerate ( options ) :
embed . add_field ( name = f " Option { i + 1 } " , value = option , inline = False )
message = await ctx . send ( embed = embed )
numbers = { 0 : " \u0030 \ufe0f \u20e3 " , 1 : " \u0031 \ufe0f \u20e3 " , 2 : " \u0032 \ufe0f \u20e3 " , 3 : " \u0033 \ufe0f \u20e3 " , 4 : " \u0034 \ufe0f \u20e3 " , 5 : " \u0035 \ufe0f \u20e3 " , 6 : " \u0036 \ufe0f \u20e3 " , 7 : " \u0037 \ufe0f \u20e3 " , 8 : " \u0038 \ufe0f \u20e3 " , 9 : " \u0039 \ufe0f \u20e3 " }
for i in range ( len ( options ) ) :
await message . add_reaction ( numbers . get ( i + 1 ) )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Roll " ,
help = " Rolls dice mostly for Dungeons and Dragons type games. Usage: !roll 3d6+2 " ,
brief = " Simulate rolling dice "
)
2023-07-09 00:57:11 -07:00
async def roll ( ctx , dice_string ) :
dice_parts = dice_string . split ( ' d ' )
num_dice = int ( dice_parts [ 0 ] )
if ' + ' in dice_parts [ 1 ] :
die_parts = dice_parts [ 1 ] . split ( ' + ' )
die_size = int ( die_parts [ 0 ] )
modifier = int ( die_parts [ 1 ] )
elif ' - ' in dice_parts [ 1 ] :
die_parts = dice_parts [ 1 ] . split ( ' - ' )
die_size = int ( die_parts [ 0 ] )
modifier = - int ( die_parts [ 1 ] )
else :
die_size = int ( dice_parts [ 1 ] )
modifier = 0
rolls = [ random . randint ( 1 , die_size ) for i in range ( num_dice ) ]
dice_str = ' + ' . join ( [ str ( roll ) for roll in rolls ] )
total = sum ( rolls ) + modifier
await ctx . send ( f ' { dice_str } + { modifier } = { total } ' if modifier != 0 else f ' { dice_str } = { total } ' )
2024-01-06 09:18:25 -08:00
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Kill " ,
help = " Kills the bot in event of an emergency. Only special users can do this! Usage: !kill " ,
2023-07-17 11:36:34 -07:00
brief = " Kill the bot " ,
hidden = True
2023-07-16 22:52:43 -07:00
)
async def kill ( ctx ) :
" Kills the bot "
2023-07-09 00:57:11 -07:00
if ctx . author . id == 242018983241318410 :
exit ( )
else :
await ctx . channel . send ( " You don ' t have permission to do that. " )
2023-07-16 22:52:43 -07:00
@bot.command (
description = " Reset " ,
help = " Resets the bot in event of an emergency. Only special users can do this! Usage: !reset " ,
2023-07-17 11:36:34 -07:00
brief = " Reset the bot " ,
hidden = True
2023-07-16 22:52:43 -07:00
)
2023-07-09 00:57:11 -07:00
async def reset ( ctx ) :
if ctx . author . id == 242018983241318410 :
python = sys . executable
os . execl ( python , python , * sys . argv )
else :
await ctx . channel . send ( " You don ' t have permission to do that. " )
2023-07-21 19:21:40 -07:00
@bot.event
async def on_reaction_add ( reaction , user ) :
if not random . randint ( 0 , 9 ) :
message = reaction . message
emoji = reaction . emoji
await message . add_reaction ( emoji )
2024-01-09 12:10:21 -08:00
async def pkmn_msg ( discord_id ) :
path = " databases/pokemon/ " + str ( discord_id ) + ' .json '
if os . path . isfile ( path ) :
with open ( path , ' r ' ) as f :
json_data = json . loads ( f . readline ( ) )
json_data [ ' buddy_xp ' ] + = random . randint ( 1 , 5 )
json_data = json . dumps ( json_data )
with open ( path , ' w ' ) as f :
f . writelines ( json_data )
2023-07-09 00:57:11 -07:00
@bot.event
async def on_message ( ctx ) :
2024-01-03 08:44:00 -08:00
#log stuff
2023-07-09 16:06:45 -07:00
logfile = " channels/logs/ {0} .log " . format ( str ( ctx . channel . id ) )
2023-07-09 00:57:11 -07:00
channel_vars = await get_channel_config ( ctx . channel . id )
chat_history_string = await log_chat_and_get_history ( ctx , logfile , channel_vars )
2024-01-09 12:10:21 -08:00
#add pokemon xp
await pkmn_msg ( ctx . author . id )
2024-01-03 08:44:00 -08:00
#handle non-text channels (dms, etc)
2024-01-06 09:18:25 -08:00
if ctx . channel . type . value != 0 and ctx . author . id != 242018983241318410 :
#This used to notify the user it cannot respond in this channel, but that spammed threads
return
2024-01-03 08:44:00 -08:00
await react_to_msg ( ctx , channel_vars [ " react_to_msgs " ] ) #emoji reactions
2023-07-09 00:57:11 -07:00
if channel_vars [ " commands_enabled " ] or ( ctx . author . id == 242018983241318410 and ctx . content [ 0 ] == " ! " ) :
await bot . process_commands ( ctx )
if not channel_vars [ " commands_enabled " ] :
await ctx . channel . send ( " This command only ran because you set it to allow to run even when commands are disabled " )
if channel_vars [ " chat_enabled " ] and not ctx . author . bot :
if ctx . content and ctx . content [ 0 ] != " ! " :
await chat_response ( ctx , channel_vars , chat_history_string )
elif not ctx . content :
await chat_response ( ctx , channel_vars , chat_history_string )
bot . run ( discord_token )