160 lines
6.5 KiB
Python
160 lines
6.5 KiB
Python
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
|