commit ed45c1eeaed9c96f306b0526d3c382d56298a814 Author: goodwin Date: Sat Jan 27 20:59:23 2024 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml new file mode 100644 index 0000000..8aef29c --- /dev/null +++ b/.idea/codeStyles/Project.xml @@ -0,0 +1,15 @@ + + + + + + \ No newline at end of file diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..79ee123 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..20e4bc5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..dc73690 --- /dev/null +++ b/pom.xml @@ -0,0 +1,49 @@ + + 4.0.0 + + org.example + testSteamPrices + 1.0-SNAPSHOT + jar + + testSteamPrices + http://maven.apache.org + + + UTF-8 + + + + + junit + junit + 3.8.1 + test + + + + com.fasterxml.jackson.core + jackson-databind + 2.16.1 + + + + redis.clients + jedis + 5.1.0 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 9 + 9 + + + + + diff --git a/src/main/java/org/example/GameInfoResponse.java b/src/main/java/org/example/GameInfoResponse.java new file mode 100644 index 0000000..d39bec1 --- /dev/null +++ b/src/main/java/org/example/GameInfoResponse.java @@ -0,0 +1,97 @@ +package org.example; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +@JsonIgnoreProperties +final class GameInfoResponse +{ + + private Map data; + private List> apps; + private Map price; + private Map platforms; + private Map controller; + + + public Map getData() + { + return data; + } + + public void setData(Map data) + { + this.data = data; + } + + public List> getApps() + { + return apps; + } + + public void setApps(List> apps) + { + this.apps = apps; + } + + public Map getPrice() + { + return price; + } + + public void setPrice(Map price) + { + this.price = price; + } + + public Map getPlatforms() + { + return platforms; + } + + public void setPlatforms(Map platforms) + { + this.platforms = platforms; + } + + public Map getController() + { + return controller; + } + + public void setController(Map controller) + { + this.controller = controller; + } + + private static final class ReleaseDate + { + public boolean isComing_soon() + { + return coming_soon; + } + + public void setComing_soon(boolean coming_soon) + { + this.coming_soon = coming_soon; + } + + public Date getDate() + { + return date; + } + + public void setDate(Date date) + { + this.date = date; + } + + private boolean coming_soon; + private Date date; + } +} + + diff --git a/src/main/java/org/example/SteamPriceParser.java b/src/main/java/org/example/SteamPriceParser.java new file mode 100644 index 0000000..2a0113f --- /dev/null +++ b/src/main/java/org/example/SteamPriceParser.java @@ -0,0 +1,129 @@ +package org.example; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import redis.clients.jedis.*; + +import javax.net.ssl.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStore; + +//TODO: move const to resources +public class SteamPriceParser +{ + + final static String GAME_DETAILS_API_TEMPLATE = "https://store.steampowered.com/api/packagedetails?packageids=%s&cc=%s&filters=price_overview"; + final static String REDIS_HOST = "rc1a-67kduigjscq90cna.mdb.yandexcloud.net"; + final static String REDIS_PASS = "Q1598520q"; + final static String PROXY_HOST = "91.147.123.214"; + final static int PROXY_PORT = 50101; + final static String PROXY_USER = "pavel0RG3T"; + final static String PROXY_PASS = "pJ9KTE9QbD"; + final static String CA_CERT_PASS = "Q1598520q"; + final static String USER_CERT_PASS = "Q1598520q"; + + + public static void main(String[] args) throws GeneralSecurityException, IOException + { + JsonNode json; + + try (JedisPooled jedis = new JedisPooled(new HostAndPort(REDIS_HOST, 6380), prepareRedisConfig())) + { + //TODO: add threads + for (int i = 0; i < 150000; i++) + { + try + { + json = loadGameJson(String.format(GAME_DETAILS_API_TEMPLATE, i, "KZ")); + } + catch (IOException e) + { + //TODO: add pushing logs to kibana or etc.. + e.printStackTrace(); + continue; + } + //TODO: add filter for successful and unsuccessful requests + jedis.set(String.valueOf(i), json.toString()); + System.out.println("Current id = " + i); + System.out.println(json.toPrettyString()); + + System.out.println("jedis value for " + i + "\n" + jedis.get(String.valueOf(i))); + } + } + + } + + + //TODO: move hostname, port, log and pass to resources + //TODO: remove deprecated URL constructor + //TODO: replace mapper towards concrete class model GameInfoResponse + private static JsonNode loadGameJson(String url) throws IOException + { + InputStream inputStream; + + Proxy proxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(PROXY_HOST, PROXY_PORT)); + Authenticator authenticator = new Authenticator() + { + public PasswordAuthentication getPasswordAuthentication() + { + return (new PasswordAuthentication(PROXY_USER, PROXY_PASS.toCharArray())); + } + }; + Authenticator.setDefault(authenticator); + URLConnection connection = new URL(url).openConnection(proxy); + inputStream = connection.getInputStream(); + + InputStreamReader reader = new InputStreamReader(inputStream); + ObjectMapper mapper = new ObjectMapper(); + return mapper.readTree(reader); + + } + + public static DefaultJedisClientConfig prepareRedisConfig() throws GeneralSecurityException, IOException + { + SSLSocketFactory sslFactory = createSslSocketFactory( + "C:\\truststore.jks", + CA_CERT_PASS, // use the password specified for keytool command + "C:\\redis-keystore.p12", + USER_CERT_PASS // use the password specified for openssl command + ); + + return DefaultJedisClientConfig.builder() + .ssl(true) + .sslSocketFactory(sslFactory) + .user("default") + .password(REDIS_PASS) + .build(); + } + + private static SSLSocketFactory createSslSocketFactory( + String caCertPath, String caCertPassword, String userCertPath, String userCertPassword) + throws IOException, GeneralSecurityException + { + + KeyStore keyStore = KeyStore.getInstance("pkcs12"); + keyStore.load(Files.newInputStream(Paths.get(userCertPath)), userCertPassword.toCharArray()); + + KeyStore trustStore = KeyStore.getInstance("jks"); + trustStore.load(Files.newInputStream(Paths.get(caCertPath)), caCertPassword.toCharArray()); + + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("X509"); + trustManagerFactory.init(trustStore); + + KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX"); + keyManagerFactory.init(keyStore, userCertPassword.toCharArray()); + + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null); + + return sslContext.getSocketFactory(); + } + + +} diff --git a/src/main/resources/config.properties b/src/main/resources/config.properties new file mode 100644 index 0000000..af24597 --- /dev/null +++ b/src/main/resources/config.properties @@ -0,0 +1 @@ +GAME_DETAILS_API_TEMPLATE = https://store.steampowered.com/api/packagedetails?packageids=%s&cc=%s&filters=price_overview \ No newline at end of file diff --git a/src/test/java/org/example/SteamPriceParserTest.java b/src/test/java/org/example/SteamPriceParserTest.java new file mode 100644 index 0000000..c3362ac --- /dev/null +++ b/src/test/java/org/example/SteamPriceParserTest.java @@ -0,0 +1,38 @@ +package org.example; + +import junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +/** + * Unit test for simple App. + */ +public class SteamPriceParserTest + extends TestCase +{ + /** + * Create the test case + * + * @param testName name of the test case + */ + public SteamPriceParserTest(String testName ) + { + super( testName ); + } + + /** + * @return the suite of tests being tested + */ + public static Test suite() + { + return new TestSuite( SteamPriceParserTest.class ); + } + + /** + * Rigourous Test :-) + */ + public void testApp() + { + assertTrue( true ); + } +}