diff options
Diffstat (limited to 'src/main/java/zajc/gogarchiver/api/GameDownload.java')
-rw-r--r-- | src/main/java/zajc/gogarchiver/api/GameDownload.java | 149 |
1 files changed, 149 insertions, 0 deletions
diff --git a/src/main/java/zajc/gogarchiver/api/GameDownload.java b/src/main/java/zajc/gogarchiver/api/GameDownload.java new file mode 100644 index 0000000..61a1d41 --- /dev/null +++ b/src/main/java/zajc/gogarchiver/api/GameDownload.java | |||
@@ -0,0 +1,149 @@ | |||
1 | //SPDX-License-Identifier: GPL-3.0 | ||
2 | /* | ||
3 | * gogarchiver-ng, an archival tool for GOG.com | ||
4 | * Copyright (C) 2024 Marko Zajc | ||
5 | * | ||
6 | * This program is free software: you can redistribute it and/or modify it under the | ||
7 | * terms of the GNU General Public License as published by the Free Software | ||
8 | * Foundation, version 3. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY | ||
11 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A | ||
12 | * PARTICULAR PURPOSE. See the GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with this | ||
15 | * program. If not, see <https://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | package zajc.gogarchiver.api; | ||
18 | |||
19 | import static java.lang.Integer.parseInt; | ||
20 | import static java.lang.String.format; | ||
21 | import static java.nio.charset.StandardCharsets.UTF_8; | ||
22 | import static java.util.Objects.hash; | ||
23 | import static java.util.regex.Pattern.compile; | ||
24 | import static zajc.gogarchiver.api.GameDownload.Type.*; | ||
25 | import static zajc.gogarchiver.util.Utilities.warn; | ||
26 | |||
27 | import java.io.IOException; | ||
28 | import java.net.URLDecoder; | ||
29 | import java.nio.file.Path; | ||
30 | import java.util.Objects; | ||
31 | import java.util.regex.Pattern; | ||
32 | |||
33 | import javax.annotation.*; | ||
34 | |||
35 | import kong.unirest.json.JSONObject; | ||
36 | import me.tongfei.progressbar.ProgressBar; | ||
37 | import zajc.gogarchiver.util.LazyValue; | ||
38 | |||
39 | public record GameDownload(@Nonnull Game game, @Nonnull String originalUrl, @Nonnull LazyValue<String> resolvedUrl, | ||
40 | @Nonnull Platform platform, @Nullable String name, @Nullable String version, | ||
41 | @Nonnull Type type, int part) { | ||
42 | |||
43 | private static final Pattern TYPE_PATTERN = compile("\\d+(\\p{IsLatin}+)"); | ||
44 | private static final Pattern PART_PATTERN = compile("\\d+$"); | ||
45 | |||
46 | @Nonnull | ||
47 | public static GameDownload fromJson(@Nonnull Game game, @Nonnull JSONObject download, @Nonnull Platform platform) { | ||
48 | var url = "https://www.gog.com/" + download.getString("manualUrl").substring(1); | ||
49 | var name = download.optString("name"); | ||
50 | var version = download.optString("version"); | ||
51 | var type = parseType(url); | ||
52 | var part = parsePart(url); | ||
53 | |||
54 | return new GameDownload(game, url, new LazyValue<>(), platform, name, version, type, part); | ||
55 | } | ||
56 | |||
57 | @Nonnull | ||
58 | private static Type parseType(@Nonnull String url) { | ||
59 | var m = TYPE_PATTERN.matcher(url.substring(url.lastIndexOf('/') + 1)); | ||
60 | if (!m.find()) { | ||
61 | warn("Could not extract download type from the url: %s. Please report this to marko@zajc.eu.org.", url); | ||
62 | return UNKNOWN; | ||
63 | } | ||
64 | |||
65 | return switch (m.group(1)) { | ||
66 | case "installer" -> INSTALLER; | ||
67 | case "patch" -> PATCH; | ||
68 | default -> { | ||
69 | warn("Unknown download type: %s. Please report this to marko@zajc.eu.org.", m.group(1)); | ||
70 | yield UNKNOWN; | ||
71 | } | ||
72 | }; | ||
73 | } | ||
74 | |||
75 | private static int parsePart(@Nonnull String url) { | ||
76 | var m = PART_PATTERN.matcher(url); | ||
77 | if (!m.find()) { | ||
78 | warn("Could not extract part number from the url: %s. Please report this to marko@zajc.eu.org.", url); | ||
79 | return 0; | ||
80 | |||
81 | } else { | ||
82 | return parseInt(m.group()); | ||
83 | } | ||
84 | } | ||
85 | |||
86 | @SuppressWarnings("null") | ||
87 | public void downloadTo(@Nonnull Path outputDirectory, @Nullable ProgressBar monitor) throws IOException { | ||
88 | game().getUser().downloadTo(this, outputDirectory.resolve(path()), monitor); | ||
89 | } | ||
90 | |||
91 | @Nonnull | ||
92 | @SuppressWarnings("null") | ||
93 | public Path path() { | ||
94 | return Path.of(this.game.getTitle(), this.platform.toString().toLowerCase(), this.type.toString().toLowerCase(), | ||
95 | URLDecoder.decode(url().substring(url().lastIndexOf('/') + 1), UTF_8)); | ||
96 | } | ||
97 | |||
98 | @Nonnull | ||
99 | @SuppressWarnings("null") | ||
100 | public String url() { | ||
101 | return this.resolvedUrl.get(() -> game().getUser().resolveUrl(this)); | ||
102 | } | ||
103 | |||
104 | @Nonnull | ||
105 | @SuppressWarnings("null") | ||
106 | public String getProgressTitle() { | ||
107 | return format("%s (%s%s%s, %s)", game().getTitle(), this.part != 0 ? "part " + (part() + 1) + ", " : "", | ||
108 | version() != null ? "ver. " + version() + ", " : "", platform().toString().toLowerCase(), | ||
109 | type().toString().toLowerCase()); | ||
110 | } | ||
111 | |||
112 | @Override | ||
113 | public int hashCode() { | ||
114 | return hash(this.game, this.name, this.originalUrl, this.platform, this.type, this.version); | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public boolean equals(Object obj) { | ||
119 | if (this == obj) | ||
120 | return true; | ||
121 | if (obj instanceof GameDownload other) | ||
122 | return Objects.equals(this.game, other.game) && Objects.equals(this.name, other.name) | ||
123 | && Objects.equals(this.originalUrl, other.originalUrl) && this.platform == other.platform | ||
124 | && this.type == other.type && Objects.equals(this.version, other.version); | ||
125 | else | ||
126 | return false; | ||
127 | } | ||
128 | |||
129 | public enum Platform { | ||
130 | |||
131 | LINUX, | ||
132 | WINDOWS, | ||
133 | MAC; | ||
134 | |||
135 | @Override | ||
136 | public String toString() { | ||
137 | return name().toLowerCase(); | ||
138 | } | ||
139 | } | ||
140 | |||
141 | public enum Type { | ||
142 | |||
143 | INSTALLER, | ||
144 | PATCH, | ||
145 | UNKNOWN; | ||
146 | |||
147 | } | ||
148 | |||
149 | } | ||