mirror of
https://github.com/tiennm99/store-scraper-bot-java.git
synced 2026-05-14 09:53:03 +00:00
feat(api): init
This commit is contained in:
@@ -1,2 +1,3 @@
|
||||
# store-scraper-bot
|
||||
|
||||
Telegram bot that support scrape infos of an app on stores
|
||||
|
||||
+19
-2
@@ -9,12 +9,29 @@ repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
configurations {
|
||||
compileOnly {
|
||||
extendsFrom(configurations.annotationProcessor.get())
|
||||
}
|
||||
testCompileOnly {
|
||||
extendsFrom(configurations.testAnnotationProcessor.get())
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation(platform("org.junit:junit-bom:5.10.0"))
|
||||
annotationProcessor("org.projectlombok:lombok:1.18.36")
|
||||
implementation("com.couchbase.client:java-client:3.4.11")
|
||||
implementation("org.apache.logging.log4j:log4j-1.2-api:2.24.3")
|
||||
implementation("org.apache.logging.log4j:log4j-core:2.24.3")
|
||||
implementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3")
|
||||
implementation("org.telegram:telegrambots-abilities:8.0.0")
|
||||
|
||||
testAnnotationProcessor("org.projectlombok:lombok:1.18.36")
|
||||
testImplementation(platform("org.junit:junit-bom:5.11.4"))
|
||||
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
|
||||
tasks.test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
couchbase:
|
||||
image: couchbase:community-7.6.2
|
||||
ports:
|
||||
- "8091-8097:8091-8097"
|
||||
- "9123:9123"
|
||||
- "11207:11207"
|
||||
- "11210:11210"
|
||||
- "11280:11280"
|
||||
- "18091-18097:18091-18097"
|
||||
volumes:
|
||||
- couchbase_data:/opt/couchbase/var
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
couchbase_data:
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.miti99;
|
||||
package com.miti99.storescraperbot;
|
||||
|
||||
// TIP To <b>Run</b> code, press <shortcut actionId="Run"/> or
|
||||
// click the <icon src="AllIcons.Actions.Execute"/> icon in the gutter.
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.miti99.storescraperbot.api.apple;
|
||||
|
||||
import com.couchbase.client.core.deps.io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import com.couchbase.client.core.deps.io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import com.miti99.storescraperbot.api.apple.request.AppleAppRequest;
|
||||
import com.miti99.storescraperbot.api.apple.response.AppleAppResponse;
|
||||
import com.miti99.storescraperbot.util.JacksonUtil;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpClient.Redirect;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class AppStoreScraper {
|
||||
public static final String BASE_URL = "https://miti-app-store-scraper.vercel.app/";
|
||||
|
||||
@SneakyThrows
|
||||
public static AppleAppResponse app(AppleAppRequest request) {
|
||||
var httpRequest =
|
||||
HttpRequest.newBuilder()
|
||||
.uri(URI.create(BASE_URL + "/app"))
|
||||
// .timeout(Duration.ofMillis(TIMEOUT))
|
||||
.header(
|
||||
HttpHeaderNames.CONTENT_TYPE.toString(),
|
||||
HttpHeaderValues.APPLICATION_JSON.toString())
|
||||
.POST(BodyPublishers.ofString(JacksonUtil.writeValueAsString(request)))
|
||||
.build();
|
||||
|
||||
var body =
|
||||
HttpClient.newBuilder()
|
||||
.followRedirects(Redirect.NORMAL)
|
||||
// .connectTimeout(Duration.ofMillis(TIMEOUT))
|
||||
.build()
|
||||
.send(httpRequest, BodyHandlers.ofString())
|
||||
.body();
|
||||
return JacksonUtil.readValue(body, AppleAppResponse.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.miti99.storescraperbot.api.apple.request;
|
||||
|
||||
public record AppleAppRequest(String appId) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.miti99.storescraperbot.api.apple.response;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record AppleAppResponse(
|
||||
String title,
|
||||
String description,
|
||||
String descriptionHTML,
|
||||
String summary,
|
||||
String installs,
|
||||
long minInstalls,
|
||||
long maxInstalls,
|
||||
double score,
|
||||
String scoreText,
|
||||
long ratings,
|
||||
long reviews,
|
||||
Map<String, Long> histogram,
|
||||
double price,
|
||||
boolean free,
|
||||
String currency,
|
||||
String priceText,
|
||||
boolean offersIAP,
|
||||
String IAPRange,
|
||||
String androidVersion,
|
||||
String androidVersionText,
|
||||
String androidMaxVersion,
|
||||
String developer,
|
||||
String developerId,
|
||||
String developerEmail,
|
||||
String developerWebsite,
|
||||
String developerAddress,
|
||||
String developerLegalName,
|
||||
String developerLegalEmail,
|
||||
String developerLegalAddress,
|
||||
String developerLegalPhoneNumber,
|
||||
String privacyPolicy,
|
||||
String developerInternalID,
|
||||
String genre,
|
||||
String genreId,
|
||||
List<Category> categories,
|
||||
String icon,
|
||||
String headerImage,
|
||||
List<String> screenshots,
|
||||
String video,
|
||||
String videoImage,
|
||||
String previewVideo,
|
||||
String contentRating,
|
||||
String contentRatingDescription,
|
||||
boolean adSupported,
|
||||
String released,
|
||||
String updated,
|
||||
String version,
|
||||
String recentChanges,
|
||||
List<String> comments,
|
||||
boolean preregister,
|
||||
boolean earlyAccessEnabled,
|
||||
boolean isAvailableInPlayPass,
|
||||
boolean editorsChoice,
|
||||
List<Feature> features,
|
||||
String appId,
|
||||
String url) {
|
||||
|
||||
public record Category(String name, String id) {}
|
||||
|
||||
public record Feature(String title, String description) {}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.miti99.storescraperbot.api.google;
|
||||
|
||||
import com.couchbase.client.core.deps.io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import com.couchbase.client.core.deps.io.netty.handler.codec.http.HttpHeaderValues;
|
||||
import com.miti99.storescraperbot.api.google.request.GoogleAppRequest;
|
||||
import com.miti99.storescraperbot.api.google.response.GoogleAppResponse;
|
||||
import com.miti99.storescraperbot.util.JacksonUtil;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpClient.Redirect;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpRequest.BodyPublishers;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class GooglePlayScraper {
|
||||
public static final String BASE_URL = "https://miti-google-play-scraper.vercel.app/";
|
||||
|
||||
@SneakyThrows
|
||||
public static GoogleAppResponse app(GoogleAppRequest request) {
|
||||
var httpRequest =
|
||||
HttpRequest.newBuilder()
|
||||
.uri(URI.create(BASE_URL + "/app"))
|
||||
// .timeout(Duration.ofMillis(TIMEOUT))
|
||||
.header(
|
||||
HttpHeaderNames.CONTENT_TYPE.toString(),
|
||||
HttpHeaderValues.APPLICATION_JSON.toString())
|
||||
.POST(BodyPublishers.ofString(JacksonUtil.writeValueAsString(request)))
|
||||
.build();
|
||||
|
||||
var body =
|
||||
HttpClient.newBuilder()
|
||||
// .connectTimeout(Duration.ofMillis(TIMEOUT))
|
||||
.followRedirects(Redirect.NORMAL)
|
||||
.build()
|
||||
.send(httpRequest, BodyHandlers.ofString())
|
||||
.body();
|
||||
return JacksonUtil.readValue(body, GoogleAppResponse.class);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.miti99.storescraperbot.api.google.request;
|
||||
|
||||
public record GoogleAppRequest(String appId) {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.miti99.storescraperbot.api.google.response;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public record GoogleAppResponse(
|
||||
String title,
|
||||
String description,
|
||||
String descriptionHTML,
|
||||
String summary,
|
||||
String installs,
|
||||
long minInstalls,
|
||||
long maxInstalls,
|
||||
double score,
|
||||
String scoreText,
|
||||
long ratings,
|
||||
long reviews,
|
||||
Map<String, Long> histogram,
|
||||
double price,
|
||||
boolean free,
|
||||
String currency,
|
||||
String priceText,
|
||||
boolean offersIAP,
|
||||
String IAPRange,
|
||||
String androidVersion,
|
||||
String androidVersionText,
|
||||
String androidMaxVersion,
|
||||
String developer,
|
||||
String developerId,
|
||||
String developerEmail,
|
||||
String developerWebsite,
|
||||
String developerAddress,
|
||||
String developerLegalName,
|
||||
String developerLegalEmail,
|
||||
String developerLegalAddress,
|
||||
String developerLegalPhoneNumber,
|
||||
String privacyPolicy,
|
||||
String developerInternalID,
|
||||
String genre,
|
||||
String genreId,
|
||||
List<Category> categories,
|
||||
String icon,
|
||||
String headerImage,
|
||||
List<String> screenshots,
|
||||
String video,
|
||||
String videoImage,
|
||||
String previewVideo,
|
||||
String contentRating,
|
||||
String contentRatingDescription,
|
||||
boolean adSupported,
|
||||
Long released,
|
||||
long updated,
|
||||
String version,
|
||||
String recentChanges,
|
||||
List<String> comments,
|
||||
boolean preregister,
|
||||
boolean earlyAccessEnabled,
|
||||
boolean isAvailableInPlayPass,
|
||||
boolean editorsChoice,
|
||||
List<Feature> features,
|
||||
String appId,
|
||||
String url) {
|
||||
|
||||
public record Category(String name, String id) {}
|
||||
|
||||
public record Feature(String title, String description) {}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.miti99.storescraperbot.config;
|
||||
|
||||
public class Config {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package com.miti99.storescraperbot.util;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||
import com.fasterxml.jackson.annotation.PropertyAccessor;
|
||||
import com.fasterxml.jackson.core.JsonParser.Feature;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import lombok.SneakyThrows;
|
||||
|
||||
public class JacksonUtil {
|
||||
public static ObjectMapper MAPPER = objectMapper();
|
||||
|
||||
private static ObjectMapper objectMapper() {
|
||||
var objectMapper = new ObjectMapper();
|
||||
|
||||
objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
|
||||
objectMapper.disable(
|
||||
SerializationFeature.FAIL_ON_EMPTY_BEANS,
|
||||
SerializationFeature.INDENT_OUTPUT,
|
||||
SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
|
||||
|
||||
objectMapper.enable(
|
||||
DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,
|
||||
DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY,
|
||||
DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);
|
||||
objectMapper.enable(
|
||||
Feature.ALLOW_SINGLE_QUOTES, Feature.ALLOW_UNQUOTED_FIELD_NAMES, Feature.IGNORE_UNDEFINED);
|
||||
objectMapper.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING);
|
||||
|
||||
objectMapper.setSerializationInclusion(Include.NON_NULL);
|
||||
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
|
||||
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static <T> T readValue(String input, Class<T> valueType) {
|
||||
return MAPPER.readValue(input, valueType);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static String writeValueAsString(Object input) {
|
||||
return MAPPER.writeValueAsString(input);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.miti99.storescraperbot.api.apple;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.miti99.storescraperbot.api.apple.request.AppleAppRequest;
|
||||
import com.miti99.storescraperbot.util.JacksonUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AppStoreScraperTest {
|
||||
@Test
|
||||
void testApp() {
|
||||
var request = new AppleAppRequest("com.mpt.kvtm");
|
||||
var response = AppStoreScraper.app(request);
|
||||
System.out.println(JacksonUtil.writeValueAsString(response));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.miti99.storescraperbot.api.google;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import com.miti99.storescraperbot.api.google.request.GoogleAppRequest;
|
||||
import com.miti99.storescraperbot.util.JacksonUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class GooglePlayScraperTest {
|
||||
@Test
|
||||
void testApp() {
|
||||
var request = new GoogleAppRequest("vn.kvtm.js");
|
||||
var response = GooglePlayScraper.app(request);
|
||||
System.out.println(JacksonUtil.writeValueAsString(response));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user