mirror of
https://github.com/brandons209/Red-bot-Cogs.git
synced 2024-06-03 11:05:18 +12:00
uploaded v3 cog
This commit is contained in:
parent
aebda8d165
commit
8fcba72d10
6
events/__init__.py
Normal file
6
events/__init__.py
Normal file
|
@ -0,0 +1,6 @@
|
|||
from .events import Events
|
||||
|
||||
def setup(bot):
|
||||
n = Events(bot)
|
||||
bot.add_cog(n)
|
||||
bot.loop.create_task(n.update_events())
|
192
events/events.py
Normal file
192
events/events.py
Normal file
|
@ -0,0 +1,192 @@
|
|||
import discord
|
||||
from redbot.core import checks, commands
|
||||
from redbot.core.utils.chat_formatting import *
|
||||
from redbot.core import Config
|
||||
|
||||
import time
|
||||
import random
|
||||
import asyncio
|
||||
import datetime
|
||||
import pytz
|
||||
from tzlocal import get_localzone
|
||||
|
||||
|
||||
basic_colors = [discord.Colour.blue(), discord.Colour.teal(), discord.Colour.dark_teal(), discord.Colour.green(), discord.Colour.dark_green(), discord.Colour.dark_blue(), discord.Colour.purple(), discord.Colour.dark_purple(), discord.Colour.magenta(), discord.Colour.gold(), discord.Colour.orange(), discord.Colour.red(), discord.Colour.dark_red(), discord.Colour.blurple(), discord.Colour.greyple()]
|
||||
class Events(commands.Cog):
|
||||
"""
|
||||
Set events that track time since set events
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
super().__init__()
|
||||
self.config = Config.get_conf(self, identifier=6748392754)
|
||||
self.timezone = get_localzone()
|
||||
self.bot = bot
|
||||
# set default values
|
||||
self.config.register_guild(events={}, channel=0)
|
||||
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
async def event(self, ctx):
|
||||
"""
|
||||
Track time since event occured.
|
||||
"""
|
||||
pass
|
||||
|
||||
@event.command(name="add")
|
||||
async def addevent(self, ctx, start_time: str, *, event_name: str = ""):
|
||||
"""
|
||||
Add event to track. If start time is not given, the current data and time is used.
|
||||
Start time should be a UNIX timestamp
|
||||
"""
|
||||
guild = ctx.guild
|
||||
channel_id = await self.config.guild(guild).channel()
|
||||
if channel_id == 0:
|
||||
await ctx.send("Channel not setup, use ``{}eventset channel` to set channel for events.".format(ctx.prefix))
|
||||
return
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
if not channel:
|
||||
await ctx.send("Channel set not found, please setup channel.")
|
||||
return
|
||||
try:
|
||||
start_time = datetime.datetime.utcfromtimestamp(int(start_time))
|
||||
except:
|
||||
event_name = start_time + " " + event_name
|
||||
start_time = datetime.datetime.utcnow()
|
||||
|
||||
elapsed_time = datetime.datetime.utcnow() - start_time
|
||||
embed = discord.Embed(title=event_name, colour=random.choice(basic_colors))
|
||||
embed.add_field(name="Event time", value=start_time.replace(tzinfo=pytz.utc).astimezone(self.timezone).strftime("%b %d, %Y, %H:%M"))
|
||||
day_msg = "{} day{},".format(elapsed_time.days, "s" if elapsed_time.days > 1 else "")
|
||||
hour_msg = " {} hour{}".format(int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else "")
|
||||
if elapsed_time.days > 0 or int(elapsed_time.seconds / 60 / 60) > 0:
|
||||
minute_msg = ", and {} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
|
||||
else:
|
||||
minute_msg = "{} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
|
||||
msg = "{}{}{}".format(day_msg if elapsed_time.days > 0 else "", hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "", minute_msg)
|
||||
embed.add_field(name="Elapsed time", value=msg)
|
||||
message = await channel.send(embed=embed)
|
||||
async with self.config.guild(guild).events() as events:
|
||||
new_event = {"start_time" : int(start_time.replace(tzinfo=pytz.utc).timestamp()), "name" : event_name}
|
||||
events[message.id] = new_event
|
||||
await ctx.send("Event added!")
|
||||
|
||||
@event.command(name="del")
|
||||
async def delevent(self, ctx):
|
||||
"""
|
||||
Delete an event. Interactive deletion, so just run the command.
|
||||
"""
|
||||
guild = ctx.guild
|
||||
channel_id = await self.config.guild(guild).channel()
|
||||
if channel_id == 0:
|
||||
await ctx.send("Channel not setup, use `{}eventset channel` to set channel for events.".format(ctx.prefix))
|
||||
return
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
if not channel:
|
||||
await ctx.send("Channel set not found, please setup channel.")
|
||||
return
|
||||
|
||||
counter = 0
|
||||
msg = "```"
|
||||
async with self.config.guild(guild).events() as events:
|
||||
for num, event in events.items():
|
||||
msg += "{}\t{}\n".format(counter, event["name"])
|
||||
if len(msg + "```") + 100 > 2000:
|
||||
msg += "```"
|
||||
await ctx.send(msg)
|
||||
msg = "```"
|
||||
counter += 1
|
||||
msg += "```"
|
||||
await ctx.send(msg)
|
||||
await ctx.send("Please choose which event you want to delete. (type number in chat)")
|
||||
def m_check(m):
|
||||
try:
|
||||
return m.author.id == ctx.author.id and m.channel.id == ctx.channel.id and int(m.content) <= counter and int(m.content) >= 0
|
||||
except:
|
||||
return False
|
||||
try:
|
||||
response = await self.bot.wait_for('message', timeout=30, check=m_check)
|
||||
except:
|
||||
await ctx.send("Timed out, event deletion cancelled.")
|
||||
return
|
||||
for i, num in enumerate(events.keys()):
|
||||
if i == int(response.content):
|
||||
event_num = num
|
||||
try:
|
||||
message = await channel.fetch_message(event_num)
|
||||
await message.delete()
|
||||
except:
|
||||
await ctx.send("Event message in {} was not found.".format(channel.mention))
|
||||
|
||||
await ctx.send("{} has been deleted!".format(events[event_num]["name"]))
|
||||
del events[event_num]
|
||||
|
||||
@event.command(name="list")
|
||||
async def listevent(self, ctx):
|
||||
"""
|
||||
List all events for server.
|
||||
"""
|
||||
guild = ctx.guild
|
||||
msg = "```\n"
|
||||
async with self.config.guild(guild).events() as events:
|
||||
if len(events) == 0:
|
||||
msg += "None"
|
||||
for num, event in events.items():
|
||||
msg += "{}\n".format(event["name"])
|
||||
if len(msg + "```") + 3 > 2000:
|
||||
msg += "```"
|
||||
await ctx.send(msg)
|
||||
msg = "```"
|
||||
|
||||
msg += "```"
|
||||
await ctx.send(msg)
|
||||
|
||||
@commands.group()
|
||||
@commands.guild_only()
|
||||
@checks.admin_or_permissions(administrator=True)
|
||||
async def eventset(self, ctx: commands.Context):
|
||||
"""Manages event settings"""
|
||||
pass
|
||||
|
||||
@eventset.command(name="channel")
|
||||
async def _channel_set(self, ctx, channel: discord.TextChannel):
|
||||
"""
|
||||
Set channel to send event messages too
|
||||
"""
|
||||
guild = ctx.guild
|
||||
await self.config.guild(guild).channel.set(channel.id)
|
||||
await ctx.send("Channel now set to {}".format(channel.mention))
|
||||
|
||||
async def update_events(self):
|
||||
while True:
|
||||
if self is not self.bot.get_cog("Events"):
|
||||
print("events cog has been lost")
|
||||
return
|
||||
guilds = self.bot.guilds
|
||||
for guild in guilds:
|
||||
async with self.config.guild(guild).events() as events:
|
||||
channel_id = await self.config.guild(guild).channel()
|
||||
if channel_id == 0:
|
||||
continue
|
||||
channel = self.bot.get_channel(channel_id)
|
||||
if channel is None:
|
||||
continue
|
||||
for message_id, event in events.items():
|
||||
try:
|
||||
message = await channel.fetch_message(message_id)
|
||||
except:
|
||||
continue
|
||||
start_time = datetime.datetime.utcfromtimestamp(event["start_time"])
|
||||
elapsed_time = datetime.datetime.utcnow() - start_time
|
||||
embed = message.embeds[0]
|
||||
embed.clear_fields()
|
||||
embed.add_field(name="Event time", value=start_time.replace(tzinfo=pytz.utc).astimezone(self.timezone).strftime("%b %d, %Y, %H:%M"))
|
||||
day_msg = "{} day{},".format(elapsed_time.days, "s" if elapsed_time.days > 1 else "")
|
||||
hour_msg = " {} hour{}".format(int(elapsed_time.seconds / 60 / 60), "s" if int(elapsed_time.seconds / 60 / 60) > 1 else "")
|
||||
if elapsed_time.days > 0 or int(elapsed_time.seconds / 60 / 60) > 0:
|
||||
minute_msg = ", and {} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
|
||||
else:
|
||||
minute_msg = "{} minute{}".format(int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60), "s" if int(elapsed_time.seconds / 60 - int(elapsed_time.seconds / 60 / 60) * 60) > 1 else "")
|
||||
msg = "{}{}{}".format(day_msg if elapsed_time.days > 0 else "", hour_msg if int(elapsed_time.seconds / 60 / 60) > 0 else "", minute_msg)
|
||||
embed.add_field(name="Elapsed time", value=msg)
|
||||
await message.edit(embed=embed)
|
||||
await asyncio.sleep(40)
|
|
@ -1,269 +0,0 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from cogs.utils import checks
|
||||
from cogs.utils.dataIO import dataIO
|
||||
import asyncio
|
||||
import os
|
||||
import random
|
||||
|
||||
class Referral:
|
||||
"""
|
||||
Creates a referral system with raffle like selection for prizes for discord users.
|
||||
"""
|
||||
def __init__(self, bot):
|
||||
self.settings_path = 'data/referral/settings.json'
|
||||
self.bot = bot
|
||||
self.settings = dataIO.load_json(self.settings_path)
|
||||
|
||||
def add_non_refer(self, member):
|
||||
if member.server.id not in self.settings.keys():
|
||||
self.settings[member.server.id] = {}
|
||||
self.settings[member.server.id]["NON-REFERRALS"] = []
|
||||
elif "NON-REFERRALS" not in self.settings[member.server.id].keys():
|
||||
self.settings[member.server.id]["NON-REFERRALS"] = []
|
||||
|
||||
self.settings[member.server.id]["NON-REFERRALS"].append(member.id)
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
|
||||
def clear_refers(self, server):
|
||||
"""
|
||||
Clears entire referral and non referral list, then adds all current users in server to non referral list.
|
||||
"""
|
||||
self.settings[server.id]["NON-REFERRALS"] = []
|
||||
self.settings[server.id]["REFERRALS"] = {}
|
||||
for member in server.members:
|
||||
self.settings[server.id]["NON-REFERRALS"].append(member.id)
|
||||
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
|
||||
async def member_join_listener(self, member):
|
||||
"""
|
||||
Checks user against main invite link to determine if they went through the main invite link or an alternate one
|
||||
"""
|
||||
server = member.server
|
||||
default_inv = self.settings.get(server.id, {}).get("DEFAULT_INVITE", {})
|
||||
invite = None
|
||||
|
||||
if not default_inv:
|
||||
# TODO logging
|
||||
return
|
||||
else:
|
||||
try:
|
||||
invite = await self.bot.get_invite(default_inv["ID"])
|
||||
except:
|
||||
invite = None
|
||||
|
||||
if not invite:
|
||||
# TODO: put logging here
|
||||
return
|
||||
|
||||
if invite.uses > int(default_inv["USES"]):
|
||||
self.add_non_refer(member)
|
||||
self.settings[server.id]["DEFAULT_INVITE"]["USES"] = invite.uses
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
|
||||
@commands.group(pass_context=True, invoke_without_command=True, no_pm=True)
|
||||
@checks.admin_or_permissions(administrator=True)
|
||||
async def referralset(self, ctx):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await self.bot.send_cmd_help(ctx)
|
||||
|
||||
@referralset.command(pass_context=True, no_pm=True, name="default-invite")
|
||||
async def default_invite(self, ctx, invite_id : str):
|
||||
"""
|
||||
!!! Not functional !!!
|
||||
Set default invite for server. Give a valid invite ID.
|
||||
"""
|
||||
server = ctx.message.server
|
||||
try:
|
||||
invite = await self.bot.get_invite(invite_id)
|
||||
except:
|
||||
await self.bot.say("Could not retrieve invite, make sure to use a valid invite ID.")
|
||||
return
|
||||
|
||||
if server.id not in self.settings.keys():
|
||||
self.settings[server.id] = {}
|
||||
self.settings[server.id]["DEFAULT_INVITE"] = {}
|
||||
elif "DEFAULT_INVITE" not in self.settings[server.id].keys():
|
||||
self.settings[server.id]["DEFAULT_INVITE"] = {}
|
||||
|
||||
self.settings[server.id]["DEFAULT_INVITE"]["ID"] = invite_id
|
||||
self.settings[server.id]["DEFAULT_INVITE"]["USES"] = invite.uses
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("Counts: {}".format(invite.uses))
|
||||
await self.bot.say("Default invite changed.")
|
||||
|
||||
@referralset.command(pass_context=True, no_pm=True, name="min-account-age")
|
||||
async def min_account_age(self, ctx, days : int):
|
||||
"""
|
||||
Set the min age (in days) a new user must have been on discord before they can set a referer.
|
||||
"""
|
||||
server = ctx.message.server
|
||||
|
||||
if server.id not in self.settings.keys():
|
||||
self.settings[server.id] = {}
|
||||
self.settings[server.id]["MIN_ACCOUNT_AGE"] = 0
|
||||
elif "MIN_ACCOUNT_AGE" not in self.settings[server.id].keys():
|
||||
self.settings[server.id]["MIN_ACCOUNT_AGE"] = 0
|
||||
|
||||
self.settings[server.id]["MIN_ACCOUNT_AGE"] = days
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("Minimum account age set to {}.".format(days))
|
||||
|
||||
@referralset.command(pass_context=True, no_pm=True, name="clear")
|
||||
async def clear_refer_data(self, ctx):
|
||||
"""
|
||||
Clears ALL current referrals and refer blacklist.
|
||||
It then puts all current server's members onto the blacklist.
|
||||
"""
|
||||
await self.bot.say("All current referral data (not settings) will be cleared, continue? (y/n)")
|
||||
message = await self.bot.wait_for_message(author=ctx.message.author, channel=ctx.message.channel)
|
||||
server = ctx.message.server
|
||||
|
||||
if message.content.lower() == "y":
|
||||
self.clear_refers(ctx.message.server)
|
||||
await self.bot.say("Referral data cleared.")
|
||||
else:
|
||||
await self.bot.say("Cancelled.")
|
||||
|
||||
@referralset.command(pass_context=True, no_pm=True, name="setup")
|
||||
async def setup(self, ctx):
|
||||
"""
|
||||
Setup referral cog for server.
|
||||
When first loading the referral module, make sure to run setup to add all current users to the blacklist for referrals.
|
||||
!!! WILL CLEAR ALL DATA FOR SERVER! !!!
|
||||
"""
|
||||
await self.bot.say("All current data will be cleared, continue? (y/n)")
|
||||
message = await self.bot.wait_for_message(author=ctx.message.author, channel=ctx.message.channel)
|
||||
server = ctx.message.server
|
||||
|
||||
if message.content.lower() == "y":
|
||||
self.settings[server.id] = {}
|
||||
self.settings[server.id]["MIN_ACCOUNT_AGE"] = 0
|
||||
self.settings[server.id]["DEFAULT_INVITE"] = {}
|
||||
#self.settings[server.id]["NON-REFERRALS"] = []
|
||||
#self.settings[server.id]["REFERRALS"] = {}
|
||||
self.clear_refers(server)
|
||||
await self.bot.say("Referral cog setup for this server!")
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
else:
|
||||
await self.bot.say("Canceled. No changes made")
|
||||
|
||||
@commands.group(pass_context=True, invoke_without_command=True, no_pm=True)
|
||||
async def refer(self, ctx, user: discord.Member):
|
||||
server = ctx.message.server
|
||||
if user:
|
||||
author = ctx.message.author
|
||||
thresh = self.settings.get(server.id, {}).get("MIN_ACCOUNT_AGE", 0)
|
||||
author_days_old = (ctx.message.timestamp - author.created_at).days
|
||||
user_days_old = (ctx.message.timestamp - user.created_at).days
|
||||
if author_days_old > thresh and user_days_old > thresh:
|
||||
if author.id in self.settings[server.id]["NON-REFERRALS"]:
|
||||
await self.bot.say("Sorry, you already set someone as your referrer or were already on the server.")
|
||||
return
|
||||
elif author.id == user.id:
|
||||
await self.bot.say("Sorry, you cannot refer yourself.")
|
||||
return
|
||||
elif user.id == self.bot.user.id:
|
||||
await self.bot.say("Thanks for trying, but you cannot set me as your referrer.")
|
||||
return
|
||||
if user.id not in self.settings[server.id]["REFERRALS"].keys():
|
||||
self.settings[server.id]["REFERRALS"][user.id] = [author.id]
|
||||
else:
|
||||
self.settings[server.id]["REFERRALS"][user.id].append(author.id)
|
||||
await self.bot.say("Referrer set to {}, thank you!".format(user.name))
|
||||
self.add_non_refer(author)
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
elif author_days_old < thresh:
|
||||
await self.bot.say("Sorry, your account is too new! Your account needs to be at least {} days old but it is {} days old.".format(thresh, author_days_old))
|
||||
else:
|
||||
await self.bot.say("Sorry, your referrer's account is too new! Their account needs to be at least {} days old but it is {} days old.".format(thresh, user_days_old))
|
||||
elif ctx.invoked_subcommand is None:
|
||||
await self.bot.send_cmd_help(ctx)
|
||||
|
||||
@refer.command(pass_context=True, no_pm=True, name="list")
|
||||
async def check_referrals(self, ctx):
|
||||
"""
|
||||
Checks how many people you have referred, and who referred you.
|
||||
"""
|
||||
author = ctx.message.author
|
||||
server = ctx.message.server
|
||||
settings = self.settings.get(server.id, {})
|
||||
msg = "Your Referrals:\n"
|
||||
referrals = settings.get("REFERRALS", {})
|
||||
author_referrals = settings.get("REFERRALS", {}).get(author.id, None)
|
||||
|
||||
if not author_referrals:
|
||||
msg += "**None**\n"
|
||||
else:
|
||||
for refer in author_referrals:
|
||||
member = await self.bot.get_user_info(refer)
|
||||
msg += "`{}`\n".format(member.name)
|
||||
|
||||
msg += "\nYour referer:\n"
|
||||
flag = 0
|
||||
for user_id in referrals.keys():
|
||||
for refer in referrals[user_id]:
|
||||
if refer == author.id:
|
||||
user = await self.bot.get_user_info(user_id)
|
||||
msg += "`{}`\n".format(user.name)
|
||||
flag = 1
|
||||
break
|
||||
if flag:
|
||||
break
|
||||
|
||||
if not flag:
|
||||
msg += "**None**\n"
|
||||
|
||||
await self.bot.say(msg)
|
||||
|
||||
@refer.command(pass_context=True, no_pm=True, name="raffle")
|
||||
@checks.admin_or_permissions(administrator=True)
|
||||
async def raffle(self, ctx, winners : int):
|
||||
"""
|
||||
Chooses specified amount of winners from users who have referrals. Each referral is a "raffle ticket" for the user.
|
||||
Once a winner is chooses, they cannot be choosen again.
|
||||
"""
|
||||
server = ctx.message.server
|
||||
settings = self.settings.get(server.id, {})
|
||||
|
||||
referrers = list(settings.get("REFERRALS", {}).keys())
|
||||
raffle_list = []
|
||||
|
||||
if not referrers:
|
||||
await self.bot.say("No one has referred anyone yet.")
|
||||
return
|
||||
|
||||
for refer in referrers:
|
||||
for _ in range(len(settings.get("REFERRALS", {}).get(refer, []))):
|
||||
raffle_list.append(refer)
|
||||
|
||||
random.shuffle(raffle_list)
|
||||
selection = []
|
||||
for i in range(winners):
|
||||
winner = random.choice(raffle_list)
|
||||
selection.append(winner)
|
||||
raffle_list = [x for x in raffle_list if x != winner]
|
||||
if not raffle_list:
|
||||
break
|
||||
|
||||
|
||||
msg = "**Here are the winners!**\n"
|
||||
for i, winner in enumerate(selection):
|
||||
user = await self.bot.get_user_info(winner)
|
||||
msg += "{}. `{}`\n".format(i + 1, user.display_name)
|
||||
|
||||
await self.bot.say(msg)
|
||||
|
||||
|
||||
def check_files():
|
||||
if not os.path.exists('data/referral/settings.json'):
|
||||
os.makedirs('data/referral', exist_ok=True)
|
||||
dataIO.save_json('data/referral/settings.json', {})
|
||||
|
||||
|
||||
def setup(bot):
|
||||
check_files()
|
||||
n = Referral(bot)
|
||||
bot.add_cog(n)
|
||||
#bot.add_listener(n.member_join_listener, "on_member_join")
|
|
@ -1,2 +0,0 @@
|
|||
tensorflow==1.5
|
||||
keras
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"AUTHOR" : "Brandon Silva",
|
||||
"INSTALL_MSG" : "Thanks for installing my cog!",
|
||||
"NAME" : "ScriptCog",
|
||||
"SHORT" : "Generates text from keras model.",
|
||||
"DESCRIPTION" : "Uses a keras model to generate text.",
|
||||
"TAGS" : ["mlp"],
|
||||
"REQUIREMENTS" : ["tensorflow", "keras"],
|
||||
"HIDDEN" : false
|
||||
}
|
|
@ -1,373 +0,0 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from cogs.utils import checks
|
||||
from cogs.utils.converters import GlobalUser
|
||||
|
||||
from keras.models import load_model
|
||||
from keras.preprocessing.sequence import pad_sequences
|
||||
|
||||
import numpy as np
|
||||
import os
|
||||
import pickle
|
||||
import time
|
||||
import asyncio
|
||||
|
||||
from .utils.dataIO import dataIO
|
||||
from .utils.chat_formatting import warning
|
||||
|
||||
#loads dictionary from file
|
||||
def _load_dict(path):
|
||||
with open(path, 'rb') as file:
|
||||
dict = pickle.load(file)
|
||||
return dict
|
||||
|
||||
#dictionaries for tokenizing puncuation and converting it back
|
||||
punctuation_to_tokens = {'!':' ||exclaimation_mark|| ', ',':' ||comma|| ', '"':' ||quotation_mark|| ',
|
||||
';':' ||semicolon|| ', '.':' ||period|| ', '?':' ||question_mark|| ', '(':' ||left_parentheses|| ',
|
||||
')':' ||right_parentheses|| ', '--':' ||dash|| ', '\n':' ||return|| ', ':':' ||colon|| '}
|
||||
|
||||
tokens_to_punctuation = {token.strip(): punc for punc, token in punctuation_to_tokens.items()}
|
||||
|
||||
#for all of the puncuation in replace_list, convert it to tokens
|
||||
def _tokenize_punctuation(text):
|
||||
replace_list = ['.', ',', '!', '"', ';', '?', '(', ')', '--', '\n', ':']
|
||||
for char in replace_list:
|
||||
text = text.replace(char, punctuation_to_tokens[char])
|
||||
return text
|
||||
|
||||
#convert tokens back to puncuation
|
||||
def _untokenize_punctuation(text):
|
||||
replace_list = ['||period||', '||comma||', '||exclaimation_mark||', '||quotation_mark||',
|
||||
'||semicolon||', '||question_mark||', '||left_parentheses||', '||right_parentheses||',
|
||||
'||dash||', '||return||', '||colon||']
|
||||
for char in replace_list:
|
||||
if char == '||left_parentheses||':#added this since left parentheses had an extra space
|
||||
text = text.replace(' ' + char + ' ', tokens_to_punctuation[char])
|
||||
text = text.replace(' ' + char, tokens_to_punctuation[char])
|
||||
return text
|
||||
|
||||
"""
|
||||
helper function that instead of just doing argmax for prediction, actually taking a sample of top possible words
|
||||
takes a tempature which defines how many predictions to consider. lower means the word picked will be closer to the highest predicted word.
|
||||
"""
|
||||
def _sample(prediction, temp=0):
|
||||
if temp <= 0:
|
||||
return np.argmax(prediction)
|
||||
prediction = prediction[0]
|
||||
prediction = np.asarray(prediction).astype('float64')
|
||||
prediction = np.log(prediction) / temp
|
||||
expo_prediction = np.exp(prediction)
|
||||
prediction = expo_prediction / np.sum(expo_prediction)
|
||||
probabilities = np.random.multinomial(1, prediction, 1)
|
||||
return np.argmax(probabilities)
|
||||
|
||||
def _resolve_role_list(server: discord.Server, roles: list) -> list:
|
||||
gen = (_role_from_string(server, name) for name in roles)
|
||||
return list(filter(None, gen))
|
||||
|
||||
def _role_from_string(server, rolename, roles=None):
|
||||
if roles is None:
|
||||
roles = server.roles
|
||||
|
||||
roles = [r for r in roles if r is not None]
|
||||
role = discord.utils.find(lambda r: r.name.lower() == rolename.lower(), roles)
|
||||
# if couldnt find by role name, try to find by role id
|
||||
if role is None:
|
||||
role = discord.utils.find(lambda r: r.id == rolename, roles)
|
||||
|
||||
return role
|
||||
|
||||
def format_list(*items, join='and', delim=', '):
|
||||
if len(items) > 1:
|
||||
return (' %s ' % join).join((delim.join(items[:-1]), items[-1]))
|
||||
elif items:
|
||||
return items[0]
|
||||
else:
|
||||
return ''
|
||||
|
||||
"""This cog generates scripts based on imported model, I used a keras model. """
|
||||
class ScriptCog:
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
self.model_path = "data/scriptcog/model.h5"
|
||||
self.dict_path = "data/scriptcog/dicts/"
|
||||
|
||||
self.cooldown = time.time()
|
||||
|
||||
try:
|
||||
self.model = load_model(self.model_path)
|
||||
except:
|
||||
self.model = None
|
||||
|
||||
self.settings_path = "data/scriptcog/settings.json"
|
||||
self.settings = dataIO.load_json(self.settings_path)
|
||||
|
||||
self.default_word_limit = 300
|
||||
self.default_cooldown_limit = 30
|
||||
self.default_tv_show = "My Little Pony"
|
||||
self.default_price = 0
|
||||
|
||||
try:
|
||||
self.word_to_int = _load_dict(self.dict_path + 'word_to_int.pkl')
|
||||
self.int_to_word = _load_dict(self.dict_path + 'int_to_word.pkl')
|
||||
self.sequence_length = _load_dict(self.dict_path + 'sequence_length.pkl')
|
||||
except:
|
||||
self.word_to_int = None
|
||||
self.int_to_word = None
|
||||
self.sequence_length = None
|
||||
|
||||
@commands.group(pass_context=True, invoke_without_command=True, no_pm=True)
|
||||
@checks.admin_or_permissions(administrator=True)
|
||||
async def genscriptset(self, ctx):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await self.bot.send_cmd_help(ctx)
|
||||
|
||||
@genscriptset.command(pass_context=True, no_pm=True, name="word-limit")
|
||||
@checks.is_owner()
|
||||
async def genscriptset_set_word_limit(self, ctx, num_words : int):
|
||||
"""
|
||||
Set the word limit for generating scripts.
|
||||
"""
|
||||
try:
|
||||
self.settings[ctx.message.server.id]["WORD_LIMIT"] = num_words
|
||||
except:
|
||||
self.settings[ctx.message.server.id] = {}
|
||||
self.settings[ctx.message.server.id]["WORD_LIMIT"] = num_words
|
||||
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("Maximum number of words is now {}".format(num_words))
|
||||
|
||||
@genscriptset.command(pass_context=True, no_pm=True, name="tv-show")
|
||||
@checks.is_owner()
|
||||
async def genscriptset_set_tv_show(self, ctx, *, show):
|
||||
"""
|
||||
Sets the TV show the scripts are generated from.
|
||||
"""
|
||||
try:
|
||||
self.settings[ctx.message.server.id]["TV_SHOW"] = show
|
||||
except:
|
||||
self.settings[ctx.message.server.id] = {}
|
||||
self.settings[ctx.message.server.id]["TV_SHOW"] = show
|
||||
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("TV show is now {}.".format(show))
|
||||
|
||||
@genscriptset.command(pass_context=True, no_pm=True, name="cooldown")
|
||||
@checks.is_owner()
|
||||
async def genscriptset_set_cooldown(self, ctx, cooldown : int):
|
||||
"""
|
||||
Sets the cooldown period between generating scripts in seconds.
|
||||
"""
|
||||
try:
|
||||
self.settings[ctx.message.server.id]["COOLDOWN"] = cooldown
|
||||
except:
|
||||
self.settings[ctx.message.server.id] = {}
|
||||
self.settings[ctx.message.server.id]["COOLDOWN"] = cooldown
|
||||
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("Script cooldown is now {}.".format(cooldown))
|
||||
|
||||
@genscriptset.command(pass_context=True, no_pm=True, name="price")
|
||||
async def genscriptset_set_price(self, ctx, price : int):
|
||||
"""
|
||||
Sets the price for generating scripts.
|
||||
"""
|
||||
try:
|
||||
self.settings[ctx.message.server.id]["PRICE"] = price
|
||||
except:
|
||||
self.settings[ctx.message.server.id] = {}
|
||||
self.settings[ctx.message.server.id]["PRICE"] = price
|
||||
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
await self.bot.say("Price is now {}.".format(price))
|
||||
|
||||
@genscriptset.command(pass_context=True, no_pm=True, name="free-roles")
|
||||
async def genscriptset_free_roles(self, ctx, *, rolelist=None):
|
||||
"""Set roles that do not have to pay to generate scripts.
|
||||
|
||||
COMMA SEPARATED LIST (e.g. Admin,Staff,Mod), Can also use role IDs as well.
|
||||
|
||||
To get current list, run command with no roles.
|
||||
|
||||
Add role_list_clear as the role to clear the server\'s free role list.
|
||||
"""
|
||||
server = ctx.message.server
|
||||
current_roles = _resolve_role_list(server, self.settings[server.id].get("FREE_ROLE_LIST", []))
|
||||
|
||||
if rolelist is None:
|
||||
if current_roles:
|
||||
names_list = format_list(*(r.name for r in current_roles))
|
||||
await self.bot.say("Current list of roles that do not have to pay: {}".format(names_list))
|
||||
else:
|
||||
await self.bot.say("No roles defined.")
|
||||
return
|
||||
elif "role_list_clear" in rolelist.lower():
|
||||
await self.bot.say("Free role list cleared.")
|
||||
self.settings[server.id]["FREE_ROLE_LIST"] = []
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
return
|
||||
|
||||
found_roles = set()
|
||||
notfound_names = set()
|
||||
|
||||
for lookup in rolelist.split(","):
|
||||
lookup = lookup.strip()
|
||||
role = _role_from_string(server, lookup)
|
||||
|
||||
if role:
|
||||
found_roles.add(role)
|
||||
else:
|
||||
notfound_names.add(lookup)
|
||||
|
||||
if notfound_names:
|
||||
fmt_list = format_list(*("`{}`".format(x) for x in notfound_names))
|
||||
await self.bot.say(warning("These roles were not found: {}\n\nPlease try again.".format(fmt_list)))
|
||||
elif server.default_role in found_roles:
|
||||
await self.bot.say(warning("The everyone role cannot be added.\n\nPlease try again."))
|
||||
elif found_roles == set(current_roles):
|
||||
await self.bot.say("No changes to make.")
|
||||
else:
|
||||
if server.id not in self.settings:
|
||||
self.settings[server.id] = {}
|
||||
else:
|
||||
extra = ""
|
||||
|
||||
self.settings[server.id]["FREE_ROLE_LIST"] = [r.id for r in found_roles]
|
||||
dataIO.save_json(self.settings_path, self.settings)
|
||||
|
||||
fmt_list = format_list(*(r.name for r in found_roles))
|
||||
await self.bot.say("These roles will not have to pay for scripts: {}.{}".format(fmt_list, extra))
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def genscriptinfo(self, ctx):
|
||||
server_id = ctx.message.server.id
|
||||
word_limit = self.settings.get(server_id, {}).get("WORD_LIMIT", self.default_word_limit)
|
||||
cooldown = self.settings.get(server_id, {}).get("COOLDOWN", self.default_cooldown_limit)
|
||||
tv_show = self.settings.get(server_id, {}).get("TV_SHOW", self.default_tv_show)
|
||||
price = self.settings.get(server_id, {}).get("PRICE", self.default_price)
|
||||
await self.bot.say("```Word Limit: {0}\nCooldown Time: {1} seconds\nShow: {2}\nPrice for {0} words: {3}, which is {4} bits per word```".format(word_limit, cooldown, tv_show, price, price / word_limit))
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def genscripthelp(self, ctx):
|
||||
await self.bot.say("--------------------\nGenerate original TV scripts for {0} using Neural Networks!\nUsage: `{1}genscript <number of words to generate> <word variance> <starting text>`\nUse starting texts such as:\n`pinkie pie::`\n`fluttershy::`\n`twilight sparkle::`\nor other names of characters in the show. Otherwise, you can use any words said in the show.\n\nWord variance helps gives the script better results. A variance of 0 will mean that with the same starting text, it will always have the same output. Variance up to 1.0 will give more variety to words, however going closer to 1 can introduce more grammar and spelling mistakes.\n\nGenerating scripts cost bits, depending on how many words you want to generate. Use `{1}genscriptinfo` to get information on the cost.\n-------------------".format(self.settings.get(ctx.message.server.id, {}).get("TV_SHOW", self.default_tv_show), ctx.prefix))
|
||||
|
||||
@commands.command(pass_context=True, no_pm=True)
|
||||
async def genscript(self, ctx, num_words_to_generate : int, variance : float, *, seed):
|
||||
"""
|
||||
Generate a script using the power of Neural Networks!
|
||||
Please use the genscripthelp command to get a complete explaination of how to use the command.
|
||||
"""
|
||||
server_id = ctx.message.server.id
|
||||
word_limit = self.settings.get(server_id, {}).get("WORD_LIMIT", self.default_word_limit)
|
||||
cooldown = self.settings.get(server_id, {}).get("COOLDOWN", self.default_cooldown_limit)
|
||||
price = self.settings.get(server_id, {}).get("PRICE", self.default_price)
|
||||
user = ctx.message.author
|
||||
|
||||
if num_words_to_generate > word_limit:
|
||||
await self.bot.say("Please keep script sizes to {} words or less.".format(word_limit))
|
||||
return
|
||||
elif time.time() - self.cooldown < cooldown:
|
||||
await self.bot.say("Sorry, I am cooling down, please wait {:.0f} seconds.".format(cooldown - (time.time() - self.cooldown)))
|
||||
return
|
||||
|
||||
if not self.check_free_role(user):
|
||||
price = int((price / word_limit) * num_words_to_generate)
|
||||
return_val = self.charge_user(user, price)
|
||||
if return_val == 1: #if this worked, dont need to check when getting econ cog
|
||||
balance = self.bot.get_cog('Economy').bank.get_balance(user)
|
||||
await self.bot.say("Charged: {}, Balance: {}".format(price, balance))
|
||||
else:
|
||||
await self.charge_user_check(return_val, price, user)
|
||||
return
|
||||
|
||||
self.cooldown = time.time()
|
||||
|
||||
if variance > 1.0:
|
||||
variance = 1.0
|
||||
elif variance < 0:
|
||||
variance = 0
|
||||
|
||||
await self.bot.say("Generating script, please wait...")
|
||||
await self.get_model_output(num_words_to_generate, variance, seed)
|
||||
|
||||
async def get_model_output(self, num_words, temp, seed):
|
||||
input_text = seed
|
||||
for _ in range(num_words):
|
||||
#tokenize text to ints
|
||||
int_text = _tokenize_punctuation(input_text)
|
||||
int_text = int_text.lower()
|
||||
int_text = int_text.split()
|
||||
try:
|
||||
int_text = np.array([self.word_to_int[word] for word in int_text], dtype=np.int32)
|
||||
except KeyError:
|
||||
await self.bot.say("Sorry, that seed word is not in my vocabulary.\nPlease try an English word from the show.\n")
|
||||
return
|
||||
#pad text if it is too short, pads with zeros at beginning of text, so shouldnt have too much noise added
|
||||
int_text = pad_sequences([int_text], maxlen=self.sequence_length)
|
||||
#predict next word:
|
||||
prediction = self.model.predict(int_text, verbose=0)
|
||||
output_word = self.int_to_word[_sample(prediction, temp=temp)]
|
||||
#append to the result
|
||||
input_text += ' ' + output_word
|
||||
#convert tokenized punctuation and other characters back
|
||||
result = _untokenize_punctuation(input_text)
|
||||
await self.bot.say("------------------------")
|
||||
await self.bot.say(result)
|
||||
await self.bot.say("------------------------")
|
||||
|
||||
def charge_user(self, user, amount):
|
||||
"""
|
||||
Takes a user and a amount and charges the user. Returns 1 on success, 0 if economy cog cannot be loaded, -1 if the user does not have a bank account, and -2 if the user doesn't have enough credits.
|
||||
"""
|
||||
econ_cog = self.bot.get_cog('Economy')
|
||||
if not econ_cog:
|
||||
return 0
|
||||
if not econ_cog.bank.account_exists(user):
|
||||
return -1
|
||||
if not econ_cog.bank.can_spend(user, amount):
|
||||
return -2
|
||||
econ_cog.bank.withdraw_credits(user, amount)
|
||||
return 1
|
||||
|
||||
async def charge_user_check(self, return_val, amount, user):
|
||||
"""
|
||||
takes in return vals from charge_user and gives apporiate response
|
||||
"""
|
||||
econ_cog = self.bot.get_cog('Economy')
|
||||
if not econ_cog:
|
||||
await self.bot.say("Error loading economy cog!")
|
||||
return
|
||||
if return_val == 0:
|
||||
await self.bot.say("Economy cog not found! Please check to make sure the economy cog is loaded.")
|
||||
elif return_val == -1:
|
||||
await self.bot.say("You appear to not have a bank account. Use [p]bank register to open an account.")
|
||||
elif return_val == -2:
|
||||
await self.bot.say("You do not have enough credits. The sound command costs {} and you have {} credits in your bank account.".format(amount, econ_cog.bank.get_balance(user)))
|
||||
|
||||
def check_free_role(self, user):
|
||||
"""
|
||||
Checks if the user has a role that grants them free sounds. Returns 1 if the user does have one of these roles, zero otherwise.
|
||||
"""
|
||||
server = user.server
|
||||
free_roles = self.settings.get(server.id, {}).get("FREE_ROLE_LIST", [])
|
||||
if not free_roles:
|
||||
return 0
|
||||
user_roles = [r.id for r in user.roles]
|
||||
|
||||
for role in free_roles:
|
||||
if role in user_roles:
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
def check_folders():
|
||||
os.makedirs("data/scriptcog", exist_ok=True)
|
||||
os.makedirs("data/scriptcog/dicts", exist_ok=True)
|
||||
f = "data/scriptcog/settings.json"
|
||||
if not dataIO.is_valid_json(f):
|
||||
dataIO.save_json(f, {})
|
||||
|
||||
def setup(bot):
|
||||
check_folders()
|
||||
bot.add_cog(ScriptCog(bot))
|
Loading…
Reference in a new issue