Coverage for seedboxsync/front/views/settings/info.py: 100%

31 statements  

« prev     ^ index     » next       coverage.py v7.16.1, created at 2026-09-26 17:14 +0000

1# 

2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr> 

3# 

4# For the full copyright and license information, please view the LICENSE 

5# file that was distributed with this source code. 

6# 

7"""SeedboxSync Flask view for info.""" 

8 

9from datetime import datetime 

10from flask import render_template 

11from humanize import filesize, precisedelta 

12from peewee import fn 

13from seedboxsync.__version__ import __version__ as version 

14from seedboxsync.core import current_app 

15from seedboxsync.core.database.models import Download, TaskStatus 

16from seedboxsync.front.cache import cache 

17from seedboxsync.front.login_manager import login_required 

18from seedboxsync.front.views import bp_settings as bp 

19 

20 

21@bp.route("/info") 

22@bp.route("") 

23@login_required # type: ignore[untyped-decorator] 

24def info() -> str: 

25 """ 

26 Render the system information view. 

27 

28 Gathers download metrics, system task statuses, database versioning, 

29 and application runtime statistics (cached for 60 seconds). 

30 

31 Returns: 

32 str: Rendered HTML template containing overall application information. 

33 """ 

34 return render_template("settings/info.html", info=_get_info_data()) 

35 

36 

37@cache.memoize(timeout=60) 

38def _get_info_data() -> dict[str, object]: 

39 """ 

40 Fetch and calculate application system information. 

41 

42 Queries download metrics, background task statuses, application version, 

43 and database migration metadata. Cached for 60 seconds. 

44 

45 Returns: 

46 dict[str, object]: Dictionary containing gathered system statistics 

47 and status flags. 

48 """ 

49 # Download statistics 

50 query_stats = Download.select().where(Download.finished != 0) 

51 total_files = query_stats.count() 

52 total_size = sum([d.seedbox_size for d in query_stats if d.seedbox_size]) 

53 sync_blackhole: TaskStatus | bool 

54 sync_seedbox: TaskStatus | bool 

55 

56 # Get statues 

57 keys = ["sync-blackhole", "sync-seedbox", "heartbeat"] 

58 statuses = {ts.key: ts for ts in TaskStatus.select().where(TaskStatus.key.in_(keys))} 

59 sync_blackhole = statuses.get("sync-blackhole", False) 

60 sync_seedbox = statuses.get("sync-seedbox", False) 

61 heartbeat = statuses.get("heartbeat", False) 

62 

63 # First download statistics 

64 first_date = Download.select(fn.MIN(Download.finished)).where(Download.finished != 0).scalar() 

65 first_delta = "" 

66 if first_date is not None: 

67 first_delta = datetime.now() - first_date 

68 first_delta = precisedelta(first_delta, minimum_unit="days") 

69 

70 return { 

71 "stats_total_files": total_files, 

72 "stats_total_size": filesize.naturalsize(total_size, True), 

73 "stats_first": first_date, 

74 "stats_first_delta": first_delta, 

75 "version": version, 

76 "last_migration": current_app.config.get("LAST_MIGRATION"), 

77 "sync_blackhole": sync_blackhole, 

78 "sync_seedbox": sync_seedbox, 

79 "heartbeat": heartbeat, 

80 }