Spaces:
Paused
Paused
import os | |
import requests | |
import random | |
import time | |
import logging | |
import threading | |
from fastapi import FastAPI | |
from dataclasses import dataclass, field | |
# Configuración de logging | |
logging.basicConfig( | |
level=logging.INFO, | |
format="%(asctime)s - %(levelname)s - %(message)s" | |
) | |
logger = logging.getLogger("DiscordLogger") | |
# Token y headers para la API de Discord | |
TOKEN = os.getenv("TOKEN") # Asegúrate de configurar la variable de entorno TOKEN | |
HEADERS = { | |
"User-Agent": "Mozilla/5.0", | |
"Accept": "*/*", | |
"Content-Type": "application/json", | |
"Authorization": TOKEN | |
} | |
# Listas por defecto de stickers y GIFs (puedes personalizarlos) | |
SANDRA_STICKER_IDS = [ | |
"1004733061377839155", "1069462756597714954", "1069464246276083783", | |
"1071961877590069329", "1135522478924496968", "1143089446959456266", | |
"1151968132378931341", "1167322137225342986", "1203740621668483112", | |
"1238703199091953725", "1240964158388961331", "1243564218741952663", | |
"1257957401236344915", "1260907231549980734", "1263109894807097404", | |
"1338763640630804490", "1338945320498888745" | |
] | |
SMASH_STICKERS_IDS = ["1275122399796531320", "1297373976481501236", "1297374313728446555", "1297374469744099368", "1297374773172502609", "1297375195337723904", "1299157034696179783", "1313635370059038725", "1325679489413550130", "1327084487603126323", "1328103130998505503", "1329330186612637706", "1330322740292354108", "1330592946613129286", "1333509212730298440", "1334940407296950355", "1338581218266185769", "1338766114863448085", "1339776105468395540", "1340047409430003782", "1340047616276172881", "1340821158399840357", "1341437725177286656", "1341909889789853748"] | |
SANDRA_GIF_URLS = [ | |
"https://tenor.com/view/cute-impatient-dog-bulldog-happy-gif-25124319", | |
"https://media.discordapp.net/attachments/978373982011150369/981008116990771270/9C48BE6C-EA86-49CF-90DB-C07F58AAE464.gif?ex=67b7d881&is=67b68701&hm=5b3a233dafc4de52414bae4280cb644fda85e12430a30470d7b2b59c78605d5a&", | |
"https://cdn.discordapp.com/attachments/1330367547249524788/1335016420110630992/SPOILER_Kiss-ezgif.com-speed.gif?ex=67b7aeed&is=67b65d6d&hm=fc5b5f4fed5e4af289dd4b257640d6891b3722b967aed56689057e1ce5ca0de9&", | |
"https://media.discordapp.net/attachments/1304500459565744161/1306263414607450142/media-iv-text.gif?ex=67b7e3db&is=67b6925b&hm=88be547a870fa4dc2ced25b470c2324a87b7ed7d0bfe8158a426f289c7b7d312&", | |
"https://media.discordapp.net/attachments/753808274062573639/809190519594025050/arana.gif?ex=67b7ade5&is=67b65c65&hm=422e139b8d883a76476022acfdddf8cb9dd0492bbc775540b228f1479828590f&", | |
"https://cdn.discordapp.com/attachments/1334611383442083901/1334611429583618138/cd16102f-4f11-45a3-b34a-0ccf58e3f982.gif?ex=67b78740&is=67b635c0&hm=6b129cbfe287257f6f476c3bb696b2b5d15614e93bb722e42051e639c0011be0&", | |
"https://media.discordapp.net/attachments/1330367547249524788/1334973793940144138/image0.gif?ex=67b7873b&is=67b635bb&hm=7429b7df7a90562babde0111e9bbcbfee1974ebbee12c857e8bbc59a2623a0af&=", | |
"https://media.discordapp.net/attachments/1037060119881601195/1176932252559622204/voicemessage.gif?ex=67b76193&is=67b61013&hm=394a35f837da28653683cb229f2209deeed4a9d6aaba2441de88968a34103342&=", | |
"https://tenor.com/view/funny-gif-11026644638307910936", | |
"https://tenor.com/view/bee-gif-2221550446572997929", | |
"https://cdn.discordapp.com/attachments/1330367547249524788/1341925949138010173/PERDONAME_POR_TODO_ALISON.gif?ex=67b7c56e&is=67b673ee&hm=0f974f8d5888ef5732f9b0ebee9276466e4dce4c99b7cc959327b0758a577357&", | |
"https://tenor.com/view/cats-cat-cute-run-kitten-gif-14804766", | |
"https://tenor.com/view/ok-i-pull-up-gif-27257886", | |
"https://tenor.com/view/fat-cat-fatty-sleepy-sleepfat-gif-27064818", | |
"https://tenor.com/view/angry-cat-gif-25783770", | |
"https://tenor.com/view/jalkiy-kotenok-gif-2203365976465100550", | |
"https://tenor.com/view/cute-cat-gif-21549091", | |
"https://tenor.com/view/cat-funny-cathands-cat-in-hat-cat-with-hands-silly-cat-gif-14981685377760273746", | |
"https://tenor.com/view/gatito-cat-kitty-cute-silly-cat-gif-3290956017813741423", | |
"https://tenor.com/view/cat-nyash-meow-gif-27316147", | |
"https://tenor.com/view/hello-hi-cute-kitten-cat-gif-19842512", | |
"https://tenor.com/view/hollyweencandy-cat-cat-drink-milk-cat-eating-cat-drinking-gif-16978701194275077898" | |
] | |
SMASH_GIF_URLS = [ | |
"Listo para la acción.", | |
"¿Sí?", | |
"¿Hmmm?", | |
"¿Qué quieres?", | |
"¿Tengo que hacer algo?", | |
"Puedo hacerlo.", | |
"Estaré encantado.", | |
"Trabajo trabajo.", | |
"Okey McKey.", | |
"¡Okey McKey!", | |
"¡A por ellos!", | |
"Vale...", | |
"¿Por qué no?", | |
"¿Quéee?", | |
"Yo ocupado. ¡Dejadme en paz!", | |
"No tiempo para jueguecitos.", | |
"¡Yo no ser ese tipo de orco!", | |
"¡Mi vida por la Horda!", | |
"¿Eh?", | |
"¿Jefe?", | |
"¡Dabu!", | |
"¡Lok'tar!", | |
"¡Swobu!", | |
"¡Zug zug!", | |
"¡Tiempo de matar!", | |
"¡Rrrr!", | |
"¡Tiempo de morir!", | |
"¡Por la Horda!", | |
"¿Qué demonios quieres esta vez?", | |
"¿Por qué no te buscas un ejército y dejas de tocarme las narices?", | |
"Fisgar, fisgar y fisgar, ¿eso es lo único que sabes hacer?", | |
"Ooh, eso sí que ha sido bonito...", | |
"Yo tener cuernos, yo herir a ti hace tiempo.", | |
"Yo no como Yoda hablar. ¿O hacerlo?", | |
"(cantando) ¡Ser verde no es nada fácil!", | |
"Listos para cabalgar.", | |
"¿Sí jefe?", | |
"Mmm", | |
"¿Necesitas algo?", | |
"Di la palabra.", | |
"No problem.", | |
"¡Yujuu!", | |
"¡Vamos!", | |
"En marcha.", | |
"¡Acaba con ellos!", | |
"¡Prueba mi acero!", | |
"¡Por Doomhammer!", | |
"¡Por la gloria del Jefe!", | |
"Piltrafilla.", | |
"Estás molestando a mi perro.", | |
"¿A qué huele? Oh, ¡perro malo!", | |
"Tengo más hambre que el lobo de Caperucita Roja.", | |
"Que los ancestros me protejan.", | |
"Provócalo.", | |
"Puedo ayudar.", | |
"¿Cómo? ¿Ahora?", | |
"Por las tribus", | |
"Inmediatamente.", | |
"Bien hecho.", | |
"¡Muerte a los enemigos de la Horda!", | |
"¡Muerte al enemigo!", | |
"¡Empezad a correr!", | |
"(Bramidos)", | |
"No me empujes que te doy un meneo de cuernos.", | |
"Eh toro, eh.", | |
"¿Tienes leche?", | |
"¡Cuate, aquí hay tomate!", | |
"Eh, ¿qué son esas letras grabadas en mi trasero?", | |
"Olé.", | |
"(se rompen muchas cosas) Lo siento.", | |
"Venganza por Zul'jin.", | |
"¿Quién tú querer matar yo?", | |
"¿Qué?", | |
"¿Qué querer tú hacer yo?", | |
"¿Dónde tú querer ir yo?", | |
"Aah.", | |
"Lo que desees.", | |
"Lo tienes, chico.", | |
"Sí... (risa)", | |
"¡Taz'dingo!" | |
] | |
TEXTS = [ | |
"No te metas con el chico malo.", | |
"Hora de hacer correr la sangre.", | |
"¡¿Por qué me molestas?!", | |
"Déjamelo a mí, te quitaré ese peso de encima.", | |
"¿Quieres comprar habanos?", | |
"La noche me confunde.", | |
"¡Saluda a mi amiguito!", | |
"¿Alguien ha pedido un médico?", | |
"Oigo los llamamientos.", | |
"¿En qué puedo ayudar?", | |
"¿Necesitas mi ayuda?", | |
"¿Que ansías ahora buen señor?", | |
"Ahora mismo.", | |
"Tío, eso sí que es una buena elección.", | |
"Lo hago ¡ahora!", | |
"¡Aaaah!", | |
"¡Yeaaah!", | |
"Abracadabra, pata de cabra.", | |
"¿Te encuentras bien?", | |
"Quizás tenga algo para ti.", | |
"¡Será pegajoso!", | |
"¡Es un libro de cocina, es un libro de cocina!", | |
"¡Con tanto bicho muerto podríamos llenar un trolebus!", | |
"¡Por la Horda!", | |
"Lok-regar ogull.", | |
"Vamos allá.", | |
"Los espíritus están inquietos.", | |
"Hmmm.", | |
"Sí.", | |
"Dabu.", | |
"Por honor.", | |
"Lok-narosh!", | |
"¡Nadie sobrevivirá!", | |
"¡Por Doomhammer!", | |
"¡Ha llegado tu hora!", | |
"¡Pero no soy estúpido!", | |
"Mi pueblo es fuerte.", | |
"Lo conduciré a su destino.", | |
"Los espíritus me guiarán.", | |
"Es verdad que he crecido con los humanos." | |
] | |
# Definición de la clase de configuración para cada canal | |
class DiscordChannel: | |
name: str | |
url: str | |
min_interval: int # ✅ Mover estos antes de los que tienen valores por defecto | |
max_interval: int | |
sticker_ids: list = field(default_factory=list) | |
gif_urls: list = field(default_factory=list) | |
texts: list = field(default_factory=list) | |
# Configuración de los canales | |
channels = [ | |
DiscordChannel( | |
name="sandra", | |
url="https://discord.com/api/v9/channels/1330367547249524788/messages", | |
min_interval=65, | |
max_interval=80, | |
sticker_ids=SANDRA_STICKER_IDS, | |
gif_urls=SANDRA_GIF_URLS | |
), | |
DiscordChannel( | |
name="smash", | |
url="https://discord.com/api/v9/channels/1211488388935450746/messages", | |
min_interval=130, | |
max_interval=250, | |
sticker_ids=SMASH_STICKERS_IDS, | |
gif_urls=SMASH_GIF_URLS, | |
texts=TEXTS | |
) | |
] | |
def send_message(data: dict, channel: DiscordChannel): | |
""" | |
Envía un mensaje al canal de Discord indicado, gestionando errores y reintentos. | |
""" | |
while True: | |
try: | |
response = requests.post(channel.url, headers=HEADERS, json=data) | |
if response.status_code == 429: | |
retry_after = response.json().get("retry_after", 5) | |
logger.warning(f"[{channel.name}] Límite alcanzado. Reintentando en {retry_after}s...") | |
time.sleep(retry_after) | |
continue | |
if response.ok: | |
logger.info(f"[{channel.name}] Mensaje enviado correctamente: {data}") | |
else: | |
logger.error(f"[{channel.name}] Error {response.status_code}: {response.text}") | |
response.raise_for_status() | |
break | |
except requests.exceptions.RequestException as e: | |
logger.error(f"[{channel.name}] Error de conexión: {e}") | |
time.sleep(5) | |
def send_random_channel(channel: DiscordChannel): | |
""" | |
Envía aleatoriamente un sticker o un GIF al canal especificado, esperando un intervalo aleatorio entre envíos. | |
""" | |
while True: | |
# Se elige aleatoriamente entre enviar sticker o GIF | |
action_type = random.choice(["sticker", "gif"]) | |
if action_type == "sticker" and channel.sticker_ids: | |
data = {"sticker_ids": [random.choice(channel.sticker_ids)]} | |
elif action_type == "gif" and channel.gif_urls: | |
data = {"content": random.choice(channel.gif_urls)} | |
else: | |
# Si por alguna razón no hay stickers o GIFs disponibles, se envía un mensaje de texto simple | |
data = {"content": random.choice(channel.texts)} | |
send_message(data, channel) | |
sleep_time = random.randint(channel.min_interval, channel.max_interval) | |
logger.info(f"[{channel.name}] Esperando {sleep_time} segundos antes del próximo envío.") | |
time.sleep(sleep_time) | |
app = FastAPI() | |
def read_root(): | |
return {"status": "ok"} | |
def ping(): | |
return {"message": "pong"} | |
def start_background_tasks(): | |
""" | |
Al arrancar FastAPI, se inicia un hilo en segundo plano para cada canal. | |
""" | |
for channel in channels: | |
thread = threading.Thread(target=send_random_channel, args=(channel,), daemon=True) | |
thread.start() | |
logger.info(f"Iniciado hilo de fondo para el canal: {channel.name}") | |