06-sep: [videoclub] flujo unificado torrents/bajar en novedades+pelicula+serie, sin URLs, /limpiar borra todo el chat (IDD+OpenCode), parental CAROLINA con fallback MAC en vivo
This commit is contained in:
@@ -247,7 +247,7 @@ def formatear_titulos(resultados):
|
|||||||
if not resultados:
|
if not resultados:
|
||||||
return ["No se encontraron resultados para ese termino."]
|
return ["No se encontraron resultados para ese termino."]
|
||||||
lineas = [f"🎬 <b>Resultados globales ({len(resultados)}):</b>",
|
lineas = [f"🎬 <b>Resultados globales ({len(resultados)}):</b>",
|
||||||
"Responde <b>/bajar <numero></b> para ver torrents.", ""]
|
"Responde <b>/torrents <numero></b> para ver torrents.", ""]
|
||||||
for i, r in enumerate(resultados, 1):
|
for i, r in enumerate(resultados, 1):
|
||||||
icono = "📺" if r["type"] == "series" else "🎬"
|
icono = "📺" if r["type"] == "series" else "🎬"
|
||||||
y = f" ({r['year']})" if r.get("year") else ""
|
y = f" ({r['year']})" if r.get("year") else ""
|
||||||
|
|||||||
60
videoclub/listados/2026-09-06.md
Normal file
60
videoclub/listados/2026-09-06.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
# Videoclub — 2026-09-06
|
||||||
|
|
||||||
|
**Total disponibles: 51** | Novedades: 0
|
||||||
|
|
||||||
|
## Películas (37)
|
||||||
|
|
||||||
|
- Backrooms 2160p 4K WEB x265 10bit AAC5 1 (2026) `https://real-debrid.com/d/WC7MIGNKYMMEAFED`
|
||||||
|
- Disclosure Day 1080p ViruseProject (2026) `https://real-debrid.com/d/7AKRWAMVG2A7OFA6`
|
||||||
|
- Disclosure Day NO-ADS 1080p x265 MD-AAC5 1+2 0 ITA-ENG MmTRaXx DD-CREW-IlCosaro (2026) `https://real-debrid.com/d/ZWPJNGU5EKGA61D4`
|
||||||
|
- Downloads
|
||||||
|
- El dia de la revelacion Disclosure Day (2026) `https://real-debrid.com/d/AHBLKPLNL56KOBBC`
|
||||||
|
- El día de la revelacion Disclosure Day (2026) `https://real-debrid.com/d/NSHXB2IFNLNEK7C8`
|
||||||
|
- El Pasajero Nocturno (2026) `https://real-debrid.com/d/52MMX6GHV6U5639B`
|
||||||
|
- El Pasajero Nocturno (2026) `https://real-debrid.com/d/MBLS4EMXARKVM5C4`
|
||||||
|
- Fiasco total La tragedia del festival Astroworld (2025) `https://real-debrid.com/d/YCBMS3HYQPLU27E1`
|
||||||
|
- Fiasco total La tragedia del festival Astroworld (2025) `https://real-debrid.com/d/YCBMS3HYQPLU27E1`
|
||||||
|
- Fiasco total La tragedia del festival Astroworld (2025) `https://real-debrid.com/d/YCBMS3HYQPLU27E1`
|
||||||
|
- Greenland `https://real-debrid.com/d/LUZ3G5KBQZYES397`
|
||||||
|
- Greenland 2 `https://real-debrid.com/d/FS4OAHZSNYHFK568`
|
||||||
|
- Greenland El Ultimo Refugio (2020) `https://real-debrid.com/d/MJR44YRCTRDMY2C9`
|
||||||
|
- He-Man y los Masters del Universo (2026) `https://real-debrid.com/d/APGDE3Z7ADR3U58B`
|
||||||
|
- Iron Lung 2026 1080p `https://real-debrid.com/d/I6BVHXX7IFSUE1DB`
|
||||||
|
- La maldicion de Shelby Oaks (2026) `https://real-debrid.com/d/T4FFNHSB2XBV4D92`
|
||||||
|
- La momia de Lee Cronin Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p `https://real-debrid.com/d/QDPUO2UWMDWX6C6E`
|
||||||
|
- Luger (2026) `https://real-debrid.com/d/VWUUZIQGVLO76357`
|
||||||
|
- Obsession 2160p UHD x265 10bit DV HDR r00t (2026) `https://real-debrid.com/d/XFJULZ3HFQ6VG8A4`
|
||||||
|
- Obsession 2160p UHD x265 10bit DV HDR TrueHD Atmos 7 1 r00t (2026) `https://real-debrid.com/d/LMJHM23CEYXZOA66`
|
||||||
|
- Obsession Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p `https://real-debrid.com/d/LESH2XGOLRWYKEC8`
|
||||||
|
- Posesion infernal En llamas (2026) `https://real-debrid.com/d/RF2IRCGKIKISI174`
|
||||||
|
- Project Hail Mary 2160p KinoRip h265 En Es Dual YG (2026) `https://real-debrid.com/d/OMCP4MAMM775Q17A`
|
||||||
|
- Project Hail Mary 2160p KinoRip h265 En Es Dual YG (2026) `https://real-debrid.com/d/OMCP4MAMM775Q17A`
|
||||||
|
- Project Hail Mary 2160p KinoRip h265 En Es Dual YG (2026) `https://real-debrid.com/d/OMCP4MAMM775Q17A`
|
||||||
|
- Resident Evil `https://real-debrid.com/d/6VMIEUSOVVIXYBD2`
|
||||||
|
- Salvacion (2026) `https://real-debrid.com/d/BF3FGPVABGL6A610`
|
||||||
|
- Salvacion (2026) `https://real-debrid.com/d/4Q6AFXH6KSKRO2AF`
|
||||||
|
- Scary Movie (2026) `https://real-debrid.com/d/7FHGHGOXV7ELY3E6`
|
||||||
|
- Spider-Man No Way Home 4Kremux2160 atomixhq link `https://real-debrid.com/d/S7GR3CYFAWOWC7AC`
|
||||||
|
- Steven Spielberg el rey midas de Hollywood wolfmax4k com (2024) `https://real-debrid.com/d/WWCMHPUY4FPFAF67`
|
||||||
|
- Super Mario Galaxy La película (2026) `https://real-debrid.com/d/VNTK5JCJGRHJOF0E`
|
||||||
|
- super mario galaxy la película Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p `https://real-debrid.com/d/3GQUITYMNB4TUE1C`
|
||||||
|
- The End of Oak Street 1080p HC V2 x264-DKS (2026) `https://real-debrid.com/d/JI3KPXS4HEY7Y234`
|
||||||
|
- TheAdventuresOfTomSawyer `https://real-debrid.com/d/XJVUAD7LIIMFKDCC`
|
||||||
|
- Twilight Saga 2008-2012 2160p H265 HDR10 AC3 5 1 ITA ENG sub ita eng Sp33dy94-MIRCrew `https://real-debrid.com/d/II6EYH6KIMNUI10A`
|
||||||
|
|
||||||
|
## Series (14)
|
||||||
|
|
||||||
|
- Euphoria `https://real-debrid.com/d/YOFHJHFSKN6HOB11`
|
||||||
|
- From - S02E01 - Strangers in a Strange Land - WEBDL-1080p - Spanish 2x01 - audio - sub `https://real-debrid.com/d/B64L3AL7NWVN41D1`
|
||||||
|
- Heidi Girl of the Alps Alps no Shoujo Heidi Season 1 BD 1080p HEVC x265 10bit Eng-Subs -Judas `https://real-debrid.com/d/3V5DNKCHKQOPGF89`
|
||||||
|
- Monarch El Legado De Los Monstruos wolfmax4k com `https://real-debrid.com/d/LRB4AEEJCYOCU1E0`
|
||||||
|
- Star Trek Strange New Worlds `https://real-debrid.com/d/UCVH7W3HSXDKS4E5`
|
||||||
|
- Stargate Sg-1 05x09 Entre Dos Fuegos `https://real-debrid.com/d/TYLADWGS6AEMQ28C`
|
||||||
|
- Stargate Sg-1 05x10 2001 `https://real-debrid.com/d/LHQ7LEN7VCRSS1C4`
|
||||||
|
- Stargate Sg-1 05x12 Agujero X-Tremo `https://real-debrid.com/d/7BTWUVXH2KH7KCC5`
|
||||||
|
- Supergirl (2026) `https://real-debrid.com/d/65RUKRSI3YERQDCB`
|
||||||
|
- Supergirl (2026) `https://real-debrid.com/d/ZKB3MUWMEM52G885`
|
||||||
|
- The Studio `https://real-debrid.com/d/6AQCY2YCPY6FE9A9`
|
||||||
|
- The Studio `https://real-debrid.com/d/L7DDTFXUCCPF47A5`
|
||||||
|
- The Studio `https://real-debrid.com/d/P3J5H2OCFG76WC67`
|
||||||
|
- The Studio wolfmax4k com `https://real-debrid.com/d/KHLUHJ4W7JMKA663`
|
||||||
413
videoclub/snapshots/2026-09-06.json
Normal file
413
videoclub/snapshots/2026-09-06.json
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
{
|
||||||
|
"fecha": "2026-09-06",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": "realdebrid:Downloads",
|
||||||
|
"name": "Downloads",
|
||||||
|
"clean": "Downloads",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:O47SZPHDEIJD4",
|
||||||
|
"name": "Posesion infernal En llamas (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "Posesion infernal En llamas",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/RF2IRCGKIKISI174"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:5DLXRYNWASICQ",
|
||||||
|
"name": "The.End.of.Oak.Street.2026.1080p.HC.V2.x264-DKS.mkv",
|
||||||
|
"clean": "The End of Oak Street 1080p HC V2 x264-DKS",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/JI3KPXS4HEY7Y234"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:TEGQKYCCQBXXO",
|
||||||
|
"name": "Supergirl (2026) [Bluray 720p][Esp].mkv",
|
||||||
|
"clean": "Supergirl",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/65RUKRSI3YERQDCB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:HARMOP47F3AP2",
|
||||||
|
"name": "Obsession Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5.1 BD-Rip hd 1080p.mkv",
|
||||||
|
"clean": "Obsession Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/LESH2XGOLRWYKEC8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:V7XUZQ6APSG4Q",
|
||||||
|
"name": "Scary Movie (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "Scary Movie",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/7FHGHGOXV7ELY3E6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:MBGEYHZC4MKYU",
|
||||||
|
"name": "Star Trek Strange New Worlds [HDTV 1080p][Cap.401].mkv",
|
||||||
|
"clean": "Star Trek Strange New Worlds",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/UCVH7W3HSXDKS4E5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:HEIP5O2XB5V66",
|
||||||
|
"name": "He-Man y los Masters del Universo (2026) [Bluray 1080p][Esp].mkv",
|
||||||
|
"clean": "He-Man y los Masters del Universo",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/APGDE3Z7ADR3U58B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:SLJ2UJGPDFZLW",
|
||||||
|
"name": "Supergirl (2026) [Bluray 1080p][Esp].mkv",
|
||||||
|
"clean": "Supergirl",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/ZKB3MUWMEM52G885"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:FC5FZS2J4HUFS",
|
||||||
|
"name": "El dia de la revelacion (Disclosure Day) (2026) [Bluray 1080p][Esp].mkv",
|
||||||
|
"clean": "El dia de la revelacion Disclosure Day",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/AHBLKPLNL56KOBBC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:A5XIYLPNAZNZM",
|
||||||
|
"name": "El día de la revelacion (Disclosure Day) (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "El día de la revelacion Disclosure Day",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/NSHXB2IFNLNEK7C8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:7XL55PFQOE4OO",
|
||||||
|
"name": "El Pasajero Nocturno (2026) [Bluray 1080p][Esp].mkv",
|
||||||
|
"clean": "El Pasajero Nocturno",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/52MMX6GHV6U5639B"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:5IHX4PFCFP5QY",
|
||||||
|
"name": "El Pasajero Nocturno (2026) [Bluray][Esp].avi",
|
||||||
|
"clean": "El Pasajero Nocturno",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/MBLS4EMXARKVM5C4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:S52E6GZH2FSNK",
|
||||||
|
"name": "Disclosure.Day.(2026).(NO-ADS).1080p.x265.MD-AAC5.1+2.0.ITA-ENG.MmTRaXx(DD-CREW-IlCosaro).mkv",
|
||||||
|
"clean": "Disclosure Day NO-ADS 1080p x265 MD-AAC5 1+2 0 ITA-ENG MmTRaXx DD-CREW-IlCosaro",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/ZWPJNGU5EKGA61D4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:FOTT5OF2CNCQO",
|
||||||
|
"name": "Disclosure.Day.2026.1080p.CAMRip.ViruseProject.mkv",
|
||||||
|
"clean": "Disclosure Day 1080p ViruseProject",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/7AKRWAMVG2A7OFA6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:FEWY5OUINFE6I",
|
||||||
|
"name": "Obsession (2026) (2160p UHD BluRay x265 10bit DV HDR r00t).mkv",
|
||||||
|
"clean": "Obsession 2160p UHD x265 10bit DV HDR r00t",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/XFJULZ3HFQ6VG8A4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:GE3KLARBGACYC",
|
||||||
|
"name": "Obsession (2026) (2160p UHD BluRay x265 10bit DV HDR TrueHD Atmos 7.1 r00t)",
|
||||||
|
"clean": "Obsession 2160p UHD x265 10bit DV HDR TrueHD Atmos 7 1 r00t",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/LMJHM23CEYXZOA66"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:REQOOWL7R3X5M",
|
||||||
|
"name": "Backrooms.2026.2160p.4K.WEB.x265.10bit.AAC5.1-[YTS.GG - YTS.BZ].mkv",
|
||||||
|
"clean": "Backrooms 2160p 4K WEB x265 10bit AAC5 1",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/WC7MIGNKYMMEAFED"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:HEVMDYWAXLSLM",
|
||||||
|
"name": "Luger (2026) [Bluray 720p][Esp].mkv",
|
||||||
|
"clean": "Luger",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/VWUUZIQGVLO76357"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:MBSDHRJMTC3S2",
|
||||||
|
"name": "Spider-Man No Way Home 4Kremux2160.atomixhq.link.mkv",
|
||||||
|
"clean": "Spider-Man No Way Home 4Kremux2160 atomixhq link",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/S7GR3CYFAWOWC7AC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:YVLXIF6ILFL2U",
|
||||||
|
"name": "Iron Lung 2026 1080p.mkv",
|
||||||
|
"clean": "Iron Lung 2026 1080p",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/I6BVHXX7IFSUE1DB"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:DLUAAXNZJ2ZHW",
|
||||||
|
"name": "From - S02E01 - Strangers in a Strange Land - WEBDL-1080p - Spanish 2x01 - audio [ES+EN] - sub [ES+EN].mkv",
|
||||||
|
"clean": "From - S02E01 - Strangers in a Strange Land - WEBDL-1080p - Spanish 2x01 - audio - sub",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/B64L3AL7NWVN41D1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:UP7DPBWVMH7JS",
|
||||||
|
"name": "La maldicion de Shelby Oaks (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "La maldicion de Shelby Oaks",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/T4FFNHSB2XBV4D92"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:PMBQI365H7PU6",
|
||||||
|
"name": "Steven Spielberg el rey midas de Hollywood (2024) [HDTV 1080p][Esp](wolfmax4k.com).mkv",
|
||||||
|
"clean": "Steven Spielberg el rey midas de Hollywood wolfmax4k com",
|
||||||
|
"year": "2024",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/WWCMHPUY4FPFAF67"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:OWWSTBTFG4ZFO",
|
||||||
|
"name": "Fiasco total La tragedia del festival Astroworld (2025) [HDTV 1080p][Esp].mkv",
|
||||||
|
"clean": "Fiasco total La tragedia del festival Astroworld",
|
||||||
|
"year": "2025",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/YCBMS3HYQPLU27E1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:M4UVGSNUKTLA6",
|
||||||
|
"name": "Fiasco total La tragedia del festival Astroworld (2025) [HDTV 1080p][Esp].mkv",
|
||||||
|
"clean": "Fiasco total La tragedia del festival Astroworld",
|
||||||
|
"year": "2025",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/YCBMS3HYQPLU27E1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:7HQN7ELMLWTDI",
|
||||||
|
"name": "Fiasco total La tragedia del festival Astroworld (2025) [HDTV 1080p][Esp].mkv",
|
||||||
|
"clean": "Fiasco total La tragedia del festival Astroworld",
|
||||||
|
"year": "2025",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/YCBMS3HYQPLU27E1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:BRNWEZP2TGOEQ",
|
||||||
|
"name": "La momia de Lee Cronin Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5.1 BD-Rip hd 1080p.mkv",
|
||||||
|
"clean": "La momia de Lee Cronin Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/QDPUO2UWMDWX6C6E"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:3MNHGJ3UM73VY",
|
||||||
|
"name": "super mario galaxy la película Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5.1 BD-Rip hd 1080p.mkv",
|
||||||
|
"clean": "super mario galaxy la película Castellano-Ingles+Subt Castellano-Ingles H264 E-AC3 5 1 BD-Rip hd 1080p",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/3GQUITYMNB4TUE1C"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:PKZ3B7VEZXWZQ",
|
||||||
|
"name": "Super Mario Galaxy La película (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "Super Mario Galaxy La película",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/VNTK5JCJGRHJOF0E"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:6RE4EY5ZP2ILA",
|
||||||
|
"name": "Proyecto Salvacion (2026) [Bluray 1080p][Esp].mkv",
|
||||||
|
"clean": "Salvacion",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/BF3FGPVABGL6A610"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:ASX6FSY2ZZD36",
|
||||||
|
"name": "Heidi Girl of the Alps (Alps no Shoujo Heidi) (Season 1) (BD 1080p)(HEVC x265 10bit)(Eng-Subs)-Judas[TGx]",
|
||||||
|
"clean": "Heidi Girl of the Alps Alps no Shoujo Heidi Season 1 BD 1080p HEVC x265 10bit Eng-Subs -Judas",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/3V5DNKCHKQOPGF89"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:K4CJIWAJF3NKS",
|
||||||
|
"name": "Greenland El Ultimo Refugio (2020) [BluRay Rip][AC3 5.1 Castellano][www.PctFenix.com].avi",
|
||||||
|
"clean": "Greenland El Ultimo Refugio",
|
||||||
|
"year": "2020",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/MJR44YRCTRDMY2C9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:KDWFL34NA3MXE",
|
||||||
|
"name": "Greenland [4K UHDremux][2160p][HDR10][AC3 5.1 Castellano-True HD 7.1-Ingles+Subs][ES-EN]",
|
||||||
|
"clean": "Greenland",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/LUZ3G5KBQZYES397"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:KW4WNKPELJM5O",
|
||||||
|
"name": "Greenland 2 [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "Greenland 2",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/FS4OAHZSNYHFK568"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:WEFMCETRL5BZM",
|
||||||
|
"name": "Resident Evil [FullUHD 2160p][Castellano AC3 5.1-Ingles DolbyTrueHD 7.1+Subs]",
|
||||||
|
"clean": "Resident Evil",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/6VMIEUSOVVIXYBD2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:CFPM3BI4C7EXO",
|
||||||
|
"name": "Proyecto Salvacion (2026) [4k 2160p][Esp].mkv",
|
||||||
|
"clean": "Salvacion",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/4Q6AFXH6KSKRO2AF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:5W6E6YBRA7V22",
|
||||||
|
"name": "Project.Hail.Mary.2026.2160p.KinoRip.h265.En.Es.Dual YG.mkv",
|
||||||
|
"clean": "Project Hail Mary 2160p KinoRip h265 En Es Dual YG",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/OMCP4MAMM775Q17A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:3GJHZMZQUQ544",
|
||||||
|
"name": "Project.Hail.Mary.2026.2160p.KinoRip.h265.En.Es.Dual YG.mkv",
|
||||||
|
"clean": "Project Hail Mary 2160p KinoRip h265 En Es Dual YG",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/OMCP4MAMM775Q17A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:YAFM2WGO4IR64",
|
||||||
|
"name": "Project.Hail.Mary.2026.2160p.KinoRip.h265.En.Es.Dual YG.mkv",
|
||||||
|
"clean": "Project Hail Mary 2160p KinoRip h265 En Es Dual YG",
|
||||||
|
"year": "2026",
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/OMCP4MAMM775Q17A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:RBESCUG7LBCH2",
|
||||||
|
"name": "Twilight Saga (2008-2012) 2160p H265 HDR10 AC3 5.1 ITA.ENG sub ita.eng Sp33dy94-MIRCrew",
|
||||||
|
"clean": "Twilight Saga 2008-2012 2160p H265 HDR10 AC3 5 1 ITA ENG sub ita eng Sp33dy94-MIRCrew",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/II6EYH6KIMNUI10A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:ZYLMP5J4H3VE6",
|
||||||
|
"name": "Monarch El Legado De Los Monstruos [4k 2160p][Cap.101](wolfmax4k.com).mkv",
|
||||||
|
"clean": "Monarch El Legado De Los Monstruos wolfmax4k com",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/LRB4AEEJCYOCU1E0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:37ZFJ63K6W7PM",
|
||||||
|
"name": "Stargate_Sg-1_05x12_Agujero_X-Tremo.avi",
|
||||||
|
"clean": "Stargate Sg-1 05x12 Agujero X-Tremo",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/7BTWUVXH2KH7KCC5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:6JJIFVQ5MZQEI",
|
||||||
|
"name": "TheAdventuresOfTomSawyer",
|
||||||
|
"clean": "TheAdventuresOfTomSawyer",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "pelicula",
|
||||||
|
"enlace": "https://real-debrid.com/d/XJVUAD7LIIMFKDCC"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:5KFSC2OVN37MO",
|
||||||
|
"name": "The Studio [HDTV 1080p][Cap.105]",
|
||||||
|
"clean": "The Studio",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/6AQCY2YCPY6FE9A9"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:3AS7OJ3EXXKMC",
|
||||||
|
"name": "Stargate_Sg-1_05x10_2001.avi",
|
||||||
|
"clean": "Stargate Sg-1 05x10 2001",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/LHQ7LEN7VCRSS1C4"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:UYIBLKOIL5HD6",
|
||||||
|
"name": "The Studio [HDTV 1080p][Cap.104]",
|
||||||
|
"clean": "The Studio",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/L7DDTFXUCCPF47A5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:CQ5CWIAKCM3ZS",
|
||||||
|
"name": "The Studio [HDTV 1080p][Cap.103]",
|
||||||
|
"clean": "The Studio",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/P3J5H2OCFG76WC67"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:TMZRDVHVHUHRQ",
|
||||||
|
"name": "The Studio [HDTV 1080p][cap.102](wolfmax4k.com).mkv",
|
||||||
|
"clean": "The Studio wolfmax4k com",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/KHLUHJ4W7JMKA663"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:S5HO3BW6ADQYI",
|
||||||
|
"name": "Euphoria [4k 2160p][Cap.302].mkv",
|
||||||
|
"clean": "Euphoria",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/YOFHJHFSKN6HOB11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "realdebrid:CCDJGDZJK3FRA",
|
||||||
|
"name": "Stargate_Sg-1_05x09_Entre_Dos_Fuegos.avi",
|
||||||
|
"clean": "Stargate Sg-1 05x09 Entre Dos Fuegos",
|
||||||
|
"year": null,
|
||||||
|
"tipo": "serie",
|
||||||
|
"enlace": "https://real-debrid.com/d/TYLADWGS6AEMQ28C"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -252,20 +252,29 @@ def formatear_peliculas(resultados):
|
|||||||
calidad = "4K" if "4k" in (it.get("name") or "").lower() or \
|
calidad = "4K" if "4k" in (it.get("name") or "").lower() or \
|
||||||
"2160p" in (it.get("name") or "").lower() else "HD"
|
"2160p" in (it.get("name") or "").lower() else "HD"
|
||||||
idioma = "cast." if it.get("castellano") else "ing."
|
idioma = "cast." if it.get("castellano") else "ing."
|
||||||
enlace = it.get("enlace") or ""
|
|
||||||
lineas.append(f"<b>{i}.</b> {it['clean']}{y} — {calidad}, {idioma}")
|
lineas.append(f"<b>{i}.</b> {it['clean']}{y} — {calidad}, {idioma}")
|
||||||
if enlace:
|
|
||||||
lineas.append(f" <code>descargar {enlace}</code>")
|
|
||||||
lineas.append("")
|
lineas.append("")
|
||||||
lineas.append("Responde con el <b>numero</b> para descargar.")
|
lineas.append("Responde <b>/torrents NUMERO</b> para ver opciones y descargar.")
|
||||||
return trocear_texto(lineas)
|
return trocear_texto(lineas)
|
||||||
|
|
||||||
|
|
||||||
|
def aplanar_series(grupos):
|
||||||
|
"""Devuelve lista plana de episodios en el mismo orden de visualizacion
|
||||||
|
(grupos ordenados, episodios ordenados). La usa el bot para que el numero
|
||||||
|
elegido con /torrents coincida con lo mostrado."""
|
||||||
|
planos = []
|
||||||
|
for base in sorted(grupos, key=lambda x: x.lower()):
|
||||||
|
for it in grupos[base]:
|
||||||
|
planos.append(it)
|
||||||
|
return planos
|
||||||
|
|
||||||
|
|
||||||
def formatear_series(grupos):
|
def formatear_series(grupos):
|
||||||
"""Formatea resultados de series como lista de mensajes Telegram numerados."""
|
"""Formatea resultados de series como lista de mensajes Telegram numerados."""
|
||||||
if not grupos:
|
if not grupos:
|
||||||
return ["No se encontraron series con ese termino."]
|
return ["No se encontraron series con ese termino."]
|
||||||
lineas = []
|
lineas = []
|
||||||
|
num_global = 1
|
||||||
for base in sorted(grupos, key=lambda x: x.lower()):
|
for base in sorted(grupos, key=lambda x: x.lower()):
|
||||||
eps = grupos[base]
|
eps = grupos[base]
|
||||||
temp_max = max(parsear_episodio(e["name"])[0] for e in eps)
|
temp_max = max(parsear_episodio(e["name"])[0] for e in eps)
|
||||||
@@ -273,7 +282,6 @@ def formatear_series(grupos):
|
|||||||
lineas.append("")
|
lineas.append("")
|
||||||
|
|
||||||
temp_actual = 0
|
temp_actual = 0
|
||||||
num_global = 1
|
|
||||||
for it in eps:
|
for it in eps:
|
||||||
temp, cap = parsear_episodio(it["name"])
|
temp, cap = parsear_episodio(it["name"])
|
||||||
if temp != temp_actual:
|
if temp != temp_actual:
|
||||||
@@ -282,18 +290,15 @@ def formatear_series(grupos):
|
|||||||
lineas.append(f"<b>Temporada {temp}:</b>")
|
lineas.append(f"<b>Temporada {temp}:</b>")
|
||||||
resto = _limpiar_titulo_ep(it["name"][SERIE_EP_RE.search(it["name"]).end():]) \
|
resto = _limpiar_titulo_ep(it["name"][SERIE_EP_RE.search(it["name"]).end():]) \
|
||||||
if SERIE_EP_RE.search(it["name"]) else it["clean"]
|
if SERIE_EP_RE.search(it["name"]) else it["clean"]
|
||||||
enlace = it.get("enlace") or ""
|
|
||||||
if temp > 0:
|
if temp > 0:
|
||||||
etiqueta = f"S{temp:02d}E{cap:02d}"
|
etiqueta = f"S{temp:02d}E{cap:02d}"
|
||||||
else:
|
else:
|
||||||
etiqueta = it["clean"]
|
etiqueta = it["clean"]
|
||||||
lineas.append(f" <b>{num_global}.</b> {etiqueta} — {resto}")
|
lineas.append(f" <b>{num_global}.</b> {etiqueta} — {resto}")
|
||||||
if enlace:
|
|
||||||
lineas.append(f" <code>descargar {enlace}</code>")
|
|
||||||
num_global += 1
|
num_global += 1
|
||||||
lineas.append("")
|
lineas.append("")
|
||||||
|
|
||||||
lineas.append("Responde con el <b>numero</b> de episodio para descargar.")
|
lineas.append("Responde <b>/torrents NUMERO</b> de episodio para ver opciones y descargar.")
|
||||||
return trocear_texto(lineas)
|
return trocear_texto(lineas)
|
||||||
|
|
||||||
|
|
||||||
@@ -330,10 +335,9 @@ def formatear_novedades(items):
|
|||||||
y = f" ({it['year']})" if it["year"] else ""
|
y = f" ({it['year']})" if it["year"] else ""
|
||||||
tipo = "📺" if it["tipo"] == "serie" else "🎬"
|
tipo = "📺" if it["tipo"] == "serie" else "🎬"
|
||||||
idioma = "cast." if it.get("castellano") else "ing."
|
idioma = "cast." if it.get("castellano") else "ing."
|
||||||
enlace = it.get("enlace") or ""
|
|
||||||
lineas.append(f"{tipo} <b>{i}.</b> {it['clean']}{y} — {idioma}")
|
lineas.append(f"{tipo} <b>{i}.</b> {it['clean']}{y} — {idioma}")
|
||||||
if enlace:
|
lineas.append("")
|
||||||
lineas.append(f" <code>descargar {enlace}</code>")
|
lineas.append("Responde <b>/torrents NUMERO</b> para ver opciones y descargar.")
|
||||||
return trocear_texto(lineas)
|
return trocear_texto(lineas)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -106,12 +106,39 @@ def parental_status():
|
|||||||
return json.dumps(data, ensure_ascii=False, indent=2, default=str)
|
return json.dumps(data, ensure_ascii=False, indent=2, default=str)
|
||||||
|
|
||||||
|
|
||||||
|
def _mac_en_vivo(pistas):
|
||||||
|
"""Busca en los leases DHCP actuales un dispositivo cuyo hostname
|
||||||
|
contenga alguna pista. Devuelve (ip, mac, hostname) o None.
|
||||||
|
Sirve para tablets con MAC privada aleatoria (la MAC guardada rota)."""
|
||||||
|
try:
|
||||||
|
from router_control import _inventario
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
devices, _by_mac = _inventario()
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
for ip, mac, nombre in devices:
|
||||||
|
n = normalizar_nombre(nombre)
|
||||||
|
for p in pistas:
|
||||||
|
if p and (p in n or n in p):
|
||||||
|
return ip, mac, nombre
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def cambiar_bloqueo(nombre, blocked):
|
def cambiar_bloqueo(nombre, blocked):
|
||||||
device = resolver_dispositivo(nombre)
|
device = resolver_dispositivo(nombre)
|
||||||
if not device:
|
if not device:
|
||||||
raise ValueError(f"Dispositivo no reconocido: {nombre}")
|
raise ValueError(f"Dispositivo no reconocido: {nombre}")
|
||||||
asyncio.run(_set_block(device["mac"], device["name"], blocked))
|
mac = device["mac"]
|
||||||
return f"{'Bloqueado' if blocked else 'Activado'}: {device['name']}"
|
etiqueta = device["name"]
|
||||||
|
vivo = _mac_en_vivo((normalizar_nombre(nombre),
|
||||||
|
normalizar_nombre(etiqueta)))
|
||||||
|
if vivo and vivo[1].upper() != mac.upper():
|
||||||
|
mac = vivo[1]
|
||||||
|
etiqueta = f"{etiqueta} [{vivo[2]} {vivo[0]}]"
|
||||||
|
asyncio.run(_set_block(mac, device["name"], blocked))
|
||||||
|
return f"{'Bloqueado' if blocked else 'Activado'}: {etiqueta} ({mac})"
|
||||||
|
|
||||||
|
|
||||||
async def _aimesh_data():
|
async def _aimesh_data():
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ temporizadores_parental = {} # alias normalizado -> Timer de desbloqueo
|
|||||||
menu_pendiente = {} # chat_id -> accion de texto libre esperada (menu botones)
|
menu_pendiente = {} # chat_id -> accion de texto libre esperada (menu botones)
|
||||||
menu_pausa_nombre = {} # chat_id -> nombre elegido en flujo de pausa
|
menu_pausa_nombre = {} # chat_id -> nombre elegido en flujo de pausa
|
||||||
historial_chat = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
historial_chat = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
||||||
|
entrantes_chat = {} # chat_id -> [message_id...] enviados por el usuario (para /limpiar)
|
||||||
borrar_pend = {} # chat_id -> lista de tareas NAS esperando numero a borrar
|
borrar_pend = {} # chat_id -> lista de tareas NAS esperando numero a borrar
|
||||||
|
|
||||||
BASE = os.path.dirname(os.path.abspath(__file__))
|
BASE = os.path.dirname(os.path.abspath(__file__))
|
||||||
@@ -278,8 +279,10 @@ def borrar(chat_id, message_id):
|
|||||||
|
|
||||||
|
|
||||||
def limpiar_pantalla(chat_id):
|
def limpiar_pantalla(chat_id):
|
||||||
"""Borra los mensajes que el bot ha enviado en este chat (/limpiar)."""
|
"""Borra TODO el chat visible: mensajes del bot y del usuario (/limpiar).
|
||||||
|
Limite de Telegram: solo mensajes de menos de 48h se pueden borrar."""
|
||||||
lista = historial_chat.pop(chat_id, None) or []
|
lista = historial_chat.pop(chat_id, None) or []
|
||||||
|
lista += entrantes_chat.pop(chat_id, None) or []
|
||||||
borrados = 0
|
borrados = 0
|
||||||
for mid in reversed(lista):
|
for mid in reversed(lista):
|
||||||
try:
|
try:
|
||||||
@@ -292,7 +295,7 @@ def limpiar_pantalla(chat_id):
|
|||||||
borrados += 1
|
borrados += 1
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
aviso = enviar(f"🧹 Pantalla limpia ({borrados} mensajes borrados).", chat_id)
|
aviso = enviar(f"🧹 Chat limpio ({borrados} mensajes borrados).", chat_id)
|
||||||
if aviso:
|
if aviso:
|
||||||
threading.Timer(6.0, borrar, args=(chat_id, aviso)).start()
|
threading.Timer(6.0, borrar, args=(chat_id, aviso)).start()
|
||||||
|
|
||||||
@@ -943,6 +946,8 @@ def procesar_buscador_pelicula(nombre, chat_id):
|
|||||||
for m in mensajes:
|
for m in mensajes:
|
||||||
enviar(m, chat_id)
|
enviar(m, chat_id)
|
||||||
if resultados:
|
if resultados:
|
||||||
|
ultima_titulos[chat_id] = {"query": nombre, "results": resultados,
|
||||||
|
"origen": "catalogo"}
|
||||||
log(f"BUSCADOR pelis '{nombre}': {len(resultados)} resultados")
|
log(f"BUSCADOR pelis '{nombre}': {len(resultados)} resultados")
|
||||||
|
|
||||||
|
|
||||||
@@ -967,6 +972,9 @@ def procesar_buscador_serie(nombre, chat_id):
|
|||||||
enviar(m, chat_id)
|
enviar(m, chat_id)
|
||||||
if grupos:
|
if grupos:
|
||||||
total_eps = sum(len(v) for v in grupos.values())
|
total_eps = sum(len(v) for v in grupos.values())
|
||||||
|
ultima_titulos[chat_id] = {"query": nombre,
|
||||||
|
"results": vcb.aplanar_series(grupos),
|
||||||
|
"origen": "catalogo"}
|
||||||
log(f"BUSCADOR series '{nombre}': {len(grupos)} series, {total_eps} capitulos")
|
log(f"BUSCADOR series '{nombre}': {len(grupos)} series, {total_eps} capitulos")
|
||||||
|
|
||||||
|
|
||||||
@@ -989,6 +997,10 @@ def procesar_novedades(chat_id):
|
|||||||
return
|
return
|
||||||
for m in mensajes:
|
for m in mensajes:
|
||||||
enviar(m, chat_id)
|
enviar(m, chat_id)
|
||||||
|
if items:
|
||||||
|
ultima_titulos[chat_id] = {"query": "novedades", "results": items,
|
||||||
|
"origen": "catalogo"}
|
||||||
|
log(f"NOVEDADES: {len(items)} items")
|
||||||
|
|
||||||
|
|
||||||
def _int_arg(texto):
|
def _int_arg(texto):
|
||||||
@@ -1071,19 +1083,38 @@ def _mostrar_catalogo_genero(chat_id, tipo, genero, categoria):
|
|||||||
|
|
||||||
|
|
||||||
def procesar_torrents(n, chat_id):
|
def procesar_torrents(n, chat_id):
|
||||||
"""Muestra los torrents (Torrentio) del titulo numero n de la ultima busqueda."""
|
"""Muestra las opciones de descarga del numero n de la ultima busqueda
|
||||||
|
(/busca, /pelicula, /serie, /novedades o /genero)."""
|
||||||
estado = ultima_titulos.get(chat_id)
|
estado = ultima_titulos.get(chat_id)
|
||||||
if not estado or n is None or n < 1 or n > len(estado["results"]):
|
if not estado or n is None or n < 1 or n > len(estado["results"]):
|
||||||
enviar("Primero usa <b>/busca <nombre></b> y luego "
|
enviar("Primero usa <b>/busca</b>, <b>/pelicula</b>, <b>/serie</b>, "
|
||||||
|
"<b>/novedades</b> o <b>/genero</b> y luego "
|
||||||
"<b>/torrents <numero></b>.", chat_id)
|
"<b>/torrents <numero></b>.", chat_id)
|
||||||
return
|
return
|
||||||
|
r = estado["results"][n - 1]
|
||||||
|
if not r.get("imdb_id") and r.get("enlace"):
|
||||||
|
# Item de catalogo: ya trae enlace directo, sin paso por Torrentio.
|
||||||
|
nombre = r.get("clean") or r.get("name") or "titulo"
|
||||||
|
ultimos_torrents[chat_id] = {
|
||||||
|
"titulo": nombre,
|
||||||
|
"torrents": [{"filename": nombre, "calidad": "directo",
|
||||||
|
"size": None, "enlace": r["enlace"]}],
|
||||||
|
}
|
||||||
|
enviar(f"🧲 <b>{nombre}</b> — enlace directo disponible:\n"
|
||||||
|
"<b>1.</b> Descarga directa al NAS\n\n"
|
||||||
|
"Responde <b>/bajar 1</b> para descargarlo.", chat_id)
|
||||||
|
log(f"TORRENTS catalogo '{nombre}': enlace directo")
|
||||||
|
return
|
||||||
|
if not r.get("imdb_id"):
|
||||||
|
enviar("❌ Ese resultado no tiene enlace de descarga. "
|
||||||
|
"Prueba con <b>/busca <nombre></b>.", chat_id)
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
gol = _import_global_buscar()
|
gol = _import_global_buscar()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"global_buscar import error: {e}")
|
log(f"global_buscar import error: {e}")
|
||||||
enviar("❌ No se pudo cargar el modulo", chat_id)
|
enviar("❌ No se pudo cargar el modulo", chat_id)
|
||||||
return
|
return
|
||||||
r = estado["results"][n - 1]
|
|
||||||
enviar(f"🧲 Buscando torrents de <b>{r['name']}</b>...", chat_id)
|
enviar(f"🧲 Buscando torrents de <b>{r['name']}</b>...", chat_id)
|
||||||
try:
|
try:
|
||||||
torrents = gol.torrents_de(r["imdb_id"], r["type"])
|
torrents = gol.torrents_de(r["imdb_id"], r["type"])
|
||||||
@@ -1104,16 +1135,32 @@ def procesar_bajar(n, chat_id):
|
|||||||
"""Descarga el torrent numero n al NAS (Download Station via magnet)."""
|
"""Descarga el torrent numero n al NAS (Download Station via magnet)."""
|
||||||
estado = ultimos_torrents.get(chat_id)
|
estado = ultimos_torrents.get(chat_id)
|
||||||
if not estado or n is None or n < 1 or n > len(estado["torrents"]):
|
if not estado or n is None or n < 1 or n > len(estado["torrents"]):
|
||||||
enviar("Primero usa <b>/busca <nombre></b> y luego "
|
enviar("Primero usa <b>/busca</b>, <b>/pelicula</b>, <b>/serie</b>, "
|
||||||
|
"<b>/novedades</b> o <b>/genero</b>, luego "
|
||||||
"<b>/torrents <numero></b>.", chat_id)
|
"<b>/torrents <numero></b>.", chat_id)
|
||||||
return
|
return
|
||||||
|
t = estado["torrents"][n - 1]
|
||||||
|
if t.get("enlace") and not t.get("info_hash"):
|
||||||
|
# Enlace directo de catalogo: al NAS sin magnet.
|
||||||
|
try:
|
||||||
|
import nas_dl
|
||||||
|
ok = nas_dl.add_torrent(t["enlace"])
|
||||||
|
except Exception as e:
|
||||||
|
log(f"bajar error: {e}")
|
||||||
|
enviar(f"❌ Error al anadir al NAS: {e}", chat_id)
|
||||||
|
return
|
||||||
|
if ok:
|
||||||
|
enviar(f"📥 Añadido al NAS: <b>{t.get('filename') or estado['titulo']}</b>.",
|
||||||
|
chat_id)
|
||||||
|
else:
|
||||||
|
enviar("❌ No se pudo añadir al NAS.", chat_id)
|
||||||
|
return
|
||||||
try:
|
try:
|
||||||
gol = _import_global_buscar()
|
gol = _import_global_buscar()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log(f"global_buscar import error: {e}")
|
log(f"global_buscar import error: {e}")
|
||||||
enviar("❌ No se pudo cargar el modulo", chat_id)
|
enviar("❌ No se pudo cargar el modulo", chat_id)
|
||||||
return
|
return
|
||||||
t = estado["torrents"][n - 1]
|
|
||||||
magnet = gol.magnet_de(t)
|
magnet = gol.magnet_de(t)
|
||||||
log(f"BAJAR '{estado['titulo']}' torrent {n}: {magnet[:60]}...")
|
log(f"BAJAR '{estado['titulo']}' torrent {n}: {magnet[:60]}...")
|
||||||
try:
|
try:
|
||||||
@@ -1167,6 +1214,11 @@ def _atender_update(upd):
|
|||||||
return
|
return
|
||||||
texto = msg.get("text")
|
texto = msg.get("text")
|
||||||
chat_id = msg["chat"]["id"]
|
chat_id = msg["chat"]["id"]
|
||||||
|
if msg.get("message_id"):
|
||||||
|
lista = entrantes_chat.setdefault(chat_id, [])
|
||||||
|
lista.append(msg["message_id"])
|
||||||
|
if len(lista) > 300:
|
||||||
|
entrantes_chat[chat_id] = lista[-300:]
|
||||||
if texto:
|
if texto:
|
||||||
procesar(texto, chat_id)
|
procesar(texto, chat_id)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ bloqueos = {} # chat_id -> True (procesando mensaje)
|
|||||||
sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None}
|
sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None}
|
||||||
repos_cache = [] # lista de {'slug','dir'}
|
repos_cache = [] # lista de {'slug','dir'}
|
||||||
sentidos = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
sentidos = {} # chat_id -> [message_id...] enviados por el bot (para /limpiar)
|
||||||
|
entrantes = {} # chat_id -> [message_id...] enviados por el usuario (para /limpiar)
|
||||||
menu_msg = {} # chat_id -> message_id del menu abierto
|
menu_msg = {} # chat_id -> message_id del menu abierto
|
||||||
|
|
||||||
|
|
||||||
@@ -560,8 +561,10 @@ def cmd_salir(chat):
|
|||||||
|
|
||||||
|
|
||||||
def cmd_limpiar(chat):
|
def cmd_limpiar(chat):
|
||||||
"""Borra los mensajes que el bot ha enviado en este chat."""
|
"""Borra TODO el chat visible: mensajes del bot y del usuario.
|
||||||
|
Limite de Telegram: solo mensajes de menos de 48h se pueden borrar."""
|
||||||
lista = sentidos.get(str(chat)) or []
|
lista = sentidos.get(str(chat)) or []
|
||||||
|
lista += entrantes.get(str(chat)) or []
|
||||||
borrados = 0
|
borrados = 0
|
||||||
for mid in reversed(lista):
|
for mid in reversed(lista):
|
||||||
try:
|
try:
|
||||||
@@ -573,7 +576,8 @@ def cmd_limpiar(chat):
|
|||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
sentidos[str(chat)] = []
|
sentidos[str(chat)] = []
|
||||||
enviar(chat, f"🧹 Pantalla limpia ({borrados} mensajes borrados).")
|
entrantes[str(chat)] = []
|
||||||
|
enviar(chat, f"🧹 Chat limpio ({borrados} mensajes borrados).")
|
||||||
# borra tambien este aviso al cabo de unos segundos
|
# borra tambien este aviso al cabo de unos segundos
|
||||||
threading.Timer(6.0, _autolimpia, args=(chat,)).start()
|
threading.Timer(6.0, _autolimpia, args=(chat,)).start()
|
||||||
|
|
||||||
@@ -887,6 +891,11 @@ def main():
|
|||||||
log(f"Bloqueado chat {chat}")
|
log(f"Bloqueado chat {chat}")
|
||||||
continue
|
continue
|
||||||
texto = msg.get("text")
|
texto = msg.get("text")
|
||||||
|
if msg.get("message_id"):
|
||||||
|
lista = entrantes.setdefault(chat, [])
|
||||||
|
lista.append(msg["message_id"])
|
||||||
|
if len(lista) > 300:
|
||||||
|
entrantes[chat] = lista[-300:]
|
||||||
if texto:
|
if texto:
|
||||||
threading.Thread(target=procesar, args=(texto, chat),
|
threading.Thread(target=procesar, args=(texto, chat),
|
||||||
daemon=True).start()
|
daemon=True).start()
|
||||||
|
|||||||
Reference in New Issue
Block a user