|
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) |
|
|
|
|
|
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 |
|
|
|
|
|
is_shiny = pet_name.startswith("Shiny ") |
|
|
|
|
|
if is_shiny: |
|
|
|
base_name = pet_name.replace("Shiny ", "") |
|
title = f"✨ ***SHINY*** {base_name} was rolled! ✨" |
|
embed_color = discord.Color.from_rgb(255, 255, 255) |
|
else: |
|
|
|
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) |