Created
May 12, 2024 00:51
-
-
Save Ednaordinary/aa90a46ba3d75508a68460e954e5ca57 to your computer and use it in GitHub Desktop.
Discord bot with a command to efficiently scan through the server and find every time a user has reacted with an emoji, then compile it into a report
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import nextcord as discord | |
from dotenv import load_dotenv | |
import sys | |
import time | |
import textwrap | |
import os | |
load_dotenv() | |
TOKEN = os.getenv('DISCORD_TOKEN') | |
intents = discord.Intents.all() | |
client = discord.Client(intents=intents) | |
@client.event | |
async def on_error(event, *args, **kwargs): | |
exc_type, exc_obj, exc_tb = sys.exc_info() | |
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] | |
print(exc_type, fname, exc_tb.tb_lineno) | |
print(repr(event)) | |
raise | |
@client.event | |
async def on_ready(): | |
print(f'{client.user.name} has connected to Discord! STEALING PEOPLE NOW') | |
@client.slash_command(description="Report how many times a user has reacted with an emoji in a server") | |
async def get_all_reactions( | |
interaction: discord.Interaction, | |
user: discord.Member, | |
emoji: str, | |
): | |
target = discord.PartialEmoji.from_str(emoji.strip()) | |
counts = {} | |
overall = [0, 0] | |
await interaction.send("Starting scan..") | |
for channel in interaction.guild.channels: | |
print(channel.name) | |
if type(channel) == discord.TextChannel: | |
await interaction.edit_original_message(content="Now reading " + str(channel.name)) | |
counts[channel] = [0, 0] | |
err_count = 0 | |
while True: | |
try: | |
async for message in channel.history(limit=None): | |
print(".", end='', flush=True) | |
for reaction in message.reactions: | |
if str(target) == str(reaction.emoji): | |
user_manager = reaction.users() | |
try: | |
reacted = user_manager.get(id=user.id) | |
except: | |
reacted = await user_manager.get(id=user.id) | |
if reacted is not None: | |
counts[channel][0] += 1 | |
print("+", end='', flush=True) | |
counts[channel][1] += 1 | |
overall[0] += counts[channel][0] | |
overall[1] += counts[channel][1] | |
break | |
except Exception as e: | |
exc_type, exc_obj, exc_tb = sys.exc_info() | |
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] | |
print(exc_type, fname, exc_tb.tb_lineno) | |
print(repr(e)) | |
if isinstance(e, discord.errors.Forbidden): | |
del counts[channel] | |
break | |
else: | |
time.sleep(5) | |
await interaction.edit_original_message(content="Hit a limit! scanning " + str(channel.name) + " again (" + str(err_count) + ")") | |
err_count += 1 | |
counts[channel] = [0, 0] | |
elif type(channel) == discord.ForumChannel: | |
for thread in channel.threads: | |
await interaction.edit_original_message(content="Now reading " + str(thread.name) + " (" + str(channel.name) + ")") | |
counts[thread] = [0, 0] | |
err_count = 0 | |
while True: | |
try: | |
async for message in thread.history(limit=None): | |
print(".", end='', flush=True) | |
for reaction in message.reactions: | |
if str(target) == str(reaction.emoji): | |
user_manager = reaction.users() | |
try: | |
reacted = user_manager.get(id=user.id) | |
except: | |
reacted = await user_manager.get(id=user.id) | |
if reacted is not None: | |
counts[thread][0] += 1 | |
print("+", end='', flush=True) | |
counts[thread][1] += 1 | |
overall[0] += counts[thread][0] | |
overall[1] += counts[thread][1] | |
break | |
except Exception as e: | |
exc_type, exc_obj, exc_tb = sys.exc_info() | |
fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1] | |
print(exc_type, fname, exc_tb.tb_lineno) | |
print(repr(e)) | |
if isinstance(e, discord.errors.Forbidden): | |
del counts[channel] | |
break | |
else: | |
time.sleep(5) | |
await interaction.edit_original_message(content="Hit a limit! scanning " + str(thread) + " again (" + str(err_count) + ")") | |
err_count += 1 | |
counts[thread] = [0, 0] | |
await interaction.edit_original_message(content="Done reading") | |
try: | |
analysis_content = "Overall: " + str(round((overall[0]/overall[1])*100, 2)) + "%\nReacted messages: " + str(overall[0]) + "\nTotal messages: " + str(overall[1]) + "\n" | |
for channel, count in counts.items(): | |
if not count[1] == 0: | |
analysis_content = analysis_content + "\n" + str(channel.name) + ": " + str(round((count[0]/count[1])*100, 2)) + "% (" + str(count[0]) + "/" + str(count[1]) + ")" | |
contents = textwrap.wrap(analysis_content, 2000, break_long_words=False, replace_whitespace=False) | |
for content in contents: | |
await interaction.channel.send(content) | |
except: | |
await interaction.channel.send("failed to compile report :frowning2:") | |
client.run(TOKEN) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment