|
|
|
@ -7,6 +7,15 @@ from config import VIDEOS_PER_PAGE, DASHBOARD_PER_PAGE
|
|
|
|
|
|
|
|
|
|
|
|
web = Blueprint("web", __name__)
|
|
|
|
web = Blueprint("web", __name__)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import requests
|
|
|
|
|
|
|
|
def _get_recording_streamers() -> set[str]:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
resp = requests.get("http://localhost:5000/api/get_recording/", timeout=3)
|
|
|
|
|
|
|
|
resp.raise_for_status()
|
|
|
|
|
|
|
|
return resp.json()
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
|
|
return set()
|
|
|
|
|
|
|
|
|
|
|
|
from datetime import date, datetime, timedelta
|
|
|
|
from datetime import date, datetime, timedelta
|
|
|
|
def _parse_dates(timeframe: str, start_str: str | None, end_str: str | None):
|
|
|
|
def _parse_dates(timeframe: str, start_str: str | None, end_str: str | None):
|
|
|
|
"""Return (start, end) as date objects or (None, None). End inclusive by day."""
|
|
|
|
"""Return (start, end) as date objects or (None, None). End inclusive by day."""
|
|
|
|
@ -37,22 +46,24 @@ def dashboard():
|
|
|
|
query = request.args.get("q", "").lower().strip()
|
|
|
|
query = request.args.get("q", "").lower().strip()
|
|
|
|
sort = request.args.get("sort", "total_size")
|
|
|
|
sort = request.args.get("sort", "total_size")
|
|
|
|
dir_ = request.args.get("dir", "desc")
|
|
|
|
dir_ = request.args.get("dir", "desc")
|
|
|
|
|
|
|
|
reverse = (dir_ == "desc")
|
|
|
|
|
|
|
|
|
|
|
|
timeframe = request.args.get("timeframe", "all")
|
|
|
|
timeframe = request.args.get("timeframe", "all")
|
|
|
|
start_str = request.args.get("start")
|
|
|
|
start_str = request.args.get("start")
|
|
|
|
end_str = request.args.get("end")
|
|
|
|
end_str = request.args.get("end")
|
|
|
|
reverse = (dir_ == "desc")
|
|
|
|
show_online_first = request.args.get("online") == "1"
|
|
|
|
|
|
|
|
|
|
|
|
start, end = _parse_dates(timeframe, start_str, end_str)
|
|
|
|
start, end = _parse_dates(timeframe, start_str, end_str)
|
|
|
|
|
|
|
|
|
|
|
|
# ---- build cache over timeframe ----
|
|
|
|
# ---- build cache over timeframe ----
|
|
|
|
cache = build_cache(start=start, end=end)
|
|
|
|
cache = build_cache(start=start, end=end)
|
|
|
|
items = list(cache["storage_usage"].items())
|
|
|
|
items = list(cache["storage_usage"].items()) # [("user::platform", {...}), ...]
|
|
|
|
|
|
|
|
|
|
|
|
# ---- search ----
|
|
|
|
# ---- search ----
|
|
|
|
if query:
|
|
|
|
if query:
|
|
|
|
items = [e for e in items if query in e[0].split("::")[0].lower()]
|
|
|
|
items = [e for e in items if query in e[0].split("::")[0].lower()]
|
|
|
|
|
|
|
|
|
|
|
|
# ---- sort ----
|
|
|
|
# ---- sort keys ----
|
|
|
|
def k_user(x): return x[0].split("::")[0].lower()
|
|
|
|
def k_user(x): return x[0].split("::")[0].lower()
|
|
|
|
def k_platform(x): return x[0].split("::")[1].lower()
|
|
|
|
def k_platform(x): return x[0].split("::")[1].lower()
|
|
|
|
def k_total(x): return x[1]["total_size"]
|
|
|
|
def k_total(x): return x[1]["total_size"]
|
|
|
|
@ -66,7 +77,48 @@ def dashboard():
|
|
|
|
"video_count": k_count,
|
|
|
|
"video_count": k_count,
|
|
|
|
"avg_size": k_avg,
|
|
|
|
"avg_size": k_avg,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
items.sort(key=key_map.get(sort, k_total), reverse=reverse)
|
|
|
|
base_key = key_map.get(sort, k_total)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---- get recording list → two sets: online + recording_offline ----
|
|
|
|
|
|
|
|
# _get_recording_streamers() returns: [{"username": "...", "is_online": true/false}, ...]
|
|
|
|
|
|
|
|
online_usernames: set[str] = set()
|
|
|
|
|
|
|
|
recording_offline_usernames: set[str] = set()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if show_online_first:
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
|
|
|
rec_list = _get_recording_streamers()
|
|
|
|
|
|
|
|
for s in rec_list or []:
|
|
|
|
|
|
|
|
u = (s.get("username") or "").lower()
|
|
|
|
|
|
|
|
if not u:
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
if s.get("is_online"):
|
|
|
|
|
|
|
|
online_usernames.add(u)
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
recording_offline_usernames.add(u)
|
|
|
|
|
|
|
|
except Exception:
|
|
|
|
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def user_of(item) -> str:
|
|
|
|
|
|
|
|
return item[0].split("::")[0]
|
|
|
|
|
|
|
|
def is_online(item) -> bool:
|
|
|
|
|
|
|
|
return user_of(item).lower() in online_usernames
|
|
|
|
|
|
|
|
def is_recording_offline(item) -> bool:
|
|
|
|
|
|
|
|
u = user_of(item).lower()
|
|
|
|
|
|
|
|
return (u in recording_offline_usernames) and (u not in online_usernames)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ---- sort with optional grouping ----
|
|
|
|
|
|
|
|
if show_online_first:
|
|
|
|
|
|
|
|
online_items = [x for x in items if is_online(x)]
|
|
|
|
|
|
|
|
recording_offline_items= [x for x in items if is_recording_offline(x)]
|
|
|
|
|
|
|
|
the_rest = [x for x in items if (x not in online_items) and (x not in recording_offline_items)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
online_items.sort(key=base_key, reverse=reverse)
|
|
|
|
|
|
|
|
recording_offline_items.sort(key=base_key, reverse=reverse)
|
|
|
|
|
|
|
|
the_rest.sort(key=base_key, reverse=reverse)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
items = online_items + recording_offline_items + the_rest
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
items.sort(key=base_key, reverse=reverse)
|
|
|
|
|
|
|
|
|
|
|
|
# ---- paginate ----
|
|
|
|
# ---- paginate ----
|
|
|
|
page = max(1, int(request.args.get("page", 1)))
|
|
|
|
page = max(1, int(request.args.get("page", 1)))
|
|
|
|
@ -85,7 +137,11 @@ def dashboard():
|
|
|
|
dir=dir_,
|
|
|
|
dir=dir_,
|
|
|
|
timeframe=timeframe,
|
|
|
|
timeframe=timeframe,
|
|
|
|
start_date=start_str,
|
|
|
|
start_date=start_str,
|
|
|
|
end_date=end_str
|
|
|
|
end_date=end_str,
|
|
|
|
|
|
|
|
online="1" if show_online_first else "0",
|
|
|
|
|
|
|
|
# send both sets so we can color dots
|
|
|
|
|
|
|
|
online_set=online_usernames,
|
|
|
|
|
|
|
|
recording_offline_set=recording_offline_usernames,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@web.route("/refresh")
|
|
|
|
@web.route("/refresh")
|
|
|
|
|