2022-12-01 12:22:11 +00:00
|
|
|
import io
|
|
|
|
import os
|
2022-11-18 14:11:53 +00:00
|
|
|
from typing import Tuple, Optional
|
|
|
|
|
2022-11-13 23:16:47 +00:00
|
|
|
import discord
|
|
|
|
import aiohttp
|
|
|
|
import random
|
|
|
|
from discord.ext import commands
|
|
|
|
|
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
# noinspection DuplicatedCode
|
2022-11-13 23:16:47 +00:00
|
|
|
class OtherCog(commands.Cog):
|
|
|
|
def __init__(self, bot):
|
|
|
|
self.bot = bot
|
2022-11-14 17:20:31 +00:00
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
async def analyse_text(self, text: str) -> Optional[Tuple[float, float, float, float]]:
|
|
|
|
"""Analyse text for positivity, negativity and neutrality."""
|
|
|
|
|
|
|
|
def inner():
|
|
|
|
try:
|
|
|
|
from utils.sentiment_analysis import intensity_analyser
|
|
|
|
except ImportError:
|
|
|
|
return None
|
|
|
|
scores = intensity_analyser.polarity_scores(text)
|
|
|
|
return scores["pos"], scores["neu"], scores["neg"], scores["compound"]
|
|
|
|
|
|
|
|
async with self.bot.training_lock:
|
|
|
|
return await self.bot.loop.run_in_executor(None, inner)
|
|
|
|
|
2022-11-14 17:20:31 +00:00
|
|
|
@staticmethod
|
|
|
|
async def get_xkcd(session: aiohttp.ClientSession, n: int) -> dict | None:
|
|
|
|
async with session.get("https://xkcd.com/{!s}/info.0.json".format(n)) as response:
|
|
|
|
if response.status == 200:
|
2022-11-13 23:16:47 +00:00
|
|
|
data = await response.json()
|
2022-11-14 17:20:31 +00:00
|
|
|
return data
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def random_xkcd_number(session: aiohttp.ClientSession) -> int:
|
|
|
|
async with session.get("https://c.xkcd.com/random/comic") as response:
|
|
|
|
if response.status != 302:
|
|
|
|
number = random.randint(100, 999)
|
|
|
|
else:
|
2022-11-18 14:11:53 +00:00
|
|
|
number = int(response.headers["location"].split("/")[-2])
|
2022-11-14 17:20:31 +00:00
|
|
|
return number
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def random_xkcd(session: aiohttp.ClientSession) -> dict | None:
|
|
|
|
"""Fetches a random XKCD.
|
|
|
|
|
|
|
|
Basically a shorthand for random_xkcd_number and get_xkcd.
|
|
|
|
"""
|
|
|
|
number = await OtherCog.random_xkcd_number(session)
|
|
|
|
return await OtherCog.get_xkcd(session, number)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_xkcd_embed(data: dict) -> discord.Embed:
|
2022-11-13 23:16:47 +00:00
|
|
|
embed = discord.Embed(
|
2022-11-18 14:11:53 +00:00
|
|
|
title=data["safe_title"], description=data["alt"], color=discord.Colour.embed_background()
|
2022-11-13 23:16:47 +00:00
|
|
|
)
|
2022-11-18 14:11:53 +00:00
|
|
|
embed.set_footer(text="XKCD #{!s}".format(data["num"]))
|
|
|
|
embed.set_image(url=data["img"])
|
2022-11-14 17:20:31 +00:00
|
|
|
return embed
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
async def generate_xkcd(n: int = None) -> discord.Embed:
|
|
|
|
async with aiohttp.ClientSession() as session:
|
|
|
|
if n is None:
|
|
|
|
data = await OtherCog.random_xkcd(session)
|
2022-11-18 14:11:53 +00:00
|
|
|
n = data["num"]
|
2022-11-14 17:20:31 +00:00
|
|
|
else:
|
|
|
|
data = await OtherCog.get_xkcd(session, n)
|
|
|
|
if data is None:
|
|
|
|
return discord.Embed(
|
2022-11-18 14:11:53 +00:00
|
|
|
title="Failed to load XKCD :(", description="Try again later.", color=discord.Colour.red()
|
2022-11-14 17:20:31 +00:00
|
|
|
).set_footer(text="Attempted to retrieve XKCD #{!s}".format(n))
|
|
|
|
return OtherCog.get_xkcd_embed(data)
|
|
|
|
|
|
|
|
class XKCDGalleryView(discord.ui.View):
|
|
|
|
def __init__(self, n: int):
|
|
|
|
super().__init__(timeout=300, disable_on_timeout=True)
|
|
|
|
self.n = n
|
|
|
|
|
2022-11-16 17:28:47 +00:00
|
|
|
def __rich_repr__(self):
|
|
|
|
yield "n", self.n
|
|
|
|
yield "message", self.message
|
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
@discord.ui.button(label="Previous", style=discord.ButtonStyle.blurple)
|
2022-11-14 17:20:31 +00:00
|
|
|
async def previous_comic(self, _, interaction: discord.Interaction):
|
|
|
|
self.n -= 1
|
|
|
|
await interaction.response.defer()
|
|
|
|
await interaction.edit_original_response(embed=await OtherCog.generate_xkcd(self.n))
|
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
@discord.ui.button(label="Random", style=discord.ButtonStyle.blurple)
|
2022-11-14 17:20:31 +00:00
|
|
|
async def random_comic(self, _, interaction: discord.Interaction):
|
|
|
|
await interaction.response.defer()
|
|
|
|
await interaction.edit_original_response(embed=await OtherCog.generate_xkcd())
|
|
|
|
self.n = random.randint(1, 999)
|
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
@discord.ui.button(label="Next", style=discord.ButtonStyle.blurple)
|
2022-11-14 17:20:31 +00:00
|
|
|
async def next_comic(self, _, interaction: discord.Interaction):
|
|
|
|
self.n += 1
|
|
|
|
await interaction.response.defer()
|
|
|
|
await interaction.edit_original_response(embed=await OtherCog.generate_xkcd(self.n))
|
|
|
|
|
|
|
|
@commands.slash_command()
|
|
|
|
async def xkcd(self, ctx: discord.ApplicationContext, *, number: int = None):
|
|
|
|
"""Shows an XKCD comic"""
|
|
|
|
embed = await self.generate_xkcd(number)
|
|
|
|
view = self.XKCDGalleryView(number)
|
|
|
|
return await ctx.respond(embed=embed, view=view)
|
2022-11-13 23:16:47 +00:00
|
|
|
|
2022-11-18 14:11:53 +00:00
|
|
|
@commands.slash_command()
|
|
|
|
async def sentiment(self, ctx: discord.ApplicationContext, *, text: str):
|
|
|
|
"""Attempts to detect a text's tone"""
|
|
|
|
await ctx.defer()
|
|
|
|
if not text:
|
|
|
|
return await ctx.respond("You need to provide some text to analyse.")
|
|
|
|
result = await self.analyse_text(text)
|
|
|
|
if result is None:
|
|
|
|
return await ctx.edit(content="Failed to load sentiment analysis module.")
|
|
|
|
embed = discord.Embed(title="Sentiment Analysis", color=discord.Colour.embed_background())
|
|
|
|
embed.add_field(name="Positive", value="{:.2%}".format(result[0]))
|
|
|
|
embed.add_field(name="Neutral", value="{:.2%}".format(result[2]))
|
|
|
|
embed.add_field(name="Negative", value="{:.2%}".format(result[1]))
|
|
|
|
embed.add_field(name="Compound", value="{:.2%}".format(result[3]))
|
|
|
|
return await ctx.edit(content=None, embed=embed)
|
|
|
|
|
|
|
|
@commands.message_command(name="Detect Sentiment")
|
|
|
|
async def message_sentiment(self, ctx: discord.ApplicationContext, message: discord.Message):
|
|
|
|
await ctx.defer()
|
|
|
|
text = str(message.clean_content)
|
|
|
|
if not text:
|
|
|
|
return await ctx.respond("You need to provide some text to analyse.")
|
|
|
|
await ctx.respond("Analyzing (this may take some time)...")
|
|
|
|
result = await self.analyse_text(text)
|
|
|
|
if result is None:
|
|
|
|
return await ctx.edit(content="Failed to load sentiment analysis module.")
|
|
|
|
embed = discord.Embed(title="Sentiment Analysis", color=discord.Colour.embed_background())
|
|
|
|
embed.add_field(name="Positive", value="{:.2%}".format(result[0]))
|
|
|
|
embed.add_field(name="Neutral", value="{:.2%}".format(result[2]))
|
|
|
|
embed.add_field(name="Negative", value="{:.2%}".format(result[1]))
|
|
|
|
embed.add_field(name="Compound", value="{:.2%}".format(result[3]))
|
|
|
|
embed.url = message.jump_url
|
|
|
|
return await ctx.edit(content=None, embed=embed)
|
|
|
|
|
2022-12-01 12:22:11 +00:00
|
|
|
corrupt_file = discord.SlashCommandGroup(
|
|
|
|
name="corrupt-file",
|
|
|
|
description="Corrupts files.",
|
|
|
|
)
|
|
|
|
|
|
|
|
@corrupt_file.command(name="generate")
|
|
|
|
async def generate_corrupt_file(self, ctx: discord.ApplicationContext, file_name: str, size_in_megabytes: float):
|
|
|
|
"""Generates a "corrupted" file."""
|
|
|
|
if size_in_megabytes > 8:
|
|
|
|
return await ctx.respond("File size must be less than 8 MB.")
|
|
|
|
await ctx.defer()
|
|
|
|
file = io.BytesIO()
|
|
|
|
file.write(os.urandom(int(size_in_megabytes * 1024 * 1024)))
|
|
|
|
file.seek(0)
|
|
|
|
return await ctx.respond(file=discord.File(file, file_name))
|
|
|
|
|
|
|
|
@corrupt_file.command(name="ruin")
|
|
|
|
async def ruin_corrupt_file(self, ctx: discord.ApplicationContext, file: discord.Attachment, passes: int = 10):
|
|
|
|
"""Takes a file and corrupts parts of it"""
|
|
|
|
await ctx.defer()
|
|
|
|
attachment = file
|
|
|
|
file = io.BytesIO(await file.read())
|
|
|
|
file.seek(0)
|
|
|
|
for _ in range(passes):
|
|
|
|
file.seek(random.randint(0, file.getbuffer().nbytes))
|
|
|
|
file.write(os.urandom(random.randint(256, 2048)))
|
|
|
|
file.seek(0)
|
|
|
|
if len(file.read()) >= ctx.guild.filesize_limit:
|
|
|
|
file.seek(0)
|
|
|
|
_data = file.read()
|
|
|
|
_data = _data[:ctx.guild.filesize_limit - 100]
|
|
|
|
file.write(_data)
|
|
|
|
file.seek(0)
|
2022-12-01 12:26:29 +00:00
|
|
|
file.seek(0)
|
2022-12-01 12:22:11 +00:00
|
|
|
return await ctx.respond(file=discord.File(file, attachment.filename))
|
|
|
|
|
2022-11-13 23:16:47 +00:00
|
|
|
|
|
|
|
def setup(bot):
|
|
|
|
bot.add_cog(OtherCog(bot))
|