|
import os |
|
import requests |
|
import discord |
|
from discord.ext import commands |
|
import asyncio |
|
import re |
|
from datetime import datetime, timedelta |
|
from collections import defaultdict |
|
from aiohttp import web |
|
|
|
|
|
app = web.Application() |
|
|
|
async def hello(request): |
|
return web.Response(text="Hello World") |
|
|
|
app.router.add_get('/', hello) |
|
|
|
TOKEN = os.environ.get('token') |
|
|
|
|
|
intents = discord.Intents.default() |
|
intents.message_content = True |
|
bot = commands.Bot(command_prefix='!', intents=intents) |
|
|
|
CHANNEL_ID = 1298830206387228682 |
|
PETS_API = 'https://petsapi.deno.dev/' |
|
EXISTS_API = 'https://existsapi.deno.dev/' |
|
RAP_API = 'https://rapapi.deno.dev/' |
|
|
|
pet_images = {} |
|
pet_difficulties = {} |
|
pet_raps = {} |
|
hourly_hatches = defaultdict(list) |
|
|
|
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}") |
|
|
|
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"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): |
|
if is_change and current_value > previous_value: |
|
hatches = current_value - previous_value |
|
for _ in range(hatches): |
|
hourly_hatches[pet_name].append(datetime.now()) |
|
|
|
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") |
|
|
|
if isinstance(rap_value, (int, float)): |
|
rap_display = f"{rap_value:,}" |
|
else: |
|
rap_display = rap_value |
|
|
|
if isinstance(difficulty, (int, float)): |
|
difficulty_display = f"{difficulty:,}" |
|
else: |
|
difficulty_display = difficulty |
|
|
|
if isinstance(current_value, (int, float)): |
|
current_display = f"{current_value:,}" |
|
else: |
|
current_display = current_value |
|
|
|
if isinstance(previous_value, (int, float)): |
|
previous_display = f"{previous_value:,}" |
|
else: |
|
previous_display = previous_value |
|
|
|
embed = discord.Embed( |
|
title=f"π² A {pet_name} was rolled! π²", |
|
description=f"{pet_name} exists: **{current_display}**\nDifficulty: **1 in {difficulty_display}**\nRAP Value: **{rap_display}**", |
|
color=discord.Color.blue() if not is_change else discord.Color.orange(), |
|
) |
|
|
|
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() |
|
lastknown = {pet: None for pet in tracked_pets} |
|
print(f"Initially tracking {len(tracked_pets)} pets") |
|
|
|
while True: |
|
cleanup_old_hatches() |
|
|
|
if not tracked_pets: |
|
tracked_pets = await get_huge_secret_pets() |
|
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]: |
|
await send_embed_message(channel, pet, lastknown[pet], value, is_change=True) |
|
lastknown[pet] = value |
|
else: |
|
print("Broken check") |
|
|
|
if len(tracked_pets) > 0: |
|
new_pets = await get_huge_secret_pets() |
|
if 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) |
|
|
|
def cleanup_old_hatches(): |
|
one_hour_ago = datetime.now() - timedelta(hours=1) |
|
for pet in hourly_hatches: |
|
hourly_hatches[pet] = [timestamp for timestamp in hourly_hatches[pet] |
|
if timestamp > one_hour_ago] |
|
|
|
@bot.command(name='lasthour') |
|
async def last_hour_stats(ctx): |
|
cleanup_old_hatches() |
|
|
|
if not hourly_hatches: |
|
await ctx.send("No pets have been hatched in the last hour.") |
|
return |
|
|
|
total_hatches = sum(len(hatches) for hatches in hourly_hatches.values()) |
|
|
|
embed = discord.Embed( |
|
title="π Last Hour Hatch Statistics π", |
|
description=f"Total hatches in the last hour: **{total_hatches}**", |
|
color=discord.Color.green() |
|
) |
|
|
|
sorted_pets = sorted( |
|
hourly_hatches.items(), |
|
key=lambda x: len(x[1]), |
|
reverse=True |
|
) |
|
|
|
for pet_name, hatches in sorted_pets: |
|
if hatches: |
|
count = len(hatches) |
|
difficulty = pet_difficulties.get(pet_name, "Unknown") |
|
rap_value = pet_raps.get(pet_name, "No RAP") |
|
|
|
if isinstance(rap_value, (int, float)): |
|
rap_display = f"{rap_value:,}" |
|
else: |
|
rap_display = rap_value |
|
|
|
if isinstance(difficulty, (int, float)): |
|
difficulty_display = f"{difficulty:,}" |
|
else: |
|
difficulty_display = difficulty |
|
|
|
embed.add_field( |
|
name=pet_name, |
|
value=f"Hatches: **{count}**\nDifficulty: 1 in {difficulty_display}\nRAP: {rap_display}", |
|
inline=True |
|
) |
|
|
|
embed.set_footer(text=f"Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") |
|
|
|
await ctx.send(embed=embed) |
|
|
|
@bot.event |
|
async def on_ready(): |
|
print(f'Logged in as {bot.user.name}') |
|
bot.loop.create_task(main_loop()) |
|
|
|
runner = web.AppRunner(app) |
|
await runner.setup() |
|
site = web.TCPSite(runner, '0.0.0.0', 7860) |
|
await site.start() |
|
print(f"Web server started on port 7860") |
|
|
|
def run_bot(): |
|
bot.run(TOKEN) |
|
|
|
if __name__ == "__main__": |
|
run_bot() |