From 6a227a2b2b9b90693095ba27aaf58051e24d453c Mon Sep 17 00:00:00 2001 From: mabrams17 Date: Thu, 4 May 2017 11:26:11 -0400 Subject: [PATCH] Debug option for importing games from Steam (#111) Adds debug option in menubar for importing Steam game libraries from an online XML file --- .../SteamCommunityGameImporter.java | 125 ++++++++++++++++++ src/virtualgameshelf/gui/MainMenuBar.java | 34 ++++- src/virtualgameshelf/gui/NewGameWindow.java | 2 - 3 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/virtualgameshelf/backend/persistance/SteamCommunityGameImporter.java diff --git a/src/virtualgameshelf/backend/persistance/SteamCommunityGameImporter.java b/src/virtualgameshelf/backend/persistance/SteamCommunityGameImporter.java new file mode 100644 index 0000000..8850339 --- /dev/null +++ b/src/virtualgameshelf/backend/persistance/SteamCommunityGameImporter.java @@ -0,0 +1,125 @@ +package virtualgameshelf.backend.persistance; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.DocumentBuilder; +import org.w3c.dom.Document; +import org.w3c.dom.NodeList; + +import virtualgameshelf.backend.domain.Game; +import virtualgameshelf.gui.GameShelf; + +import org.w3c.dom.Node; +import org.w3c.dom.Element; +import java.net.URL; + +/* + * XML DOM example + * https://www.mkyong.com/java/how-to-read-xml-file-in-java-dom-parser/ + */ + +public class SteamCommunityGameImporter { + /** + * Imports games from Steam community profile. Profile must be set to public + * in 'My Privacy Settings'. + *

+ * Games are retrieved via an XML file located by appending '&xml=1' to the + * URL for a profile's gamelist. + * + * @param id + * Steam profile ID. (ie: https://steamcommunity.com/id/[ID]) + */ + + // TODO: Will not work for accounts that have not set up a profile ID. + // For example, https://steamcommunity.com/profiles/76561198043604940 + + /* DOM vs SAX + * + * DOM (Document Object Model) Parsing + * - loads whole XML document in memory + * - is slower the larger the XML file + * + * + * SAX (Simple API for XML) Parsing + * - loads small part of the XML file in memory + * - faster then DOM for large XML file cause requires less memory + * - better for unknown file size + * + * DOM winner + */ + + // Steven: Possibly use https://github.com/xPaw/SteamID.php to convert + // between URL types? The conversion could happen in the GUI level, so this + // file just receives the profile ID + + public void steamCommunityAddGames(String id) { + try { + String url = "http://steamcommunity.com/id/" + id + "/games/?tab=all&xml=1"; + DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); + DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); + Document doc = dBuilder.parse(new URL(url).openStream()); + + // optional, but recommended + // read this - + // http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work + doc.getDocumentElement().normalize(); + + // System.out.println("Root element :" + doc.getDocumentElement().getNodeName()); //Check to make sure of correct RootElement + + NodeList nList = doc.getElementsByTagName("game"); + + // System.out.println("----------------------------"); // Used to Differentiate the stuff below and the stuff above. Not needed + + for (int temp = 0; temp < nList.getLength(); temp++) { + + Node nNode = nList.item(temp); + + if (nNode.getNodeType() == Node.ELEMENT_NODE) { + + Element eElement = (Element) nNode; + + String name = ""; + name = (eElement.getElementsByTagName("name").item(0).getTextContent()); + //System.out.println(name); //Used for finding which game causes the break + /* + * This is apparently Unneeded + * name = name.substring(10, name.length() - 4); + */ + + int hours = 0; + if(eElement.getElementsByTagName("hoursOnRecord").getLength() > 0){ + String stringHours = (eElement.getElementsByTagName("hoursOnRecord").item(0).getTextContent()); + //System.out.println(stringHours); //Used for finding which games hours cause the break + + //Checking to see if the hours is going to have a comma in it and if so, removes the comma + if(stringHours.length() >= 7) + { + stringHours = stringHours.substring(0,stringHours.indexOf(",")) + stringHours.substring(stringHours.indexOf(",")+1); + //System.out.println(stringHours); //Used to test if the comma was correctly removed + } + hours = (int) Math.round(Double.parseDouble(stringHours)); + } + + String completion = "Unfinished"; + if (hours == 0) { + completion = "Unplayed"; + } + + //Makes sure we are actually creating a game that has a name. + if(!(name.equals(""))) { + Game game = new Game(); + game.setName(name); + game.setSystem("PC"); + game.setHours(hours); + game.setCompletion(completion); + game.setRating(0); + GameShelf.gameList.addGame(game); + } + + } + } + } catch (Exception e) { + e.printStackTrace(); + } + GameShelf.refreshGameList(); + } +} diff --git a/src/virtualgameshelf/gui/MainMenuBar.java b/src/virtualgameshelf/gui/MainMenuBar.java index aef8674..7eb7b17 100644 --- a/src/virtualgameshelf/gui/MainMenuBar.java +++ b/src/virtualgameshelf/gui/MainMenuBar.java @@ -11,6 +11,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Optional; import com.opencsv.CSVParser; import com.opencsv.CSVReader; @@ -20,6 +21,7 @@ import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; +import javafx.scene.control.TextInputDialog; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; @@ -27,6 +29,7 @@ import javafx.stage.Stage; import virtualgameshelf.backend.domain.Game; import virtualgameshelf.backend.domain.GameList; +import virtualgameshelf.backend.persistance.SteamCommunityGameImporter; public class MainMenuBar extends MenuBar { /** Default folder for saving user data and settings */ @@ -88,6 +91,10 @@ public MainMenuBar(Stage mainStage) { MenuItem menuItemOpenSystemList = new MenuItem("Import/Export system_list.csv"); menuItemOpenSystemList.setOnAction(e -> onImportExportSystemList()); menuDebug.getItems().add(menuItemOpenSystemList); + + MenuItem menuItemTestImportSteamLibraryXML = new MenuItem("Test importing Steam library (.XML)"); + menuItemTestImportSteamLibraryXML.setOnAction(e -> onTestImportSteamLibraryXML()); + menuDebug.getItems().add(menuItemTestImportSteamLibraryXML); } /** Clears current gameList. */ @@ -111,7 +118,7 @@ public void onOpen() { if (file.canRead()) { try { CSVReader reader = new CSVReader(new FileReader(file), ',', CSVParser.DEFAULT_QUOTE_CHARACTER, 1); - //String[] header = Game.getColumnHeaders(); + // String[] header = Game.getColumnHeaders(); // read line by line String[] record = null; @@ -260,7 +267,7 @@ public static void onImportExportSystemList() { // Output arrayList to screen for (String[] s : arrayList) { - System.out.println(Arrays.toString(s)); + System.out.println(Arrays.toString(s)); } // Output arrayList to file @@ -275,6 +282,29 @@ public static void onImportExportSystemList() { } } + /** Test importing games into gamelist from Steam library (.xml file). */ + public static void onTestImportSteamLibraryXML() { + // TODO: ID field should be empty by default in final code. + // Leaving 'Stevoisiak' as default ID for testing. + + // TODO: Accept multiple formats for Steam ID. + // (ie: gabelogannewell, 76561197960287930, STEAM_0:0:11101, + // [U:1:22202], http://steamcommunity.com/id/gabelogannewell/, + // http://steamcommunity.com/profiles/76561197960287930/, + // http://steamcommunity.com/profiles/[U:1:22202]/) + // Convert types with (https://github.com/xPaw/SteamID.php)? + TextInputDialog steamIdDialog = new TextInputDialog("Stevoisiak"); + steamIdDialog.setTitle("Import library from Steam"); + steamIdDialog.setHeaderText(null); + steamIdDialog.setContentText("Please enter your steam ID."); + + Optional steamID = steamIdDialog.showAndWait(); + if (steamID.isPresent()) { + SteamCommunityGameImporter importer = new SteamCommunityGameImporter(); + importer.steamCommunityAddGames(steamID.get()); + } + } + /** * Configure FileChooser window for saving/opening GameList from file. * diff --git a/src/virtualgameshelf/gui/NewGameWindow.java b/src/virtualgameshelf/gui/NewGameWindow.java index cf51480..41757b1 100644 --- a/src/virtualgameshelf/gui/NewGameWindow.java +++ b/src/virtualgameshelf/gui/NewGameWindow.java @@ -205,8 +205,6 @@ private void onClickAddGame() { newGame.setRating(0); } - //newGame.print(); - // Close window after successful game addition (http://stackoverflow.com/a/25038465) Stage stage = (Stage) addButton.getScene().getWindow(); stage.close();