Skip to content

Instantly share code, notes, and snippets.

@Ednaordinary
Created May 12, 2024 00:51
Show Gist options
  • Save Ednaordinary/aa90a46ba3d75508a68460e954e5ca57 to your computer and use it in GitHub Desktop.
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
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