fix: added floorp to not dim

This commit is contained in:
Hannes committed 2026-10-21 18:39:44 +02:00
1 parent b3b3f9825b
commit 693802ff26
3 files changed
+185 -54

No files matched your search

+176 -54
View File
@@ -1,74 +1,196 @@
#!/bin/bash
#!/usr/bin/env python3
"""Lookup TMDB ID for the TMDB browser tab on a Hyprland workspace
and type "<Clean Title> (<year>) [tmdb-<id>]" via wtype.
tmdbid() {
local type q url
type="$1"
shift
Uses the TMDB API v3 (stdlib only, no curl/jq needed).
API key can be overridden without editing the file:
export TMDB_API_KEY="your-key"
q=$(printf '%s' "$*" | jq -sRr @uri)
Usage:
tmdb.sh [workspace] [--print]
--print / -p : print result to stdout instead of typing (for testing)
"""
if [ "$type" = "tv" ]; then
url="https://www.themoviedb.org/search/tv?query=$q"
else
url="https://www.themoviedb.org/search/movie?query=$q"
fi
import json
import os
import re
import shutil
import subprocess
import sys
import time
import urllib.parse
import urllib.request
curl -sL -A 'Mozilla/5.0' "$url" \
| grep -oE '/(movie|tv)/[0-9]+' \
| head -1 \
| cut -d/ -f3
}
TMDB_API_KEY = os.environ.get("TMDB_API_KEY", "7ba1c818fea0dec15d3f4d27bf1ffbdb")
TMDB_API = "https://api.themoviedb.org/3"
TMDB_LANG = "en-US"
clean_title() {
local s="$1"
# Characters illegal on Windows (< > : " / \ | ? *) plus "/" (separator on
# Linux/macOS too). Everything else - incl. numbers, unicode letters and
# harmless punctuation like - _ . ' & , ! ( ) [ ] - is kept.
UNSAFE_RE = re.compile(r'[/\\:*?"<>|]')
CONTROL_RE = re.compile(r"[\x00-\x1f\x7f]")
YEAR_PARENS_RE = re.compile(r"\s*\([^)]*\d{4}[^)]*\)")
ANY_PARENS_RE = re.compile(r"\s*\([^)]*\)\s*")
YEAR_RE = re.compile(r"(\d{4})")
TV_RE = re.compile(r"TV\s+Series", re.IGNORECASE)
# remove (year) or (TV Series year) style parentheses
s=$(echo "$s" | sed -E 's/ *\([^)]*[0-9]{4}[^)]*\)//')
UMLAUTS = str.maketrans({
"ä": "ae", "ö": "oe", "ü": "ue",
"Ä": "Ae", "Ö": "Oe", "Ü": "Ue",
"ß": "ss",
})
# umlaut replacement
s="${s//ä/ae}"; s="${s//ö/oe}"; s="${s//ü/ue}"
s="${s//Ä/Ae}"; s="${s//Ö/Oe}"; s="${s//Ü/Ue}"
# remove all numbers
s=$(echo "$s" | tr -d '0-9')
def die(msg: str) -> "NoReturn":
print(f"tmdb: {msg}", file=sys.stderr)
if shutil.which("notify-send"):
subprocess.run(["notify-send", "tmdb.sh", msg], check=False)
sys.exit(1)
# remove special characters except spaces and letters
s=$(echo "$s" | tr -cd '[:alpha:] [:space:]')
# clean extra spaces
s=$(echo "$s" | tr -s ' ')
def clean_title(s: str) -> str:
# Remove "(year)" / "(TV Series year...)" blocks; the wrapper re-adds
# "(year)" itself so this avoids "Title (2013) (2013)".
s = YEAR_PARENS_RE.sub("", s)
s = s.translate(UMLAUTS)
s = UNSAFE_RE.sub(" ", s)
s = CONTROL_RE.sub(" ", s)
s = re.sub(r"\s+", " ", s).strip()
s = re.sub(r"[. ]+$", "", s).strip()
return s
echo "$s"
}
ws="${1:-3}"
def get_browser_title(workspace: int) -> str:
try:
out = subprocess.run(
["hyprctl", "clients", "-j"],
capture_output=True, text=True, timeout=10, check=True,
)
except FileNotFoundError:
die("missing dependency: hyprctl")
except subprocess.CalledProcessError as e:
die(f"hyprctl failed: {e.stderr.strip() or e}")
try:
clients = json.loads(out.stdout)
except json.JSONDecodeError as e:
die(f"could not parse hyprctl output: {e}")
for client in clients:
try:
ws = client.get("workspace", {}).get("id")
except AttributeError:
continue
title = client.get("title", "") or ""
if ws == workspace and "The Movie Database" in title:
return title
die(f"no TMDB tab found on workspace {workspace}")
title=$(hyprctl clients -j | jq ".[] | select(.workspace.id == $ws)" | grep "The Movie Database" | sed 's/ — The Movie Database.*//' | sed 's/ "title": "//' | sed 's/"$//')
search_title=$(echo "$title" | sed -E 's/ *\([^)]*\) *//g')
def strip_tmdb_suffix(title: str) -> str:
# TMDB tab titles look like: "Dampfnudelblues (2013) — The Movie Database (TMDB)"
for sep in (" — ", " -- ", " - The Movie Database"):
if sep in title:
title = title.split(sep, 1)[0]
break
return title.strip()
if echo "$title" | grep -qi "TV [Ss]eries"; then
type="tv"
else
type="movie"
fi
tmdbid=$(tmdbid "$type" "$search_title")
def tmdb_search(media_type: str, query: str, want_year: str = ""):
"""Return (id, title, date) for the best hit, or None."""
if len(query) < 2:
return None
endpoint = f"{TMDB_API}/search/{'tv' if media_type == 'tv' else 'movie'}"
params = {
"api_key": TMDB_API_KEY,
"language": TMDB_LANG,
"page": "1",
"include_adult": "false",
"query": query,
}
url = endpoint + "?" + urllib.parse.urlencode(params)
req = urllib.request.Request(url, headers={"Accept": "application/json"})
try:
with urllib.request.urlopen(req, timeout=15) as resp:
data = json.load(resp)
except Exception as e:
print(f"tmdb: API request failed: {e}", file=sys.stderr)
return None
if isinstance(data, dict) and data.get("success") is False:
print(f"tmdb: API error: {data.get('status_message', 'unknown error')}",
file=sys.stderr)
return None
results = data.get("results") or []
if want_year:
for r in results:
date = str(r.get("release_date") or r.get("first_air_date") or "")
if date.startswith(want_year):
return (r.get("id"), r.get("title") or r.get("name") or "", date)
if results:
r = results[0]
return (r.get("id"), r.get("title") or r.get("name") or "",
str(r.get("release_date") or r.get("first_air_date") or ""))
return None
if [ -z "$tmdbid" ]; then
if [ "$type" = "tv" ]; then
tmdbid=$(tmdbid "movie" "$search_title")
else
tmdbid=$(tmdbid "tv" "$search_title")
fi
fi
if [[ $title =~ ([0-9]{4}) ]]; then
year="${BASH_REMATCH[1]}"
else
year=""
fi
def main() -> None:
args = sys.argv[1:]
do_print = any(a in ("-p", "--print", "--dry-run") for a in args)
args = [a for a in args if a not in ("-p", "--print", "--dry-run")]
clean=$(clean_title "$title")
ws = 3
if args:
if not re.fullmatch(r"\d+", args[0]):
die(f"invalid workspace id: {args[0]}")
ws = int(args[0])
wtype "$clean ($year) [tmdb-$tmdbid]"
if not TMDB_API_KEY:
die("TMDB_API_KEY is empty")
if shutil.which("hyprctl") is None:
die("missing dependency: hyprctl")
if not do_print and shutil.which("wtype") is None:
die("missing dependency: wtype")
raw_title = get_browser_title(ws)
title = strip_tmdb_suffix(raw_title).strip()
search_title = ANY_PARENS_RE.sub(" ", title)
search_title = re.sub(r"\s+", " ", search_title).strip()
if not search_title:
die(f"could not derive search title from: {title}")
media_type = "tv" if TV_RE.search(title) else "movie"
m = YEAR_RE.search(title)
want_year = m.group(1) if m else ""
result = tmdb_search(media_type, search_title, want_year)
if result is None:
fallback = "movie" if media_type == "tv" else "tv"
result = tmdb_search(fallback, search_title, want_year)
if result is None or result[0] is None:
die(f"no TMDB result for: {search_title}")
tmdb_id, api_title, api_date = result
clean = clean_title(api_title) if api_title else clean_title(title)
year = want_year
if not year:
m = YEAR_RE.search(api_date or "")
year = m.group(1) if m else ""
out = f"{clean} ({year}) [tmdb-{tmdb_id}]" if year else f"{clean} [tmdb-{tmdb_id}]"
if do_print:
print(out)
return
# Let the macro-pad key release before typing, otherwise held modifiers
# can mangle/overwrite the typed text in the focused window.
time.sleep(0.25)
try:
subprocess.run(["wtype", "--", out], check=True)
except subprocess.CalledProcessError as e:
die(f"wtype failed: {e}")
if __name__ == "__main__":
main()