Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions .env.sample

This file was deleted.

15 changes: 14 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,17 @@ bin-release/
*.raw

# fly.io configs
fly.toml
fly.toml

# Virtual environments
venv/
.env/
.venv/

# Python cache
__pycache__/
*.pyc

# IDEs
.vscode/
.idea/
11 changes: 10 additions & 1 deletion pyUltroid/fns/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,20 @@ async def updater():
ac_br = repo.active_branch.name
repo.create_remote("upstream", off_repo) if "upstream" not in repo.remotes else None
ups_rem = repo.remote("upstream")
ups_rem.fetch(ac_br)

try:
ups_rem.fetch(ac_br)
except GitCommandError:
LOGS.warning(
f"Updater skipped: branch '{ac_br}' not found in upstream"
)
return False

changelog, tl_chnglog = await gen_chlog(repo, f"HEAD..upstream/{ac_br}")
return bool(changelog)



# ----------------Fast Upload/Download----------------
# @1danish_00 @new-dev0 @buddhhu

Expand Down
83 changes: 53 additions & 30 deletions pyUltroid/fns/ytdl.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,17 @@
# Ultroid - UserBot
# Copyright (C) 2021-2025 TeamUltroid
#
# This file is a part of < https://github.com/TeamUltroid/Ultroid/ >
# PLease read the GNU Affero General Public License in
# <https://github.com/TeamUltroid/pyUltroid/blob/main/LICENSE>.

import glob
import os
import re
import time

from telethon import Button

try:
from youtubesearchpython import Playlist, VideosSearch
except ImportError:
Playlist, VideosSearch = None, None

from yt_dlp import YoutubeDL

from .. import LOGS, udB
from .helper import download_file, humanbytes, run_async, time_formatter
from .tools import set_attributes


# ------------ Progreso de descarga ------------
async def ytdl_progress(k, start_time, event):
if k["status"] == "error":
return await event.edit("error")
Expand All @@ -42,14 +30,26 @@ async def ytdl_progress(k, start_time, event):
LOGS.error(f"ytdl_progress: {ex}")


# ------------ Obtener el enlace de YouTube (ahora con yt-dlp) ------------
def get_yt_link(query):
search = VideosSearch(query, limit=1).result()
ydl_opts = {
"quiet": True,
"default_search": "ytsearch1", # Búsqueda en YouTube
"skip_download": True, # No descargamos, solo extraemos la URL
"nocheckcertificate": True, # Desactivar la verificación del certificado SSL
}

try:
return search["result"][0]["link"]
except IndexError:
return
with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(query, download=False)
if "entries" in info and info["entries"]:
return info["entries"][0].get("webpage_url")
except Exception as e:
LOGS.error(f"Error al obtener el enlace: {e}")
return None


# ------------ Descargar el video o playlist ------------
async def download_yt(event, link, ytd):
reply_to = event.reply_to_msg_id or event
info = await dler(event, link, ytd, download=True)
Expand Down Expand Up @@ -162,10 +162,25 @@ async def download_yt(event, link, ytd):
pass


# ---------------YouTube Downloader Inline---------------
# @New-Dev0 @buddhhu @1danish-00
# --------------- Obtener enlaces de videos en una playlist (usando yt-dlp) ---------------
async def get_videos_link(url):
to_return = []

ydl_opts = {
"quiet": True,
"extract_flat": True, # Esto solo extrae los enlaces sin descargarlos
}

with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
if 'entries' in info:
for entry in info['entries']:
to_return.append(entry['url'])

return to_return


# --------------- Obtener los botones de calidad de video y audio ---------------
def get_formats(type, id, data):
if type == "audio":
audio = []
Expand Down Expand Up @@ -209,6 +224,7 @@ def get_formats(type, id, data):
return []


# --------------- Crear botones para selección de formatos ---------------
def get_buttons(listt):
id = listt[0]["ytid"]
butts = [
Expand All @@ -227,6 +243,7 @@ def get_buttons(listt):
return buttons


# --------------- Función para obtener el enlace del video ---------------
async def dler(event, url, opts: dict = {}, download=False):
await event.edit("`Getting Data...`")
if "quiet" not in opts:
Expand All @@ -242,6 +259,7 @@ async def dler(event, url, opts: dict = {}, download=False):
return


# --------------- Descargar el video usando yt-dlp ---------------
@run_async
def ytdownload(url, opts):
try:
Expand All @@ -250,20 +268,25 @@ def ytdownload(url, opts):
LOGS.error(ex)


# --------------- Extraer información del video ---------------
@run_async
def extract_info(url, opts):
return YoutubeDL(opts).extract_info(url=url, download=False)


@run_async
def get_videos_link(url):
# --------------- Obtener los enlaces de los videos de la playlist ---------------
async def get_videos_link(url):
to_return = []
regex = re.search(r"\?list=([(\w+)\-]*)", url)
if not regex:
return to_return
playlist_id = regex.group(1)
videos = Playlist(playlist_id)
for vid in videos.videos:
link = re.search(r"\?v=([(\w+)\-]*)", vid["link"]).group(1)
to_return.append(f"https://youtube.com/watch?v={link}")
return to_return

ydl_opts = {
"quiet": True,
"extract_flat": True, # Esto solo extrae los enlaces sin descargarlos
}

with YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
if 'entries' in info:
for entry in info['entries']:
to_return.append(entry['url'])

return to_return
Loading
Loading