Add complete Flask web application with Telegram bot integration, multiple AI provider support (llama.cpp, OpenRouter, z.ai, StepFun), extensive order banks for BDSM-themed gameplay, automated cron scheduling, and responsive web UI with inference parameter controls.
265 lines
9.3 KiB
Python
Executable File
265 lines
9.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Sistema de envio automático de Ordens do Mestre para o Telegram.
|
|
Lê a agenda diária, mapeia horário → categoria e envia ordens
|
|
contextuais em intervalos variados.
|
|
"""
|
|
import logging
|
|
import os
|
|
import random
|
|
import sys
|
|
import time
|
|
from datetime import datetime
|
|
|
|
import requests
|
|
|
|
# Importado com alias para nao colidir com o wrapper local de mesmo nome
|
|
# (gerar_ordem_dinamica) definido mais abaixo neste modulo.
|
|
from dados import gerar_ordem_dinamica as gerar_ordem_dinamica_dados, gerar_ordem_sozinho_completa
|
|
from dados_plug import banco_plug
|
|
from dados_picantes import banco_picantes
|
|
from ia_llamacpp import (
|
|
estado_revisao_cron_ativo,
|
|
revisar_ordem_ia,
|
|
servidor_disponivel,
|
|
)
|
|
|
|
# ── Logging ──
|
|
logging.basicConfig(
|
|
level=logging.INFO,
|
|
format="%(asctime)s [%(levelname)s] %(message)s",
|
|
datefmt="%Y-%m-%d %H:%M:%S",
|
|
)
|
|
logger = logging.getLogger("ordem_mestre")
|
|
|
|
# ── Telegram ──
|
|
BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
|
|
CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
|
|
|
|
if not BOT_TOKEN or not CHAT_ID:
|
|
logger.error("TELEGRAM_BOT_TOKEN e TELEGRAM_CHAT_ID devem estar definidos no .env")
|
|
sys.exit(1)
|
|
|
|
TELEGRAM_API = f"https://api.telegram.org/bot{BOT_TOKEN}/sendMessage"
|
|
|
|
|
|
def enviar_telegram(texto):
|
|
"""Envia uma mensagem de texto para o Telegram com timestamp."""
|
|
agora = datetime.now().strftime("%d/%m/%Y %H:%M")
|
|
texto_completo = f"{texto}\n\n📅 {agora}"
|
|
try:
|
|
resp = requests.post(TELEGRAM_API, json={
|
|
"chat_id": CHAT_ID,
|
|
"text": texto_completo,
|
|
"parse_mode": "HTML",
|
|
}, timeout=15)
|
|
if resp.status_code != 200:
|
|
logger.warning("Telegram retornou %s: %s", resp.status_code, resp.text[:200])
|
|
else:
|
|
logger.info("Mensagem enviada ao Telegram.")
|
|
except requests.RequestException as exc:
|
|
logger.error("Falha ao enviar Telegram: %s", exc)
|
|
|
|
|
|
def revisar_com_ia_se_ativo(texto, tipo="ordem"):
|
|
"""Devolve *texto* possivelmente reescrito pela IA antes do envio.
|
|
|
|
Quando o recurso "IA revisa o Cron" está ativado (pelo painel web), a IA
|
|
analisa e reescreve a ordem escolhida. Em qualquer falha (recurso
|
|
desligado, IA offline, resposta vazia ou erro) a ordem original é
|
|
devolvida intacta, de forma que nenhuma ordem agendada deixe de ser
|
|
enviada.
|
|
"""
|
|
if not estado_revisao_cron_ativo():
|
|
return texto
|
|
try:
|
|
if not servidor_disponivel():
|
|
logger.warning("🧠 Revisão de cron ativa, mas a IA está offline. "
|
|
"Enviando ordem original.")
|
|
return texto
|
|
logger.info("🧠 IA está analisando e reescrevendo a ordem %s...", tipo)
|
|
revisada = revisar_ordem_ia(texto)
|
|
if revisada and revisada.strip():
|
|
logger.info("✅ Ordem %s reescrita pela IA.", tipo)
|
|
return revisada.strip()
|
|
logger.warning("IA retornou resposta vazia; enviando ordem original.")
|
|
except Exception as exc: # noqa: BLE001
|
|
logger.error("Falha ao revisar ordem com a IA: %s. Enviando original.", exc)
|
|
return texto
|
|
|
|
|
|
# ── Agenda ──
|
|
AGENDA = [
|
|
("06:00", "07:30", "☀️ Matinal", ["banco_sozinho_masturbacao", "banco_sozinho_vibracao"]),
|
|
("07:30", "10:00", "💻 Home Office", ["banco_estudos_auto_ditadas"]),
|
|
("10:00", "11:30", "🧹 Doméstico", ["banco_trabalhos_domesticos"]),
|
|
("11:30", "13:00", "🧹 Doméstico", ["banco_trabalhos_domesticos"]),
|
|
("13:00", "16:00", "💻 Home Office", ["banco_estudos_auto_ditadas"]),
|
|
("16:00", "19:00", "📚 Estudos", ["banco_estudos_auto_ditadas"]),
|
|
("19:00", "19:30", "🚿 Banho", ["banco_banho"]),
|
|
("19:30", "20:30", "🧹 Doméstico", ["banco_trabalhos_domesticos"]),
|
|
("20:30", "22:00", "📚 Estudos / Áudio-books", ["banco_estudos_auto_ditadas"]),
|
|
("22:00", "06:00", "🌙 Noturna", ["banco_sozinho_edging"]),
|
|
]
|
|
|
|
BANCOS_CATEGORIA = {}
|
|
|
|
|
|
def _carregar_bancos():
|
|
"""Carrega os bancos de dados sob demanda."""
|
|
from dados import (
|
|
banco_sozinho_masturbacao, banco_sozinho_vibracao,
|
|
banco_sozinho_exposicao, banco_sozinho_humilhacao,
|
|
banco_sozinho_plug, banco_sozinho_edging,
|
|
banco_trabalhos_domesticos,
|
|
banco_estudos_auto_ditadas,
|
|
banco_banho,
|
|
)
|
|
|
|
BANCOS_CATEGORIA.update({
|
|
"banco_sozinho_masturbacao": banco_sozinho_masturbacao,
|
|
"banco_sozinho_vibracao": banco_sozinho_vibracao,
|
|
"banco_sozinho_exposicao": banco_sozinho_exposicao,
|
|
"banco_sozinho_humilhacao": banco_sozinho_humilhacao,
|
|
"banco_sozinho_plug": banco_sozinho_plug,
|
|
"banco_sozinho_edging": banco_sozinho_edging,
|
|
"banco_trabalhos_domesticos": banco_trabalhos_domesticos,
|
|
"banco_estudos_auto_ditadas": banco_estudos_auto_ditadas,
|
|
"banco_banho": banco_banho,
|
|
})
|
|
|
|
|
|
def categoria_atual():
|
|
"""Retorna a categoria com base no horário atual."""
|
|
agora = datetime.now()
|
|
hora_min = agora.hour * 100 + agora.minute
|
|
for inicio, fim, cat, _ in AGENDA:
|
|
h_ini = int(inicio[:2]) * 100 + int(inicio[3:])
|
|
h_fim = int(fim[:2]) * 100 + int(fim[3:])
|
|
if h_ini <= h_fim:
|
|
if h_ini <= hora_min < h_fim:
|
|
return cat
|
|
else:
|
|
if hora_min >= h_ini or hora_min < h_fim:
|
|
return cat
|
|
return "☀️ Matinal"
|
|
|
|
|
|
def bancos_para_categoria(cat_nome):
|
|
"""Retorna os bancos de dados associados a uma categoria."""
|
|
for _, _, cat, bancos_nomes in AGENDA:
|
|
if cat == cat_nome:
|
|
bancos = []
|
|
for nome in bancos_nomes:
|
|
b = BANCOS_CATEGORIA.get(nome)
|
|
if b:
|
|
bancos.append(b)
|
|
return bancos
|
|
return []
|
|
|
|
|
|
def gerar_ordem_contextual():
|
|
"""Gera uma ordem baseada na categoria do horário atual."""
|
|
cat = categoria_atual()
|
|
bancos = bancos_para_categoria(cat)
|
|
if bancos:
|
|
banco = random.choice(bancos)
|
|
return f"🔥 ORDEM DO MESTRE [{cat}]\n\n{random.choice(banco)}"
|
|
return f"🔥 ORDEM DO MESTRE [{cat}]\n\n{gerar_ordem_sozinho_completa()}"
|
|
|
|
|
|
def gerar_ordem_plug():
|
|
"""Pega uma ordem aleatória do banco de plugs."""
|
|
cat = categoria_atual()
|
|
ordem = random.choice(banco_plug)
|
|
return f"🔌 ORDEM DE PLUG [{cat}]\n\n{ordem}"
|
|
|
|
|
|
def gerar_ordem_picante():
|
|
"""Pega uma ordem aleatória do banco de picantes."""
|
|
cat = categoria_atual()
|
|
ordem = random.choice(banco_picantes)
|
|
return f"🔥 ORDEM PICANTE [{cat}]\n\n{ordem}"
|
|
|
|
|
|
def gerar_ordem_dinamica():
|
|
"""Gera uma ordem dinâmica aleatória (wrapper com cabeçalho de categoria)."""
|
|
cat = categoria_atual()
|
|
ordem = gerar_ordem_dinamica_dados()
|
|
return f"⚡ ORDEM DINÂMICA [{cat}]\n\n{ordem}"
|
|
|
|
|
|
# ── Timers ──
|
|
ultimo_envio = {
|
|
"contextual": 0,
|
|
"plug": 0,
|
|
"picante": 0,
|
|
"dinamica": 0,
|
|
}
|
|
|
|
|
|
def deve_enviar(tipo, intervalo_min, intervalo_max=None):
|
|
"""Verifica se passou tempo suficiente desde o último envio."""
|
|
agora = time.time()
|
|
if intervalo_max:
|
|
intervalo = random.randint(intervalo_min, intervalo_max)
|
|
else:
|
|
intervalo = intervalo_min
|
|
if agora - ultimo_envio[tipo] >= intervalo:
|
|
ultimo_envio[tipo] = agora
|
|
return True
|
|
return False
|
|
|
|
|
|
def loop_principal():
|
|
"""Loop infinito que envia ordens nos intervalos definidos."""
|
|
logger.info("🧠 Sistema de Ordens do Mestre iniciado.")
|
|
logger.info("Bot: @hermesjogo1000")
|
|
logger.info("Intervalos: contextual 10-40min | plug 45min | picante 15min | dinâmica 20min")
|
|
enviar_telegram("🧠 SISTEMA DE ORDENS DO MESTRE ATIVADO.\n"
|
|
"Ordens automáticas serão enviadas conforme sua agenda diária.")
|
|
|
|
_carregar_bancos()
|
|
|
|
while True:
|
|
try:
|
|
agora = time.time()
|
|
|
|
# ── Ordens picantes: a cada 15 min ──
|
|
if deve_enviar("picante", 15 * 60):
|
|
texto = gerar_ordem_picante()
|
|
logger.info("Enviando ordem picante...")
|
|
enviar_telegram(revisar_com_ia_se_ativo(texto, "picante"))
|
|
|
|
# ── Ordens dinâmicas: a cada 20 min ──
|
|
if deve_enviar("dinamica", 20 * 60):
|
|
texto = gerar_ordem_dinamica()
|
|
logger.info("Enviando ordem dinâmica...")
|
|
enviar_telegram(revisar_com_ia_se_ativo(texto, "dinâmica"))
|
|
|
|
# ── Ordens de plug: a cada 45 min ──
|
|
if deve_enviar("plug", 45 * 60):
|
|
texto = gerar_ordem_plug()
|
|
logger.info("Enviando ordem de plug...")
|
|
enviar_telegram(revisar_com_ia_se_ativo(texto, "plug"))
|
|
|
|
# ── Ordens contextuais (normais): 10-40 min ──
|
|
if deve_enviar("contextual", 10 * 60, 40 * 60):
|
|
texto = gerar_ordem_contextual()
|
|
logger.info("Enviando ordem contextual (%s)...", categoria_atual())
|
|
enviar_telegram(revisar_com_ia_se_ativo(texto, "contextual"))
|
|
|
|
# Dorme 30 segundos antes de verificar novamente
|
|
time.sleep(30)
|
|
|
|
except KeyboardInterrupt:
|
|
logger.info("Sistema encerrado pelo usuário.")
|
|
enviar_telegram("⏹ SISTEMA DE ORDENS DO MESTRE DESATIVADO.")
|
|
break
|
|
except Exception as exc:
|
|
logger.exception("Erro no loop principal: %s", exc)
|
|
time.sleep(60)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
loop_principal() |