Make script delete all messages in a given server
This commit is contained in:
@ -1,49 +1,40 @@
|
|||||||
#!/bin/python3
|
#!/bin/python3
|
||||||
import asyncio, aiohttp, os, sys, json
|
import asyncio, aiohttp, os, sys, json
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
import argparse
|
||||||
|
|
||||||
# method to print out the usage instructions if the program was called incorrectly
|
|
||||||
def usage():
|
|
||||||
sys.exit("Usage: ./purge_discord.py [OPTION]... [ARGUMENT]...\n"
|
|
||||||
"Delete all the user's messages in the given Discord channel.\n"
|
|
||||||
"The channel may be specified using one of the following options:\n"
|
|
||||||
# "\t-i, --channel-id delete messages in the channel corresponding to the supplied ID\n"
|
|
||||||
"\t-u, --channel-url delete messages in the channel corresponding to the supplied URL")
|
|
||||||
|
|
||||||
|
|
||||||
async def main():
|
async def main():
|
||||||
# parsing command-line arguments
|
parser = argparse.ArgumentParser(description="Script to delete all a user's messages in a given Discord server")
|
||||||
if len(sys.argv) == 3:
|
parser.add_argument("-u", "--channel-url", type=str, help="URL of a channel in the server", required=True)
|
||||||
# if sys.argv[1] == "-i" or sys.argv[1] == "--channel-id":
|
args=parser.parse_args()
|
||||||
# channel = sys.argv[2]
|
|
||||||
# elif sys.argv[1] == "-u" or sys.argv[1] == "--channel-url":
|
|
||||||
if sys.argv[1] == "-u" or sys.argv[1] == "--channel-url":
|
|
||||||
guild = sys.argv[2].split("/")[-2] # parsing the server (guild) ID from the URL by splitting it on `/` and taking the second last segment
|
|
||||||
channel = sys.argv[2].split("/")[-1] # parsing the channel ID from the URL by splitting it on `/` and taking the last segment
|
|
||||||
|
|
||||||
# setting host URL based on whether the channel is in @me or in a guild/server
|
|
||||||
if (guild == "@me"):
|
|
||||||
guild_url = "https://discord.com/api/v9/channels/" + channel
|
|
||||||
channel_url = guild_url
|
|
||||||
else:
|
|
||||||
guild_url = "https://discord.com/api/v9/guilds/" + guild
|
|
||||||
channel_url = "https://discord.com/api/v9/channels/" + channel
|
|
||||||
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
else:
|
|
||||||
usage()
|
|
||||||
|
|
||||||
|
|
||||||
# reading Discord token from the .env file. should be in the format `DISCORD_TOKEN=<insert_discord_token_here>`
|
# reading Discord token from the .env file. should be in the format `DISCORD_TOKEN=<insert_discord_token_here>`
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
token = os.getenv("DISCORD_TOKEN")
|
token = os.getenv("DISCORD_TOKEN")
|
||||||
|
|
||||||
if not token:
|
if not token:
|
||||||
sys.exit("DISCORD_TOKEN environment variable is not set")
|
raise Exception("DISCORD_TOKEN environment variable is not set")
|
||||||
|
|
||||||
|
guild = args.channel_url.split("/")[-2] # "guild" is discord's internal name for servers
|
||||||
|
channel = args.channel_url.split("/")[-1]
|
||||||
|
|
||||||
|
# setting host URL based on whether the channel is in @me or in a guild/server
|
||||||
|
if (guild == "@me"):
|
||||||
|
guild_url = "https://discord.com/api/v9/channels/" + channel
|
||||||
|
channel_url = guild_url
|
||||||
|
else:
|
||||||
|
guild_url = "https://discord.com/api/v9/guilds/" + guild
|
||||||
|
channel_url = "https://discord.com/api/v9/channels/" + channel
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"accept": "*/*",
|
||||||
|
"accept-language": "en-GB,en;q=0.8",
|
||||||
|
"authorization": token,
|
||||||
|
"origin": "https://discord.com",
|
||||||
|
"priority": "u=1, i",
|
||||||
|
"referer": "https://discord.com/channels/" + guild + "/" + channel,
|
||||||
|
}
|
||||||
|
|
||||||
headers = {"authorization": token}
|
|
||||||
offset = 0 # messages are received from the API in batches of 25, so need to keep track of the offset when requesting to make sure no old messages are received
|
offset = 0 # messages are received from the API in batches of 25, so need to keep track of the offset when requesting to make sure no old messages are received
|
||||||
to_delete = [] # list of messages to be deleted
|
to_delete = [] # list of messages to be deleted
|
||||||
|
|
||||||
@ -54,8 +45,7 @@ async def main():
|
|||||||
try:
|
try:
|
||||||
user = (await response.json())["id"]
|
user = (await response.json())["id"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("User ID not found in JSON response. Actual JSON response: " + json.dumps(await response.json(), indent=4))
|
raise Exception("User ID not found in JSON response. Actual JSON response: " + json.dumps(await response.json(), indent=4))
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# looping to fill up list of messages by requesting batches of messages from the API and adding them to the list
|
# looping to fill up list of messages by requesting batches of messages from the API and adding them to the list
|
||||||
while True:
|
while True:
|
||||||
@ -74,11 +64,9 @@ async def main():
|
|||||||
try:
|
try:
|
||||||
print(json.dumps(await response.json(), indent=4))
|
print(json.dumps(await response.json(), indent=4))
|
||||||
print("Channel is not yet indexed. Waiting for " + str((await response.json())["retry_after"]) + "s as requested by the Discord API")
|
print("Channel is not yet indexed. Waiting for " + str((await response.json())["retry_after"]) + "s as requested by the Discord API")
|
||||||
sys.exit(1)
|
|
||||||
await asyncio.sleep((await response.json())["retry_after"])
|
await asyncio.sleep((await response.json())["retry_after"])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
print("Unexpected JSON response received from Discord after trying to search for messages. Actual JSON response: " + json.dumps(await response.json(), indent=4))
|
raise Exception("Unexpected JSON response received from Discord after trying to search for messages. Actual JSON response: " + json.dumps(await response.json(), indent=4))
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# if the batch is not empty, adding the messages in batch to the list of messages to be deleted
|
# if the batch is not empty, adding the messages in batch to the list of messages to be deleted
|
||||||
if batch:
|
if batch:
|
||||||
@ -98,7 +86,7 @@ async def main():
|
|||||||
|
|
||||||
# looping infinitely until message is successfully deleted
|
# looping infinitely until message is successfully deleted
|
||||||
while True:
|
while True:
|
||||||
async with session.request("DELETE", channel_url + "/messages/" + message[0]["id"], headers=headers) as response:
|
async with session.request("DELETE", "https://discord.com/api/v9/channels/" + message[0]["channel_id"] + "/messages/" + message[0]["id"], headers=headers) as response:
|
||||||
# if successful status returned, printing success message and breaking out of loop
|
# if successful status returned, printing success message and breaking out of loop
|
||||||
if 200 <= response.status <= 299:
|
if 200 <= response.status <= 299:
|
||||||
deleted_messages += 1
|
deleted_messages += 1
|
||||||
@ -119,8 +107,7 @@ async def main():
|
|||||||
# otherwise, printing out json response and aborting
|
# otherwise, printing out json response and aborting
|
||||||
else:
|
else:
|
||||||
print(response.status)
|
print(response.status)
|
||||||
print("Unexpected HTTP status code received. Actual response: " + json.dumps(await response.json(), indent=4))
|
raise Exception("Unexpected HTTP status code received. Actual response: " + json.dumps(await response.json(), indent=4))
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
Reference in New Issue
Block a user