Compare commits

..

4 Commits

Author SHA1 Message Date
Jeddunk
3bf33b0d4c Update 'README.md' 2020-12-30 11:03:47 +00:00
da947e1f51 Code refactoring, improved logging, Drone CI improvements 2020-12-03 00:02:59 +01:00
21a7ec98dd Code changes 2020-10-24 00:45:10 +02:00
992f2fb20c Fixed and enabled SteamDB DLC functionality 2020-10-21 15:47:58 +02:00
9 changed files with 305 additions and 190 deletions

View File

@ -7,5 +7,34 @@ steps:
image: maven:3-amazoncorretto-8 image: maven:3-amazoncorretto-8
commands: commands:
- mvn install - mvn install
- name: gitea_release
image: plugins/gitea-release
settings:
api_key:
from_secret: gitea_token
base_url: https://git.jeddunk.xyz
files:
- auto-cream-api-*.zip
checksum:
- md5
- sha1
- sha256
- sha512
- adler32
- crc32
when:
event:
- tag
- name: discord_webhook
image: appleboy/drone-discord
settings:
webhook_id:
from_secret: discord_webhook_id
webhook_token:
from_secret: discord_webhook_token
message: >
{{#success build.status}}
build {{build.number}} succeeded.
{{else}}
build {{build.number}} failed.
{{/success}}

View File

@ -13,7 +13,7 @@
<component name="ProjectKey"> <component name="ProjectKey">
<option name="state" value="project://e79810c8-c5c8-43b1-b19c-90c1f4095425" /> <option name="state" value="project://e79810c8-c5c8-43b1-b19c-90c1f4095425" />
</component> </component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8 (amazon)" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

View File

@ -1,5 +1,8 @@
# Auto-CreamAPI # Auto-CreamAPI
## Development is continuing [here](https://git.jeddunk.xyz/jeddunk/auto-creamapi-2)! However you're still welcome to use this version.
[![ko-fi](https://www.ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/H2H4330U3)
[![Build Status](https://ci.jeddunk.xyz/api/badges/jeddunk/auto-cream-api/status.svg)](https://ci.jeddunk.xyz/jeddunk/auto-cream-api) [![Build Status](https://ci.jeddunk.xyz/api/badges/jeddunk/auto-cream-api/status.svg)](https://ci.jeddunk.xyz/jeddunk/auto-cream-api)
Set your game automatically up for use with CreamAPI. Set your game automatically up for use with CreamAPI.

View File

@ -56,7 +56,7 @@
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.maven.wagon:wagon-http-lightweight:1.0-beta-2" level="project" /> <orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.maven.wagon:wagon-http-lightweight:1.0-beta-2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.maven.wagon:wagon-http-shared:1.0-beta-2" level="project" /> <orderEntry type="library" scope="RUNTIME" name="Maven: org.apache.maven.wagon:wagon-http-shared:1.0-beta-2" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: jtidy:jtidy:4aug2000r7-dev" level="project" /> <orderEntry type="library" scope="RUNTIME" name="Maven: jtidy:jtidy:4aug2000r7-dev" level="project" />
<orderEntry type="library" scope="RUNTIME" name="Maven: xml-apis:xml-apis:1.0.b2" level="project" /> <orderEntry type="library" name="Maven: xml-apis:xml-apis:1.0.b2" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.reporting:maven-reporting-api:2.0.9" level="project" /> <orderEntry type="library" name="Maven: org.apache.maven.reporting:maven-reporting-api:2.0.9" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.doxia:doxia-sink-api:1.0-alpha-10" level="project" /> <orderEntry type="library" name="Maven: org.apache.maven.doxia:doxia-sink-api:1.0-alpha-10" level="project" />
<orderEntry type="library" name="Maven: org.apache.maven.wagon:wagon-provider-api:1.0-beta-2" level="project" /> <orderEntry type="library" name="Maven: org.apache.maven.wagon:wagon-provider-api:1.0-beta-2" level="project" />
@ -79,5 +79,24 @@
<orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" /> <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.2.3" level="project" />
<orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" /> <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
<orderEntry type="library" name="Maven: org.fusesource.jansi:jansi:1.18" level="project" /> <orderEntry type="library" name="Maven: org.fusesource.jansi:jansi:1.18" level="project" />
<orderEntry type="library" name="Maven: net.sourceforge.htmlunit:htmlunit:2.44.0" level="project" />
<orderEntry type="library" name="Maven: xalan:xalan:2.7.2" level="project" />
<orderEntry type="library" name="Maven: xalan:serializer:2.7.2" level="project" />
<orderEntry type="library" name="Maven: net.sourceforge.htmlunit:htmlunit-core-js:2.44.0" level="project" />
<orderEntry type="library" name="Maven: net.sourceforge.htmlunit:neko-htmlunit:2.44.0" level="project" />
<orderEntry type="library" name="Maven: xerces:xercesImpl:2.12.0" level="project" />
<orderEntry type="library" name="Maven: net.sourceforge.htmlunit:htmlunit-cssparser:1.6.0" level="project" />
<orderEntry type="library" name="Maven: commons-io:commons-io:2.8.0" level="project" />
<orderEntry type="library" name="Maven: commons-net:commons-net:3.7.1" level="project" />
<orderEntry type="library" name="Maven: org.brotli:dec:0.1.2" level="project" />
<orderEntry type="library" name="Maven: com.shapesecurity:salvation2:3.0.0" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-client:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-client:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-http:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-xml:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-util:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty:jetty-io:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-common:9.4.32.v20200930" level="project" />
<orderEntry type="library" name="Maven: org.eclipse.jetty.websocket:websocket-api:9.4.32.v20200930" level="project" />
</component> </component>
</module> </module>

13
pom.xml
View File

@ -21,7 +21,7 @@
<groupId>xyz.jeddunk</groupId> <groupId>xyz.jeddunk</groupId>
<artifactId>auto-cream-api</artifactId> <artifactId>auto-cream-api</artifactId>
<version>1.2.1</version> <version>1.2.2</version>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
@ -110,7 +110,7 @@
<destinationFile>${dist}/steam_api.dll</destinationFile> <destinationFile>${dist}/steam_api.dll</destinationFile>
</fileSet> </fileSet>
<fileSet> <fileSet>
<sourceFile>${project.basedir}/steam_api.dll</sourceFile> <sourceFile>${project.basedir}/steam_api64.dll</sourceFile>
<destinationFile>${dist}/steam_api64.dll</destinationFile> <destinationFile>${dist}/steam_api64.dll</destinationFile>
</fileSet> </fileSet>
<fileSet> <fileSet>
@ -150,7 +150,7 @@
<enabled>false</enabled> <enabled>false</enabled>
</snapshots> </snapshots>
<id>bintray-jerady-maven</id> <id>bintray-jerady-maven</id>
<name>bintray</name> <name>bintray-jerady</name>
<url>https://dl.bintray.com/jerady/maven</url> <url>https://dl.bintray.com/jerady/maven</url>
</repository> </repository>
</repositories> </repositories>
@ -160,7 +160,7 @@
<enabled>false</enabled> <enabled>false</enabled>
</snapshots> </snapshots>
<id>bintray-jerady-maven</id> <id>bintray-jerady-maven</id>
<name>bintray-plugins</name> <name>bintray-jerady-plugins</name>
<url>https://dl.bintray.com/jerady/maven</url> <url>https://dl.bintray.com/jerady/maven</url>
</pluginRepository> </pluginRepository>
</pluginRepositories> </pluginRepositories>
@ -229,5 +229,10 @@
<artifactId>jansi</artifactId> <artifactId>jansi</artifactId>
<version>1.18</version> <version>1.18</version>
</dependency> </dependency>
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.44.0</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -132,10 +132,7 @@ public class Controller implements Initializable {
@FXML @FXML
@Override @Override
public void initialize(URL location, ResourceBundle resources) { public void initialize(URL location, ResourceBundle resources) {
// steamdb_dlc_checkbox.setSelected(true); steamdb_dlc_checkbox.setSelected(true);
// Disable SteamDB DLC checking for now until it's fix
steamdb_dlc_checkbox.setSelected(false);
steamdb_dlc_checkbox.setDisable(true);
appId_textfield.textProperty().addListener(appIdChangesGameName()); appId_textfield.textProperty().addListener(appIdChangesGameName());
game_name_textfield.setOnKeyReleased(event -> { game_name_textfield.setOnKeyReleased(event -> {
KeyCode code = event.getCode(); KeyCode code = event.getCode();
@ -147,13 +144,24 @@ public class Controller implements Initializable {
language_combobox.setTooltip(new Tooltip()); language_combobox.setTooltip(new Tooltip());
language_combobox.setEditable(false); language_combobox.setEditable(false);
new ComboBoxAutoComplete<>(language_combobox); new ComboBoxAutoComplete<>(language_combobox);
//retrieveDlcList_button.setDisable(true); // WIP dlc_textarea.setPromptText("List of DLC...\r0000 = DLC Name");
generate_tooltips(); generate_tooltips();
fix_dlc_textarea_prompt_text();
reset(true); reset(true);
state_label.setText("Ready."); state_label.setText("Ready.");
} }
private void generate_tooltips() {
Tooltip extra_protection_tooltip = new Tooltip("\"extra protection\"");
extra_protection_checkbox.setTooltip(extra_protection_tooltip);
Tooltip.install(extra_protection_checkbox, extra_protection_tooltip);
Tooltip steamdb_dlc_tooltip = new Tooltip("Additionally get DLC data from SteamDB.\n" +
"Especially useful for DLC that is not listed on the Steam Store.\n" +
"This sometimes doesn't work because SteamDB may block access for scrapers.");
steamdb_dlc_checkbox.setTooltip(steamdb_dlc_tooltip);
Tooltip.install(steamdb_dlc_checkbox, steamdb_dlc_tooltip);
}
private void read() { private void read() {
language_combobox.getSelectionModel().select(config.getLanguage()); language_combobox.getSelectionModel().select(config.getLanguage());
appId_textfield.setText(config.getAppId().toString()); appId_textfield.setText(config.getAppId().toString());
@ -177,23 +185,6 @@ public class Controller implements Initializable {
unlockAll_disableDlcTextArea(); unlockAll_disableDlcTextArea();
} }
private void fix_dlc_textarea_prompt_text() {
dlc_textarea.setPromptText("List of DLC...\r0000 = DLC Name");
}
private void generate_tooltips() {
Tooltip extra_protection_tooltip = new Tooltip("\"extra protection\"");
extra_protection_checkbox.setTooltip(extra_protection_tooltip);
Tooltip.install(extra_protection_checkbox, extra_protection_tooltip);
/*Tooltip steamdb_dlc_tooltip = new Tooltip("Additionally get DLC data from SteamDB.\n" +
"Especially useful for DLC that is not listed on the Steam Store.\n" +
"This sometimes doesn't work because SteamDB may block access for scrapers.");*/
Tooltip steamdb_dlc_tooltip = new Tooltip("Currently broken.");
steamdb_dlc_checkbox.setTooltip(steamdb_dlc_tooltip);
Tooltip.install(steamdb_dlc_checkbox, steamdb_dlc_tooltip);
}
private ChangeListener<String> appIdChangesGameName() { private ChangeListener<String> appIdChangesGameName() {
return (observable, oldValue, newValue) -> { return (observable, oldValue, newValue) -> {
int appId; int appId;
@ -272,47 +263,7 @@ public class Controller implements Initializable {
} }
public void save() { public void save() {
Service<Void> s = new Service<Void>() { saveService().start();
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() {
try {
setUpCreamApi();
config.setDlcListFromString(dlc_textarea.getText());
config.setAppId(Integer.parseInt(appId_textfield.getText()));
config.setExtraProtection(extra_protection_checkbox.isSelected());
config.setForceOffline(offline_checkbox.isSelected());
config.setUnlockAll(unlock_all_checkbox.isSelected());
config.setLanguage(language_combobox.getValue());
config.sync();
} catch (IOException | ConfigurationException e) {
e.printStackTrace();
cancel();
} catch (NullPointerException e) {
logger.warn("No configuration file set!");
cancel();
}
updateIndicators();
return null;
}
};
}
};
s.setOnRunning(event -> {
setDisableAllButtons(true);
state_label.setText("Saving...");
});
s.setOnSucceeded(event -> {
setDisableAllButtons(false);
state_label.setText("Saved successfully!");
});
s.setOnCancelled(event -> {
setDisableAllButtons(false);
state_label.setText("Could not save configuration file!");
});
s.start();
} }
public void getAppId() { public void getAppId() {
@ -357,6 +308,143 @@ public class Controller implements Initializable {
* also lists DLC not available for purchase. * also lists DLC not available for purchase.
*/ */
public void getDlcList() { public void getDlcList() {
getDlcListService().start();
}
public void openFileChooser() {
FileChooser chooser = new FileChooser();
chooser.setTitle("Choose steam_api(64).dll...");
FileChooser.ExtensionFilter filter =
new FileChooser.ExtensionFilter("Steam API DLL",
"steam_api.dll", "steam_api64.dll");
chooser.getExtensionFilters().add(filter);
File file = chooser.showOpenDialog(path_button.getScene().getWindow());
try {
config.setConfig(file.getParent() + "\\cream_api.ini");
path_textfield.setText(file.getParent());
steamApiPathString = file.getAbsolutePath();
} catch (ConfigurationException | IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
logger.warn("Could not set config file location! Did you cancel the file chooser?");
}
emptyFields();
reset(true);
logger.info("File chosen: " + steamApiPathString);
logger.info("Ready.");
state_label.setText("Ready.");
}
/**
* Check if CreamAPI version of DLL is there, if not, rename original to steam_api(64)_o.dll and copy
* CreamAPI DLL to the path. Also looks for alternative Steam DLL (which means it patches both 64 and 32 bit
* DLLs at once if found)
*
* @throws IOException If file is missing or not accessible/modifiable.
*/
private void setUpCreamApi() throws IOException {
logger.info("Setting up DLL...");
Path path = Paths.get(steamApiPathString);
copyDllFile(path, isSameFile);
findAdditionalDll(path);
logger.info("Set up DLL successfully!");
}
private void findAdditionalDll(Path path) throws IOException {
String aDllString = is64Bit ? "\\steam_api.dll" : "\\steam_api64.dll";
Path dir = path.getParent();
Path aDll = Paths.get(dir.toString() + aDllString);
if (Files.exists(aDll)) {
logger.info("Additional DLL found: (" + aDll.toString() + ")!");
InputStream is = Files.newInputStream(aDll);
String md5 = DigestUtils.md5Hex(is);
boolean aIsSameFile = Objects.equals(md5, handler.getDllMd5(!is64Bit));
copyDllFile(aDll, aIsSameFile);
}
}
private void copyDllFile(Path path, boolean isSameFile) throws IOException {
if (!isSameFile) {
String pathOrigString = steamApiPathString;
String replacement = is64Bit ? "steam_api64_o.dll" : "steam_api_o.dll";
pathOrigString =
pathOrigString
.replaceFirst(REGEX, replacement);
Path pathOrig = Paths.get(pathOrigString);
if (!Files.exists(pathOrig)) {
logger.info("Renaming " + path.toString() + " to " + replacement + "...");
Files.move(path, pathOrig);
} else {
logger.info(pathOrigString + " already exists!");
String pathBakString = steamApiPathString;
pathBakString =
pathBakString
.replaceFirst(REGEX, is64Bit ? "steam_api64.dll.backup" : "steam_api.dll.backup");
Path pathBak = Paths.get(pathBakString);
Files.move(path, pathBak, StandardCopyOption.REPLACE_EXISTING);
}
logger.info("Copying CreamAPI DLL to " + path.toString() + " ...");
Files.copy(handler.getDllPath(is64Bit), path);
}
}
private void setDisableAllButtons(boolean b) {
reset_button.setDisable(b);
save_button.setDisable(b);
getAppId_button.setDisable(b);
path_button.setDisable(b);
getDlcList_button.setDisable(b);
}
public void resetFromButton() {
reset(false);
}
private Service<Void> saveService() {
Service<Void> s = new Service<Void>() {
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() {
try {
setUpCreamApi();
config.setDlcListFromString(dlc_textarea.getText());
config.setAppId(Integer.parseInt(appId_textfield.getText()));
config.setExtraProtection(extra_protection_checkbox.isSelected());
config.setForceOffline(offline_checkbox.isSelected());
config.setUnlockAll(unlock_all_checkbox.isSelected());
config.setLanguage(language_combobox.getValue());
config.sync();
} catch (IOException | ConfigurationException e) {
e.printStackTrace();
cancel();
} catch (NullPointerException e) {
logger.warn("No configuration file set!");
cancel();
}
updateIndicators();
return null;
}
};
}
};
s.setOnRunning(event -> {
setDisableAllButtons(true);
state_label.setText("Saving...");
});
s.setOnSucceeded(event -> {
setDisableAllButtons(false);
state_label.setText("Saved successfully!");
});
s.setOnCancelled(event -> {
setDisableAllButtons(false);
state_label.setText("Could not save configuration file!");
});
return s;
}
private Service<Void> getDlcListService() {
Service<Void> s = new Service<Void>() { Service<Void> s = new Service<Void>() {
@Override @Override
protected Task<Void> createTask() { protected Task<Void> createTask() {
@ -385,90 +473,7 @@ public class Controller implements Initializable {
setDisableAllButtons(false); setDisableAllButtons(false);
state_label.setText("Could not get list of DLCs!"); state_label.setText("Could not get list of DLCs!");
}); });
s.start(); return s;
}
public void openFileChooser() {
FileChooser chooser = new FileChooser();
chooser.setTitle("Choose steam_api(64).dll...");
FileChooser.ExtensionFilter filter =
new FileChooser.ExtensionFilter("Steam API DLL",
"steam_api.dll", "steam_api64.dll");
chooser.getExtensionFilters().add(filter);
File file = chooser.showOpenDialog(path_button.getScene().getWindow());
try {
config.setConfig(file.getParent() + "\\cream_api.ini");
path_textfield.setText(file.getParent());
steamApiPathString = file.getAbsolutePath();
} catch (ConfigurationException | IOException e) {
e.printStackTrace();
} catch (NullPointerException e) {
logger.warn("Could not set config file location! Did you cancel the file chooser?");
}
emptyFields();
reset(true);
state_label.setText("Ready.");
}
/**
* Check if CreamAPI version of DLL is there, if not, rename original to steam_api(64)_o.dll and copy
* CreamAPI DLL to the path. Also looks for alternative Steam DLL (which means it patches both 64 and 32 bit
* DLLs at once if found)
*
* @throws IOException If file is missing or not accessible/modifiable.
*/
private void setUpCreamApi() throws IOException {
Path path = Paths.get(steamApiPathString);
copyDllFile(path, isSameFile);
findAdditionalDll(path);
}
private void findAdditionalDll(Path path) throws IOException {
String secondDllString = is64Bit ? "\\steam_api.dll" : "\\steam_api64.dll";
Path dir = path.getParent();
Path secondDll = Paths.get(dir.toString() + secondDllString);
if (Files.exists(secondDll)) {
//System.out.println("Alternative DLL found!");
logger.info("Second DLL found: (" + secondDll.toString() + ")!");
InputStream is = Files.newInputStream(secondDll);
String md5 = DigestUtils.md5Hex(is);
boolean isSameFile1 = Objects.equals(md5, handler.getDllMd5(!is64Bit));
copyDllFile(secondDll, isSameFile1);
}
}
private void copyDllFile(Path path, boolean isSameFile) throws IOException {
if (!isSameFile) {
String pathOrigString = steamApiPathString;
pathOrigString =
pathOrigString
.replaceFirst(REGEX, is64Bit ? "steam_api64_o.dll" : "steam_api_o.dll");
Path pathOrig = Paths.get(pathOrigString);
if (!Files.exists(pathOrig)) {
Files.move(path, pathOrig);
} else {
String pathBakString = steamApiPathString;
pathBakString =
pathBakString
.replaceFirst(REGEX, is64Bit ? "steam_api64.dll.backup" : "steam_api.dll.backup");
Path pathBak = Paths.get(pathBakString);
Files.move(path, pathBak, StandardCopyOption.REPLACE_EXISTING);
}
//Files.deleteIfExists(path);
Files.copy(handler.getDllPath(is64Bit), path);
}
}
private void setDisableAllButtons(boolean b) {
reset_button.setDisable(b);
save_button.setDisable(b);
getAppId_button.setDisable(b);
path_button.setDisable(b);
getDlcList_button.setDisable(b);
}
public void resetFromButton() {
reset(false);
} }
static class ComboBoxAutoComplete<T> { static class ComboBoxAutoComplete<T> {

View File

@ -54,7 +54,7 @@ public class CreamApiConfig {
config = CONFIGS.ini(path); config = CONFIGS.ini(path);
config.setCommentLeadingCharsUsedInInput(";"); config.setCommentLeadingCharsUsedInInput(";");
} catch (ConfigurationException e) { } catch (ConfigurationException e) {
logger.warn("No config file found in default location!"); logger.warn("No config file found!");
//e.printStackTrace(); //e.printStackTrace();
} }
@ -109,6 +109,7 @@ public class CreamApiConfig {
} }
public void read() throws NullPointerException, NoSuchElementException { public void read() throws NullPointerException, NoSuchElementException {
logger.info("Reading config file...");
appId = config.getInt("steam.appid"); appId = config.getInt("steam.appid");
language = config.getString("steam.language"); language = config.getString("steam.language");
if (language == null) { if (language == null) {
@ -119,9 +120,11 @@ public class CreamApiConfig {
forceOffline = config.getBoolean("steam.forceoffline"); forceOffline = config.getBoolean("steam.forceoffline");
final SubnodeConfiguration dlc_section = config.getSection("dlc"); final SubnodeConfiguration dlc_section = config.getSection("dlc");
dlc_section.getKeys().forEachRemaining(k -> dlc.put(Integer.parseInt(k), dlc_section.getString(k))); dlc_section.getKeys().forEachRemaining(k -> dlc.put(Integer.parseInt(k), dlc_section.getString(k)));
logger.info("Successfully read config file!");
} }
public void sync() throws ConfigurationException { public void sync() throws ConfigurationException {
logger.info("Saving config file...");
FileBasedConfigurationBuilder<INIConfiguration> builder = CONFIGS.iniBuilder(path); FileBasedConfigurationBuilder<INIConfiguration> builder = CONFIGS.iniBuilder(path);
config = builder.getConfiguration(); config = builder.getConfiguration();
config.setCommentLeadingCharsUsedInInput(";"); config.setCommentLeadingCharsUsedInInput(";");
@ -142,6 +145,7 @@ public class CreamApiConfig {
config.setProperty("steam_misc.disableuserinterface", false); config.setProperty("steam_misc.disableuserinterface", false);
builder.save(); builder.save();
logger.info("Saved successfully!");
} }
// DLC list parsing // DLC list parsing

View File

@ -31,10 +31,8 @@ public class CreamApiDllHandler {
private final String steamApi64DllMd5; private final String steamApi64DllMd5;
private CreamApiDllHandler() throws IOException { private CreamApiDllHandler() throws IOException {
String steamApiDllMd5 = DigestUtils.md5Hex(Files.newInputStream(steamApiDllPath)); this.steamApiDllMd5 = DigestUtils.md5Hex(Files.newInputStream(steamApiDllPath));
String steamApi64DllMd5 = DigestUtils.md5Hex(Files.newInputStream(steamApi64DllPath)); this.steamApi64DllMd5 = DigestUtils.md5Hex(Files.newInputStream(steamApi64DllPath));
this.steamApiDllMd5 = steamApiDllMd5;
this.steamApi64DllMd5 = steamApi64DllMd5;
} }
public static synchronized CreamApiDllHandler getInstance() throws IOException { public static synchronized CreamApiDllHandler getInstance() throws IOException {

View File

@ -15,6 +15,11 @@
package xyz.jeddunk.autocreamapi.util; package xyz.jeddunk.autocreamapi.util;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.gargoylesoftware.htmlunit.util.Cookie;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException; import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken; import com.google.gson.reflect.TypeToken;
@ -35,6 +40,7 @@ import xyz.jeddunk.autocreamapi.util.env.MainEnv;
import java.io.*; import java.io.*;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.net.URL;
import java.time.Duration; import java.time.Duration;
import java.time.Instant; import java.time.Instant;
import java.util.*; import java.util.*;
@ -47,7 +53,7 @@ public class SteamAppsListCache {
private SteamAppsList list = new SteamAppsList(); private SteamAppsList list = new SteamAppsList();
private final File cacheFile = new File("steamapps.json"); private final File cacheFile = new File("steamapps.json");
private MainEnv env; private MainEnv env;
//private String key; private String cfduid = "";
public SteamAppsListCache() { public SteamAppsListCache() {
try { try {
@ -151,12 +157,13 @@ public class SteamAppsListCache {
} }
public Map<Integer, String> getDlcMap(String appId, boolean use_steamdb) { public Map<Integer, String> getDlcMap(String appId, boolean use_steamdb) {
logger.info("Getting list of DLC for AppID: " + appId + "...");
Map<Integer, String> steamStoreDLCs = new HashMap<>(); Map<Integer, String> steamStoreDLCs = new HashMap<>();
Map<Integer, String> steamDbDLCs = new HashMap<>(); Map<Integer, String> steamDbDLCs = new HashMap<>();
//StringBuilder sb = new StringBuilder();
// Steam Store // Steam Store
try { try {
logger.info("Trying to get DLC from Steam store page...");
Document steamDoc = Jsoup Document steamDoc = Jsoup
.connect("https://store.steampowered.com/app/" + appId + "/") .connect("https://store.steampowered.com/app/" + appId + "/")
.cookie("birthtime", "470703601") .cookie("birthtime", "470703601")
@ -170,13 +177,12 @@ public class SteamAppsListCache {
.text().replace("\n", "").trim(); .text().replace("\n", "").trim();
steamStoreDLCs.put(Integer.parseInt(dlc_id), dlc_name); steamStoreDLCs.put(Integer.parseInt(dlc_id), dlc_name);
} }
logger.info("Got DLC from Steam store page successfully.");
} catch (HttpStatusException e) { } catch (HttpStatusException e) {
logger.error(e.getUrl()); logger.error(e.getUrl());
if (e.getStatusCode() == 404) { if (e.getStatusCode() == 404) {
logger.error("App ID empty or not found! (HTTP Status Code: 404)"); logger.error("App ID empty or not found! (HTTP Status Code: 404)");
} else { } else {
/*System.err.printf("Error occurred while trying to get list of DLCs " +
"(HTTP Status Code: %d)%n", e.getStatusCode());*/
logger.error("Error occurred while trying to get list of DLCs " + logger.error("Error occurred while trying to get list of DLCs " +
"(HTTP Status Code: " + e.getStatusCode() + ")"); "(HTTP Status Code: " + e.getStatusCode() + ")");
} }
@ -186,39 +192,85 @@ public class SteamAppsListCache {
// SteamDB // SteamDB
if (use_steamdb) { if (use_steamdb) {
try {
Document steamDbDoc = Jsoup logger.info("Trying to get DLC from SteamDB...");
.connect("https://steamdb.info/app/" + appId + "/dlc/") if (cfduid.equals("")) {
.userAgent("Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Firefox/78.0") logger.info("Missing CF cookie, trying to get it...");
.get(); WebClient client = new WebClient(BrowserVersion.CHROME);
Element steamDbDlcSection = steamDbDoc.getElementById("dlc");
Elements steamDbDLCElements = steamDbDlcSection.getElementsByClass("app"); client.getOptions().setCssEnabled(false);
for (Element dlc : steamDbDLCElements) { client.getOptions().setJavaScriptEnabled(false);
String dlc_id = dlc.attr("data-appid"); client.getOptions().setThrowExceptionOnFailingStatusCode(false);
String dlc_name = "Unknown DLC " + dlc_id; client.getOptions().setRedirectEnabled(true);
Elements td = dlc.getElementsByTag("td"); client.getCache().setMaxSize(0);
if (!td.isEmpty()) { /*client.waitForBackgroundJavaScript(10000);
dlc_name = td.get(1).text().replace("\n", "").trim(); client.setJavaScriptTimeout(10000);
client.waitForBackgroundJavaScriptStartingBefore(10000);*/
try {
String urlString = "https://steamdb.info/";
HtmlPage page = client.getPage(urlString);
//noinspection SynchronizationOnLocalVariableOrMethodParameter
synchronized (page) {
page.wait(8000);
} }
steamDbDLCs.put(Integer.parseInt(dlc_id), dlc_name); //Print cookies for test purposes. Comment out in production.
URL url = new URL(urlString);
for (Cookie c : client.getCookies(url)) {
//System.out.println(c.getName() +"="+c.getValue());
if (c.getName().equals("__cfduid")) {
cfduid = c.getValue();
logger.info("Got CF cookie successfully.");
}
}
//This prints the content after bypassing Cloudflare.
// System.out.println(client.getPage(url).getWebResponse().getContentAsString());
} catch (FailingHttpStatusCodeException | IOException | InterruptedException e) {
// e.printStackTrace();
logger.error("Could not get CF cookie, skipping SteamDB DLC list...");
} }
} catch (HttpStatusException e) { }
logger.error(e.getUrl());
if (e.getStatusCode() == 404) { if ((!(cfduid.equals(""))) && (!(cfduid.equals("N/A")))) {
logger.error("App ID empty or not found! (HTTP Status Code: 404)"); try {
} else { Document steamDbDoc = Jsoup
/*System.err.printf("Error occurred while trying to get list of DLCs " + .connect("https://steamdb.info/app/" + appId + "/dlc/")
"(HTTP Status Code: %d)%n", e.getStatusCode());*/ .cookie("__cfduid", cfduid)
logger.error("Error occurred while trying to get list of DLCs " + .userAgent(BrowserVersion.CHROME.getUserAgent())
"(HTTP Status Code: " + e.getStatusCode() + ")"); .get();
Element steamDbDlcSection = steamDbDoc.getElementById("dlc");
Elements steamDbDLCElements = steamDbDlcSection.getElementsByClass("app");
for (Element dlc : steamDbDLCElements) {
String dlc_id = dlc.attr("data-appid");
String dlc_name = "Unknown DLC " + dlc_id;
Elements td = dlc.getElementsByTag("td");
if (!td.isEmpty()) {
dlc_name = td.get(1).text().replace("\n", "").trim();
}
steamDbDLCs.put(Integer.parseInt(dlc_id), dlc_name);
}
logger.info("Got DLC from SteamDB successfully.");
} catch (HttpStatusException e) {
logger.error(e.getUrl());
if (e.getStatusCode() == 404) {
logger.error("App ID empty or not found! (HTTP Status Code: 404)");
} else {
logger.error("Error occurred while trying to get list of DLCs " +
"(HTTP Status Code: " + e.getStatusCode() + ")");
}
} catch (NullPointerException | IOException e) {
// ignore
} }
} catch (NullPointerException | IOException e) {
// ignore
} }
} }
logger.info("Merging both DLC lists...");
Map<Integer, String> allDLCs = new HashMap<>(steamStoreDLCs); Map<Integer, String> allDLCs = new HashMap<>(steamStoreDLCs);
steamDbDLCs.forEach(allDLCs::putIfAbsent); steamDbDLCs.forEach(allDLCs::putIfAbsent);
logger.info("DLC list is done!");
return allDLCs.entrySet().stream() return allDLCs.entrySet().stream()
.sorted(Map.Entry.comparingByKey()) .sorted(Map.Entry.comparingByKey())
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,