Add files via upload
This commit is contained in:
parent
07f2ed525b
commit
6e7f0c1505
37 changed files with 4084 additions and 20 deletions
102
app/backend/search.py
Normal file
102
app/backend/search.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
import requests
|
||||
import yt_dlp
|
||||
from backend.downloader import ffmpeg_path
|
||||
|
||||
_UA = (
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/124.0.0.0 Safari/537.36"
|
||||
)
|
||||
|
||||
|
||||
def _fmt_duration(seconds) -> str:
|
||||
try:
|
||||
seconds = int(seconds)
|
||||
except (TypeError, ValueError):
|
||||
return ""
|
||||
m, s = divmod(seconds, 60)
|
||||
return f"{m}:{s:02d}"
|
||||
|
||||
|
||||
def _ytdlp_search(prefix: str, query: str, limit: int) -> list:
|
||||
opts = {"quiet": True, "no_warnings": True, "ignoreerrors": True, "extract_flat": "in_playlist"}
|
||||
ffmpeg = ffmpeg_path()
|
||||
if ffmpeg:
|
||||
opts["ffmpeg_location"] = ffmpeg
|
||||
|
||||
results = []
|
||||
try:
|
||||
with yt_dlp.YoutubeDL(opts) as ydl:
|
||||
info = ydl.extract_info(f"{prefix}{limit}:{query}", download=False)
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
if not info:
|
||||
return []
|
||||
|
||||
entries = info.get("entries") or []
|
||||
for e in entries:
|
||||
if not e:
|
||||
continue
|
||||
results.append(
|
||||
{
|
||||
"title": e.get("title") or "",
|
||||
"artist": e.get("uploader") or e.get("channel") or "",
|
||||
"cover_url": e.get("thumbnail") or (e.get("thumbnails") or [{}])[-1].get("url"),
|
||||
"duration": _fmt_duration(e.get("duration")),
|
||||
"url": e.get("url") or e.get("webpage_url") or e.get("id"),
|
||||
"source": "youtube" if prefix == "ytsearch" else "soundcloud",
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
def search_youtube(query: str, limit: int = 10) -> list:
|
||||
return _ytdlp_search("ytsearch", query, limit)
|
||||
|
||||
|
||||
def search_soundcloud(query: str, limit: int = 10) -> list:
|
||||
return _ytdlp_search("scsearch", query, limit)
|
||||
|
||||
|
||||
def search_apple_music(query: str, limit: int = 10) -> list:
|
||||
try:
|
||||
resp = requests.get(
|
||||
"https://itunes.apple.com/search",
|
||||
params={"term": query, "media": "music", "entity": "song", "limit": limit},
|
||||
headers={"User-Agent": _UA},
|
||||
timeout=10,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
results = []
|
||||
for row in data.get("results", []):
|
||||
cover = (row.get("artworkUrl100") or "").replace("100x100bb", "600x600bb")
|
||||
results.append(
|
||||
{
|
||||
"title": row.get("trackName") or "",
|
||||
"artist": row.get("artistName") or "",
|
||||
"cover_url": cover,
|
||||
"duration": _fmt_duration((row.get("trackTimeMillis") or 0) // 1000),
|
||||
"url": row.get("trackViewUrl") or "",
|
||||
"source": "apple_music",
|
||||
}
|
||||
)
|
||||
return results
|
||||
|
||||
|
||||
SEARCH_FUNCS = {
|
||||
"youtube": search_youtube,
|
||||
"soundcloud": search_soundcloud,
|
||||
"apple_music": search_apple_music,
|
||||
}
|
||||
|
||||
|
||||
def search(platform: str, query: str, limit: int = 10) -> list:
|
||||
fn = SEARCH_FUNCS.get(platform)
|
||||
if not fn:
|
||||
raise ValueError(f"Unknown platform: {platform}")
|
||||
return fn(query, limit)
|
||||
Loading…
Add table
Add a link
Reference in a new issue