Mass update to latest discord.py
This commit is contained in:
parent
ace8f0524f
commit
0b530493a7
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,4 +1,2 @@
|
|||||||
/sqlPass.txt
|
/scr/modules/TMC/ChangeServer/text.txt
|
||||||
/token.txt
|
/settings.json
|
||||||
/scr/Modules/TMC/ChangeServer/text.txt
|
|
||||||
/rcon.txt
|
|
||||||
|
3
.idea/Discord Bot.iml
generated
3
.idea/Discord Bot.iml
generated
@ -5,8 +5,9 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/scr" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/scr" isTestSource="false" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
<excludeFolder url="file://$MODULE_DIR$/venv" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/venv-linux" />
|
<excludeFolder url="file://$MODULE_DIR$/venv-linux" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/.venv" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Python 3.8 (discord_bot)" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Python 3.13 (discord_bot)" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="R User Library" level="project" />
|
<orderEntry type="library" name="R User Library" level="project" />
|
||||||
<orderEntry type="library" name="R Skeletons" level="application" />
|
<orderEntry type="library" name="R Skeletons" level="application" />
|
||||||
|
5
.idea/misc.xml
generated
5
.idea/misc.xml
generated
@ -1,4 +1,7 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (discord_bot)" project-jdk-type="Python SDK" />
|
<component name="Black">
|
||||||
|
<option name="sdkName" value="Python 3.12 (discord_bot)" />
|
||||||
|
</component>
|
||||||
|
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.13 (discord_bot)" project-jdk-type="Python SDK" />
|
||||||
</project>
|
</project>
|
6
.idea/sqldialects.xml
generated
6
.idea/sqldialects.xml
generated
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="SqlDialectMappings">
|
|
||||||
<file url="PROJECT" dialect="MySQL" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,4 +1,5 @@
|
|||||||
# Discord_Bot
|
# Discord_Bot
|
||||||
|
|
||||||
bot.py in root is the main bot file
|
bot.py in root is the main bot file
|
||||||
bot.py in /OLD is the bot file before the rewrite
|
bot.py in /OLD is the bot file before the rewrite
|
||||||
/modules is the folder for all the modules
|
/modules is the folder for all the modules
|
||||||
|
@ -1,121 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
|
|
||||||
import discord
|
|
||||||
import pymysql
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
password = open("../../../../sqlPass.txt", 'r')
|
|
||||||
|
|
||||||
con = pymysql.connect(host='localhost',
|
|
||||||
user='Bot',
|
|
||||||
password=f'{password}',
|
|
||||||
db='serverIDs',
|
|
||||||
charset='utf8mb4',
|
|
||||||
cursorclass=pymysql.cursors.DictCursor)
|
|
||||||
|
|
||||||
|
|
||||||
class AddServer(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_message(self, ctx):
|
|
||||||
if isinstance(ctx.channel, discord.DMChannel) and (ctx.content.lower() == "add server"):
|
|
||||||
try:
|
|
||||||
await ctx.channel.send("Send me an invite to the server. Say ``cancel`` anytime to cancel.")
|
|
||||||
invite = await self.client.wait_for("message", check=lambda message: message.author == ctx.author
|
|
||||||
and message.channel == ctx.channel,
|
|
||||||
timeout=20)
|
|
||||||
invite = await self.client.fetch_invite(invite.content)
|
|
||||||
if invite == "cancel":
|
|
||||||
await ctx.channel.send("Process canceled")
|
|
||||||
return
|
|
||||||
|
|
||||||
categorys = self.client.get_channel(656998225076551680)
|
|
||||||
print(categorys.channels)
|
|
||||||
category_names = ""
|
|
||||||
for channel in categorys.channels:
|
|
||||||
category_names = category_names + '`' + channel.name + '` | '
|
|
||||||
await ctx.channel.send("Please slect a category from the following. This will change how the server"
|
|
||||||
"is shown in the Hub server \n" + category_names)
|
|
||||||
category = await self.client.wait_for("message", check=lambda message: message.author == ctx.author
|
|
||||||
and message.channel == ctx.channel, timeout=20)
|
|
||||||
category = category.content.lower
|
|
||||||
if category == "cancel":
|
|
||||||
await ctx.channel.send("Process canceled")
|
|
||||||
return
|
|
||||||
for channel in categorys.channels:
|
|
||||||
if category == channel.name:
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
category = "other"
|
|
||||||
|
|
||||||
await ctx.channel.send("Please send a list of tags separated by a "
|
|
||||||
"comma(,) no spaces")
|
|
||||||
tags = await self.client.wait_for("message", check=lambda message: message.author == ctx.author
|
|
||||||
and message.channel == ctx.channel,
|
|
||||||
timeout=20)
|
|
||||||
if tags == "cancel":
|
|
||||||
await ctx.channel.send("Process canceled")
|
|
||||||
return
|
|
||||||
|
|
||||||
await ctx.channel.send("Please send a description of the server")
|
|
||||||
description = await self.client.wait_for("message", check=lambda message: message.author == ctx.author
|
|
||||||
and message.channel == ctx.channel,
|
|
||||||
timeout=20)
|
|
||||||
if description == "cancel":
|
|
||||||
await ctx.channel.send("Process canceled")
|
|
||||||
return
|
|
||||||
|
|
||||||
nsfw = 0
|
|
||||||
for channel in invite.guild.channels:
|
|
||||||
try:
|
|
||||||
if channel.is_nsfw():
|
|
||||||
nsfw = 1
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
try:
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute(f"INSERT INTO servers "
|
|
||||||
f"(ID, name, category, tags, description, nsfw, invite, submitter) "
|
|
||||||
f"VALUES ({invite.guild.id},'"
|
|
||||||
f"{invite.guild.name}','"
|
|
||||||
f"{category}','"
|
|
||||||
f"{tags.content}','"
|
|
||||||
f"{description.content}','"
|
|
||||||
f"{nsfw}','"
|
|
||||||
f"{invite.code}','"
|
|
||||||
f"{ctx.author.id}')")
|
|
||||||
await ctx.channel.send("Server added successfully")
|
|
||||||
|
|
||||||
embed = discord.Embed(
|
|
||||||
colour=discord.Colour.green()
|
|
||||||
)
|
|
||||||
embed.set_author(name="Server Added")
|
|
||||||
embed.add_field(name="ID", value=f"{invite.guild.id}", inline=False)
|
|
||||||
embed.add_field(name="Name", value=f"{invite.guild.name}", inline=False)
|
|
||||||
embed.add_field(name="Tags", value=f"{tags.content}", inline=False)
|
|
||||||
embed.add_field(name="Code", value=f"{invite.code}", inline=False)
|
|
||||||
embed.add_field(name="Description", value=f"{description.content}", inline=False)
|
|
||||||
await self.client.get_channel(658442038475358238).send(embed=embed)
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
await ctx.channel.send("An error has occurred and will be fixed"
|
|
||||||
"shortly.")
|
|
||||||
print(e)
|
|
||||||
await self.client.get_channel(656997125627969546).send(e)
|
|
||||||
await self.client. \
|
|
||||||
get_channel(656997125627969546). \
|
|
||||||
send("<@305589587215122432>")
|
|
||||||
|
|
||||||
except asyncio.TimeoutError:
|
|
||||||
await ctx.channel.send("Process timeout")
|
|
||||||
return
|
|
||||||
await self.client.process_commands(ctx)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(AddServer(client))
|
|
@ -1,16 +0,0 @@
|
|||||||
import pymysql.cursors
|
|
||||||
|
|
||||||
password = open("../../../../sqlPass.txt", 'r')
|
|
||||||
|
|
||||||
con = pymysql.connect(host='localhost',
|
|
||||||
user='Bot',
|
|
||||||
password=f'{password}',
|
|
||||||
db='serverIDs',
|
|
||||||
charset='utf8mb4',
|
|
||||||
cursorclass=pymysql.cursors.DictCursor)
|
|
||||||
|
|
||||||
with con:
|
|
||||||
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute("INSERT INTO servers (name, tags, invite, description) VALUES ('Not Very Official Changed Server','furry, rp', 'invitelink.com','N/A')")
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
|||||||
import pymysql
|
|
||||||
|
|
||||||
password = open("../../../../sqlPass.txt", 'r')
|
|
||||||
|
|
||||||
con = pymysql.connect(host='localhost',
|
|
||||||
user='Bot',
|
|
||||||
password=f'{password}',
|
|
||||||
db='serverIDs',
|
|
||||||
charset='utf8mb4',
|
|
||||||
cursorclass=pymysql.cursors.DictCursor)
|
|
||||||
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
print(cur.execute("SELECT ID FROM servers WHERE ID = 1"))
|
|
@ -1 +0,0 @@
|
|||||||
SELECT ID FROM servers WHERE ID = 1;
|
|
@ -1,59 +0,0 @@
|
|||||||
import discord
|
|
||||||
import pymysql
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
password = open("../../../../sqlPass.txt", 'r')
|
|
||||||
|
|
||||||
con = pymysql.connect(host='localhost',
|
|
||||||
user='Bot',
|
|
||||||
password=f'{password}',
|
|
||||||
db='serverIDs',
|
|
||||||
charset='utf8mb4',
|
|
||||||
cursorclass=pymysql.cursors.DictCursor)
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveServer(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_message(self, ctx):
|
|
||||||
if isinstance(ctx.channel, discord.DMChannel):
|
|
||||||
if ctx.content.lower() == "remove server":
|
|
||||||
await ctx.channel.send("Send the server ID.")
|
|
||||||
server_id = await self.client.wait_for("message", check=lambda message: message.author == ctx.author)
|
|
||||||
try:
|
|
||||||
server_id = int(server_id.content)
|
|
||||||
except ValueError:
|
|
||||||
await ctx.channel.send("Invalid server ID")
|
|
||||||
|
|
||||||
try:
|
|
||||||
member = self.client.get_guild(server_id).get_member(ctx.author.id)
|
|
||||||
if member.guild_permissions.manage_guild:
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
server_exists = cur.execute(f"SELECT ID FROM servers WHERE ID = {server_id}")
|
|
||||||
if server_exists == 0:
|
|
||||||
with con:
|
|
||||||
cur = con.cursor()
|
|
||||||
cur.execute(f"DELETE FROM servers WHERE ID={server_id}")
|
|
||||||
else:
|
|
||||||
await ctx.channel.send("That server could not be found in our databases")
|
|
||||||
|
|
||||||
except AttributeError:
|
|
||||||
await ctx.channel.send("Cannot verify server ownership. "
|
|
||||||
"Either you are not the guild owner or "
|
|
||||||
"the bot has not been added to verify ownership.\n"
|
|
||||||
"Add the bot here : https://discordapp.com/api/oauth2"
|
|
||||||
"/authorize?client_id=501485906801459200&permissions=1024"
|
|
||||||
"&scope=bot\n"
|
|
||||||
"Once the bot is added restart the verification process "
|
|
||||||
"using ``remove server`` in this DM\n"
|
|
||||||
"After ownership is verified the bot can be removed.")
|
|
||||||
await self.client.process_commands(ctx)
|
|
||||||
|
|
||||||
|
|
||||||
# todo
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(RemoveServer(client))
|
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,195 +0,0 @@
|
|||||||
from typing import Union
|
|
||||||
import discord
|
|
||||||
from discord.ext import commands
|
|
||||||
import math
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import pymysql
|
|
||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
||||||
|
|
||||||
password = open("../sqlPass.txt", 'r').read()
|
|
||||||
|
|
||||||
scheduler = AsyncIOScheduler({
|
|
||||||
'apscheduler.jobstores.default': {
|
|
||||||
'type': 'sqlalchemy',
|
|
||||||
'url': f'mysql+pymysql://quentin:{password}@192.168.1.52:5618/discord_bot?charset=utf8mb4',
|
|
||||||
},
|
|
||||||
'apscheduler.job_defaults.coalesce': 'True',
|
|
||||||
'apscheduler.timezone': 'America/Chicago'
|
|
||||||
})
|
|
||||||
|
|
||||||
scheduler.start()
|
|
||||||
|
|
||||||
mcSelf = None
|
|
||||||
|
|
||||||
|
|
||||||
def get_con() -> pymysql.Connection:
|
|
||||||
return pymysql.connect(host='192.168.1.52',
|
|
||||||
port=5618,
|
|
||||||
user='quentin',
|
|
||||||
password=f'{password}',
|
|
||||||
db='minecraft',
|
|
||||||
charset='utf8mb4',
|
|
||||||
cursorclass=pymysql.cursors.DictCursor)
|
|
||||||
|
|
||||||
|
|
||||||
async def get_poll_results(choices: dict, pollMessageId: int, channelId: int):
|
|
||||||
print("run")
|
|
||||||
|
|
||||||
getPollResultsReactions = (await McRoll.get_message(mcSelf, pollMessageId, channelId)).reactions
|
|
||||||
for reaction in getPollResultsReactions:
|
|
||||||
async for user in reaction.users():
|
|
||||||
serverIP = reaction_to_serverip(reaction)
|
|
||||||
if not user.bot:
|
|
||||||
choices[serverIP]['votes'] = choices[serverIP]['votes'] + 1
|
|
||||||
|
|
||||||
choices[serverIP]['score'] = choices[serverIP]['votes'] * round(
|
|
||||||
2 * math.log10(choices[serverIP]['lastActivated'] + 1) + 1, 2)
|
|
||||||
prune_results(choices)
|
|
||||||
if len(choices) >= 3:
|
|
||||||
await McRoll.main_poll_recursion(mcSelf, choices, channelId)
|
|
||||||
else:
|
|
||||||
await McRoll.declare_winner(mcSelf, choices, channelId)
|
|
||||||
|
|
||||||
|
|
||||||
def reaction_to_serverip(reaction: Union[discord.Reaction, str]) -> int:
|
|
||||||
con = get_con()
|
|
||||||
reaction = str(reaction.emoji.id) \
|
|
||||||
if isinstance(reaction.emoji, discord.Emoji) else reaction.emoji.encode('unicode_escape').decode('utf-8')
|
|
||||||
|
|
||||||
with con.cursor() as cursor:
|
|
||||||
cursor.execute("SELECT serverIP FROM minecraft.server_list WHERE reaction=%s;", reaction)
|
|
||||||
serverIp = cursor.fetchone()
|
|
||||||
con.close()
|
|
||||||
return serverIp['serverIP']
|
|
||||||
|
|
||||||
|
|
||||||
def get_choices() -> dict:
|
|
||||||
con = get_con()
|
|
||||||
choices = {}
|
|
||||||
with con.cursor() as cursor:
|
|
||||||
cursor.execute("SELECT serverIP, serverName, lastActivated, reaction, getEmoji, onlyServer "
|
|
||||||
"FROM minecraft.server_list WHERE lastActivated is not null and permanent=0")
|
|
||||||
row = cursor.fetchone()
|
|
||||||
while row is not None:
|
|
||||||
row['votes'] = 0
|
|
||||||
row['score'] = 0
|
|
||||||
choices[row['serverIP']] = row
|
|
||||||
row = cursor.fetchone()
|
|
||||||
con.close()
|
|
||||||
return choices
|
|
||||||
|
|
||||||
|
|
||||||
def pop_lowest(choices: dict):
|
|
||||||
lowest = {'score': 10}
|
|
||||||
pop = False
|
|
||||||
for choice in list(choices):
|
|
||||||
if choices[choice]['score'] < lowest['score']:
|
|
||||||
lowest = choices[choice]
|
|
||||||
pop = True
|
|
||||||
if pop:
|
|
||||||
choices.pop(lowest['serverIP'])
|
|
||||||
|
|
||||||
|
|
||||||
def prune_results(choices: dict):
|
|
||||||
for serverIp, choice in list(choices.items()):
|
|
||||||
if choice['votes'] <= 0:
|
|
||||||
del choices[serverIp]
|
|
||||||
if len(choices) >= 4:
|
|
||||||
pop_lowest(choices)
|
|
||||||
pop_lowest(choices)
|
|
||||||
elif len(choices) == 3:
|
|
||||||
pop_lowest(choices)
|
|
||||||
|
|
||||||
|
|
||||||
class McRoll(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
self.embedInfo = """Each server has a multiplier based on how long it has been sense that server has been
|
|
||||||
rolled. When this poll is over all servers with 0 votes will be disregarded. If there are 4 or more servers
|
|
||||||
left the two with the lowest votes will be disregarded. Poll is rerun until there are only 2 servers,
|
|
||||||
these two are the winners. Ties reroll the poll. You can only vote for one server per poll. """
|
|
||||||
self.pollMessageId = None
|
|
||||||
global mcSelf
|
|
||||||
mcSelf = self # This is a bad way of doing things but it works
|
|
||||||
|
|
||||||
@commands.command()
|
|
||||||
async def mc_roll(self, ctx):
|
|
||||||
if ctx.message.author.id != 305589587215122432:
|
|
||||||
return
|
|
||||||
choices = get_choices()
|
|
||||||
await self.main_poll_recursion(choices, ctx.channel.id)
|
|
||||||
|
|
||||||
async def main_poll_recursion(self, choices, channelId):
|
|
||||||
self.pollMessageId = (await self.poll(choices, channelId)).id
|
|
||||||
scheduler.add_job(get_poll_results, 'date',
|
|
||||||
run_date=(datetime.now() + timedelta(seconds=6)),
|
|
||||||
args=[choices, self.pollMessageId, channelId],
|
|
||||||
coalesce=True)
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_reaction_add(self, reaction, user):
|
|
||||||
if self.pollMessageId is None:
|
|
||||||
return
|
|
||||||
reactedUsers = {}
|
|
||||||
if reaction.message.id == self.pollMessageId and user.id != 533427166193385494:
|
|
||||||
for iReaction in reaction.message.reactions:
|
|
||||||
async for iUser in iReaction.users():
|
|
||||||
if iUser.id != 533427166193385494:
|
|
||||||
if iUser.id not in reactedUsers:
|
|
||||||
reactedUsers[iUser.id] = False
|
|
||||||
if reactedUsers[iUser.id]:
|
|
||||||
await reaction.remove(user)
|
|
||||||
self.pollMessageId = reaction.message.id
|
|
||||||
await user.send(
|
|
||||||
"You can only vote for one option, please remove your previous vote to change it.")
|
|
||||||
return
|
|
||||||
self.pollMessageId = reaction.message.id
|
|
||||||
reactedUsers[iUser.id] = True
|
|
||||||
|
|
||||||
async def poll(self, choices: dict, channel: int) -> discord.Message:
|
|
||||||
channel = await self.client.fetch_channel(channel)
|
|
||||||
embed = discord.Embed(title="Poll", description=self.embedInfo,
|
|
||||||
timestamp=(datetime.utcnow() + timedelta(days=1)))
|
|
||||||
for choice in choices.values():
|
|
||||||
embed.add_field(
|
|
||||||
name=(choice['serverName'] + ' ' +
|
|
||||||
(str(self.client.get_emoji(int(choice['reaction'])))
|
|
||||||
if choice['getEmoji']
|
|
||||||
else bytes(choice['reaction'], "utf-8").decode("unicode_escape"))),
|
|
||||||
value=("Multiplier : " + str(round(2 * math.log10(choice['lastActivated'] + 1) + 1, 2)) +
|
|
||||||
'\n' + "Last Rolled : " + str(choice['lastActivated'] * 2) + " weeks ago." +
|
|
||||||
("\nThis is an only server, meaning if it wins it will be the only winner" if choice['onlyServer']
|
|
||||||
else " ")))
|
|
||||||
|
|
||||||
pollMessage = await channel.send(embed=embed)
|
|
||||||
await channel.send('@everyone')
|
|
||||||
|
|
||||||
for choice in choices.values():
|
|
||||||
await pollMessage.add_reaction(self.client.get_emoji(int(choice['reaction']))
|
|
||||||
if choice['getEmoji']
|
|
||||||
else bytes(choice['reaction'], "utf-8").decode("unicode_escape"))
|
|
||||||
return pollMessage
|
|
||||||
|
|
||||||
async def declare_winner(self, choices, channelId):
|
|
||||||
embed = discord.Embed(title="Winner", description="Congratulations")
|
|
||||||
for item in list(choices):
|
|
||||||
winner = choices[item]
|
|
||||||
embed.add_field(
|
|
||||||
name=winner['serverName'],
|
|
||||||
value="Multiplier : " + str(round(2 * math.log10(winner['lastActivated'] + 1) + 1, 2)) + '\n' +
|
|
||||||
"Last Rolled : " + str(winner['lastActivated'] * 2) + " weeks ago." + '\n' +
|
|
||||||
"Votes : " + str(winner['votes']) + '\n' +
|
|
||||||
"Calculated Votes: " + str(
|
|
||||||
winner['votes'] * round(2 * math.log10(winner['lastActivated'] + 1) + 1, 2))
|
|
||||||
)
|
|
||||||
channel = await self.client.fetch_channel(channelId)
|
|
||||||
await channel.send(embed=embed)
|
|
||||||
await channel.send("@everyone")
|
|
||||||
|
|
||||||
async def get_message(self, messageId, channelId):
|
|
||||||
channel = await self.client.fetch_channel(channelId)
|
|
||||||
return await channel.fetch_message(messageId)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(McRoll(client))
|
|
@ -1,23 +0,0 @@
|
|||||||
import re
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
|
|
||||||
class ParseForIssues(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_message(self, message):
|
|
||||||
if message.author.id == 533427166193385494:
|
|
||||||
return
|
|
||||||
content = message.content.lower()
|
|
||||||
matches = re.findall("ttg-[0-9]+", content)
|
|
||||||
for match in matches:
|
|
||||||
await message.channel.send("https://youtrack.themissingcrowbar.com:8942/issue/"+match)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(ParseForIssues(client))
|
|
@ -1,38 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import time
|
|
||||||
import logging
|
|
||||||
from datetime import datetime, timedelta, date
|
|
||||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
|
||||||
from apscheduler.schedulers.blocking import BlockingScheduler
|
|
||||||
|
|
||||||
scheduler = AsyncIOScheduler({
|
|
||||||
'apscheduler.jobstores.default': {
|
|
||||||
'type': 'sqlalchemy',
|
|
||||||
'url': f'mysql+pymysql://Quentin:kaPl0wskii@192.168.1.52:5618/discord_bot?charset=utf8mb4'
|
|
||||||
},
|
|
||||||
'apscheduler.executors.default': {
|
|
||||||
'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
|
|
||||||
'max_workers': '20'
|
|
||||||
},
|
|
||||||
'apscheduler.executors.processpool': {
|
|
||||||
'type': 'processpool',
|
|
||||||
'max_workers': '5'
|
|
||||||
},
|
|
||||||
'apscheduler.job_defaults.coalesce': 'true',
|
|
||||||
'apscheduler.job_defaults.max_instances': '3',
|
|
||||||
'apscheduler.timezone': 'America/Chicago',
|
|
||||||
})
|
|
||||||
|
|
||||||
scheduler.start()
|
|
||||||
|
|
||||||
async def hello():
|
|
||||||
print("hello world")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
# scheduler.add_job(hello, 'date', run_date=datetime.now()+timedelta(seconds=20))
|
|
||||||
|
|
||||||
try:
|
|
||||||
asyncio.get_event_loop().run_forever()
|
|
||||||
except (KeyboardInterrupt, SystemExit):
|
|
||||||
pass
|
|
@ -1,36 +0,0 @@
|
|||||||
import random
|
|
||||||
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
content = [", was just chosen to be the one.",
|
|
||||||
", has joined!",
|
|
||||||
", looks like someone took the slow train from Philly.",
|
|
||||||
", just bought the house!",
|
|
||||||
", has a new home.",
|
|
||||||
", if in ten years i haven't had a baby and you haven't had a baby?",
|
|
||||||
" is hear to play minecraft and get killed by my sword!",
|
|
||||||
", is most definitely a furry.",
|
|
||||||
", did you bring your sword?",
|
|
||||||
", welcome!"]
|
|
||||||
|
|
||||||
|
|
||||||
class Join(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_member_join(self, member):
|
|
||||||
if member.guild.id == 605932352736067585:
|
|
||||||
if member.id == 234703033924059138:
|
|
||||||
await self.client.get_channel(605932352736067589).send(
|
|
||||||
member.mention +
|
|
||||||
", is most definitely both a furry and a weeb. We should all bully him because he stinks."
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
await self.client.get_channel(605932352736067589).send(member.mention +
|
|
||||||
random.choice(content) + "[Join]")
|
|
||||||
await member.add_roles(self.client.get_guild(605932352736067585).get_role(605934866676056070))
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(Join(client))
|
|
@ -1,26 +0,0 @@
|
|||||||
import random
|
|
||||||
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
content = [" just bit the dust.",
|
|
||||||
" gave up on life.",
|
|
||||||
" couldn't take the heat anymore.",
|
|
||||||
" boarded the train.",
|
|
||||||
" was pricked to death.",
|
|
||||||
" just left.",
|
|
||||||
" ragequit.",
|
|
||||||
" doesn't like me anymore"]
|
|
||||||
|
|
||||||
|
|
||||||
class Join(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_member_remove(self, member):
|
|
||||||
if member.guild.id == 605932352736067585:
|
|
||||||
await self.client.get_channel(605932352736067589).send(member.mention + random.choice(content) + "[Leave")
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(Join(client))
|
|
@ -1,31 +0,0 @@
|
|||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
|
|
||||||
class Spam(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.Cog.listener()
|
|
||||||
async def on_message(self, message):
|
|
||||||
dump = []
|
|
||||||
print(len(dump))
|
|
||||||
print((dump[len(dump)-1].created_at - dump[1].created_at).total_seconds())
|
|
||||||
async for temp in message.channel.history(limit=5):
|
|
||||||
if temp.author == message.author:
|
|
||||||
dump.append(temp)
|
|
||||||
if (dump[len(dump)-1].created_at - dump[1].created_at).total_seconds() <= 2:
|
|
||||||
await message.delete()
|
|
||||||
await self.client.process_commands(message)
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(Spam(client))
|
|
||||||
|
|
||||||
|
|
||||||
""" async for tempMessage in message.channel.history(limit=5):
|
|
||||||
if tempMessage.id == message.id:
|
|
||||||
pass
|
|
||||||
elif tempMessage.author == message.author:
|
|
||||||
difference = message.created_at - tempMessage.created_at
|
|
||||||
if difference.total_seconds() <= 2:
|
|
||||||
await message.delete()"""
|
|
@ -1,20 +0,0 @@
|
|||||||
import asyncio
|
|
||||||
import math
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
|
|
||||||
import discord
|
|
||||||
import pymysql
|
|
||||||
from discord.ext import commands
|
|
||||||
|
|
||||||
|
|
||||||
class doym(commands.Cog):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@commands.command()
|
|
||||||
async def doymCMD(self, ctx):
|
|
||||||
await ctx.channel.send("https://www.youtube.com/watch?v=5t53TcKIlMc")
|
|
||||||
|
|
||||||
|
|
||||||
def setup(client):
|
|
||||||
client.add_cog(doym(client))
|
|
100
scr/config.py
Normal file
100
scr/config.py
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class MysqlSettings:
|
||||||
|
user: str
|
||||||
|
password: str
|
||||||
|
host: str
|
||||||
|
port: int
|
||||||
|
db: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class BotSettings:
|
||||||
|
token: str
|
||||||
|
guildId: int
|
||||||
|
prefix: str
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class RoleSettings:
|
||||||
|
member: str
|
||||||
|
|
||||||
|
roles: BotSettings.RoleSettings
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class ChannelSettings:
|
||||||
|
joinLog: int
|
||||||
|
leaveLog: int
|
||||||
|
|
||||||
|
channels: BotSettings.ChannelSettings
|
||||||
|
|
||||||
|
class CommandSettings:
|
||||||
|
def load(self, data):
|
||||||
|
pass
|
||||||
|
|
||||||
|
commands: dict[str, CommandSettings]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class YoutrackSettings:
|
||||||
|
url: str
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
def __init__(self, configFile: str = "./settings.json"):
|
||||||
|
self.configFile = configFile
|
||||||
|
|
||||||
|
with open(self.configFile, 'r') as file:
|
||||||
|
self.configData = json.loads(file.read())
|
||||||
|
|
||||||
|
self.__load_mysql()
|
||||||
|
self.__load_bot()
|
||||||
|
self.__load_youtrack()
|
||||||
|
|
||||||
|
def register_command_settings(self, settingJson: str):
|
||||||
|
def decorator(cls: type[BotSettings.CommandSettings]):
|
||||||
|
currentSettings = self.BOT.commands.get(settingJson)
|
||||||
|
if currentSettings is not None:
|
||||||
|
raise Exception(f"Setting {settingJson} already loaded.")
|
||||||
|
instance = cls()
|
||||||
|
instance.load(self.commandData[settingJson])
|
||||||
|
self.BOT.commands[settingJson] = instance
|
||||||
|
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
def __load_mysql(self):
|
||||||
|
mysqlData = self.configData["mysql"]
|
||||||
|
self.MYSQL = MysqlSettings(
|
||||||
|
user=mysqlData["user"],
|
||||||
|
password=mysqlData["password"],
|
||||||
|
host=mysqlData["host"],
|
||||||
|
port=mysqlData["port"],
|
||||||
|
db=mysqlData["db"]
|
||||||
|
)
|
||||||
|
|
||||||
|
def __load_bot(self):
|
||||||
|
botData = self.configData["bot"]
|
||||||
|
self.BOT = BotSettings(
|
||||||
|
token=botData["token"],
|
||||||
|
guildId=botData["guild"],
|
||||||
|
prefix=botData["prefix"],
|
||||||
|
roles=BotSettings.RoleSettings(
|
||||||
|
member=botData["roles"]["member"]
|
||||||
|
),
|
||||||
|
channels=BotSettings.ChannelSettings(
|
||||||
|
joinLog=botData["channels"]["joinLog"],
|
||||||
|
leaveLog=botData["channels"]["leaveLog"]
|
||||||
|
),
|
||||||
|
commands={}
|
||||||
|
)
|
||||||
|
self.commandData = botData["commands"]
|
||||||
|
|
||||||
|
def __load_youtrack(self):
|
||||||
|
youtrackData = self.configData["youtrack"]
|
||||||
|
self.YOUTRACK = YoutrackSettings(
|
||||||
|
url=youtrackData["url"]
|
||||||
|
)
|
15
scr/main.py
Normal file
15
scr/main.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
from config import Config
|
||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
config = Config()
|
||||||
|
bot = MyBot(config=config)
|
||||||
|
|
||||||
|
|
||||||
|
@bot.event
|
||||||
|
async def on_ready():
|
||||||
|
print(f'Bot started as {bot.user}')
|
||||||
|
|
||||||
|
modules = ["modules.youtrackIntegration",
|
||||||
|
"modules.TMC"]
|
||||||
|
for module in modules:
|
||||||
|
await bot.load_extension(module)
|
9
scr/modules/TMC/__init__.py
Normal file
9
scr/modules/TMC/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
cogs = [".autoReply",
|
||||||
|
".commands"]
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
for cog in cogs:
|
||||||
|
await bot.load_extension(cog, package="modules.TMC")
|
9
scr/modules/TMC/autoReply/__init__.py
Normal file
9
scr/modules/TMC/autoReply/__init__.py
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
cogs = [".join",
|
||||||
|
".leave"]
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
for cog in cogs:
|
||||||
|
await bot.load_extension(cog, package=__package__)
|
37
scr/modules/TMC/autoReply/join.py
Normal file
37
scr/modules/TMC/autoReply/join.py
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
content = [", was just chosen to be the one.",
|
||||||
|
", has joined!",
|
||||||
|
", looks like someone took the slow train from Philly.",
|
||||||
|
", just bought the house!",
|
||||||
|
", has a new home.",
|
||||||
|
", if in ten years I haven't had a baby and you haven't had a baby?",
|
||||||
|
" is hear to play minecraft and get killed by my sword!",
|
||||||
|
", is most definitely a furry.",
|
||||||
|
", did you bring your sword?",
|
||||||
|
", welcome!",
|
||||||
|
", two trucks?",
|
||||||
|
", *Who needs atom clamps! I have a funny robot!!",
|
||||||
|
" DO NOT POST FNF MUCKBANG.",
|
||||||
|
" just joined, hmm. *sniffs*. Eww.",
|
||||||
|
", hold by pee, I've gotta beer."]
|
||||||
|
|
||||||
|
|
||||||
|
class Join(commands.Cog):
|
||||||
|
def __init__(self, bot: MyBot):
|
||||||
|
self.client = bot
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_member_join(self, member):
|
||||||
|
if member.guild.id == 605932352736067585:
|
||||||
|
await self.client.get_channel(605932352736067589).send("[Join] " + member.mention +
|
||||||
|
random.choice(content))
|
||||||
|
await member.add_roles(self.client.get_guild(605932352736067585).get_role(605934866676056070))
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
await bot.add_cog(Join(bot))
|
36
scr/modules/TMC/autoReply/leave.py
Normal file
36
scr/modules/TMC/autoReply/leave.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import random
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
content = [" just bit the dust.",
|
||||||
|
" gave up on life.",
|
||||||
|
" couldn't take the heat anymore.",
|
||||||
|
" boarded the train.",
|
||||||
|
" was pricked to death.",
|
||||||
|
" just left.",
|
||||||
|
" ragequit.",
|
||||||
|
" doesn't like me anymore.",
|
||||||
|
" chickened out.",
|
||||||
|
", you're*",
|
||||||
|
" held the pee.",
|
||||||
|
", Shit & Pants ~Jack Black",
|
||||||
|
" rolled off with the root beer.",
|
||||||
|
" doesn't feel like it anymore.",
|
||||||
|
" didn't install the microwave ovens.",
|
||||||
|
" was slower than an i7 Q 740m @ 1.73GHz!"]
|
||||||
|
|
||||||
|
|
||||||
|
class Leave(commands.Cog):
|
||||||
|
def __init__(self, bot: MyBot):
|
||||||
|
self.client = bot
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_member_remove(self, member):
|
||||||
|
if member.guild.id == 605932352736067585:
|
||||||
|
await self.client.get_channel(605932352736067589).send("[Leave] " + member.mention + random.choice(content))
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(myBot: MyBot):
|
||||||
|
await myBot.add_cog(Leave(myBot))
|
8
scr/modules/TMC/commands/__init__.py
Normal file
8
scr/modules/TMC/commands/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
cogs = [".mcRoll"]
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
for cog in cogs:
|
||||||
|
await bot.load_extension(cog, package=__package__)
|
226
scr/modules/TMC/commands/mcRoll.py
Normal file
226
scr/modules/TMC/commands/mcRoll.py
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
import math
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from datetime import datetime, timedelta, timezone, date
|
||||||
|
|
||||||
|
import discord
|
||||||
|
import pymysql
|
||||||
|
import pymysql.cursors
|
||||||
|
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||||
|
from discord.ext import commands
|
||||||
|
from discord.ext.commands import Context
|
||||||
|
from tzlocal import get_localzone_name
|
||||||
|
|
||||||
|
from config import BotSettings
|
||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class PollChoice:
|
||||||
|
lastActivated: date
|
||||||
|
votes: int
|
||||||
|
score: float
|
||||||
|
reaction: str
|
||||||
|
serverName: str
|
||||||
|
getEmoji: int
|
||||||
|
|
||||||
|
bot_instance_registry = {}
|
||||||
|
|
||||||
|
async def poll_result_dispatcher(class_name, instance_id, *args):
|
||||||
|
instance = bot_instance_registry.get((class_name, instance_id))
|
||||||
|
if instance:
|
||||||
|
await instance.get_poll_results(*args)
|
||||||
|
else:
|
||||||
|
print(f"No instance found for {class_name}:{instance_id}")
|
||||||
|
|
||||||
|
|
||||||
|
def get_multiplier(choice: PollChoice):
|
||||||
|
activatedNWeeksAgo = (datetime.now().date() - choice.lastActivated).days / 7
|
||||||
|
return round(1.7 * math.log10(activatedNWeeksAgo + 1) + 1, 2)
|
||||||
|
|
||||||
|
|
||||||
|
def pop_lowest(choices: dict[int, PollChoice]):
|
||||||
|
if not choices:
|
||||||
|
return
|
||||||
|
|
||||||
|
pop = min(choices.items(), key=lambda item: item[1].score)[0]
|
||||||
|
del choices[pop]
|
||||||
|
|
||||||
|
|
||||||
|
def find_choice_by_reaction(choices: dict[int, PollChoice], reaction: discord.Reaction) -> PollChoice | None:
|
||||||
|
for choice in choices.values():
|
||||||
|
if choice.reaction == str(reaction):
|
||||||
|
return choice
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class McRoll(commands.Cog):
|
||||||
|
def __init__(self, bot: MyBot):
|
||||||
|
self.bot = bot
|
||||||
|
self.embedInfo = (f"Each server has a multiplier based on how long it has been sense that server has been rolled. "
|
||||||
|
f"When this poll is over all servers with 0 votes will be disregarded. "
|
||||||
|
f"1/3rd of the servers with the lowest votes will be disregarded. "
|
||||||
|
f"If there are 4 or more servers Poll is rerun until there are only {self.bot.config.BOT.commands["mc_roll"].pollRuntimeHours} servers, "
|
||||||
|
f"these are the winners. Ties reroll the poll. You can only vote for one server per poll. ")
|
||||||
|
self.pollMessageId = None
|
||||||
|
bot_instance_registry[('McRoll', id)] = self
|
||||||
|
|
||||||
|
mysqlConf = self.bot.config.MYSQL
|
||||||
|
self.scheduler = AsyncIOScheduler({
|
||||||
|
'apscheduler.jobstores.default': {
|
||||||
|
'type': 'sqlalchemy',
|
||||||
|
'url': f'mysql+pymysql://{mysqlConf.user}:{mysqlConf.password}@{mysqlConf.host}:{mysqlConf.port}/{mysqlConf.db}?charset=utf8mb4',
|
||||||
|
},
|
||||||
|
'apscheduler.job_defaults.coalesce': 'True',
|
||||||
|
'apscheduler.timezone': get_localzone_name()
|
||||||
|
})
|
||||||
|
|
||||||
|
self.scheduler.start()
|
||||||
|
|
||||||
|
def prune_results(self, choices: dict[int, PollChoice]):
|
||||||
|
for key, choice in list(choices.items()):
|
||||||
|
if choice.votes <= 0:
|
||||||
|
del choices[key]
|
||||||
|
amountToPop = round(len(choices) * .33)
|
||||||
|
if (len(choices) - amountToPop) <= self.bot.config.BOT.commands["mc_roll"].runningServers:
|
||||||
|
for i in range(len(choices) - self.bot.config.BOT.commands["mc_roll"].runningServers):
|
||||||
|
pop_lowest(choices)
|
||||||
|
return
|
||||||
|
for i in range(amountToPop):
|
||||||
|
pop_lowest(choices)
|
||||||
|
|
||||||
|
def get_con(self) -> pymysql.Connection:
|
||||||
|
mysqlConf = self.bot.config.MYSQL
|
||||||
|
return pymysql.connect(host=mysqlConf.host,
|
||||||
|
port=mysqlConf.port,
|
||||||
|
user=mysqlConf.user,
|
||||||
|
password=mysqlConf.password,
|
||||||
|
db=mysqlConf.db,
|
||||||
|
charset='utf8mb4',
|
||||||
|
cursorclass=pymysql.cursors.DictCursor)
|
||||||
|
|
||||||
|
async def get_poll_results(self, choices: dict[int, PollChoice], pollMessageId: int, channelId: int):
|
||||||
|
reactions = (await self.get_message(pollMessageId, channelId)).reactions
|
||||||
|
for reaction in reactions:
|
||||||
|
async for user in reaction.users():
|
||||||
|
choice = find_choice_by_reaction(choices, reaction)
|
||||||
|
if choice is None:
|
||||||
|
continue
|
||||||
|
if not user.bot:
|
||||||
|
choice.votes = choice.votes + 1
|
||||||
|
|
||||||
|
choice.score = choice.votes * get_multiplier(choice)
|
||||||
|
self.prune_results(choices)
|
||||||
|
if len(choices) > self.bot.config.BOT.commands["mc_roll"].runningServers:
|
||||||
|
await self.main_poll_recursion(choices, channelId)
|
||||||
|
else:
|
||||||
|
await self.declare_winner(choices, channelId)
|
||||||
|
|
||||||
|
def get_choices(self) -> dict[int, PollChoice]:
|
||||||
|
with self.get_con() as con:
|
||||||
|
choices: dict[int, PollChoice] = {}
|
||||||
|
with con.cursor() as cursor:
|
||||||
|
cursor.execute("SELECT id, serverName, lastActivated, reaction, getEmoji FROM server_list WHERE disabled=false")
|
||||||
|
records = cursor.fetchall()
|
||||||
|
for row in records:
|
||||||
|
choice = PollChoice(
|
||||||
|
lastActivated=datetime.now().date() if row["lastActivated"] is None else row["lastActivated"],
|
||||||
|
votes=0,
|
||||||
|
score=0,
|
||||||
|
reaction=row["reaction"],
|
||||||
|
serverName=row["serverName"],
|
||||||
|
getEmoji=row["getEmoji"]
|
||||||
|
)
|
||||||
|
choices[row["id"]] = choice
|
||||||
|
return choices
|
||||||
|
|
||||||
|
@commands.command()
|
||||||
|
async def mc_roll(self, ctx: Context):
|
||||||
|
if not ctx.author.guild_permissions.administrator:
|
||||||
|
return
|
||||||
|
choices = self.get_choices()
|
||||||
|
await self.main_poll_recursion(choices, ctx.channel.id)
|
||||||
|
|
||||||
|
async def main_poll_recursion(self, choices, channelId):
|
||||||
|
self.pollMessageId = (await self.poll(choices, channelId)).id
|
||||||
|
self.scheduler.add_job(poll_result_dispatcher, 'date',
|
||||||
|
run_date=(datetime.now() + timedelta(self.bot.config.BOT.commands["mc_roll"].pollRuntimeHours)),
|
||||||
|
args=['McRoll', id, choices, self.pollMessageId, channelId],
|
||||||
|
coalesce=True)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_reaction_add(self, reaction, user):
|
||||||
|
if self.pollMessageId is None:
|
||||||
|
return
|
||||||
|
reactedUsers = {}
|
||||||
|
if reaction.message.id == self.pollMessageId and user.id != self.bot.user.id:
|
||||||
|
for iReaction in reaction.message.reactions:
|
||||||
|
async for iUser in iReaction.users():
|
||||||
|
if iUser.id != self.bot.user.id:
|
||||||
|
if iUser.id not in reactedUsers:
|
||||||
|
reactedUsers[iUser.id] = False
|
||||||
|
if reactedUsers[iUser.id]:
|
||||||
|
await reaction.remove(user)
|
||||||
|
self.pollMessageId = reaction.message.id
|
||||||
|
await user.send(
|
||||||
|
"You can only vote for one option, please remove your previous vote to change it.")
|
||||||
|
return
|
||||||
|
self.pollMessageId = reaction.message.id
|
||||||
|
reactedUsers[iUser.id] = True
|
||||||
|
|
||||||
|
async def poll(self, choices: dict[int, PollChoice], channel: int) -> discord.Message:
|
||||||
|
channel = await self.bot.fetch_channel(channel)
|
||||||
|
embed = discord.Embed(title="Poll", description=self.embedInfo,
|
||||||
|
timestamp=(datetime.now(timezone.utc) + timedelta(days=1)))
|
||||||
|
for choice in choices.values():
|
||||||
|
embed.add_field(
|
||||||
|
name=(choice.serverName + ' ' +
|
||||||
|
(str(self.bot.get_emoji(int(choice.reaction)))
|
||||||
|
if choice.getEmoji
|
||||||
|
else choice.reaction)),
|
||||||
|
value=("Multiplier : " + str(get_multiplier(choice)) +
|
||||||
|
'\n' + "Last Rolled : " + str(
|
||||||
|
round((datetime.now().date() - choice.lastActivated).days)) + " days ago."))
|
||||||
|
|
||||||
|
pollMessage = await channel.send(embed=embed)
|
||||||
|
await channel.send('@everyone')
|
||||||
|
|
||||||
|
for choice in choices.values():
|
||||||
|
await pollMessage.add_reaction(self.bot.get_emoji(int(choice.reaction))
|
||||||
|
if choice.getEmoji
|
||||||
|
else choice.reaction)
|
||||||
|
return pollMessage
|
||||||
|
|
||||||
|
async def declare_winner(self, choices: dict[int, PollChoice], channelId):
|
||||||
|
embed = discord.Embed(title="Winner", description="Congratulations")
|
||||||
|
for choice in choices.values():
|
||||||
|
embed.add_field(
|
||||||
|
name=choice.serverName,
|
||||||
|
value=("Multiplier : " + str(get_multiplier(choice)) + '\n' +
|
||||||
|
"Last Rolled : " + str(
|
||||||
|
round((datetime.now().date() - choice.lastActivated).days)) + " days ago." + '\n' +
|
||||||
|
"Votes : " + str(choice.votes) + '\n' +
|
||||||
|
"Calculated Votes: " + str(choice.score))
|
||||||
|
)
|
||||||
|
channel = await self.bot.fetch_channel(channelId)
|
||||||
|
await channel.send(embed=embed)
|
||||||
|
await channel.send("@everyone")
|
||||||
|
|
||||||
|
async def get_message(self, messageId, channelId):
|
||||||
|
channel = await self.bot.fetch_channel(channelId)
|
||||||
|
return await channel.fetch_message(messageId)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
@bot.config.register_command_settings("mc_roll")
|
||||||
|
class McRollSettings(BotSettings.CommandSettings):
|
||||||
|
def __init__(self):
|
||||||
|
self.runningServers: int = -1
|
||||||
|
self.pollRuntimeHours: int = -1
|
||||||
|
|
||||||
|
def load(self, data):
|
||||||
|
self.runningServers = data["runningServers"]
|
||||||
|
self.pollRuntimeHours = data["pollRuntimeHours"]
|
||||||
|
|
||||||
|
await bot.add_cog(McRoll(bot))
|
8
scr/modules/youtrackIntegration/__init__.py
Normal file
8
scr/modules/youtrackIntegration/__init__.py
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
from myBot import MyBot
|
||||||
|
|
||||||
|
cogs = [".parseForIssues"]
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
for cog in cogs:
|
||||||
|
await bot.load_extension(cog, package=__package__)
|
15
scr/modules/youtrackIntegration/api.py
Normal file
15
scr/modules/youtrackIntegration/api.py
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from config import YoutrackSettings
|
||||||
|
|
||||||
|
|
||||||
|
class Api:
|
||||||
|
def __init__(self, settings: YoutrackSettings):
|
||||||
|
self.URL = settings.url
|
||||||
|
|
||||||
|
def get_projects(self):
|
||||||
|
r = requests.get(self.URL + "api/admin/projects?fields=id,shortName")
|
||||||
|
data = json.loads(r.content)
|
||||||
|
return data
|
32
scr/modules/youtrackIntegration/parseForIssues.py
Normal file
32
scr/modules/youtrackIntegration/parseForIssues.py
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
import re
|
||||||
|
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from myBot import MyBot
|
||||||
|
from .api import Api
|
||||||
|
|
||||||
|
|
||||||
|
class ParseForIssues(commands.Cog):
|
||||||
|
def __init__(self, bot: MyBot):
|
||||||
|
self.bot = bot
|
||||||
|
self.shortProjectNames = None
|
||||||
|
self.api = Api(bot.config.YOUTRACK)
|
||||||
|
|
||||||
|
@commands.Cog.listener()
|
||||||
|
async def on_message(self, message):
|
||||||
|
if message.author.id == self.bot.user.id:
|
||||||
|
return
|
||||||
|
content = message.content.lower()
|
||||||
|
if self.shortProjectNames is None:
|
||||||
|
projects = self.api.get_projects()
|
||||||
|
self.shortProjectNames = []
|
||||||
|
for project in projects:
|
||||||
|
self.shortProjectNames.append(project["shortName"].lower())
|
||||||
|
|
||||||
|
matches = re.findall(rf"(?:{'|'.join(map(re.escape, self.shortProjectNames))})-[0-9]+", content)
|
||||||
|
for match in matches:
|
||||||
|
await message.channel.send(self.api.URL + "/issue/" + match)
|
||||||
|
|
||||||
|
|
||||||
|
async def setup(bot: MyBot):
|
||||||
|
await bot.add_cog(ParseForIssues(bot))
|
29
scr/myBot.py
Normal file
29
scr/myBot.py
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import discord
|
||||||
|
from discord.ext import commands
|
||||||
|
|
||||||
|
from config import Config
|
||||||
|
|
||||||
|
|
||||||
|
class MyBot(commands.Bot):
|
||||||
|
def __init__(self, config: Config):
|
||||||
|
intents = discord.Intents.default()
|
||||||
|
intents.message_content = True
|
||||||
|
intents.members = True
|
||||||
|
|
||||||
|
super().__init__(command_prefix=config.BOT.prefix, intents=intents)
|
||||||
|
self.config: Config = config
|
||||||
|
|
||||||
|
super().run(self.config.BOT.token)
|
||||||
|
|
||||||
|
async def setup_hook(self) -> None:
|
||||||
|
modules = [
|
||||||
|
"modules.youtrackIntegration",
|
||||||
|
"modules.TMC"
|
||||||
|
]
|
||||||
|
for module in modules:
|
||||||
|
await self.load_extension(module)
|
||||||
|
|
||||||
|
return await super().setup_hook()
|
||||||
|
|
||||||
|
async def on_ready(self):
|
||||||
|
print(f'Bot started as {self.user}')
|
Loading…
x
Reference in New Issue
Block a user