Boris Yumankulov abec9bbef8
All checks were successful
Check Translations / check-translations (push) Successful in 15s
Code and build check / Check code (push) Successful in 1m21s
Code and build check / Build with uv (push) Successful in 47s
Move repo from git to gitea
Signed-off-by: Boris Yumankulov <boria138@altlinux.org>
2025-06-01 15:21:32 +05:00

160 lines
6.5 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
from datetime import datetime, timedelta
from babel.dates import format_timedelta, format_date
from portprotonqt.config_utils import read_time_config
from portprotonqt.localization import _, get_system_locale
from portprotonqt.logger import get_logger
logger = get_logger(__name__)
def get_cache_file_path():
"""Возвращает путь к файлу кеша portproton_last_launch."""
cache_home = os.getenv("XDG_CACHE_HOME", os.path.join(os.path.expanduser("~"), ".cache"))
return os.path.join(cache_home, "PortProtonQT", "last_launch")
def save_last_launch(exe_name, launch_time):
"""
Сохраняет время запуска для exe.
Формат файла: <exe_name> <isoformatted_time>
"""
file_path = get_cache_file_path()
data = {}
if os.path.exists(file_path):
with open(file_path, encoding="utf-8") as f:
for line in f:
parts = line.strip().split(maxsplit=1)
if len(parts) == 2:
data[parts[0]] = parts[1]
data[exe_name] = launch_time.isoformat()
os.makedirs(os.path.dirname(file_path), exist_ok=True)
with open(file_path, "w", encoding="utf-8") as f:
for key, iso_time in data.items():
f.write(f"{key} {iso_time}\n")
def format_last_launch(launch_time):
"""
Форматирует время запуска с использованием Babel.
Для detail_level "detailed" возвращает относительный формат с добавлением "назад"
(например, "2 мин. назад"). Если время меньше минуты возвращает переведённую строку.
Для "brief" дату в формате "день месяц год" (например, "1 апреля 2023")
на основе системной локали.
"""
detail_level = read_time_config() or "detailed"
system_locale = get_system_locale()
if detail_level == "detailed":
# Вычисляем delta как launch_time - datetime.now() чтобы получить отрицательное значение для прошедшего времени.
delta = launch_time - datetime.now()
if abs(delta.total_seconds()) < 60:
return _("just now")
return format_timedelta(delta, locale=system_locale, granularity='second', format='short', add_direction=True)
else:
return format_date(launch_time, format="d MMMM yyyy", locale=system_locale)
def get_last_launch(exe_name):
"""
Читает время последнего запуска для заданного exe из файла кеша.
Возвращает время запуска в нужном формате или перевод строки "Never".
"""
file_path = get_cache_file_path()
if not os.path.exists(file_path):
return _("Never")
with open(file_path, encoding="utf-8") as f:
for line in f:
parts = line.strip().split(maxsplit=1)
if len(parts) == 2 and parts[0] == exe_name:
iso_time = parts[1]
launch_time = datetime.fromisoformat(iso_time)
return format_last_launch(launch_time)
return _("Never")
def parse_playtime_file(file_path):
"""
Парсит файл с данными о времени игры.
Формат строки в файле:
<полный путь к exe> <хэш> <playtime_seconds> <platform> <build>
Возвращает словарь вида:
{
'<exe_path>': playtime_seconds (int),
...
}
"""
playtime_data = {}
if not os.path.exists(file_path):
logger.error(f"Файл не найден: {file_path}")
return playtime_data
with open(file_path, encoding="utf-8") as f:
for line in f:
if not line.strip():
continue
parts = line.strip().split()
if len(parts) < 3:
continue
exe_path = parts[0]
seconds = int(parts[2])
playtime_data[exe_path] = seconds
return playtime_data
def format_playtime(seconds):
"""
Конвертирует время в секундах в форматированную строку с использованием Babel.
При "detailed" выводится полный разбор времени, без округления
(например, "1 ч 1 мин 15 сек").
При "brief":
- если время менее часа, выводится точное время с секундами (например, "9 мин 28 сек"),
- если больше часа только часы (например, "3 ч").
"""
detail_level = read_time_config() or "detailed"
system_locale = get_system_locale()
seconds = int(seconds)
if detail_level == "detailed":
days, rem = divmod(seconds, 86400)
hours, rem = divmod(rem, 3600)
minutes, secs = divmod(rem, 60)
parts = []
if days > 0:
parts.append(f"{days} " + _("d."))
if hours > 0:
parts.append(f"{hours} " + _("h."))
if minutes > 0:
parts.append(f"{minutes} " + _("min."))
if secs > 0 or not parts:
parts.append(f"{secs} " + _("sec."))
return " ".join(parts)
else:
# Режим brief
if seconds < 3600:
minutes, secs = divmod(seconds, 60)
parts = []
if minutes > 0:
parts.append(f"{minutes} " + _("min."))
if secs > 0 or not parts:
parts.append(f"{secs} " + _("sec."))
return " ".join(parts)
else:
hours = seconds // 3600
return format_timedelta(timedelta(hours=hours), locale=system_locale, granularity='hour', format='short')
def get_last_launch_timestamp(exe_name):
"""
Возвращает метку времени последнего запуска (timestamp) для заданного exe.
Если записи нет, возвращает 0.
"""
file_path = get_cache_file_path()
if not os.path.exists(file_path):
return 0
with open(file_path, encoding="utf-8") as f:
for line in f:
parts = line.strip().split(maxsplit=1)
if len(parts) == 2 and parts[0] == exe_name:
iso_time = parts[1]
dt = datetime.fromisoformat(iso_time)
return dt.timestamp()
return 0