Compare commits
30 commits
master
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
![]() |
53414148a2 | ||
![]() |
6b0c044c40 | ||
![]() |
444957dddf | ||
![]() |
526d9d72ef | ||
![]() |
5c4c6631ba | ||
![]() |
03fc4cadff | ||
![]() |
a4aaa134bb | ||
![]() |
e12609a6be | ||
![]() |
a7a92f5b51 | ||
![]() |
a3e318d4e5 | ||
![]() |
bd8cfa44d4 | ||
![]() |
b9b2b5c8b8 | ||
![]() |
6cfa3c5210 | ||
![]() |
8a4ef6947a | ||
![]() |
83b59c0fbc | ||
![]() |
8f70e65b92 | ||
![]() |
72f6bb2fd3 | ||
![]() |
956d5eef3f | ||
![]() |
584d1e1914 | ||
![]() |
01d75cf600 | ||
![]() |
0ee1c17a07 | ||
![]() |
f786f29141 | ||
![]() |
08cc01ca70 | ||
![]() |
28ccb8b10f | ||
![]() |
81c299dffb | ||
![]() |
75d5a3c664 | ||
![]() |
5a440d91ab | ||
![]() |
3724ff485e | ||
![]() |
b23fa1aa60 | ||
![]() |
937dd76fe7 |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
|||
*.json
|
||||
*.txt
|
||||
*.png
|
||||
__pycache__
|
81
api/carbon.py
Normal file
81
api/carbon.py
Normal file
|
@ -0,0 +1,81 @@
|
|||
import requests
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
import datetime
|
||||
from util import logging
|
||||
|
||||
def current_level() -> []:
|
||||
url = "https://api.carbonintensity.org.uk/intensity"
|
||||
response = requests.get(url)
|
||||
|
||||
if not response.ok:
|
||||
logging.error(f"Failed to access Carbon API: {response.status_code} [{url}]")
|
||||
|
||||
data = response.json()["data"][0]
|
||||
return [data["from"], data["intensity"]["forecast"], data["intensity"]["actual"], data["intensity"]["index"]]
|
||||
|
||||
def level_at(date: str) -> []:
|
||||
url = f"https://api.carbonintensity.org.uk/intensity/date/{date}"
|
||||
response = requests.get(url)
|
||||
|
||||
if not response.ok:
|
||||
logging.error(f"Failed to access Carbon API: {response.status_code} [{url}]")
|
||||
return []
|
||||
|
||||
if len(response.json()["data"]) == 0:
|
||||
return []
|
||||
|
||||
data = response.json()["data"][0]
|
||||
return [data["from"], data["intensity"]["forecast"], data["intensity"]["actual"], data["intensity"]["index"]]
|
||||
|
||||
def level_from_to(start: str, stop: str) -> str:
|
||||
url = f"https://api.carbonintensity.org.uk/intensity/{start}/{stop}"
|
||||
response = requests.get(url)
|
||||
|
||||
if not response.ok:
|
||||
logging.error(f"Failed to access Carbon API: {response.status_code} [{url}]")
|
||||
return ""
|
||||
|
||||
if len(response.json()["data"]) == 0:
|
||||
return []
|
||||
|
||||
data = response.json()["data"]
|
||||
|
||||
x = []
|
||||
measured = []
|
||||
indices = []
|
||||
|
||||
for i in range(len(data)):
|
||||
intensity = data[i]["intensity"]
|
||||
x.append(datetime.datetime.strptime(data[i]["from"], "%Y-%m-%dT%H:%MZ"))
|
||||
measured.append(intensity["actual"])
|
||||
indices.append(intensity["index"])
|
||||
|
||||
curr_color = indices[0]
|
||||
curr_color_index = 0
|
||||
for i in range(len(measured)):
|
||||
if indices[i] != curr_color:
|
||||
color = ""
|
||||
if curr_color == "very low":
|
||||
color = "#5bcc32"
|
||||
if curr_color == "low":
|
||||
color = "#87cc32"
|
||||
if curr_color == "moderate":
|
||||
color = "#ccc932"
|
||||
if curr_color == "high":
|
||||
color = "#cc8e32"
|
||||
if curr_color == "very high":
|
||||
color = "#cc4f32"
|
||||
|
||||
plt.plot(x[curr_color_index:i+1], measured[curr_color_index:i+1], color)
|
||||
curr_color_index = i
|
||||
curr_color = indices[i]
|
||||
|
||||
plt.xlabel("Time & Date")
|
||||
plt.ylabel("Carbon Intensity [gCO2/kWh]")
|
||||
plt.xticks(rotation=45)
|
||||
plt.gcf().subplots_adjust(bottom=0.2)
|
||||
plt.grid(b=True)
|
||||
plt.savefig("plot.png")
|
||||
plt.clf()
|
||||
return "plot.png"
|
14
api/quote.py
Normal file
14
api/quote.py
Normal file
|
@ -0,0 +1,14 @@
|
|||
import requests
|
||||
import random
|
||||
from util import logging
|
||||
|
||||
def fetch_quote() -> tuple:
|
||||
url = "https://favqs.com/api/qotd"
|
||||
response = requests.get(url)
|
||||
|
||||
if not response.ok:
|
||||
logging.error(f"Failed to access Quotes API: {response.status_code} [{url}]")
|
||||
return ()
|
||||
|
||||
data = response.json()
|
||||
return (data["quote"]["body"], data["quote"]["author"])
|
72
api/thesaurus.py
Normal file
72
api/thesaurus.py
Normal file
|
@ -0,0 +1,72 @@
|
|||
import requests
|
||||
import re, random
|
||||
import nltk
|
||||
import threading, queue
|
||||
from util import logging, config
|
||||
|
||||
key = config.settings["api_keys"]["thesaurus"]
|
||||
url = f"http://thesaurus.altervista.org/thesaurus/v1?key={key}&language=en_US&output=json&word="
|
||||
|
||||
def start_thread(target, args):
|
||||
q = queue.Queue()
|
||||
def wrapper():
|
||||
q.put(target(args))
|
||||
t = threading.Thread(target=wrapper)
|
||||
t.start()
|
||||
return q
|
||||
|
||||
def thesaurufy_sentence(sentence):
|
||||
symbols = nltk.word_tokenize(sentence)
|
||||
tags = nltk.pos_tag(symbols)
|
||||
|
||||
if len(symbols) == 0:
|
||||
return ""
|
||||
|
||||
queues = []
|
||||
for i in range(0, len(symbols)):
|
||||
queues.append(start_thread(target = handle_token, args=(tags[i])))
|
||||
|
||||
for i in range(0, len(symbols)):
|
||||
symbols[i] = queues[i].get()
|
||||
|
||||
return "".join(symbols)
|
||||
|
||||
def handle_token(args):
|
||||
token = args
|
||||
if not token[0].isalpha():
|
||||
return token[0]
|
||||
|
||||
if token[1] != "NN" and token[1] != "VB" and token[1] != "VBG" and token[1] != "VBP" and token[1] != "JJ" and token[1] != "RB":
|
||||
return (" " + token[0])
|
||||
|
||||
response = requests.get(url + token[0])
|
||||
if not response.ok:
|
||||
# logging.warning(f"Thesaurus API returned {response.status_code} ({url + token[0]})")
|
||||
return (" " + token[0])
|
||||
|
||||
responses = response.json()["response"]
|
||||
condition = ""
|
||||
if token[1] == "JJ":
|
||||
condition = "(adj)"
|
||||
elif token[1] == "RB":
|
||||
condition = "(adv)"
|
||||
elif token[1] == "NN":
|
||||
condition = "(noun)"
|
||||
else:
|
||||
condition = "(verb)"
|
||||
|
||||
try:
|
||||
words = random.choice([a for a in responses if a["list"]["category"] == condition])["list"]["synonyms"].split("|")
|
||||
except:
|
||||
return (" " + token[0])
|
||||
|
||||
# print(words)
|
||||
word = words[random.randint(0, len(words) - 1)]
|
||||
|
||||
if "(" in word:
|
||||
if "antonym" in word.split("(")[1].lower():
|
||||
return (" " + token[0])
|
||||
|
||||
word = word.split("(")[0][:-1]
|
||||
|
||||
return (" " + word)
|
50
api/translation.py
Normal file
50
api/translation.py
Normal file
|
@ -0,0 +1,50 @@
|
|||
'''
|
||||
This file provides the functionality for
|
||||
the translation function, by first converting the
|
||||
country/language name to an ISO369-1 language identifier
|
||||
and then translating it using the Yandex Translation API
|
||||
'''
|
||||
import requests, urllib.parse
|
||||
from util import logging, config
|
||||
import pycountry
|
||||
|
||||
api_key = config.settings["api_keys"]["yandex"]
|
||||
langs = pycountry.languages
|
||||
|
||||
def name_to_ISO(name: str) -> str:
|
||||
alpha = ""
|
||||
for language in langs:
|
||||
if language.name.lower() == name.lower():
|
||||
try:
|
||||
alpha = language.alpha_2
|
||||
break
|
||||
except:
|
||||
logging.warning(f"Tried to get alpha2 code of unknown language {language}")
|
||||
|
||||
return alpha
|
||||
|
||||
def ISO_to_name(ISO: str) -> str:
|
||||
name = ""
|
||||
for language in langs:
|
||||
try:
|
||||
if language.alpha_2.lower() == ISO.lower():
|
||||
try:
|
||||
name = language.name
|
||||
break
|
||||
except:
|
||||
logging.warning(f"Tried to get name of unknown language code {ISO}")
|
||||
except:
|
||||
# i dont care tbh
|
||||
pass
|
||||
|
||||
return name
|
||||
|
||||
def translate(text: str, lang: str) -> (str, str):
|
||||
url_encoded_text = urllib.parse.quote(text)
|
||||
url = f"https://translate.yandex.net/api/v1.5/tr.json/translate?key={api_key}&text={url_encoded_text}&lang={lang}"
|
||||
|
||||
response = requests.get(url)
|
||||
if not response.ok:
|
||||
logging.error(f"Failed to contact Yandex API: {response.status_code}")
|
||||
return ""
|
||||
return (response.json()["text"][0], response.json()["lang"])
|
20
bot.py
20
bot.py
|
@ -23,7 +23,7 @@ logging.info(f"Total {total}, Failed {failed}\n")
|
|||
client = commands.Bot(command_prefix=config.settings["prefix"], case_insensitive=True)
|
||||
|
||||
|
||||
@client.command()
|
||||
@client.command(name="load", description="Loads a cog", usage="load <Cog>")
|
||||
@commands.is_owner()
|
||||
async def load(ctx : commands.Context, extension : str):
|
||||
try:
|
||||
|
@ -32,7 +32,7 @@ async def load(ctx : commands.Context, extension : str):
|
|||
except:
|
||||
await ctx.message.add_reaction("👎")
|
||||
|
||||
@client.command()
|
||||
@client.command(name="unload", description="Unoads a cog", usage="unload <Cog>")
|
||||
@commands.is_owner()
|
||||
async def unload(ctx : commands.Context, extension : str):
|
||||
try:
|
||||
|
@ -41,7 +41,7 @@ async def unload(ctx : commands.Context, extension : str):
|
|||
except:
|
||||
await ctx.message.add_reaction("👎")
|
||||
|
||||
@client.command()
|
||||
@client.command(name="reload", description="Reoads a cog", usage="reload <Cog>")
|
||||
@commands.is_owner()
|
||||
async def reload(ctx : commands.Context, extension : str):
|
||||
try:
|
||||
|
@ -59,6 +59,20 @@ async def on_ready():
|
|||
total = 0
|
||||
failed = 0
|
||||
# Load all cogs on startup
|
||||
for filename in os.listdir("./cogs"):
|
||||
if filename.endswith(".py"):
|
||||
total += 1
|
||||
cog = f"cogs.{filename[:-3]}"
|
||||
|
||||
try:
|
||||
client.load_extension(cog)
|
||||
logging.info(f"Trying {cog}.....Success!")
|
||||
except Exception as e:
|
||||
logging.info(f"Trying {cog}.....Failed!")
|
||||
logging.error(str(e))
|
||||
failed += 1
|
||||
|
||||
|
||||
# Load "fun" cogs
|
||||
for filename in os.listdir("./cogs/fun"):
|
||||
if filename.endswith(".py"):
|
||||
|
|
40
cogs/api/carbon.py
Normal file
40
cogs/api/carbon.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from api import carbon
|
||||
from util import embed
|
||||
|
||||
class Carbon(commands.Cog):
|
||||
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.group(name="carbon", usage="carbon [subcommand]", description="Can accumulate data about carbon levels in the UK")
|
||||
@commands.cooldown(1, 5)
|
||||
async def carbon(self, ctx):
|
||||
pass
|
||||
|
||||
@carbon.command(name="now", usage="carbon now", description="Gets the latest available carbon intensity data")
|
||||
async def now(self, ctx):
|
||||
data = carbon.current_level()
|
||||
await ctx.send(embed=embed.make_embed_fields_footer("Carbon intensity in the UK", f"The current carbon intensity is considered **{data[3]}**.", f"{data[0]} | All values in gCO2/kWh", ("Measured", data[2]), ("Predicted", data[1])))
|
||||
|
||||
@carbon.command(name="at", usage="carbon at <Date>", description="Gets the carbon levels at the given date (YYYY-MM-DD)")
|
||||
async def at(self, ctx: discord.Client, date: str):
|
||||
data = carbon.level_at(date)
|
||||
if len(data) == 0:
|
||||
await ctx.send(embed=embed.make_error_embed(f"There is no data available for {date}."))
|
||||
else:
|
||||
await ctx.send(embed=embed.make_embed_fields_footer("Carbon intensity in the UK", f"The carbon intensity for that date is considered **{data[3]}**.", f"{data[0]} | All values in gCO2/kWh", ("Measured", data[2]), ("Predicted", data[1])))
|
||||
|
||||
@carbon.command(name="during", usage="carbon during <Start> <Stop>", description="Creates a diagram about carbon levels in the given time period (YYYY-MM-DD)")
|
||||
@commands.cooldown(1, 25)
|
||||
async def during(self, ctx: discord.Client, start: str, stop: str):
|
||||
path = carbon.level_from_to(start, stop)
|
||||
if path == "":
|
||||
await ctx.send(embed=embed.make_error_embed(f"There is no data available for the given time period."))
|
||||
else:
|
||||
data = embed.make_embed_image("Carbon intensity in the UK", path)
|
||||
await ctx.send(embed=data[0], file=data[1])
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Carbon(client))
|
|
@ -14,7 +14,7 @@ class Inspirobot(commands.Cog):
|
|||
def __init__(self, client : discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="Inspirobot", description="Sends a randomly generated inspirational quote", aliases=["inspiration", "inspiro"])
|
||||
@commands.command(name="inspirobot", description="Sends a randomly generated inspirational quote", usage="inspirobot", aliases=["inspiration", "inspiro", "insp"])
|
||||
@commands.cooldown(1, 5)
|
||||
async def inspirobot(self, ctx : commands.Context):
|
||||
image = inspirobot.get_inspirational_quote()
|
||||
|
@ -25,5 +25,11 @@ class Inspirobot(commands.Cog):
|
|||
embed.set_image(url=image)
|
||||
await ctx.send(embed=embed)
|
||||
|
||||
@commands.command(name="test", dscription="Who cares tbh")
|
||||
@commands.cooldown(1, 3)
|
||||
async def test(self, ctx):
|
||||
await self.client.get_channel(621378664977793024).send("Test")
|
||||
await ctx.send(self.client.name)
|
||||
|
||||
def setup(client : discord.Client):
|
||||
client.add_cog(Inspirobot(client))
|
||||
client.add_cog(Inspirobot(client))
|
||||
|
|
|
@ -12,7 +12,7 @@ class Nasa(commands.Cog):
|
|||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="APOD", description="Posts NASA's picture of the day.")
|
||||
@commands.command(name="apod", description="Posts NASA's picture of the day.", usage="apod")
|
||||
@commands.cooldown(1, 30)
|
||||
async def apod(self, ctx: commands.Context):
|
||||
url = nasa.image_of_the_day()
|
||||
|
|
24
cogs/api/quote.py
Normal file
24
cogs/api/quote.py
Normal file
|
@ -0,0 +1,24 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from util import embed, config
|
||||
from api import quote
|
||||
|
||||
class Quote(commands.Cog):
|
||||
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="quote", description="Sends a random quote", usage="quote", aliases=["q"])
|
||||
@commands.cooldown(1, 2)
|
||||
async def quote(self, ctx: commands.Context):
|
||||
please_kill_me = quote.fetch_quote()
|
||||
if len(please_kill_me) == 0:
|
||||
await ctx.send(embed=embed.make_error_embed("Something went wrong while fetching a random quote"))
|
||||
return
|
||||
|
||||
end_my_life = discord.Embed(title=f'"{please_kill_me[0]}"', colour=int(config.settings["color"], 16))
|
||||
end_my_life.set_footer(text=please_kill_me[1])
|
||||
await ctx.send(embed=end_my_life)
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Quote(client))
|
|
@ -11,7 +11,7 @@ class Steam(commands.Cog):
|
|||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="SteamLevel", description="Finds the steam level of a user", usage="SteamLevel <Vanity URL>", aliases=["level"])
|
||||
@commands.command(name="steamlevel", description="Finds the steam level of a user", usage="steamlevel <Vanity URL>", aliases=["level"])
|
||||
@commands.cooldown(1, 2)
|
||||
async def SteamLevel(self, ctx: commands.Context, vanity_url: str):
|
||||
level = steam.get_steam_level(vanity_url)
|
||||
|
|
18
cogs/api/thesaurus.py
Normal file
18
cogs/api/thesaurus.py
Normal file
|
@ -0,0 +1,18 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from api import thesaurus
|
||||
|
||||
class Thesaurus(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="thesaurus", description="Makes you smarter.", usage="thesaurus <message>", aliases=["saurus", "thes"])
|
||||
@commands.cooldown(1, 3)
|
||||
async def thesaurus(self, ctx, *message):
|
||||
loading = await ctx.send("Thinking...")
|
||||
saurus = thesaurus.thesaurufy_sentence(" ".join(message))
|
||||
await loading.edit(content=saurus)
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Thesaurus(client))
|
32
cogs/api/translation.py
Normal file
32
cogs/api/translation.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from util import checking, embed
|
||||
from api import translation
|
||||
|
||||
class Translation(commands.Cog):
|
||||
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="translate", description="Translates the given text", usage="translate <Language> <Text>", aliases=["tl"])
|
||||
@commands.check(checking.is_author_bot)
|
||||
async def translate(self, ctx: commands.Context, language: str, *message: str):
|
||||
# Get language code
|
||||
code = translation.name_to_ISO(language)
|
||||
text = ' '.join(message)
|
||||
if code == "":
|
||||
await ctx.send(embed=embed.make_error_embed(f"There is no language named **{language}**."))
|
||||
return
|
||||
|
||||
response = translation.translate(text, code)
|
||||
if len(response) == 0:
|
||||
await ctx.send(embed=embed.make_error_embed(f"The translation API doesn't support **{language}**."))
|
||||
return
|
||||
translated = response[0]
|
||||
direction = response[1].split("-")
|
||||
_from = translation.ISO_to_name(direction[0])
|
||||
_to = translation.ISO_to_name(direction[1])
|
||||
await ctx.send(embed=embed.make_embed_field(f"{_from} -> {_to}", None, text, translated))
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Translation(client))
|
|
@ -65,12 +65,12 @@ class AutoConvert(commands.Cog):
|
|||
for currency in self.currencies:
|
||||
if currency == element[1]:
|
||||
continue
|
||||
currency_string += f"{self.convert_currency(element[1], currency, element[0])}{currency}, "
|
||||
embed.add_field(name=str(element[0])+element[1], value=currency_string[:-2])
|
||||
currency_string += f"{currency}{self.convert_currency(element[1], currency, element[0])}, "
|
||||
embed.add_field(name=element[1]+str(element[0]), value=currency_string[:-2])
|
||||
|
||||
if not empty:
|
||||
await message.channel.send(embed=embed)
|
||||
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(AutoConvert(client))
|
||||
client.add_cog(AutoConvert(client))
|
||||
|
|
|
@ -12,7 +12,7 @@ class Coinflip(commands.Cog):
|
|||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="coinflip", description="Flips a coin and reacts with the result", aliases=["coin", "flip"])
|
||||
@commands.command(name="coinflip", description="Flips a coin and reacts with the result", usage="coin", aliases=["coin", "flip"])
|
||||
async def coinflip(self, ctx: commands.Context):
|
||||
if random.randint(0, 1) == 0:
|
||||
await ctx.message.add_reaction("🌑")
|
||||
|
|
34
cogs/fun/encryption.py
Normal file
34
cogs/fun/encryption.py
Normal file
|
@ -0,0 +1,34 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from util import embed
|
||||
|
||||
class Encryption(commands.Cog):
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="rot", description="Applies the ROT encryption", usage="rot [number] [message]")
|
||||
@commands.cooldown(1, 2)
|
||||
async def rot(self, ctx: commands.Context, shift: str, *message: str):
|
||||
if not shift.isnumeric():
|
||||
await ctx.send(embed=embed.make_error_embed(f"{shift} is not a number."))
|
||||
return
|
||||
|
||||
shift = int(shift)
|
||||
if (shift < 1) or (shift > 25):
|
||||
await ctx.send(embed=embed.make_error_embed("That's too much rotation. Stop it."))
|
||||
return
|
||||
|
||||
old_message = list(' '.join(message))
|
||||
for i in range(0, len(old_message)):
|
||||
if not old_message[i].isalpha():
|
||||
continue
|
||||
|
||||
if old_message[i].isupper():
|
||||
old_message[i] = chr(ord('A') + ((ord(old_message[i]) + shift - ord('A')) % 26))
|
||||
else:
|
||||
old_message[i] = chr(ord('a') + ((ord(old_message[i]) + shift - ord('a')) % 26))
|
||||
|
||||
await ctx.send(''.join(old_message))
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Encryption(client))
|
20
cogs/fun/math.py
Normal file
20
cogs/fun/math.py
Normal file
|
@ -0,0 +1,20 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from sympy import preview
|
||||
from util import embed
|
||||
|
||||
class Math(commands.Cog):
|
||||
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
|
||||
@commands.command(name="latex", description="Transforms a latex(math!) expression to an image", usage="latex <latex>", aliases=["lat", "tex", "l"])
|
||||
@commands.cooldown(1, 5)
|
||||
async def latex(self, ctx: commands.Context, *expr: str):
|
||||
preview(f"$${' '.join(expr)}$$", viewer='file', filename='latex.png', euler=False)
|
||||
result = embed.make_embed_image("LaTeX", "latex.png")
|
||||
await ctx.send(embed=result[0], file=result[1])
|
||||
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Math(client))
|
|
@ -29,9 +29,9 @@ class Reactions(commands.Cog):
|
|||
await message.add_reaction("🇨🇳")
|
||||
|
||||
if "america" in message.content.lower() or " usa" in message.content.lower():
|
||||
await message.add_reaction("🇬")
|
||||
await message.add_reaction("🇦")
|
||||
await message.add_reaction("🇾")
|
||||
await message.add_reaction("🇺🇸")
|
||||
await message.add_reaction("🔫")
|
||||
await message.add_reaction("🦅")
|
||||
|
||||
|
||||
if "extremejoy" in message.content.lower():
|
||||
|
|
32
cogs/fun/responses.py
Normal file
32
cogs/fun/responses.py
Normal file
|
@ -0,0 +1,32 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
|
||||
class Responses(commands.Cog):
|
||||
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message: discord.Message):
|
||||
if message.author == self.client.user:
|
||||
return
|
||||
|
||||
# @applesauce
|
||||
if ("<@!568271450176356352>" in message.content) and ("<@!657709911337074698>" in message.content):
|
||||
await message.channel.send(f"Stop pinging us {message.author.mention} <:pinged:451198700832817202>")
|
||||
return
|
||||
|
||||
"""
|
||||
if message.author.id == 478006431589728259:
|
||||
if message.content == "<@&380535423233032193> NUMBERS REEEEEEEE":
|
||||
await message.channel.send(f"<@&380535423233032193> {message.author.mention} REEEEEEEE")
|
||||
|
||||
if message.content == "<@&380535423233032193> <:nockgun:352019166288543745> 🔢":
|
||||
await message.channel.send(f"<@&380535423233032193> <:nockgun:352019166288543745> {message.author.mention}")
|
||||
|
||||
if message.content == "<@&380535423233032193> is NOT for numbers":
|
||||
await message.channel.send(f"<@&380535423233032193> ***IS*** for numbers")
|
||||
"""
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Responses(client))
|
35
cogs/fun/safety.py
Normal file
35
cogs/fun/safety.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from util import embed, logging
|
||||
import time
|
||||
|
||||
class Safety(commands.Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.msg_buffer = [".", ".", ".", ".", ".", "."]
|
||||
self.ping = "<@&380535423233032193>"
|
||||
self.channel = 439466964625391637
|
||||
self.last_action = 0
|
||||
|
||||
@commands.Cog.listener()
|
||||
async def on_message(self, message):
|
||||
if message.channel.id != self.channel:
|
||||
return
|
||||
|
||||
if (time.time() - self.last_action) < 10:
|
||||
return
|
||||
|
||||
|
||||
if self.ping in message.content:
|
||||
for msg in self.msg_buffer:
|
||||
if self.ping in msg:
|
||||
# Ping not adequately spaced
|
||||
await message.channel.send(embed=embed.make_embed("Coronavirus Safety Information", "Due to the ongoing pandemic, please remember to space your NaughtyStep pings at least six messages apart.\n Thank you."))
|
||||
self.last_action = time.time()
|
||||
break
|
||||
|
||||
self.msg_buffer.pop(0)
|
||||
self.msg_buffer.append(message.content)
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(Safety(client))
|
51
cogs/fun/schedule.py
Normal file
51
cogs/fun/schedule.py
Normal file
|
@ -0,0 +1,51 @@
|
|||
import discord
|
||||
import time
|
||||
import asyncio
|
||||
from discord.ext import commands
|
||||
from datetime import datetime, timedelta
|
||||
from random import randrange
|
||||
from util import logging
|
||||
|
||||
def ceil_dt(dt, delta):
|
||||
return dt + (datetime.min - dt) % delta
|
||||
|
||||
def random_date(start, end):
|
||||
"""
|
||||
This function will return a random datetime between two datetime
|
||||
objects.
|
||||
"""
|
||||
delta = end - start
|
||||
int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
|
||||
random_second = randrange(int_delta)
|
||||
return start + timedelta(seconds=random_second)
|
||||
|
||||
class Schedule(commands.Cog):
|
||||
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
self.threads = 0
|
||||
self.THREAD_LIMIT = 20
|
||||
|
||||
async def call_event(self, sleep_time: int, name: str, user: discord.User, channel: discord.TextChannel):
|
||||
await asyncio.sleep(sleep_time)
|
||||
await channel.send(f"{user.mention} Your event \"{name}\" starts now!")
|
||||
self.threads -= 1
|
||||
|
||||
@commands.command(name="schedule", description="Schedules an event", usage="schedule <name>", aliases=["s"])
|
||||
@commands.cooldown(1, 3)
|
||||
async def schedule(self, ctx: commands.Context, *name: str):
|
||||
date = ceil_dt(random_date(datetime.now(), datetime.now() + timedelta(days=7)), timedelta(minutes=15))
|
||||
await ctx.send(f"I scheduled \"{' '.join(name)}\" for **{date.strftime('%d.%m.%Y %H:%M CET')}**")
|
||||
|
||||
if self.threads <= self.THREAD_LIMIT:
|
||||
seconds = (date - datetime.now()).seconds
|
||||
await self.call_event(seconds, ' '.join(name), ctx.message.author, ctx.message.channel)
|
||||
self.threads += 1
|
||||
logging.info(f"Scheduled new event in {seconds} seconds. Current events: {self.threads}")
|
||||
else:
|
||||
logging.warning("Schedule: Event limit reached. Async function was not called.")
|
||||
|
||||
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(Schedule(client))
|
26
cogs/fun/wolfram.py
Normal file
26
cogs/fun/wolfram.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from wolframclient.evaluation import WolframLanguageSession
|
||||
from wolframclient.language import wl, wlexpr
|
||||
from util import embed
|
||||
|
||||
class WolframAlpha(commands.Cog):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.session = WolframLanguageSession()
|
||||
|
||||
def __del__(self):
|
||||
self.session.terminate()
|
||||
|
||||
@commands.command(name="WolframLanguage", description="Evaluates WolframLanguage expressions (Not to be confused with WolframAlpha!)", usage="WolframLanguage <expression>", aliases=["wl"])
|
||||
async def WolframLanguage(self, ctx, *, expr):
|
||||
msg = await ctx.send(embed=embed.make_embed("WolframLanguage", "Thinking..."))
|
||||
evaluate = self.session.evaluate(expr)
|
||||
|
||||
self.session.evaluate(wl.Export("eval.png", evaluate, "PNG"))
|
||||
await msg.delete()
|
||||
data = embed.make_embed_image("Result", "eval.png")
|
||||
await ctx.send(embed=data[0], file=data[1])
|
||||
|
||||
def setup(client):
|
||||
client.add_cog(WolframAlpha(client))
|
106
cogs/help.py
Normal file
106
cogs/help.py
Normal file
|
@ -0,0 +1,106 @@
|
|||
import discord
|
||||
from discord.ext import commands
|
||||
from util import config, embed, logging
|
||||
|
||||
class SetupHelp(commands.Cog):
|
||||
def __init__(self, client: discord.Client):
|
||||
self.client = client
|
||||
self._original_help_command = client.help_command
|
||||
client.help_command = Help()
|
||||
client.help_command.cog = self
|
||||
|
||||
class Help(commands.MinimalHelpCommand):
|
||||
async def command_not_found(self, string: str):
|
||||
await self.context.send(embed=embed.make_error_embed("Command not found"))
|
||||
|
||||
async def subcommand_not_found(self, command, string):
|
||||
await self.context.send(embed=embed.make_error_embed("Command not found"))
|
||||
|
||||
async def send_cog_help(self, cog):
|
||||
await self.context.send(embed=embed.make_error_embed("Command not found"))
|
||||
|
||||
async def send_group_help(self, group):
|
||||
try:
|
||||
subcmds = ""
|
||||
if group.commands != []:
|
||||
for command in group.commands:
|
||||
subcmds += "`" + command.name + "`, "
|
||||
subcmds = subcmds[:-2]
|
||||
else:
|
||||
subcmds = "`None`"
|
||||
|
||||
alias = ""
|
||||
if group.aliases != []:
|
||||
for i in range(len(group.aliases)):
|
||||
if i == len(group.aliases) - 1:
|
||||
alias = alias + '`' + group.aliases[i] + '`'
|
||||
else:
|
||||
alias = alias + '`' + group.aliases[i] + '`' + ', '
|
||||
else:
|
||||
alias = "`None`"
|
||||
|
||||
await self.context.send(embed=embed.make_embed_fields_ninl(group.name, group.description, ("Usage", f"`{config.settings['prefix']}{group.usage}`"), ("Aliases", alias), ("Subcommands", subcmds)))
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
await self.context.send(embed=embed.make_error_embed("Command not found"))
|
||||
|
||||
async def send_command_help(self, command):
|
||||
try:
|
||||
alias = ""
|
||||
if command.aliases != []:
|
||||
for i in range(len(command.aliases)):
|
||||
if i == len(command.aliases) - 1:
|
||||
alias = alias + '`' + command.aliases[i] + '`'
|
||||
else:
|
||||
alias = alias + '`' + command.aliases[i] + '`' + ', '
|
||||
else:
|
||||
alias = "`None`"
|
||||
|
||||
command_name = command.name
|
||||
if command.parent != None:
|
||||
command_name += f" ({command.parent})"
|
||||
await self.context.send(embed=embed.make_embed_fields_ninl(command_name, command.description, ("Usage", f"`{config.settings['prefix']}{command.usage}`"), ("Aliases", alias)))
|
||||
except Exception as e:
|
||||
logging.error(str(e))
|
||||
await self.context.send(embed=embed.make_error_embed("Command not found"))
|
||||
|
||||
|
||||
async def send_bot_help(self, mapping):
|
||||
# get list of commands
|
||||
cmds = []
|
||||
prefix = config.settings['prefix']
|
||||
|
||||
for cog, cog_commands in mapping.items():
|
||||
cmds = cmds + cog_commands
|
||||
cog = cog # Just so that the warning goes away
|
||||
|
||||
newCmds = []
|
||||
for item in cmds:
|
||||
newCmds.append(str(item))
|
||||
newCmds = sorted(newCmds)
|
||||
|
||||
finalCmds = []
|
||||
for item in newCmds:
|
||||
try:
|
||||
finalCmds.append(item)
|
||||
except:
|
||||
pass
|
||||
|
||||
cmdString = ""
|
||||
if len(finalCmds) != 0:
|
||||
for i in range(len(finalCmds)):
|
||||
if i == len(finalCmds)-1:
|
||||
cmdString = cmdString + '`' + finalCmds[i] + '`'
|
||||
else:
|
||||
cmdString = cmdString + '`' + finalCmds[i] + '`' + ', '
|
||||
|
||||
|
||||
if cmdString != "":
|
||||
await self.context.send(embed=embed.make_embed_field('Help', f'To get further information about a command use `{prefix}help <Command>`', "Commands", cmdString, inline=False))
|
||||
else:
|
||||
await self.context.send(embed=embed.make_error_embed("No commands found."))
|
||||
|
||||
|
||||
|
||||
def setup(client: discord.Client):
|
||||
client.add_cog(SetupHelp(client))
|
5
data/count.py
Normal file
5
data/count.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
count=0
|
||||
with open('naughty_step.txt', 'r') as file:
|
||||
for line in file:
|
||||
count += len(line)
|
||||
print(count)
|
3
screenlog.0
Normal file
3
screenlog.0
Normal file
|
@ -0,0 +1,3 @@
|
|||
[01;32mroot@h2864412[00m:[01;34m~/DeepBlue[00m# cd [K[K[Kscre[K[K[K[Kscreen -X
|
||||
Please specify a command.
|
||||
[01;32mroot@h2864412[00m:[01;34m~/DeepBlue[00m#
|
|
@ -8,6 +8,4 @@ from discord.ext import commands
|
|||
from util import logging
|
||||
|
||||
def is_author_bot(ctx : commands.Context) -> bool:
|
||||
if ctx.message.author.bot:
|
||||
return False
|
||||
return True
|
||||
return (not ctx.author.bot)
|
41
util/embed.py
Normal file
41
util/embed.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
import discord
|
||||
from util import config
|
||||
|
||||
def make_error_embed(message: str) -> discord.Embed:
|
||||
embed = discord.Embed(title="Error", description=message, colour=int(config.settings["err_color"], 16))
|
||||
return embed
|
||||
|
||||
def make_embed(title: str, desc: str) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=desc, colour=int(config.settings["color"], 16))
|
||||
return embed
|
||||
|
||||
def make_embed_field(title: str, desc: str, field_name: str, field_val: str, inline: bool = True) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=desc, colour=int(config.settings["color"], 16))
|
||||
embed.add_field(name=field_name, value=field_val, inline=inline)
|
||||
return embed
|
||||
|
||||
def make_embed_fields(title: str, desc: str, *fields: tuple) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=desc, colour=int(config.settings["color"], 16))
|
||||
for name, value in fields:
|
||||
embed.add_field(name=name, value=value)
|
||||
return embed
|
||||
|
||||
def make_embed_fields_footer(title: str, desc: str, footer: str, *fields: tuple) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=desc, colour=int(config.settings["color"], 16))
|
||||
embed.set_footer(text=footer)
|
||||
for name, value in fields:
|
||||
embed.add_field(name=name, value=value)
|
||||
return embed
|
||||
|
||||
def make_embed_fields_ninl(title: str, desc: str, *fields: tuple) -> discord.Embed:
|
||||
embed = discord.Embed(title=title, description=desc, colour=int(config.settings["color"], 16), inline=False)
|
||||
for name, value in fields:
|
||||
embed.add_field(name=name, value=value, inline=False)
|
||||
return embed
|
||||
|
||||
def make_embed_image(title: str, path: str) -> (discord.Embed, discord.File):
|
||||
embed = discord.Embed(title=title, colour=int(config.settings["color"], 16))
|
||||
attachment = discord.File(path, filename="image.png")
|
||||
embed.set_image(url='attachment://image.png')
|
||||
|
||||
return (embed, attachment)
|
Loading…
Reference in a new issue