diff --git a/DiscordBot/data/example_messages.csv b/DiscordBot/data/example_messages.csv new file mode 100644 index 00000000..d6e29018 --- /dev/null +++ b/DiscordBot/data/example_messages.csv @@ -0,0 +1,8 @@ +timestamp,author,content,avatar_url +2024-01-01 10:00:00,AliceBot,Hey everyone! How's it going?,https://localo.com/assets/img/definitions/what-is-bot.webp +2024-01-01 10:01:15,BobBot,Doing great! Just finished a new project.,https://icon2.cleanpng.com/lnd/20241228/ls/09db2e0f20aed7661d7cd78b8e501a.webp +2024-01-01 10:02:30,CharlieBot,That's awesome! What kind of project?,https://static.wikia.nocookie.net/nickelodeon/images/5/53/Team-umizoomi-bot-character-main-550x510.png/revision/latest?cb=20180623174206 +2024-01-01 10:03:45,BobBot,I'd kill for a machine learning model with sentiment analysis.,https://icon2.cleanpng.com/lnd/20241228/ls/09db2e0f20aed7661d7cd78b8e501a.webp +2024-01-01 10:05:00,AliceBot,Nice! I'd love to hear more about it.,https://localo.com/assets/img/definitions/what-is-bot.webp +2024-01-01 10:06:15,DaveBot,@AliceBot Did you see the latest research paper on transformers?,https://cdn.vectorstock.com/i/1000v/39/44/cute-cartoon-robot-on-white-background-vector-25753944.jpg +2024-01-01 10:07:30,EveBot,I think I missed that one. Can someone share the link?,https://imgcdn.stablediffusionweb.com/2024/6/6/003dbda7-b176-432c-a2b9-141131c03d03.jpg diff --git a/DiscordBot/init_server.py b/DiscordBot/init_server.py new file mode 100644 index 00000000..c8405a58 --- /dev/null +++ b/DiscordBot/init_server.py @@ -0,0 +1,109 @@ +import csv +import json +import requests +import time +from typing import List, Dict +import asyncio +import discord +import sys + +class ChannelSeeder: + """ + Seeds a Discord channel with messages from CSV files. + Uses webhooks to post messages with different bot/user personas. + """ + + def __init__(self, webhook_url: str): + """ + Initialize with a webhook URL for the target channel. + """ + self.webhook_url = webhook_url + self.bot_avatars = {} # Map bot names to avatar URLs + + + def load_messages(self, filepath: str) -> List[Dict]: + """ + Load messages from CSV. + Expected columns: timestamp, author, content, (optional: avatar_url) + """ + messages = [] + with open(filepath, 'r') as f: + reader = csv.DictReader(f) + for row in reader: + messages.append({ + 'timestamp': row.get('timestamp', ''), + 'author': row['author'].strip(), + 'content': row['content'], + 'avatar_url': row.get('avatar_url', None) + }) + + # Sort by timestamp if present + if messages and messages[0]['timestamp']: + messages.sort(key=lambda x: x['timestamp']) + + return messages + + def send_webhook_message(self, username: str, content: str, avatar_url: str = None): + """ + Send a message through the webhook with a custom username and avatar. + """ + data = { + "content": content, + "username": username + } + + if avatar_url: + data["avatar_url"] = avatar_url + + response = requests.post(self.webhook_url, json=data) + + # Discord rate limits webhooks to 5 requests per 2 seconds + if response.status_code == 429: + retry_after = response.json().get('retry_after', 2) + print(f"Rate limited. Waiting {retry_after} seconds...") + time.sleep(retry_after) + return self.send_webhook_message(username, content, avatar_url) + + if response.status_code not in [200, 204]: + print(f"Error sending message: {response.status_code} - {response.text}") + return False + + return True + + def seed_channel(self, messages_file: str, delay: float = 0.5): + """ + Seed the channel with messages from CSV. + + Args: + messages_file: Path to CSV file with messages + delay: Delay between messages in seconds (to avoid rate limits) + """ + messages = self.load_messages(messages_file) + + print(f"Seeding channel with {len(messages)} messages...") + + for i, msg in enumerate(messages): + success = self.send_webhook_message( + username=msg['author'], + content=msg['content'], + avatar_url=msg.get('avatar_url') + ) + + if success: + print(f"Sent message {i+1}/{len(messages)}: {msg['author']}: {msg['content'][:50]}...") + + time.sleep(delay) # Respect rate limits + + print("Channel seeding complete!") + + +# Example usage +if __name__ == "__main__": + # You need to create a webhook in your Discord channel first + dataset = sys.argv[1] # Pass dataset path as command line argument + WEBHOOK_URL = sys.argv[2] # Pass webhook URL as command line argument + + seeder = ChannelSeeder(WEBHOOK_URL) + + # Seed the channel with messages + seeder.seed_channel(dataset, delay=0.6) \ No newline at end of file diff --git a/README.md b/README.md index d2169bbc..679a77ef 100644 --- a/README.md +++ b/README.md @@ -117,9 +117,27 @@ You’ll need to install some libraries if you don’t have them already, namely # python3 -m pip install requests # python3 -m pip install discord.py + +#### Populating the channel +We will share with you a webhook that you can use to pre-populate your channel with a dataset of your choice. +First, make sure the dataset is in the required format, as in [the example dataset](DiscordBot/data/example_messages.csv). +Then, use the WEBHOOK url we provide you with to initialize your channel with that content: +``` +python init_server.py data/example_messages.csv +``` + +If there are any issues, carefully check the format of your dataset. + +For more information on Discord's webhooks, refer to the following [documentation](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks). + ### [Optional] Setting up your own server If you want to test out additional permissions/channels/features without having to wait for the TAs to make changes for you, you are welcome to create your own Discord server and invite your bot there instead! The starter code should support having the bot on multiple servers at once. If you do make your server, make sure to add a `group-#` and `group-#-mod` channel, as the bot’s code relies on having those channels for it to work properly. Just know that you’ll eventually need to move back into the 152 server. +If you set up your own server and would like to use the init_server.py script to pre-populate it with your dataset, you will need to add a Webhook to the relevant channel. To create a webhook: + 1. Go to your Discord server + 2. Click Settings (gear icon) > Integrations > Webhooks + 3. Click "New Webhook" and copy the webhook URL + 4. Select the relevant channel for the Webhook ## Guide To The Starter Code