gog-cli 0.2.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- gog_cli/__init__.py +5 -0
- gog_cli/api.py +143 -0
- gog_cli/aria2c.py +136 -0
- gog_cli/auth.py +217 -0
- gog_cli/backup.py +197 -0
- gog_cli/cli.py +550 -0
- gog_cli/config.py +120 -0
- gog_cli/downloader.py +196 -0
- gog_cli/errors.py +54 -0
- gog_cli/execution.py +1054 -0
- gog_cli/layout.py +72 -0
- gog_cli/listing.py +668 -0
- gog_cli/log.py +19 -0
- gog_cli/metadata.py +212 -0
- gog_cli/output.py +99 -0
- gog_cli/prompt.py +57 -0
- gog_cli/refresh.py +231 -0
- gog_cli/state.py +193 -0
- gog_cli/sync.py +146 -0
- gog_cli-0.2.1.dist-info/METADATA +193 -0
- gog_cli-0.2.1.dist-info/RECORD +25 -0
- gog_cli-0.2.1.dist-info/WHEEL +5 -0
- gog_cli-0.2.1.dist-info/entry_points.txt +2 -0
- gog_cli-0.2.1.dist-info/licenses/LICENSE +21 -0
- gog_cli-0.2.1.dist-info/top_level.txt +1 -0
gog_cli/layout.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""Backup destination directory layout and filename safety."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
from dataclasses import dataclass
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
_CONTROL_RE = re.compile(r"[\x00-\x1f\x7f]")
|
|
10
|
+
_UNSAFE_RE = re.compile(r'[<>:"|?*\\/]')
|
|
11
|
+
_MAX_FILENAME_LEN = 200
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def sanitize_filename(name: str) -> str:
|
|
15
|
+
name = _CONTROL_RE.sub("", name)
|
|
16
|
+
name = _UNSAFE_RE.sub("_", name)
|
|
17
|
+
name = name.strip().rstrip(".")
|
|
18
|
+
name = name[:_MAX_FILENAME_LEN]
|
|
19
|
+
name = name.strip().rstrip(".")
|
|
20
|
+
return name or "_"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def sanitize_directory_name(name: str, product_id: str | None = None) -> str:
|
|
24
|
+
sanitized = sanitize_filename(name)
|
|
25
|
+
if product_id:
|
|
26
|
+
return f"{sanitized}_{product_id}"
|
|
27
|
+
return sanitized
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@dataclass(frozen=True)
|
|
31
|
+
class BackupLayout:
|
|
32
|
+
root: Path
|
|
33
|
+
|
|
34
|
+
@property
|
|
35
|
+
def metadata_dir(self) -> Path:
|
|
36
|
+
return self.root / "metadata"
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def manifest_file(self) -> Path:
|
|
40
|
+
return self.metadata_dir / "manifest.json"
|
|
41
|
+
|
|
42
|
+
@property
|
|
43
|
+
def library_snapshot(self) -> Path:
|
|
44
|
+
return self.metadata_dir / "library.json"
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def games_dir(self) -> Path:
|
|
48
|
+
return self.root / "games"
|
|
49
|
+
|
|
50
|
+
def game_dir(self, slug_or_id: str) -> Path:
|
|
51
|
+
return self.games_dir / slug_or_id
|
|
52
|
+
|
|
53
|
+
def game_metadata(self, slug_or_id: str) -> Path:
|
|
54
|
+
return self.game_dir(slug_or_id) / "metadata.json"
|
|
55
|
+
|
|
56
|
+
def installers_dir(self, game_dir: Path) -> Path:
|
|
57
|
+
return game_dir / "installers"
|
|
58
|
+
|
|
59
|
+
def patches_dir(self, game_dir: Path) -> Path:
|
|
60
|
+
return game_dir / "patches"
|
|
61
|
+
|
|
62
|
+
def extras_dir(self, game_dir: Path) -> Path:
|
|
63
|
+
return game_dir / "extras"
|
|
64
|
+
|
|
65
|
+
def language_packs_dir(self, game_dir: Path) -> Path:
|
|
66
|
+
return game_dir / "language-packs"
|
|
67
|
+
|
|
68
|
+
def manuals_dir(self, game_dir: Path) -> Path:
|
|
69
|
+
return game_dir / "manuals"
|
|
70
|
+
|
|
71
|
+
def other_dir(self, game_dir: Path) -> Path:
|
|
72
|
+
return game_dir / "other"
|