aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/zajc/gogarchiver/Arguments.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/zajc/gogarchiver/Arguments.java')
-rw-r--r--src/main/java/zajc/gogarchiver/Arguments.java206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/main/java/zajc/gogarchiver/Arguments.java b/src/main/java/zajc/gogarchiver/Arguments.java
new file mode 100644
index 0000000..cd24ffa
--- /dev/null
+++ b/src/main/java/zajc/gogarchiver/Arguments.java
@@ -0,0 +1,206 @@
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;
18
19import static java.lang.Runtime.getRuntime;
20import static java.util.Collections.unmodifiableSet;
21import static java.util.stream.Collectors.toUnmodifiableSet;
22import static picocli.CommandLine.Help.Ansi.AUTO;
23import static picocli.CommandLine.Help.Visibility.ALWAYS;
24import static zajc.gogarchiver.api.GameDownload.Type.*;
25
26import java.io.IOException;
27import java.nio.file.*;
28import java.util.*;
29import java.util.function.Predicate;
30
31import javax.annotation.Nonnull;
32
33import org.eu.zajc.ef.supplier.except.all.AESupplier;
34
35import picocli.CommandLine.*;
36import picocli.CommandLine.Help.Ansi;
37import zajc.gogarchiver.api.*;
38import zajc.gogarchiver.api.GameDownload.Platform;
39import zajc.gogarchiver.exception.NotLoggedInException;
40import zajc.gogarchiver.util.LazyValue;
41
42public class Arguments {
43
44 private final LazyValue<User> user = new LazyValue<>();
45
46 @ArgGroup(exclusive = true, multiplicity = "1") private Token token;
47
48 private static class Token {
49
50 @Option(names = { "-k", "--token" }, description = "GOG token, which can be extracted from the gog-al cookie",
51 paramLabel = "TOKEN") private String tokenString;
52 @Option(names = { "-K", "--token-file" }, description = "read GOG token from a file",
53 paramLabel = "PATH") private Path tokenFile;
54
55 @Nonnull
56 @SuppressWarnings("null")
57 public String getTokenString() throws IOException {
58 var token = this.tokenString;
59 if (token == null)
60 token = Files.readString(this.tokenFile);
61 return token.strip();
62 }
63
64 }
65
66 @Option(names = { "-o", "--output" }, required = true, description = "directory to write downloaded games to",
67 paramLabel = "PATH") private Path output;
68 @Option(names = { "-t", "--threads" }, description = "number of download threads", paramLabel = "THREADS",
69 showDefaultValue = ALWAYS) private int threads = getRuntime().availableProcessors();
70 @Option(names = { "-q", "--quiet" }, description = "disable progress bars") private boolean quiet = false;
71 @Option(names = { "-c", "--color" }, description = "control output color. Supported are auto, on, off",
72 paramLabel = "MODE") private Ansi color = AUTO;
73
74 @ArgGroup(validate = false, heading = "%nFilter options%n") private Filters filters = new Filters();
75
76 private static class Filters {
77
78 @Option(names = { "--no-installers" }, description = "download installers", negatable = true,
79 showDefaultValue = ALWAYS) private boolean installers = true;
80 @Option(names = { "--no-patches" }, description = "download version patches", negatable = true,
81 showDefaultValue = ALWAYS) private boolean patches = true;
82 @Option(names = { "--no-dlcs" }, description = "download available DLCs", negatable = true,
83 showDefaultValue = ALWAYS) private boolean dlcs = true;
84
85 @ArgGroup(exclusive = true) private GameIds gameIds = new GameIds();
86
87 private static class GameIds {
88
89 @Option(names = { "-i", "--include-game" }, description = """
90 only the listed game IDs will be downloaded. Game IDs can be obtained from https://www.gogdb.org/""",
91 paramLabel = "ID", split = ",") private Set<String> included;
92 @Option(names = { "-e", "--exclude-game" }, description = """
93 all games owned by the account except those listed will be downloaded""", paramLabel = "ID",
94 split = ",") private Set<String> excluded;
95
96 @Nonnull
97 @SuppressWarnings("null")
98 public Set<String> getGameIds(@Nonnull User user) {
99 if (this.included != null)
100 return unmodifiableSet(this.included);
101
102 var library = user.getLibraryIds();
103
104 if (this.excluded == null)
105 return library;
106 else
107 return library.stream().filter(Predicate.not(this.excluded::contains)).collect(toUnmodifiableSet());
108 }
109
110 }
111
112 @ArgGroup(exclusive = true) private Platforms platforms = new Platforms();
113
114 private static class Platforms {
115
116 @Option(names = { "--include-platform" }, description = """
117 platforms to download for. Supported are linux, windows, mac""", paramLabel = "PLATFORM",
118 split = ",") private EnumSet<Platform> included;
119 @Option(names = { "--exclude-platform" }, description = """
120 platforms to not download for""", paramLabel = "PLATFORM",
121 split = ",") private EnumSet<Platform> excluded;
122
123 @Nonnull
124 @SuppressWarnings("null")
125 public Set<Platform> getPlatforms() {
126 if (this.included != null)
127 return unmodifiableSet(this.included);
128 else if (this.excluded != null)
129 return unmodifiableSet(this.excluded);
130 else
131 return EnumSet.allOf(Platform.class);
132 }
133
134 }
135
136 }
137
138 @ArgGroup(validate = false, heading = "%nAdvanced options%n") private AdvancedOptions advanced =
139 new AdvancedOptions();
140
141 private static class AdvancedOptions {
142
143 @Option(names = { "-v", "--verbose" }, description = "display verbose log messages") private boolean verbose =
144 false;
145
146 @Option(names = { "--unknown-types" }, description = "download unknown download types", negatable = true,
147 showDefaultValue = ALWAYS) private boolean unknown = false;
148
149 }
150
151 @Nonnull
152 @SuppressWarnings({ "unused", "null" })
153 public User getUser() throws IOException, NotLoggedInException {
154 return this.user.get((AESupplier<User>) () -> new User(this.token.getTokenString()));
155 }
156
157 @Nonnull
158 public Set<String> getGameIds() throws IOException, NotLoggedInException {
159 return this.filters.gameIds.getGameIds(getUser());
160 }
161
162 @Nonnull
163 @SuppressWarnings("null")
164 public Ansi getColorMode() {
165 return this.color;
166 }
167
168 public int getThreads() {
169 return this.threads;
170 }
171
172 public Path getOutputPath() {
173 return this.output;
174 }
175
176 public Set<Platform> getPlatforms() {
177 return this.filters.platforms.getPlatforms();
178 }
179
180 public boolean downloadDlcs() {
181 return this.filters.dlcs;
182 }
183
184 public Set<GameDownload.Type> getTypes() {
185 var types = EnumSet.noneOf(GameDownload.Type.class);
186 if (this.filters.installers)
187 types.add(INSTALLER);
188
189 if (this.filters.patches)
190 types.add(PATCH);
191
192 if (this.advanced.unknown)
193 types.add(UNKNOWN);
194
195 return types;
196 }
197
198 public boolean isVerbose() {
199 return this.advanced.verbose;
200 }
201
202 public boolean isQuiet() {
203 return this.quiet;
204 }
205
206}