import requests import discord from discord.ext import commands import asyncio import re from collections import deque from datetime import datetime, timedelta import os TOKEN = os.environ['TOKEN'] CHANNEL_ID = 1298830206387228682 PETS_API = 'https://petsapi.deno.dev/' EXISTS_API = 'https://existsapi.deno.dev/' RAP_API = 'https://rapapi.deno.dev/' intents = discord.Intents.default() bot = commands.Bot(command_prefix='!', intents=intents) pet_images = {} pet_difficulties = {} pet_raps = {} pet_changes = {} def format_number(number): if not isinstance(number, (int, float)): return str(number) abs_number = abs(number) if abs_number < 1000: return str(number) elif abs_number < 1000000: return f"{number/1000:.1f}K" elif abs_number < 1000000000: return f"{number/1000000:.1f}M" elif abs_number < 1000000000000: return f"{number/1000000000:.1f}B" else: return f"{number/1000000000000:.1f}T" async def update_rap_values(): try: response = requests.get(RAP_API) if response.status_code == 200: data = response.json() if data['status'] == 'ok': pet_raps.clear() for pet_data in data['data']: config_data = pet_data['configData'] pet_id = config_data['id'] value = pet_data['value'] is_shiny = config_data.get('sh', False) if is_shiny: pet_raps[f"Shiny {pet_id}"] = value else: pet_raps[pet_id] = value print(f"Updated RAP values for {len(data['data'])} pets") except Exception as e: print(f"Error fetching RAP values: {e}") def calculate_hourly_rate(pet_name): if pet_name not in pet_changes: return 0 changes = pet_changes[pet_name] if not changes: return 0 current_time = datetime.now() one_hour_ago = current_time - timedelta(hours=1) recent_changes = [change for change in changes if change['timestamp'] > one_hour_ago] if not recent_changes: return 0 if len(recent_changes) >= 2: earliest_value = recent_changes[0]['value'] latest_value = recent_changes[-1]['value'] return latest_value - earliest_value return 1 async def get_huge_secret_pets(): try: response = requests.get(PETS_API) if response.status_code == 200: data = response.json() if data['status'] == 'ok': huge_secret_pets = [] for pet in data['data']: config_data = pet['configData'] if config_data.get('huge') or config_data.get('secret'): pet_name = config_data['name'] huge_secret_pets.append(pet_name) huge_secret_pets.append(f"Shiny {pet_name}") difficulty = config_data.get('difficulty', 'Unknown') pet_difficulties[pet_name] = difficulty pet_difficulties[f"Shiny {pet_name}"] = difficulty * 100 if 'thumbnail' in config_data: pet_images[pet_name] = config_data['thumbnail'] pet_images[f"Shiny {pet_name}"] = config_data['thumbnail'] print(f"Stored image URL for {pet_name}: {config_data['thumbnail']}") for pet_name in huge_secret_pets: if pet_name not in pet_changes: pet_changes[pet_name] = deque(maxlen=100) print(f"Found {len(huge_secret_pets)} pets to track (including shiny versions)") return huge_secret_pets except Exception as e: print(f"Error fetching pets list: {e}") return [] async def send_embed_message(channel, pet_name, previous_value, current_value, is_change=False): pet_image_url = pet_images.get(pet_name, None) difficulty = pet_difficulties.get(pet_name, "Unknown") rap_value = pet_raps.get(pet_name, "No RAP") hourly_rate = calculate_hourly_rate(pet_name) # Format values with abbreviations difficulty_display = format_number(difficulty) if isinstance(difficulty, (int, float)) else difficulty rap_display = format_number(rap_value) if isinstance(rap_value, (int, float)) else rap_value current_display = format_number(current_value) if isinstance(current_value, (int, float)) else current_value previous_display = format_number(previous_value) if isinstance(previous_value, (int, float)) else previous_value hourly_rate_display = format_number(hourly_rate) if isinstance(hourly_rate, (int, float)) else hourly_rate # Check if the pet is shiny is_shiny = pet_name.startswith("Shiny ") # Format the title based on whether the pet is shiny if is_shiny: # For shiny pets: use sparkles and format "SHINY" in bold and italic base_name = pet_name.replace("Shiny ", "") title = f"✨ ***SHINY*** {base_name} was rolled! ✨" embed_color = discord.Color.from_rgb(255, 255, 255) # White color for shiny pets else: # For regular pets: use dice emoji title = f"🎲 A {pet_name} was rolled! 🎲" embed_color = discord.Color.blue() if not is_change else discord.Color.orange() embed = discord.Embed( title=title, description=f"{pet_name} exists: **{current_display}**\n" f"Difficulty: **1 in {difficulty_display}**\n" f"RAP Value: **{rap_display}**\n" f"Hourly Rate: **{hourly_rate_display}** per hour", color=embed_color ) if pet_image_url: if isinstance(pet_image_url, str): if pet_image_url.startswith('rbxassetid://'): asset_id = pet_image_url.replace('rbxassetid://', '') asset_id = re.search(r'^\d+', asset_id).group(0) pet_image_url = f"https://rbxgleaks.pythonanywhere.com/asset/{asset_id}" print(f"Using image URL for {pet_name}: {pet_image_url}") embed.set_thumbnail(url=pet_image_url) try: await channel.send(embed=embed) except discord.HTTPException as e: print(f"Failed to send embed for {pet_name}: {e}") await channel.send(f"🎲 A {pet_name} was rolled! Exists: {current_display} (Previous: {previous_display})") async def petdata(tracked_pets): try: response = requests.get(EXISTS_API) if response.status_code == 200: data = response.json() if data['status'] == 'ok': pet_values = {pet: 0 for pet in tracked_pets} for pet in data['data']: pet_id = pet['configData']['id'] is_shiny = pet['configData'].get('sh', False) value = pet['value'] pet_name = f"Shiny {pet_id}" if is_shiny else pet_id if pet_name in pet_values: print(f"Found pet: {pet_name} with exist count {value}") pet_values[pet_name] = value return pet_values print(f"Error code: {response.status_code}") except Exception as e: print(f"Error: {e}") return None async def main_loop(): channel = bot.get_channel(CHANNEL_ID) if channel is None: print("Invalid channel ID. Please check your channel ID.") return tracked_pets = await get_huge_secret_pets() if not tracked_pets: print("No pets fetched, retrying in 60 seconds...") await asyncio.sleep(60) return lastknown = {pet: None for pet in tracked_pets} print(f"Initially tracking {len(tracked_pets)} pets") while True: try: if not tracked_pets: tracked_pets = await get_huge_secret_pets() or [] lastknown.update({pet: None for pet in tracked_pets if pet not in lastknown}) await update_rap_values() vvalues = await petdata(tracked_pets) if vvalues is not None: for pet, value in vvalues.items(): if lastknown[pet] is None: print(f"Initial value for {pet}: {value}") elif value != lastknown[pet]: pet_changes[pet].append({ 'timestamp': datetime.now(), 'value': value, 'previous': lastknown[pet] }) await send_embed_message(channel, pet, lastknown[pet], value, is_change=True) lastknown[pet] = value else: print("Broken check") new_pets = await get_huge_secret_pets() or [] if new_pets and set(new_pets) != set(tracked_pets): print("Pet list updated!") tracked_pets = new_pets lastknown.update({pet: None for pet in tracked_pets if pet not in lastknown}) await asyncio.sleep(60) except Exception as e: print(f"Error in main loop: {e}") await asyncio.sleep(60) @bot.event async def on_ready(): print(f'Logged in as {bot.user.name}') bot.loop.create_task(main_loop()) bot.run(TOKEN)