├── config.json ├── t.mp3 ├── settings.json ├── readme.md ├── siftdude.py └── dude.py /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "config_filename": "settings.json" 3 | } 4 | -------------------------------------------------------------------------------- /t.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TrueStrikes/CopyCode/HEAD/t.mp3 -------------------------------------------------------------------------------- /settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "bot_token": "YOUR_USER_TOKEN", 3 | "target_user_ids": ["TARGET_USER_ID_1", "TARGET_USER_ID_2"], 4 | "target_channels": ["TARGET_CHANNEL_ID_1", "TARGET_CHANNEL_ID_2"], 5 | "auto_action_mode": false 6 | } 7 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # CopyCat Discord Bot 2 | 3 | The CopyCat Discord Bot is a Python script designed to efficiently monitor specified Discord channels for user-generated content (UGC) codes. It is intended to automate the process of sniping UGC codes, which can often be time-sensitive due to their limited availability. 4 | 5 | 6 | **Tydummy.py only works with stealing from typedummy bot** 7 | 8 | ## Purpose 9 | 10 | Many online communities frequently share UGC codes (e.g., game item codes, discounts, giveaways) within Discord channels. CopyCat provides a way to swiftly capture and utilize these codes using a bot, enhancing your chances of obtaining them before they expire. 11 | 12 | ## Instructions 13 | 14 | ### Requirements: 15 | 16 | - Python 3.6 or later 17 | - External modules: `requests`, `pygame`, `colorama`, `clipboard` 18 | 19 | ### Installation: 20 | 21 | 1. Clone this repository to your local machine or download the script. 22 | 23 | 2. Open a terminal or command prompt and navigate to the directory where the script is located. 24 | 25 | 3. Install the required external modules using the following command: 26 | 27 | 28 | ### Usage: 29 | 30 | 1. **Configuring the Bot:** 31 | 32 | - Create a new `config.json` file in the same directory as the script. 33 | - Fill in the `config.json` with the following content: 34 | 35 | ```json 36 | { 37 | "config_filename": "settings.json" 38 | } 39 | ``` 40 | 41 | - Create a new file named `settings.json` in the same directory as the script (`dude.py`) and configure it with your Discord bot token, target user IDs, and target channel IDs. For example: 42 | 43 | ```json 44 | { 45 | "bot_token": "YOUR_USER_TOKEN", 46 | "target_user_ids": ["TARGET_USER_ID_1", "TARGET_USER_ID_2"], 47 | "target_channels": ["TARGET_CHANNEL_ID_1", "TARGET_CHANNEL_ID_2"] 48 | } 49 | ``` 50 | 51 | Replace `"YOUR_USER_TOKEN"`, `"TARGET_USER_ID_1"`, `"TARGET_USER_ID_2"`, `"TARGET_CHANNEL_ID_1"`, and `"TARGET_CHANNEL_ID_2"` with your actual values. 52 | 53 | - To find your Discord user token, you can watch this tutorial video: [How to Get a Discord user Token](https://www.youtube.com/watch?v=YjiQ7CajAgg) 54 | - To find the channel ID, you can watch this tutorial video: [How to Get a Discord Channel ID](https://www.youtube.com/watch?v=YEgFvgg7ZPI) 55 | 56 | 2. **Running the Script:** 57 | 58 | - In the terminal or command prompt, navigate to the directory where the script (`dude.py`) is located. 59 | 60 | - Install the required external modules using the following command: 61 | 62 | ``` 63 | pip install requests pygame colorama clipboard 64 | ``` 65 | 66 | - Run the script using the following command: 67 | 68 | ``` 69 | python dude.py 70 | ``` 71 | 72 | - The script will start monitoring the specified Discord channels for messages from the target users. 73 | - When it detects a message from a target user, it will copy the message content to the clipboard and play the sound "t.mp3" to alert you. 74 | 75 | ### Creating Multiple "Preloads": 76 | 77 | You can set up multiple configurations ("preloads") by creating additional JSON files based on the template provided. Each JSON file can contain a different combination of bot token, target user IDs, and target channel IDs. This allows you to quickly switch between different settings without modifying the main script. 78 | 79 | Follow these steps to create and use multiple "preloads": 80 | 81 | 1. **Create a New JSON File:** 82 | 83 | - Duplicate the `settings.json` file and rename it to something meaningful (e.g., `preload1.json`, `preload2.json`, etc.). 84 | 85 | 2. **Edit the New JSON File:** 86 | 87 | - Open the new JSON file using a text editor. 88 | - Modify the `bot_token`, `target_user_ids`, and `target_channels` values to your desired settings. 89 | 90 | ```json 91 | { 92 | "bot_token": "NEW_USER_TOKEN", 93 | "target_user_ids": ["NEW_TARGET_USER_ID_1", "NEW_TARGET_USER_ID_2"], 94 | "target_channels": ["NEW_TARGET_CHANNEL_ID_1", "NEW_TARGET_CHANNEL_ID_2"] 95 | } 96 | ``` 97 | 98 | 3. **Update `config.json`:** 99 | 100 | - Open the `config.json` file and replace the `config_filename` value with the filename of your new JSON file. 101 | 102 | ```json 103 | { 104 | "config_filename": "preload1.json" 105 | } 106 | ``` 107 | 108 | - Now the script will load the settings from the new JSON file specified in `config.json`. 109 | 110 | 4. **Run the Script:** 111 | 112 | - Follow the previous instructions to install external modules and run the script using the new JSON file. 113 | 114 | Using this method, you can easily switch between different "preloads" by changing the `config.json` file. Each JSON file represents a unique configuration that you can quickly switch to without modifying the main script. 115 | 116 | **Quick note** 117 | - Auto action mode automatically click the redeem button and the textbot for you, so you can be "safe" if you have slow reflexes. 118 | 119 | ### Important Notes: 120 | 121 | - Be sure to name your new JSON files meaningfully to reflect the different configurations you're using. 122 | - Always ensure that the JSON syntax is correct in your new configuration files to avoid errors. 123 | - The script will only load settings from the JSON file specified in `config.json`. 124 | 125 | Feel free to customize and organize your configurations based on your needs. 126 | 127 | ### Disclaimer 128 | 129 | 130 | # For support join https://discord.gg/uWsd5Bp4 and create a ticket 131 | -------------------------------------------------------------------------------- /siftdude.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import os 4 | import time 5 | import threading 6 | import re 7 | import random 8 | import pygame 9 | import colorama 10 | import clipboard 11 | import keyboard 12 | import pyautogui 13 | 14 | # Initialize colorama 15 | colorama.init() 16 | 17 | # Set to keep track of retrieved message IDs and user messages 18 | retrieved_message_ids = set() 19 | user_messages = set() 20 | 21 | # Variable to indicate if the script is running 22 | running = True 23 | 24 | # Function to save auto action coordinates to a file 25 | def save_auto_action_coordinates(x, y, filename): 26 | with open(filename, "w") as f: 27 | f.write(f"{x},{y}") 28 | 29 | # Function to load auto action coordinates from a file 30 | def load_auto_action_coordinates(filename): 31 | try: 32 | with open(filename, "r") as f: 33 | coordinates = f.read().strip().split(',') 34 | if len(coordinates) == 2: 35 | return int(coordinates[0]), int(coordinates[1]) 36 | except (FileNotFoundError, ValueError): 37 | pass 38 | return None 39 | 40 | # Function to get confirmation for coordinates 41 | def get_coordinates_confirmation(filename, action_name): 42 | use_existing = input(f"Would you like to use the last {action_name} coordinates? (y/n): ") 43 | if use_existing.lower() == 'y': 44 | existing_coordinates = load_auto_action_coordinates(filename) 45 | if existing_coordinates: 46 | print(f"Using existing {action_name} coordinates: {existing_coordinates}") 47 | return existing_coordinates 48 | print(f"Please hover your mouse over the {action_name} and press 's' to save the coordinates.") 49 | keyboard.wait('s', suppress=True) 50 | new_coordinates = pyautogui.position() 51 | save_auto_action_coordinates(new_coordinates[0], new_coordinates[1], filename) 52 | print(f"New {action_name} coordinates saved: {new_coordinates}") 53 | return new_coordinates 54 | 55 | # Read the filename of the JSON file from config.json 56 | config_filename = "config.json" 57 | try: 58 | with open(config_filename, 'r') as config_file: 59 | config_data = json.load(config_file) 60 | except (FileNotFoundError, json.JSONDecodeError): 61 | config_data = {} # If there's an error or the file doesn't exist, initialize an empty config dictionary 62 | 63 | # Load the settings from the specified file 64 | settings_filename = config_data.get("config_filename", "settings.json") 65 | try: 66 | with open(settings_filename, 'r') as settings_file: 67 | settings_data = json.load(settings_file) 68 | bot_token = settings_data.get("bot_token", "") 69 | target_user_ids = settings_data.get("target_user_ids", []) 70 | target_channels = settings_data.get("target_channels", []) 71 | auto_action_mode = settings_data.get("auto_action_mode", False) 72 | textbox_coordinates_file_name = settings_data.get("textbox_coordinates_file_name", "textbox_coordinates.txt") 73 | redeem_coordinates_file_name = settings_data.get("redeem_coordinates_file_name", "redeem_coordinates.txt") 74 | except (FileNotFoundError, json.JSONDecodeError): 75 | bot_token = "" 76 | target_user_ids = [] 77 | target_channels = [] 78 | auto_action_mode = False 79 | textbox_coordinates_file_name = "textbox_coordinates.txt" 80 | redeem_coordinates_file_name = "redeem_coordinates.txt" 81 | 82 | # Check if auto action mode is enabled 83 | textbox_coordinates = None 84 | empty_space_coordinates = None 85 | redeem_coordinates = None 86 | 87 | if auto_action_mode: 88 | textbox_coordinates = get_coordinates_confirmation(textbox_coordinates_file_name, "textbox") 89 | 90 | # Prompt for an empty space between textbox and redeem 91 | empty_space_coordinates = get_coordinates_confirmation("empty_space_coordinates.txt", "empty space") 92 | 93 | redeem_coordinates = get_coordinates_confirmation(redeem_coordinates_file_name, "redeem button") 94 | 95 | else: 96 | print("Auto action mode is disabled.") 97 | 98 | def display_message(channelid, message): 99 | message_id = message.get('id') 100 | if message_id not in retrieved_message_ids: 101 | retrieved_message_ids.add(message_id) 102 | author_id = message.get('author', {}).get('id') 103 | content = message.get('content') 104 | if author_id in target_user_ids and content not in user_messages: 105 | lines = content.split('\n') 106 | if len(lines) > 1: 107 | cleaned_content = random.choice(lines) 108 | else: 109 | cleaned_content = lines[0] 110 | 111 | copy_to_clipboard(cleaned_content) 112 | play_sound("t.mp3") # Play the sound "t.mp3" 113 | 114 | if auto_action_mode: 115 | # Click the textbox (twice) 116 | pyautogui.click(textbox_coordinates[0], textbox_coordinates[1]) 117 | time.sleep(0.05) 118 | pyautogui.click(textbox_coordinates[0], textbox_coordinates[1]) 119 | 120 | keyboard.press_and_release('ctrl+a') 121 | time.sleep(0.05) 122 | keyboard.press_and_release('ctrl+a') 123 | 124 | keyboard.press_and_release('ctrl+v') 125 | pyautogui.click(empty_space_coordinates[0], empty_space_coordinates[1]) 126 | # Click the redeem button (twice) 127 | pyautogui.click(redeem_coordinates[0], redeem_coordinates[1]) 128 | pyautogui.click(redeem_coordinates[0], redeem_coordinates[1]) 129 | 130 | print(colorama.Fore.GREEN + "Auto redeem done") 131 | print(colorama.Style.RESET_ALL) 132 | 133 | if cleaned_content.strip(): # Check if the cleaned content is not empty 134 | print(colorama.Fore.YELLOW + "Message:") 135 | print(cleaned_content) 136 | print(colorama.Style.RESET_ALL) 137 | user_messages.add(content) 138 | 139 | def retrieve_latest_messages(channelid): 140 | headers = { 141 | 'authorization': bot_token 142 | } 143 | params = { 144 | 'limit': 1 # Update to retrieve the last 5 messages 145 | } 146 | r = requests.get(f'https://discord.com/api/v8/channels/{channelid}/messages', headers=headers, params=params) 147 | try: 148 | messages = json.loads(r.text) 149 | except json.JSONDecodeError as e: 150 | print("JSON decode error:", e) 151 | return [] 152 | 153 | if not isinstance(messages, list) or len(messages) == 0: 154 | return [] 155 | 156 | return messages 157 | 158 | def play_sound(sound_filename): 159 | try: 160 | pygame.mixer.init() 161 | pygame.mixer.music.load(sound_filename) 162 | pygame.mixer.music.play() 163 | except Exception as e: 164 | print("Error playing sound:", e) 165 | 166 | # Copy the message content to the clipboard 167 | def copy_to_clipboard(content): 168 | clipboard.copy(content) 169 | 170 | # Set the loop to run indefinitely 171 | while True: 172 | if running and bot_token and target_user_ids and target_channels: 173 | headers = { 174 | 'authorization': bot_token 175 | } 176 | 177 | for channel_id in target_channels: 178 | latest_messages = retrieve_latest_messages(channel_id) 179 | if latest_messages: 180 | for message in latest_messages: 181 | display_message(channel_id, message) 182 | 183 | time.sleep(0.05) # Add a wait time of 0.05 seconds before the next iteration 184 | -------------------------------------------------------------------------------- /dude.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import json 3 | import os 4 | import time 5 | import threading 6 | import re 7 | import pygame 8 | import colorama 9 | import clipboard 10 | import keyboard 11 | import pyautogui 12 | 13 | # Initialize colorama 14 | colorama.init() 15 | 16 | # Set to keep track of retrieved message IDs and user messages 17 | retrieved_message_ids = set() 18 | user_messages = set() 19 | 20 | # Variable to indicate if the script is running 21 | running = True 22 | 23 | # Function to save auto action coordinates to a file 24 | def save_auto_action_coordinates(x, y, filename): 25 | with open(filename, "w") as f: 26 | f.write(f"{x},{y}") 27 | 28 | # Function to load auto action coordinates from a file 29 | def load_auto_action_coordinates(filename): 30 | try: 31 | with open(filename, "r") as f: 32 | coordinates = f.read().strip().split(',') 33 | if len(coordinates) == 2: 34 | return int(coordinates[0]), int(coordinates[1]) 35 | except (FileNotFoundError, ValueError): 36 | pass 37 | return None 38 | 39 | # Function to get confirmation for coordinates 40 | def get_coordinates_confirmation(filename, action_name): 41 | use_existing = input(f"Would you like to use the last {action_name} coordinates? (y/n): ") 42 | if use_existing.lower() == 'y': 43 | existing_coordinates = load_auto_action_coordinates(filename) 44 | if existing_coordinates: 45 | print(f"Using existing {action_name} coordinates: {existing_coordinates}") 46 | return existing_coordinates 47 | print(f"Please hover your mouse over the {action_name} and press 's' to save the coordinates.") 48 | keyboard.wait('s', suppress=True) 49 | new_coordinates = pyautogui.position() 50 | save_auto_action_coordinates(new_coordinates[0], new_coordinates[1], filename) 51 | print(f"New {action_name} coordinates saved: {new_coordinates}") 52 | return new_coordinates 53 | 54 | # Read the filename of the JSON file from config.json 55 | config_filename = "config.json" 56 | try: 57 | with open(config_filename, 'r') as config_file: 58 | config_data = json.load(config_file) 59 | except (FileNotFoundError, json.JSONDecodeError): 60 | config_data = {} # If there's an error or the file doesn't exist, initialize an empty config dictionary 61 | 62 | # Load the settings from the specified file 63 | settings_filename = config_data.get("config_filename", "settings.json") 64 | try: 65 | with open(settings_filename, 'r') as settings_file: 66 | settings_data = json.load(settings_file) 67 | bot_token = settings_data.get("bot_token", "") 68 | target_user_ids = settings_data.get("target_user_ids", []) 69 | target_channels = settings_data.get("target_channels", []) 70 | auto_action_mode = settings_data.get("auto_action_mode", False) 71 | textbox_coordinates_file_name = settings_data.get("textbox_coordinates_file_name", "textbox_coordinates.txt") 72 | redeem_coordinates_file_name = settings_data.get("redeem_coordinates_file_name", "redeem_coordinates.txt") 73 | except (FileNotFoundError, json.JSONDecodeError): 74 | bot_token = "" 75 | target_user_ids = [] 76 | target_channels = [] 77 | auto_action_mode = False 78 | textbox_coordinates_file_name = "textbox_coordinates.txt" 79 | redeem_coordinates_file_name = "redeem_coordinates.txt" 80 | 81 | # Check if auto action mode is enabled 82 | textbox_coordinates = None 83 | empty_space_coordinates = None 84 | redeem_coordinates = None 85 | 86 | if auto_action_mode: 87 | textbox_coordinates = get_coordinates_confirmation(textbox_coordinates_file_name, "textbox") 88 | 89 | # Prompt for an empty space between textbox and redeem 90 | empty_space_coordinates = get_coordinates_confirmation("empty_space_coordinates.txt", "empty space") 91 | 92 | redeem_coordinates = get_coordinates_confirmation(redeem_coordinates_file_name, "redeem button") 93 | 94 | else: 95 | print("Auto action mode is disabled.") 96 | 97 | def display_message(channelid, message): 98 | message_id = message.get('id') 99 | if message_id not in retrieved_message_ids: 100 | retrieved_message_ids.add(message_id) 101 | author_id = message.get('author', {}).get('id') 102 | content = message.get('content') 103 | if author_id in target_user_ids and content not in user_messages: 104 | copy_to_clipboard(content) 105 | play_sound("t.mp3") # Play the sound "t.mp3" 106 | cleaned_content = remove_discord_formatting(content) 107 | if auto_action_mode: 108 | # Click the textbox (twice) 109 | pyautogui.click(textbox_coordinates[0], textbox_coordinates[1]) 110 | time.sleep(0.05) 111 | pyautogui.click(textbox_coordinates[0], textbox_coordinates[1]) 112 | 113 | keyboard.press_and_release('ctrl+a') 114 | time.sleep(0.05) 115 | keyboard.press_and_release('ctrl+a') 116 | 117 | keyboard.press_and_release('ctrl+v') 118 | pyautogui.click(empty_space_coordinates[0], empty_space_coordinates[1]) 119 | # Click the redeem button (twice) 120 | pyautogui.click(redeem_coordinates[0], redeem_coordinates[1]) 121 | pyautogui.click(redeem_coordinates[0], redeem_coordinates[1]) 122 | 123 | print(colorama.Fore.GREEN + "Auto redeem done") 124 | print(colorama.Style.RESET_ALL) 125 | if cleaned_content.strip(): # Check if the cleaned content is not empty 126 | print(colorama.Fore.YELLOW + "Message:") 127 | print(cleaned_content) 128 | print(colorama.Style.RESET_ALL) 129 | copy_to_clipboard(cleaned_content) # Copy the cleaned message content to the clipboard 130 | user_messages.add(content) 131 | def remove_discord_formatting(content): 132 | # Remove '# ' from the beginning 133 | content = re.sub(r'^#\s*', '', content) 134 | 135 | # Handle triple backticks (``` ... ```) 136 | code_blocks = re.findall(r'```.*?```', content, flags=re.DOTALL) 137 | for block in code_blocks: 138 | content = content.replace(block, block[3:-3]) # Remove triple backticks 139 | 140 | # Remove double backticks 141 | content = re.sub(r'`.*?`', '', content) 142 | 143 | # Remove strikethrough 144 | content = re.sub(r'~~(.*?)~~', r'\1', content) 145 | 146 | return content 147 | 148 | def retrieve_latest_messages(channelid): 149 | headers = { 150 | 'authorization': bot_token 151 | } 152 | params = { 153 | 'limit': 1 # Update to retrieve the last 5 messages 154 | } 155 | r = requests.get(f'https://discord.com/api/v8/channels/{channelid}/messages', headers=headers, params=params) 156 | try: 157 | messages = json.loads(r.text) 158 | except json.JSONDecodeError as e: 159 | print("JSON decode error:", e) 160 | return [] 161 | 162 | if not isinstance(messages, list) or len(messages) == 0: 163 | return [] 164 | 165 | return messages 166 | 167 | def play_sound(sound_filename): 168 | try: 169 | pygame.mixer.init() 170 | pygame.mixer.music.load(sound_filename) 171 | pygame.mixer.music.play() 172 | except Exception as e: 173 | print("Error playing sound:", e) 174 | 175 | # Copy the message content to the clipboard 176 | def copy_to_clipboard(content): 177 | clipboard.copy(content) 178 | 179 | # Perform auto enter (Ctrl + V, Enter) 180 | def perform_auto_enter(): 181 | try: 182 | keyboard.press_and_release('ctrl+a') 183 | time.sleep(0.05) 184 | keyboard.press_and_release('ctrl+v') 185 | except Exception as e: 186 | print("Error performing auto enter:", e) 187 | 188 | # Set the loop to run indefinitely 189 | while True: 190 | if running and bot_token and target_user_ids and target_channels: 191 | headers = { 192 | 'authorization': bot_token 193 | } 194 | 195 | for channel_id in target_channels: 196 | latest_messages = retrieve_latest_messages(channel_id) 197 | if latest_messages: 198 | for message in latest_messages: 199 | display_message(channel_id, message) 200 | 201 | time.sleep(0.05) # Add a wait time of 0.05 seconds before the next iteration 202 | --------------------------------------------------------------------------------