aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/zajc/gogarchiver/api/GameDownload.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/zajc/gogarchiver/api/GameDownload.java')
-rw-r--r--src/main/java/zajc/gogarchiver/api/GameDownload.java149
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 */
17package zajc.gogarchiver.api;
18
19import static java.lang.Integer.parseInt;
20import static java.lang.String.format;
21import static java.nio.charset.StandardCharsets.UTF_8;
22import static java.util.Objects.hash;
23import static java.util.regex.Pattern.compile;
24import static zajc.gogarchiver.api.GameDownload.Type.*;
25import static zajc.gogarchiver.util.Utilities.warn;
26
27import java.io.IOException;
28import java.net.URLDecoder;
29import java.nio.file.Path;
30import java.util.Objects;
31import java.util.regex.Pattern;
32
33import javax.annotation.*;
34
35import kong.unirest.json.JSONObject;
36import me.tongfei.progressbar.ProgressBar;
37import zajc.gogarchiver.util.LazyValue;
38
39public 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}