[core/utils] Implement save game file filters

This commit is contained in:
derrod 2020-05-16 12:19:06 +02:00
parent e88a369feb
commit 2ba036a654
2 changed files with 50 additions and 5 deletions

View file

@ -339,15 +339,26 @@ class LegendaryCore:
else: else:
return SaveGameStatus.REMOTE_NEWER, (dt_local, dt_remote) return SaveGameStatus.REMOTE_NEWER, (dt_local, dt_remote)
def upload_save(self, app_name, save_dir, local_dt: datetime = None): def upload_save(self, app_name, save_dir, local_dt: datetime = None,
disable_filtering: bool = False):
game = self.lgd.get_game_meta(app_name) game = self.lgd.get_game_meta(app_name)
save_path = game.metadata['customAttributes'].get('CloudSaveFolder', {}).get('value') custom_attr = game.metadata['customAttributes']
save_path = custom_attr.get('CloudSaveFolder', {}).get('value')
include_f = exclude_f = None
if not disable_filtering:
# get file inclusion and exclusion filters if they exist
if _include := custom_attr.get('CloudIncludeList', {}).get('value', None) is not None:
include_f = _include.split(',')
if _exclude := custom_attr.get('CloudExcludeList', {}).get('value', None) is not None:
exclude_f = _exclude.split(',')
if not save_path: if not save_path:
raise ValueError('Game does not support cloud saves') raise ValueError('Game does not support cloud saves')
sgh = SaveGameHelper() sgh = SaveGameHelper()
files = sgh.package_savegame(save_dir, app_name, self.egs.user.get('account_id'), files = sgh.package_savegame(save_dir, app_name, self.egs.user.get('account_id'),
save_path, local_dt) save_path, include_f, exclude_f, local_dt)
self.log.debug(f'Packed files: {str(files)}, creating cloud files...') self.log.debug(f'Packed files: {str(files)}, creating cloud files...')
resp = self.egs.create_game_cloud_saves(app_name, list(files.keys())) resp = self.egs.create_game_cloud_saves(app_name, list(files.keys()))
@ -630,7 +641,6 @@ class LegendaryCore:
@staticmethod @staticmethod
def check_installation_conditions(analysis: AnalysisResult, install: InstalledGame) -> ConditionCheckResult: def check_installation_conditions(analysis: AnalysisResult, install: InstalledGame) -> ConditionCheckResult:
# ToDo add more checks in the future
results = ConditionCheckResult(failures=set(), warnings=set()) results = ConditionCheckResult(failures=set(), warnings=set())
# if on linux, check for eac in the files # if on linux, check for eac in the files

View file

@ -2,6 +2,7 @@ import logging
import os import os
from datetime import datetime from datetime import datetime
from fnmatch import fnmatch
from hashlib import sha1 from hashlib import sha1
from io import BytesIO from io import BytesIO
from tempfile import TemporaryFile from tempfile import TemporaryFile
@ -11,6 +12,26 @@ from legendary.models.manifest import \
Manifest, ManifestMeta, CDL, FML, CustomFields, FileManifest, ChunkPart, ChunkInfo Manifest, ManifestMeta, CDL, FML, CustomFields, FileManifest, ChunkPart, ChunkInfo
def _filename_matches(filename, patterns):
"""
Helper to determine if a filename matches the filter patterns
:param filename: name of the file
:param patterns: list of patterns to match against
:return:
"""
for pattern in patterns:
if pattern.endswith('/'):
# pat is a directory, check if path starts with it
if filename.startswith(pattern):
return True
elif fnmatch(filename, pattern):
return True
return False
class SaveGameHelper: class SaveGameHelper:
def __init__(self): def __init__(self):
self.files = dict() self.files = dict()
@ -32,12 +53,16 @@ class SaveGameHelper:
def package_savegame(self, input_folder: str, app_name: str = '', def package_savegame(self, input_folder: str, app_name: str = '',
epic_id: str = '', cloud_folder: str = '', epic_id: str = '', cloud_folder: str = '',
include_filter: list = None,
exclude_filter: list = None,
manifest_dt: datetime = None): manifest_dt: datetime = None):
""" """
:param input_folder: Folder to be packaged into chunks/manifest :param input_folder: Folder to be packaged into chunks/manifest
:param app_name: App name for savegame being stored :param app_name: App name for savegame being stored
:param epic_id: Epic account ID :param epic_id: Epic account ID
:param cloud_folder: Folder the savegame resides in (based on game metadata) :param cloud_folder: Folder the savegame resides in (based on game metadata)
:param include_filter: list of patterns for files to include (excludes all others)
:param exclude_filter: list of patterns for files to exclude (includes all others)
:param manifest_dt: datetime for the manifest name (optional) :param manifest_dt: datetime for the manifest name (optional)
:return: :return:
""" """
@ -57,7 +82,17 @@ class SaveGameHelper:
files = [] files = []
for _dir, _, _files in os.walk(input_folder): for _dir, _, _files in os.walk(input_folder):
for _file in _files: for _file in _files:
files.append(os.path.join(_dir, _file)) _file_path = os.path.join(_dir, _file)
_file_path_rel = os.path.relpath(_file_path, input_folder).replace('\\', '/')
if include_filter and not _filename_matches(_file_path_rel, include_filter):
self.log.debug(f'Excluding "{_file_path_rel}" (does not match include filter)')
continue
elif exclude_filter and _filename_matches(_file_path_rel, exclude_filter):
self.log.debug(f'Excluding "{_file_path_rel}" (does match exclude filter)')
continue
files.append(_file_path)
chunk_num = 0 chunk_num = 0
cur_chunk = None cur_chunk = None