diff --git a/.gitignore b/.gitignore
index 0dc5435..a463f20 100644
--- a/.gitignore
+++ b/.gitignore
@@ -157,3 +157,4 @@ $RECYCLE.BIN/
cream_api.ini
steamapps.json
+/test.json
diff --git a/auto-cream-api.iml b/auto-cream-api.iml
index 81ae37b..4599ba8 100644
--- a/auto-cream-api.iml
+++ b/auto-cream-api.iml
@@ -18,39 +18,16 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f5203f2..dbc27e5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,6 +51,27 @@
+
+
+
+ false
+
+ bintray-jerady-maven
+ bintray
+ https://dl.bintray.com/jerady/maven
+
+
+
+
+
+ false
+
+ bintray-jerady-maven
+ bintray-plugins
+ https://dl.bintray.com/jerady/maven
+
+
+
com.jfoenix
@@ -58,11 +79,6 @@
8.0.8
compile
-
org.apache.commons
commons-configuration2
@@ -73,11 +89,6 @@
commons-beanutils
1.9.4
-
- com.ibasco.agql
- agql-steam-webapi
- 0.1.7
-
de.jensd
fontawesomefx-commons
@@ -90,5 +101,20 @@
4.7.0-5
compile
+
+ com.google.code.gson
+ gson
+ 2.8.6
+
+
+ org.jsoup
+ jsoup
+ 1.12.1
+
+
+ com.konghq
+ unirest-java
+ 3.1.02
+
\ No newline at end of file
diff --git a/src/main/java/Controller.java b/src/main/java/Controller.java
index d29c1bc..c8145f4 100644
--- a/src/main/java/Controller.java
+++ b/src/main/java/Controller.java
@@ -1,39 +1,60 @@
-import com.ibasco.agql.protocols.valve.steam.webapi.pojos.SteamApp;
import com.jfoenix.controls.*;
import javafx.beans.value.ChangeListener;
import javafx.collections.FXCollections;
-import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Tooltip;
import javafx.stage.FileChooser;
import org.apache.commons.configuration2.ex.ConfigurationException;
+import org.jsoup.Jsoup;
+import org.jsoup.nodes.Document;
+import org.jsoup.nodes.Element;
+import org.jsoup.select.Elements;
+import pojo.App;
import java.io.File;
import java.io.IOException;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.stream.Collectors;
public class Controller {
private CreamApiConfig config = CreamApiConfig.getInstance();
private SteamAppsListCache cache = new SteamAppsListCache();
- @FXML public JFXTextField path_textfield;
- @FXML public JFXTextField appId_textfield;
- @FXML public JFXTextField game_name_textfield;
- @FXML public JFXComboBox language_combobox;
- @FXML public JFXTextArea dlc_textarea;
- @FXML public JFXCheckBox extra_protection_checkbox;
- @FXML public JFXCheckBox offline_checkbox;
- @FXML public JFXCheckBox unlock_all_checkbox;
- @FXML public JFXButton reset_button;
- @FXML public JFXButton save_button;
- @FXML public JFXButton getAppId_button;
- @FXML public JFXButton path_button;
- @FXML public JFXButton retrieveDlcList_button;
+ @FXML
+ public JFXTextField path_textfield;
+ @FXML
+ public JFXTextField appId_textfield;
+ @FXML
+ public JFXTextField game_name_textfield;
+ @FXML
+ public JFXComboBox language_combobox;
+ @FXML
+ public JFXTextArea dlc_textarea;
+ @FXML
+ public JFXCheckBox extra_protection_checkbox;
+ @FXML
+ public JFXCheckBox offline_checkbox;
+ @FXML
+ public JFXCheckBox unlock_all_checkbox;
+ @FXML
+ public JFXButton reset_button;
+ @FXML
+ public JFXButton save_button;
+ @FXML
+ public JFXButton getAppId_button;
+ @FXML
+ public JFXButton path_button;
+ @FXML
+ public JFXButton retrieveDlcList_button;
- public Controller() {}
+ public Controller() {
+ }
@FXML
public void initialize() {
appId_textfield.textProperty().addListener(appIdChangesGameName());
- retrieveDlcList_button.setDisable(true); // WIP
+ //retrieveDlcList_button.setDisable(true); // WIP
generate_tooltips();
fix_dlc_textarea_prompt_text();
read();
@@ -66,7 +87,7 @@ public class Controller {
int appId;
try {
appId = Integer.parseInt(newValue);
- final SteamApp game = cache.getGame(appId);
+ final App game = cache.getGame(appId);
if (game != null) {
game_name_textfield.setText(game.getName());
} else {
@@ -98,72 +119,73 @@ public class Controller {
}
public void getAppId() {
- final SteamApp game = cache.findGame(game_name_textfield.getText());
+ final App game = cache.findGame(game_name_textfield.getText());
if (game == null) {
appId_textfield.setText("-1");
} else {
- appId_textfield.setText(String.valueOf(game.getAppid()));
+ appId_textfield.setText(String.valueOf(game.getAppId()));
}
}
public void unlockAll_disableDlcTextArea() {
dlc_textarea.setDisable(unlock_all_checkbox.isSelected());
+ retrieveDlcList_button.setDisable(unlock_all_checkbox.isSelected());
}
+ /**
+ * Gets DLC from both the Steam Store and SteamDB, since the latter has a (weird) limit of 64(?) DLCs. SteamDB
+ * also lists DLC not available for purchase.
+ */
public void getDlcList() {
- // https://github.com/Sak32009/GetDLCInfoFromSteamDB/blob/master/sak32009-get-dlc-info-from-steamdb.user.js
- /*async getData() {
- // CHECK IF THE APPID HAS DLCs
- if (!$("#dlc").length) {
- return false;
+ Map steamStoreDLCs = new HashMap<>();
+ Map steamDbDLCs = new HashMap<>();
+ //StringBuilder sb = new StringBuilder();
+ try {
+ // Steam Store
+ Document steamDoc = Jsoup
+ .connect("https://store.steampowered.com/app/" + appId_textfield.getText() + "/")
+ .get();
+ Elements steamDLCs = steamDoc.getElementsByClass("game_area_dlc_row");
+ for (Element dlc : steamDLCs) {
+ String dlc_id = dlc.attr("data-ds-appid");
+ String dlc_name = dlc
+ .getElementsByClass("game_area_dlc_name")
+ .text().replace("\n", "").trim();
+ steamStoreDLCs.put(Integer.parseInt(dlc_id), dlc_name);
}
- // SELF
- const self = this;
- // SET APPID
- this.steamDB.appID = $(".scope-app[data-appid]").data("appid");
- // SET APPID NAME
- this.steamDB.appIDName = $("td[itemprop='name']").text();
- // GET APPID DLCS FROM TAB
- $("tr.app[data-appid]").each((_index, _values) => {
- const $this = $(_values);
- const appID = $this.data("appid");
- const appIDName = $this.find(`td:nth-of-type(2)`).text().trim();
- // ADD DATA
- self.steamDB.appIDDLCs[appID] = {
- name: appIDName
- };
- // +1
- self.steamDB.appIDDLCsCount += 1;
- });
- // GET APPID DLCS FROM REQUEST
- await this.getHttpRequest(`${self.info.steamDBLinked + this.steamDB.appID}`, ({
- responseText
- }) => {
- // APPS
- const $apps = $($.parseHTML(responseText)).find("tr.app[data-appid]");
- // FETCH APPS
- $apps.each((_index, _values) => {
- const $this = $(_values);
- const appID = $this.attr("data-appid");
- const appIDType = $this.find("td:nth-of-type(2)").text().trim();
- const appIDName = $this.find("td:nth-of-type(3)").text().trim();
- // CHECK IF EXISTS
- if (!(appID in self.steamDB.appIDDLCs) && appIDType === "DLC") {
- // ADD DATA
- self.steamDB.appIDDLCs[appID] = {
- name: appIDName
- };
- // +1
- self.steamDB.appIDDLCsCount += 1;
+ // SteamDB
+ Document steamDbDoc = Jsoup
+ .connect("https://steamdb.info/app/" + appId_textfield.getText() + "/dlc/")
+ .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();
}
- });
- // RUN
- self.start();
- });
- }*/
+ steamDbDLCs.put(Integer.parseInt(dlc_id), dlc_name);
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (NullPointerException e) {
+ // ignore
+ }
+
+ Map allDLCs = new HashMap<>(steamStoreDLCs);
+ steamDbDLCs.forEach(allDLCs::putIfAbsent);
+ StringBuilder sb = new StringBuilder();
+ LinkedHashMap collect = allDLCs.entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
+ (oldValue, newValue) -> oldValue, LinkedHashMap::new));
+ collect.forEach((k, v) -> sb.append(k).append("=").append(v).append("\n"));
+ dlc_textarea.setText(sb.toString());
}
- public void openFileChooser(ActionEvent event) {
+ public void openFileChooser() {
FileChooser chooser = new FileChooser();
chooser.setTitle("Choose steam_api(64).dll...");
FileChooser.ExtensionFilter filter =
diff --git a/src/main/java/SteamAppsListCache.java b/src/main/java/SteamAppsListCache.java
index 81cbe48..62b702d 100644
--- a/src/main/java/SteamAppsListCache.java
+++ b/src/main/java/SteamAppsListCache.java
@@ -1,58 +1,66 @@
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
-import com.ibasco.agql.protocols.valve.steam.webapi.SteamWebApiClient;
-import com.ibasco.agql.protocols.valve.steam.webapi.interfaces.SteamApps;
-import com.ibasco.agql.protocols.valve.steam.webapi.pojos.SteamApp;
+import kong.unirest.HttpResponse;
+import kong.unirest.Unirest;
+import pojo.App;
+import pojo.Download;
+import pojo.SteamAppsList;
import java.io.*;
import java.lang.reflect.Type;
-import java.text.MessageFormat;
import java.time.Duration;
import java.time.Instant;
-import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@SuppressWarnings("WeakerAccess")
public class SteamAppsListCache {
- static class SteamAppsList {
- Instant timestamp;
- List steamAppsList;
- }
-
private SteamAppsList list = new SteamAppsList();
private File cacheFile = new File("steamapps.json");
public SteamAppsListCache() {
- getListFromFile();
- if (Instant.now().isAfter(list.timestamp.plus(Duration.ofDays(3)))) {
- getListFromApi();
+ boolean fileFound = true;
+ try {
+ getListFromFile();
+ } catch (FileNotFoundException e) {
+ System.err.println("File does not exist, trying to create steamapps.json for the first time...");
+ fileFound = false;
+ }
+ if (!fileFound || Instant.now().isAfter(list.getTimestamp().plus(Duration.ofDays(3)))) {
+ sync();
+ }
+ }
+
+ private void sync() {
+ getListFromApi();
+ try {
saveListToFile();
+ } catch (IOException ex) {
+ ex.printStackTrace();
}
}
- public SteamApp getGame (int appId) {
- for (SteamApp app : list.steamAppsList) {
- if (app.getAppid() == appId) {
+ public App getGame(int appId) {
+ return list.getSteamAppsList().stream().filter(app -> app.getAppId() == appId).findFirst().orElse(null);
+ }
+
+ @SuppressWarnings("unused")
+ public App getGame(String name) {
+ return list.getSteamAppsList().stream()
+ .filter(app -> app.getName().equalsIgnoreCase(name)).findFirst().orElse(null);
+ }
+
+ public App findGame(String name) {
+ for (App app : list.getSteamAppsList()) {
+ if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "")
+ .startsWith(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) {
return app;
}
}
- return null;
- }
-
- public SteamApp getGame (String name) {
- for (SteamApp app : list.steamAppsList) {
- if (app.getName().equalsIgnoreCase(name)) {
- return app;
- }
- }
- return null;
- }
-
- public SteamApp findGame(String name) {
- for (SteamApp app : list.steamAppsList) {
- if (app.getName().toLowerCase().contains(name.toLowerCase())) {
+ for (App app : list.getSteamAppsList()) {
+ if (app.getName().toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", "")
+ .contains(name.toLowerCase().replaceAll("[^a-zA-Z0-9\\s+]", ""))) {
return app;
}
}
@@ -60,44 +68,30 @@ public class SteamAppsListCache {
}
private void getListFromApi() {
- SteamWebApiClient client = new SteamWebApiClient();
- SteamApps steamApps = new SteamApps(client);
- /*SteamStorefront storefront = new SteamStorefront(client);
- StoreAppDetails appDetails = storefront.getAppDetails(440).exceptionally(throwable -> {
- System.err.println(MessageFormat.format("Error Occurred: {}", throwable));
- return new StoreAppDetails();
- }).join();
- System.out.println(appDetails);
- Gson gson = new Gson();
- System.out.println(gson.toJson(appDetails));*/
- list.timestamp = Instant.now();
- list.steamAppsList = steamApps.getAppList().exceptionally(throwable -> {
- System.err.println(MessageFormat.format("Error Occurred: {}", throwable));
- return new ArrayList<>();
- }).join();
+ HttpResponse httpResponse =
+ Unirest.get("https://api.steampowered.com/IStoreService/GetAppList/v1/" +
+ "?key=E427256C579D3CDF1D504810E8F5B948&include_games=1&max_results=50000").asString();
+ List apps = new Gson()
+ .fromJson(httpResponse.getBody(), Download.class)
+ .getResponse().getApps();
+ list.setTimestamp(Instant.now());
+ list.setSteamAppsList(apps);
}
- private void saveListToFile() {
+ private void saveListToFile() throws IOException {
Gson gson = new Gson();
String jsonString = gson.toJson(list);
- try {
- BufferedWriter fOut = new BufferedWriter(new FileWriter(cacheFile));
- fOut.write(jsonString);
- fOut.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
+ BufferedWriter fOut = new BufferedWriter(new FileWriter(cacheFile));
+ fOut.write(jsonString);
+ fOut.close();
}
- private void getListFromFile() {
- try {
- BufferedReader fIn = new BufferedReader(new FileReader(cacheFile));
- String json = fIn.lines().collect(Collectors.joining());
- final Type type = new TypeToken() {}.getType();
- Gson gson = new Gson();
- list = gson.fromJson(json, type);
- } catch (IOException e) {
- e.printStackTrace();
- }
+ private void getListFromFile() throws FileNotFoundException {
+ BufferedReader fIn = new BufferedReader(new FileReader(cacheFile));
+ String json = fIn.lines().collect(Collectors.joining());
+ final Type type = new TypeToken() {
+ }.getType();
+ Gson gson = new Gson();
+ list = gson.fromJson(json, type);
}
}
diff --git a/src/main/java/pojo/App.java b/src/main/java/pojo/App.java
new file mode 100644
index 0000000..3130f12
--- /dev/null
+++ b/src/main/java/pojo/App.java
@@ -0,0 +1,110 @@
+package pojo;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Objects;
+
+@SuppressWarnings("unused")
+public class App {
+
+ @SerializedName("appid")
+ @Expose
+ private Integer appId;
+ @SerializedName("name")
+ @Expose
+ private String name;
+ @SerializedName("last_modified")
+ @Expose
+ private Integer lastModified;
+ @SerializedName("price_change_number")
+ @Expose
+ private Integer priceChangeNumber;
+
+ public Integer getAppId() {
+ return appId;
+ }
+
+ public void setAppId(Integer appId) {
+ this.appId = appId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Integer getLastModified() {
+ return lastModified;
+ }
+
+ public void setLastModified(Integer lastModified) {
+ this.lastModified = lastModified;
+ }
+
+ public Integer getPriceChangeNumber() {
+ return priceChangeNumber;
+ }
+
+ public void setPriceChangeNumber(Integer priceChangeNumber) {
+ this.priceChangeNumber = priceChangeNumber;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(App.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
+ sb.append("appid");
+ sb.append('=');
+ sb.append(((this.appId == null)?"":this.appId));
+ sb.append(',');
+ sb.append("name");
+ sb.append('=');
+ sb.append(((this.name == null)?"":this.name));
+ sb.append(',');
+ sb.append("lastModified");
+ sb.append('=');
+ sb.append(((this.lastModified == null)?"":this.lastModified));
+ sb.append(',');
+ sb.append("priceChangeNumber");
+ sb.append('=');
+ sb.append(((this.priceChangeNumber == null)?"":this.priceChangeNumber));
+ sb.append(',');
+ if (sb.charAt((sb.length()- 1)) == ',') {
+ sb.setCharAt((sb.length()- 1), ']');
+ } else {
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = ((result* 31)+((this.name == null)? 0 :this.name.hashCode()));
+ result = ((result* 31)+((this.lastModified == null)? 0 :this.lastModified.hashCode()));
+ result = ((result* 31)+((this.priceChangeNumber == null)? 0 :this.priceChangeNumber.hashCode()));
+ result = ((result* 31)+((this.appId == null)? 0 :this.appId.hashCode()));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof App)) {
+ return false;
+ }
+ App rhs = ((App) other);
+ boolean b1 = Objects.equals(this.name, rhs.name);
+ boolean b2 = Objects.equals(this.lastModified, rhs.lastModified);
+ boolean b3 = Objects.equals(this.priceChangeNumber, rhs.priceChangeNumber);
+ boolean b4 = Objects.equals(this.appId, rhs.appId);
+ return b1 && b2 && b3 && b4;
+ }
+
+}
diff --git a/src/main/java/pojo/Download.java b/src/main/java/pojo/Download.java
new file mode 100644
index 0000000..384ef0d
--- /dev/null
+++ b/src/main/java/pojo/Download.java
@@ -0,0 +1,58 @@
+package pojo;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+import java.util.Objects;
+
+public class Download {
+
+ @SerializedName("response")
+ @Expose
+ private Rezponze response;
+
+ public Rezponze getResponse() {
+ return response;
+ }
+
+ public void setResponse(Rezponze response) {
+ this.response = response;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Download.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
+ sb.append("response");
+ sb.append('=');
+ sb.append(((this.response == null)?"":this.response));
+ sb.append(',');
+ if (sb.charAt((sb.length()- 1)) == ',') {
+ sb.setCharAt((sb.length()- 1), ']');
+ } else {
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = ((result* 31)+((this.response == null)? 0 :this.response.hashCode()));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Download)) {
+ return false;
+ }
+ Download rhs = ((Download) other);
+ return Objects.equals(this.response, rhs.response);
+ //return ((this.response == rhs.response)||((this.response!= null)&&this.response.equals(rhs.response)));
+ }
+
+}
diff --git a/src/main/java/pojo/Rezponze.java b/src/main/java/pojo/Rezponze.java
new file mode 100644
index 0000000..d2263dd
--- /dev/null
+++ b/src/main/java/pojo/Rezponze.java
@@ -0,0 +1,60 @@
+package pojo;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import com.google.gson.annotations.Expose;
+import com.google.gson.annotations.SerializedName;
+
+public class Rezponze {
+
+ @SerializedName("apps")
+ @Expose
+ private List apps = new ArrayList<>();
+
+ public List getApps() {
+ return apps;
+ }
+
+ public void setApps(List apps) {
+ this.apps = apps;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(Rezponze.class.getName()).append('@').append(Integer.toHexString(System.identityHashCode(this))).append('[');
+ sb.append("apps");
+ sb.append('=');
+ sb.append(((this.apps == null)?"":this.apps));
+ sb.append(',');
+ if (sb.charAt((sb.length()- 1)) == ',') {
+ sb.setCharAt((sb.length()- 1), ']');
+ } else {
+ sb.append(']');
+ }
+ return sb.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ int result = 1;
+ result = ((result* 31)+((this.apps == null)? 0 :this.apps.hashCode()));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+ if (!(other instanceof Rezponze)) {
+ return false;
+ }
+ Rezponze rhs = ((Rezponze) other);
+ return Objects.equals(this.apps, rhs.apps);
+ //return ((this.apps == rhs.apps)||((this.apps!= null)&&this.apps.equals(rhs.apps)));
+ }
+
+}
diff --git a/src/main/java/pojo/SteamAppsList.java b/src/main/java/pojo/SteamAppsList.java
new file mode 100644
index 0000000..24cca4a
--- /dev/null
+++ b/src/main/java/pojo/SteamAppsList.java
@@ -0,0 +1,25 @@
+package pojo;
+
+import java.time.Instant;
+import java.util.List;
+
+public class SteamAppsList {
+ private Instant timestamp;
+ private List steamAppsList;
+
+ public Instant getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(Instant timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public List getSteamAppsList() {
+ return steamAppsList;
+ }
+
+ public void setSteamAppsList(List steamAppsList) {
+ this.steamAppsList = steamAppsList;
+ }
+}
diff --git a/src/main/resources/mainWindow.fxml b/src/main/resources/mainWindow.fxml
index fbb9b04..92cc63f 100644
--- a/src/main/resources/mainWindow.fxml
+++ b/src/main/resources/mainWindow.fxml
@@ -48,7 +48,7 @@
-
+