From bdc6cf8f480581dd5ec82eba79595e32cdd29c4a Mon Sep 17 00:00:00 2001 From: juanjo Date: Sun, 6 Sep 2026 12:21:19 +0200 Subject: [PATCH] 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 --- videoclub/global_buscar.py | 2 +- videoclub/listados/2026-09-06.md | 60 ++++ videoclub/snapshots/2026-09-06.json | 413 ++++++++++++++++++++++++++++ videoclub/videoclub_buscador.py | 28 +- vigilancia/asus_api_control.py | 31 ++- vigilancia/pi_bot.py | 70 ++++- vps_opencode_bot/opencode_bot.py | 13 +- 7 files changed, 591 insertions(+), 26 deletions(-) create mode 100644 videoclub/listados/2026-09-06.md create mode 100644 videoclub/snapshots/2026-09-06.json diff --git a/videoclub/global_buscar.py b/videoclub/global_buscar.py index 3507ebd..bf973b5 100644 --- a/videoclub/global_buscar.py +++ b/videoclub/global_buscar.py @@ -247,7 +247,7 @@ def formatear_titulos(resultados): if not resultados: return ["No se encontraron resultados para ese termino."] lineas = [f"🎬 Resultados globales ({len(resultados)}):", - "Responde /bajar <numero> para ver torrents.", ""] + "Responde /torrents <numero> para ver torrents.", ""] for i, r in enumerate(resultados, 1): icono = "📺" if r["type"] == "series" else "🎬" y = f" ({r['year']})" if r.get("year") else "" diff --git a/videoclub/listados/2026-09-06.md b/videoclub/listados/2026-09-06.md new file mode 100644 index 0000000..bf2b081 --- /dev/null +++ b/videoclub/listados/2026-09-06.md @@ -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` diff --git a/videoclub/snapshots/2026-09-06.json b/videoclub/snapshots/2026-09-06.json new file mode 100644 index 0000000..cbcfde8 --- /dev/null +++ b/videoclub/snapshots/2026-09-06.json @@ -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" + } + ] +} \ No newline at end of file diff --git a/videoclub/videoclub_buscador.py b/videoclub/videoclub_buscador.py index a088dd2..42f3f57 100644 --- a/videoclub/videoclub_buscador.py +++ b/videoclub/videoclub_buscador.py @@ -252,20 +252,29 @@ def formatear_peliculas(resultados): calidad = "4K" if "4k" in (it.get("name") or "").lower() or \ "2160p" in (it.get("name") or "").lower() else "HD" idioma = "cast." if it.get("castellano") else "ing." - enlace = it.get("enlace") or "" lineas.append(f"{i}. {it['clean']}{y} — {calidad}, {idioma}") - if enlace: - lineas.append(f" descargar {enlace}") lineas.append("") - lineas.append("Responde con el numero para descargar.") + lineas.append("Responde /torrents NUMERO para ver opciones y descargar.") 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): """Formatea resultados de series como lista de mensajes Telegram numerados.""" if not grupos: return ["No se encontraron series con ese termino."] lineas = [] + num_global = 1 for base in sorted(grupos, key=lambda x: x.lower()): eps = grupos[base] temp_max = max(parsear_episodio(e["name"])[0] for e in eps) @@ -273,7 +282,6 @@ def formatear_series(grupos): lineas.append("") temp_actual = 0 - num_global = 1 for it in eps: temp, cap = parsear_episodio(it["name"]) if temp != temp_actual: @@ -282,18 +290,15 @@ def formatear_series(grupos): lineas.append(f"Temporada {temp}:") resto = _limpiar_titulo_ep(it["name"][SERIE_EP_RE.search(it["name"]).end():]) \ if SERIE_EP_RE.search(it["name"]) else it["clean"] - enlace = it.get("enlace") or "" if temp > 0: etiqueta = f"S{temp:02d}E{cap:02d}" else: etiqueta = it["clean"] lineas.append(f" {num_global}. {etiqueta} — {resto}") - if enlace: - lineas.append(f" descargar {enlace}") num_global += 1 lineas.append("") - lineas.append("Responde con el numero de episodio para descargar.") + lineas.append("Responde /torrents NUMERO de episodio para ver opciones y descargar.") return trocear_texto(lineas) @@ -330,10 +335,9 @@ def formatear_novedades(items): y = f" ({it['year']})" if it["year"] else "" tipo = "📺" if it["tipo"] == "serie" else "🎬" idioma = "cast." if it.get("castellano") else "ing." - enlace = it.get("enlace") or "" lineas.append(f"{tipo} {i}. {it['clean']}{y} — {idioma}") - if enlace: - lineas.append(f" descargar {enlace}") + lineas.append("") + lineas.append("Responde /torrents NUMERO para ver opciones y descargar.") return trocear_texto(lineas) diff --git a/vigilancia/asus_api_control.py b/vigilancia/asus_api_control.py index c871c71..ad19ea8 100644 --- a/vigilancia/asus_api_control.py +++ b/vigilancia/asus_api_control.py @@ -106,12 +106,39 @@ def parental_status(): 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): device = resolver_dispositivo(nombre) if not device: raise ValueError(f"Dispositivo no reconocido: {nombre}") - asyncio.run(_set_block(device["mac"], device["name"], blocked)) - return f"{'Bloqueado' if blocked else 'Activado'}: {device['name']}" + mac = device["mac"] + 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(): diff --git a/vigilancia/pi_bot.py b/vigilancia/pi_bot.py index 93fceac..e33cd3e 100644 --- a/vigilancia/pi_bot.py +++ b/vigilancia/pi_bot.py @@ -19,6 +19,7 @@ temporizadores_parental = {} # alias normalizado -> Timer de desbloqueo menu_pendiente = {} # chat_id -> accion de texto libre esperada (menu botones) menu_pausa_nombre = {} # chat_id -> nombre elegido en flujo de pausa 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 BASE = os.path.dirname(os.path.abspath(__file__)) @@ -278,8 +279,10 @@ def borrar(chat_id, message_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 += entrantes_chat.pop(chat_id, None) or [] borrados = 0 for mid in reversed(lista): try: @@ -292,7 +295,7 @@ def limpiar_pantalla(chat_id): borrados += 1 except Exception: pass - aviso = enviar(f"🧹 Pantalla limpia ({borrados} mensajes borrados).", chat_id) + aviso = enviar(f"🧹 Chat limpio ({borrados} mensajes borrados).", chat_id) if aviso: 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: enviar(m, chat_id) if resultados: + ultima_titulos[chat_id] = {"query": nombre, "results": resultados, + "origen": "catalogo"} log(f"BUSCADOR pelis '{nombre}': {len(resultados)} resultados") @@ -967,6 +972,9 @@ def procesar_buscador_serie(nombre, chat_id): enviar(m, chat_id) if grupos: 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") @@ -989,6 +997,10 @@ def procesar_novedades(chat_id): return for m in mensajes: 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): @@ -1071,11 +1083,31 @@ def _mostrar_catalogo_genero(chat_id, tipo, genero, categoria): 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) if not estado or n is None or n < 1 or n > len(estado["results"]): - enviar("Primero usa /busca <nombre> y luego " - "/torrents <numero>.", chat_id) + enviar("Primero usa /busca, /pelicula, /serie, " + "/novedades o /genero y luego " + "/torrents <numero>.", chat_id) + 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"🧲 {nombre} — enlace directo disponible:\n" + "1. Descarga directa al NAS\n\n" + "Responde /bajar 1 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 /busca <nombre>.", chat_id) return try: gol = _import_global_buscar() @@ -1083,7 +1115,6 @@ def procesar_torrents(n, chat_id): log(f"global_buscar import error: {e}") enviar("❌ No se pudo cargar el modulo", chat_id) return - r = estado["results"][n - 1] enviar(f"🧲 Buscando torrents de {r['name']}...", chat_id) try: torrents = gol.torrents_de(r["imdb_id"], r["type"]) @@ -1104,8 +1135,25 @@ def procesar_bajar(n, chat_id): """Descarga el torrent numero n al NAS (Download Station via magnet).""" estado = ultimos_torrents.get(chat_id) if not estado or n is None or n < 1 or n > len(estado["torrents"]): - enviar("Primero usa /busca <nombre> y luego " - "/torrents <numero>.", chat_id) + enviar("Primero usa /busca, /pelicula, /serie, " + "/novedades o /genero, luego " + "/torrents <numero>.", chat_id) + 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: {t.get('filename') or estado['titulo']}.", + chat_id) + else: + enviar("❌ No se pudo añadir al NAS.", chat_id) return try: gol = _import_global_buscar() @@ -1113,7 +1161,6 @@ def procesar_bajar(n, chat_id): log(f"global_buscar import error: {e}") enviar("❌ No se pudo cargar el modulo", chat_id) return - t = estado["torrents"][n - 1] magnet = gol.magnet_de(t) log(f"BAJAR '{estado['titulo']}' torrent {n}: {magnet[:60]}...") try: @@ -1167,6 +1214,11 @@ def _atender_update(upd): return texto = msg.get("text") 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: procesar(texto, chat_id) except Exception as e: diff --git a/vps_opencode_bot/opencode_bot.py b/vps_opencode_bot/opencode_bot.py index 5d669e6..d0b2f85 100644 --- a/vps_opencode_bot/opencode_bot.py +++ b/vps_opencode_bot/opencode_bot.py @@ -53,6 +53,7 @@ bloqueos = {} # chat_id -> True (procesando mensaje) sesiones = {} # chat_id -> {'repo': slug, 'session': id, 'model': obj|None} repos_cache = [] # lista de {'slug','dir'} 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 @@ -560,8 +561,10 @@ def cmd_salir(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 += entrantes.get(str(chat)) or [] borrados = 0 for mid in reversed(lista): try: @@ -573,7 +576,8 @@ def cmd_limpiar(chat): except Exception: pass 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 threading.Timer(6.0, _autolimpia, args=(chat,)).start() @@ -887,6 +891,11 @@ def main(): log(f"Bloqueado chat {chat}") continue 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: threading.Thread(target=procesar, args=(texto, chat), daemon=True).start()