diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 4ba6ec6..0000000 --- a/.dockerignore +++ /dev/null @@ -1,47 +0,0 @@ -**/.DS_Store -**/.classpath -**/.dockerignore -**/.env -**/.factorypath -**/.git -**/.gitignore -**/.idea -**/.project -**/.sts4-cache -**/.settings -**/.toolstarget -**/.vs -**/.vscode -**/.next -**/.cache -**/*.dbmdl -**/*.jfm -**/charts -**/docker-compose* -**/compose.y*ml -**/Dockerfile* -**/secrets.dev.yaml -**/values.dev.yaml -**/vendor -LICENSE -README.md -**/*.class -**/*.iml -**/*.ipr -**/*.iws -**/*.log -**/.apt_generated -**/.gradle -**/.gradletasknamecache -**/.nb-gradle -**/.springBeans -**/build -**/dist -**/gradle-app.setting -**/nbbuild -**/nbdist -**/nbproject/private -*.ctxt -.mtj.tmp -hs_err_pid* -replay_pid* \ No newline at end of file diff --git a/.env.example b/.env.example deleted file mode 100644 index a8fa09e..0000000 --- a/.env.example +++ /dev/null @@ -1,24 +0,0 @@ -# Copy this file to .env and customize the values for your environment -# cp .env.example .env - -# MongoDB configuration -MONGODB_CONNECTION_STRING=mongodb://localhost:27017/store-scraper-bot - -# Telegram Bot configuration -TELEGRAM_BOT_TOKEN=your_telegram_bot_token -TELEGRAM_BOT_USERNAME=your_telegram_bot_username - -# Java configuration -JAVA_OPTS=-Xmx512m - -# Logging configuration -LOG_LEVEL=INFO - -LOKI_HOST=logs-prod-020.grafana.net -LOKI_PORT=443 -LOKI_USERNAME=your_loki_username -LOKI_PASSWORD=your_loki_password - -# App configuration -ENV=DEVELOPMENT -ADMIN_IDS=1000001999,1000002000,1000002001 diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 417cfbe..0000000 --- a/.gitattributes +++ /dev/null @@ -1,6 +0,0 @@ -* text=auto - -*.java text eol=crlf - -*.sh text eol=lf -gradlew text eol=lf diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 12ad9c9..0000000 --- a/.gitignore +++ /dev/null @@ -1,48 +0,0 @@ -.idea -.env - - - -.gradle -build/ -!gradle/wrapper/gradle-wrapper.jar -!**/src/main/**/build/ -!**/src/test/**/build/ -.kotlin - -### IntelliJ IDEA ### -.idea/modules.xml -.idea/jarRepositories.xml -.idea/compiler.xml -.idea/libraries/ -*.iws -*.iml -*.ipr -out/ -!**/src/main/**/out/ -!**/src/test/**/out/ - -### Eclipse ### -.apt_generated -.classpath -.factorypath -.project -.settings -.springBeans -.sts4-cache -bin/ -!**/src/main/**/bin/ -!**/src/test/**/bin/ - -### NetBeans ### -/nbproject/private/ -/nbbuild/ -/dist/ -/nbdist/ -/.nb-gradle/ - -### VS Code ### -.vscode/ - -### Mac OS ### -.DS_Store diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index b3100cb..0000000 --- a/Dockerfile +++ /dev/null @@ -1,30 +0,0 @@ -FROM eclipse-temurin:21.0.9_10-jdk-alpine AS deps -WORKDIR /build -COPY --chmod=0755 gradlew gradlew -COPY gradle/ gradle/ -COPY build.gradle.kts settings.gradle.kts ./ -RUN --mount=type=cache,target=/root/.gradle \ - ./gradlew dependencies -x check -x test --no-daemon --parallel --build-cache - -FROM deps AS package -WORKDIR /build -COPY ./src src/ -RUN --mount=type=cache,target=/root/.gradle \ - ./gradlew distTar -x check -x test --no-daemon --parallel --build-cache && \ - mv build/distributions/*.tar app.tar - -FROM eclipse-temurin:21.0.9_10-jre-alpine AS final -ARG UID=10001 -RUN adduser \ - --disabled-password \ - --gecos "" \ - --home "/nonexistent" \ - --shell "/sbin/nologin" \ - --no-create-home \ - --uid "${UID}" \ - appuser -USER appuser -WORKDIR /app -COPY --from=package /build/app.tar app.tar -RUN tar -xf app.tar --strip-components=1 && rm app.tar -ENTRYPOINT ["sh", "-c", "cd /app && ./bin/store-scraper-bot"] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 261eeb9..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/README.md b/README.md deleted file mode 100644 index b19d497..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# store-scraper-bot - -Telegram bot that support scrape infos of an app on stores diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index bf242da..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,61 +0,0 @@ -plugins { - application - idea - java -} - -group = "com.miti99" -version = "1.0-SNAPSHOT" - -application { - mainClass = "com.miti99.storescraperbot.Main" -} - -configurations { - compileOnly { - extendsFrom(configurations.annotationProcessor.get()) - } - testCompileOnly { - extendsFrom(configurations.testAnnotationProcessor.get()) - } -} - -dependencies { - annotationProcessor("org.projectlombok:lombok:1.18.36") - implementation("com.google.code.gson:gson:2.11.0") - implementation("com.google.guava:guava:33.4.0-jre") - implementation("org.apache.commons:commons-math3:3.6.1") - implementation("org.apache.logging.log4j:log4j-core:2.24.3") - implementation("org.apache.logging.log4j:log4j-slf4j2-impl:2.24.3") - implementation("org.mongodb:mongodb-driver-sync:5.2.1") - implementation("org.telegram:telegrambots-client:8.0.0") - implementation("org.telegram:telegrambots-extensions:8.0.0") - implementation("org.telegram:telegrambots-longpolling:8.0.0") - implementation("pl.tkowalcz.tjahzi:log4j2-appender-nodep:0.9.32") - - 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") -} - -idea { - module { - isDownloadJavadoc = true - isDownloadSources = true - } -} - -java { - toolchain { - languageVersion.set(JavaLanguageVersion.of(21)) - } -} - -repositories { - mavenCentral() -} - -tasks.test { - useJUnitPlatform() -} diff --git a/compose.dev.yml b/compose.dev.yml deleted file mode 100644 index 45a9979..0000000 --- a/compose.dev.yml +++ /dev/null @@ -1,13 +0,0 @@ -services: - mongodb: - image: mongo:7.0 - env_file: - - .env - ports: - - "27017:27017" - volumes: - - mongodb_data:/data/db - restart: unless-stopped - -volumes: - mongodb_data: \ No newline at end of file diff --git a/compose.yml b/compose.yml deleted file mode 100644 index c6504ba..0000000 --- a/compose.yml +++ /dev/null @@ -1,7 +0,0 @@ -services: - server: - build: - context: . - -# If you need database, add database service -# Check compose.dev.yml for example diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 249e583..0000000 Binary files a/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 9de918f..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sun Oct 26 00:05:31 ICT 2025 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew deleted file mode 100644 index 1b6c787..0000000 --- a/gradlew +++ /dev/null @@ -1,234 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015-2021 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" -APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat deleted file mode 100644 index 107acd3..0000000 --- a/gradlew.bat +++ /dev/null @@ -1,89 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/lombok.config b/lombok.config deleted file mode 100644 index 9bb7a6e..0000000 --- a/lombok.config +++ /dev/null @@ -1,12 +0,0 @@ -lombok.addLombokGeneratedAnnotation = true -lombok.experimental.flagUsage = error -lombok.log.apacheCommons.flagUsage = error -lombok.log.flogger.flagUsage = error -lombok.log.javaUtilLogging.flagUsage = error -lombok.log.jbosslog.flagUsage = error -lombok.log.log4j.flagUsage = error -lombok.log.slf4j.flagUsage = error -lombok.log.xslf4j.flagUsage = error -lombok.synchronized.flagUsage = error -lombok.val.flagUsage = error -lombok.var.flagUsage = error diff --git a/settings.gradle.kts b/settings.gradle.kts deleted file mode 100644 index 9fafd53..0000000 --- a/settings.gradle.kts +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = "store-scraper-bot" \ No newline at end of file diff --git a/src/main/java/com/miti99/storescraperbot/Main.java b/src/main/java/com/miti99/storescraperbot/Main.java deleted file mode 100644 index af309fe..0000000 --- a/src/main/java/com/miti99/storescraperbot/Main.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.miti99.storescraperbot; - -import static com.miti99.storescraperbot.constant.Constant.SCHEDULE_CHECK_APP_TIME; -import static com.miti99.storescraperbot.constant.Constant.SECONDS_PER_DAY; -import static com.miti99.storescraperbot.constant.Constant.VIETNAM_ZONE_ID; -import static com.miti99.storescraperbot.env.Environment.CREATOR_ID; -import static com.miti99.storescraperbot.env.Environment.SOURCE_COMMIT; - -import com.miti99.storescraperbot.bot.StoreScrapeBot; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.env.Environment; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.type.Env; -import com.miti99.storescraperbot.util.SchedulerUtil; -import java.time.Duration; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.util.concurrent.TimeUnit; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.longpolling.TelegramBotsLongPollingApplication; - -@Log4j2 -public class Main { - - public static void main(String[] args) { - AdminRepository.INSTANCE.init(); - - try (var botsApplication = new TelegramBotsLongPollingApplication()) { - botsApplication.registerBot(Environment.TELEGRAM_BOT_TOKEN, StoreScrapeBot.INSTANCE); - log.info("Bot started! Version {}", SOURCE_COMMIT); - if (Environment.ENV == Env.PRODUCTION) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - CREATOR_ID, "Bot started! Version %s".formatted(SOURCE_COMMIT)); - } - scheduleCheckApp(); - Thread.currentThread().join(); - } catch (Exception e) { - log.error("Error while running bot", e); - } - } - - private static void scheduleCheckApp() { - var now = LocalDateTime.now(); - - var checkTime = - LocalDateTime.of(LocalDate.now(VIETNAM_ZONE_ID), SCHEDULE_CHECK_APP_TIME) - .atZone(VIETNAM_ZONE_ID) - .withZoneSameInstant(ZoneId.systemDefault()) - .toLocalDateTime(); - long initialDelay = Duration.between(now, checkTime).getSeconds(); - if (initialDelay < 0) { - initialDelay += SECONDS_PER_DAY; - } - SchedulerUtil.SCHEDULER.scheduleAtFixedRate( - StoreScrapeBot.INSTANCE::runCheckApp, initialDelay, SECONDS_PER_DAY, TimeUnit.SECONDS); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/api/apple/AppStoreScraper.java b/src/main/java/com/miti99/storescraperbot/api/apple/AppStoreScraper.java deleted file mode 100644 index 842779e..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/apple/AppStoreScraper.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.miti99.storescraperbot.api.apple; - -import com.miti99.storescraperbot.api.apple.request.AppleAppRequest; -import com.miti99.storescraperbot.api.apple.response.AppleAppResponse; -import com.miti99.storescraperbot.constant.Constant; -import com.miti99.storescraperbot.model.AppleApp; -import com.miti99.storescraperbot.repository.AppleAppRepository; -import com.miti99.storescraperbot.util.GsonUtil; -import com.miti99.storescraperbot.util.Time; -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 java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; - -@Log4j2 -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class AppStoreScraper { - public static final String BASE_URL = "https://store-scraper.vercel.app/apple/"; - - @SneakyThrows - public static String rawApp(AppleAppRequest request) { - var httpRequest = - HttpRequest.newBuilder() - .uri(URI.create(BASE_URL + "/app")) - // .timeout(Duration.ofMillis(TIMEOUT)) - .header("Content-Type", "application/json") - .POST(BodyPublishers.ofString(GsonUtil.toJson(request))) - .build(); - - try (var httpClient = - HttpClient.newBuilder() - .followRedirects(Redirect.NORMAL) - // .connectTimeout(Duration.ofMillis(TIMEOUT)) - .build()) { - return httpClient.send(httpRequest, BodyHandlers.ofString()).body(); - } catch (Exception e) { - log.error("rawAppResponse error - request: '{}'", GsonUtil.toJson(request), e); - return null; - } - } - - @SneakyThrows - public static AppleAppResponse app(AppleAppRequest request) { - return GsonUtil.fromJson(rawApp(request), AppleAppResponse.class); - } - - public static AppleAppResponse getAppResponse(String appId, String country) { - long now = Time.currentTimeMillis(); - AppleApp app = null; - if (AppleAppRepository.INSTANCE.exist(appId)) { - app = AppleAppRepository.INSTANCE.load(appId); - if (now - app.getMillis() > Constant.APP_CACHE_MILLIS) { - app = null; - } - } - if (app == null) { - var response = app(new AppleAppRequest(appId, country)); - AppleAppRepository.INSTANCE.init(appId); - app = AppleAppRepository.INSTANCE.load(appId); - app.setApp(response); - app.setMillis(now); - AppleAppRepository.INSTANCE.save(appId, app); - } - return app.getApp(); - } - - public static LocalDate getAppUpdated(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return LocalDate.ofInstant(Instant.ofEpochMilli(0), ZoneId.systemDefault()); - } - return LocalDate.ofInstant(Instant.parse(response.updated()), ZoneId.systemDefault()); - } - - public static double getAppScore(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return 0.0; - } - return response.score(); - } - - public static long getAppReviews(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return 0L; - } - return response.reviews(); - } - - public static long getAppRatings(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return 0L; - } - return response.ratings(); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/api/apple/request/AppleAppRequest.java b/src/main/java/com/miti99/storescraperbot/api/apple/request/AppleAppRequest.java deleted file mode 100644 index 19f5f22..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/apple/request/AppleAppRequest.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.miti99.storescraperbot.api.apple.request; - -public record AppleAppRequest(Long id, String appId, String country, Boolean ratings) { - - public AppleAppRequest(Long id, String country) { - this(id, null, country, true); - } - - public AppleAppRequest(String appId, String country) { - this(null, appId, country, true); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/api/apple/response/AppleAppResponse.java b/src/main/java/com/miti99/storescraperbot/api/apple/response/AppleAppResponse.java deleted file mode 100644 index 535bfa8..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/apple/response/AppleAppResponse.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.miti99.storescraperbot.api.apple.response; - -import java.util.List; -import java.util.Map; - -public record AppleAppResponse( - long id, - String appId, - String title, - String url, - String description, - String icon, - List genres, - List genreIds, - String primaryGenre, - int primaryGenreId, - String contentRating, - List languages, - String size, - String requiredOsVersion, - String released, - String updated, - String releaseNotes, - String version, - double price, - String currency, - boolean free, - long developerId, - String developer, - String developerUrl, - String developerWebsite, - double score, - int reviews, - double currentVersionScore, - int currentVersionReviews, - List screenshots, - List ipadScreenshots, - List appletvScreenshots, - List supportedDevices, - long ratings, - Map histogram) {} diff --git a/src/main/java/com/miti99/storescraperbot/api/google/GooglePlayScraper.java b/src/main/java/com/miti99/storescraperbot/api/google/GooglePlayScraper.java deleted file mode 100644 index f191e63..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/google/GooglePlayScraper.java +++ /dev/null @@ -1,112 +0,0 @@ -package com.miti99.storescraperbot.api.google; - -import com.miti99.storescraperbot.api.google.request.GoogleAppRequest; -import com.miti99.storescraperbot.api.google.response.GoogleAppResponse; -import com.miti99.storescraperbot.constant.Constant; -import com.miti99.storescraperbot.model.GoogleApp; -import com.miti99.storescraperbot.repository.GoogleAppRepository; -import com.miti99.storescraperbot.util.GsonUtil; -import com.miti99.storescraperbot.util.Time; -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 java.time.Instant; -import java.time.LocalDate; -import java.time.ZoneId; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; - -@Log4j2 -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class GooglePlayScraper { - public static final String BASE_URL = "https://store-scraper.vercel.app/google/"; - - @SneakyThrows - public static String rawApp(GoogleAppRequest request) { - var httpRequest = - HttpRequest.newBuilder() - .uri(URI.create(BASE_URL + "/app")) - // .timeout(Duration.ofMillis(TIMEOUT)) - .header("Content-Type", "application/json") - .POST(BodyPublishers.ofString(GsonUtil.toJson(request))) - .build(); - - try (var httpClient = - HttpClient.newBuilder() - // .connectTimeout(Duration.ofMillis(TIMEOUT)) - .followRedirects(Redirect.NORMAL) - .build()) { - return httpClient.send(httpRequest, BodyHandlers.ofString()).body(); - } catch (Exception e) { - log.error("rawAppResponse error - request: '{}'", GsonUtil.toJson(request), e); - return null; - } - } - - public static GoogleAppResponse app(GoogleAppRequest request) { - return GsonUtil.fromJson(rawApp(request), GoogleAppResponse.class); - } - - private static GoogleAppResponse getAppResponse(String appId, String country) { - long now = Time.currentTimeMillis(); - GoogleApp app = null; - if (GoogleAppRepository.INSTANCE.exist(appId)) { - app = GoogleAppRepository.INSTANCE.load(appId); - if (now - app.getMillis() > Constant.APP_CACHE_MILLIS) { - app = null; - } - } - if (app == null) { - var response = app(new GoogleAppRequest(appId, country)); - GoogleAppRepository.INSTANCE.init(appId); - app = GoogleAppRepository.INSTANCE.load(appId); - app.setApp(response); - app.setMillis(now); - GoogleAppRepository.INSTANCE.save(appId, app); - } - return app.getApp(); - } - - public static LocalDate getLastUpdateOfApp(String appId, String country) { - var response = getAppResponse(appId, country); - long lastUpdateMillis = 0; - if (response != null) { - lastUpdateMillis = response.updated(); - } else { - log.error("response is null"); - } - return LocalDate.ofInstant(Instant.ofEpochMilli(lastUpdateMillis), ZoneId.systemDefault()); - } - - public static double getAppScore(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return 0.0; - } - return response.score(); - } - - public static String getAppScoreText(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return ""; - } - return response.scoreText(); - } - - public static long getAppRatings(String appId, String country) { - var response = getAppResponse(appId, country); - if (response == null) { - log.error("response is null"); - return 0L; - } - return response.ratings(); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/api/google/request/GoogleAppRequest.java b/src/main/java/com/miti99/storescraperbot/api/google/request/GoogleAppRequest.java deleted file mode 100644 index 4c2066a..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/google/request/GoogleAppRequest.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.miti99.storescraperbot.api.google.request; - -public record GoogleAppRequest(String appId, String country) { - public GoogleAppRequest(String appId) { - this(appId, "vn"); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/api/google/response/GoogleAppResponse.java b/src/main/java/com/miti99/storescraperbot/api/google/response/GoogleAppResponse.java deleted file mode 100644 index 7e9c2ef..0000000 --- a/src/main/java/com/miti99/storescraperbot/api/google/response/GoogleAppResponse.java +++ /dev/null @@ -1,67 +0,0 @@ -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 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 categories, - String icon, - String headerImage, - List screenshots, - String video, - String videoImage, - String previewVideo, - String contentRating, - String contentRatingDescription, - boolean adSupported, - String released, - long updated, - String version, - String recentChanges, - List comments, - boolean preregister, - boolean earlyAccessEnabled, - boolean isAvailableInPlayPass, - boolean editorsChoice, - List features, - String appId, - String url) { - - public record Category(String name, String id) {} - - public record Feature(String title, String description) {} -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBot.java b/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBot.java deleted file mode 100644 index c69a3e3..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBot.java +++ /dev/null @@ -1,176 +0,0 @@ -package com.miti99.storescraperbot.bot; - -import static com.miti99.storescraperbot.constant.Constant.VIETNAM_ZONE_ID; -import static com.miti99.storescraperbot.constant.Constant.WEEKENDS; - -import com.miti99.storescraperbot.api.apple.AppStoreScraper; -import com.miti99.storescraperbot.api.google.GooglePlayScraper; -import com.miti99.storescraperbot.bot.command.AddAppleAppCommand; -import com.miti99.storescraperbot.bot.command.AddGoogleAppCommand; -import com.miti99.storescraperbot.bot.command.AddGroupCommand; -import com.miti99.storescraperbot.bot.command.CheckAppCommand; -import com.miti99.storescraperbot.bot.command.CheckAppScoreCommand; -import com.miti99.storescraperbot.bot.command.DeleteAppleAppCommand; -import com.miti99.storescraperbot.bot.command.DeleteGoogleAppCommand; -import com.miti99.storescraperbot.bot.command.DeleteGroupCommand; -import com.miti99.storescraperbot.bot.command.InfoCommand; -import com.miti99.storescraperbot.bot.command.ListAppCommand; -import com.miti99.storescraperbot.bot.command.ListGroupCommand; -import com.miti99.storescraperbot.bot.command.RawAppleAppCommand; -import com.miti99.storescraperbot.bot.command.RawGoogleAppCommand; -import com.miti99.storescraperbot.bot.entity.NonUpdatedApp; -import com.miti99.storescraperbot.bot.table.Table; -import com.miti99.storescraperbot.constant.Constant; -import com.miti99.storescraperbot.env.Environment; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; -import java.util.ArrayList; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.extensions.bots.commandbot.CommandLongPollingTelegramBot; -import org.telegram.telegrambots.meta.api.methods.ParseMode; -import org.telegram.telegrambots.meta.api.methods.commands.SetMyCommands; -import org.telegram.telegrambots.meta.api.methods.send.SendMessage; -import org.telegram.telegrambots.meta.api.objects.Update; -import org.telegram.telegrambots.meta.api.objects.commands.BotCommand; -import org.telegram.telegrambots.meta.exceptions.TelegramApiException; - -@Log4j2 -public class StoreScrapeBot extends CommandLongPollingTelegramBot { - public static final StoreScrapeBot INSTANCE = new StoreScrapeBot(); - - StoreScrapeBot() { - super(StoreScrapeBotTelegramClient.INSTANCE, true, StoreScrapeBotUsernameSupplier.INSTANCE); - register(InfoCommand.INSTANCE); - - register(RawAppleAppCommand.INSTANCE); - register(RawGoogleAppCommand.INSTANCE); - - register(AddGroupCommand.INSTANCE); - register(DeleteGroupCommand.INSTANCE); - register(ListGroupCommand.INSTANCE); - - register(AddAppleAppCommand.INSTANCE); - register(DeleteAppleAppCommand.INSTANCE); - register(AddGoogleAppCommand.INSTANCE); - register(DeleteAppleAppCommand.INSTANCE); - register(DeleteGoogleAppCommand.INSTANCE); - register(ListAppCommand.INSTANCE); - register(CheckAppCommand.INSTANCE); - register(CheckAppScoreCommand.INSTANCE); - setMyCommands(); - } - - private void setMyCommands() { - try { - var commands = - getRegisteredCommands().stream() - .map(cmd -> new BotCommand(cmd.getCommandIdentifier(), cmd.getDescription())) - .toList(); - var setMyCommands = SetMyCommands.builder().commands(commands).build(); - StoreScrapeBotTelegramClient.INSTANCE.execute(setMyCommands); - } catch (TelegramApiException e) { - log.error("register error", e); - } - } - - @Override - public void processNonCommandUpdate(Update update) { - // Ignore - } - - public void runCheckApp() { - try { - var admin = AdminRepository.INSTANCE.load(); - for (var groupId : admin.getGroups()) { - try { - checkAppForGroup(groupId); - } catch (Exception e) { - log.error("runCheckApp error - groupId: {}", groupId, e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - Environment.CREATOR_ID, "runCheckApp error - groupId: %d".formatted(groupId)); - } - } - } catch (Exception e) { - log.error("runCheckApp error", e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - Environment.CREATOR_ID, "runCheckApp error"); - } - } - - public void checkAppForGroup(long groupId) { - var group = GroupRepository.INSTANCE.load(groupId); - var now = LocalDate.now(); - - var nonUpdatedAppleApps = new ArrayList(); - for (var app : group.getAppleApps()) { - var appId = app.appId(); - var updated = AppStoreScraper.getAppUpdated(appId, app.country()); - long days = ChronoUnit.DAYS.between(updated, now); - if (days > Constant.NUM_DAYS_WARNING_NOT_UPDATED) { - nonUpdatedAppleApps.add(new NonUpdatedApp(appId, updated, days)); - } - } - var nonUpdatedGoogleApps = new ArrayList(); - for (var app : group.getGoogleApps()) { - var appId = app.appId(); - var updated = GooglePlayScraper.getLastUpdateOfApp(appId, app.country()); - long days = ChronoUnit.DAYS.between(updated, now); - if (days > Constant.NUM_DAYS_WARNING_NOT_UPDATED) { - nonUpdatedGoogleApps.add(new NonUpdatedApp(appId, updated, days)); - } - } - int numNonUpdatedApps = nonUpdatedAppleApps.size() + nonUpdatedGoogleApps.size(); - if (numNonUpdatedApps == 0) return; - - var sb = - new StringBuilder("You have %d app(s) need to be updated!\n".formatted(numNonUpdatedApps)); - if (!nonUpdatedAppleApps.isEmpty()) { - sb.append("%d Apple Apps:\n".formatted(nonUpdatedAppleApps.size())); - sb.append("\n"); - var appleTable = new Table("#", "AppId", "Updated", "Days"); - int i = 0; - for (var app : nonUpdatedAppleApps) { - i++; - var appId = app.appId(); - var updated = app.updated(); - long days = app.days(); - appleTable.addRow(i, appId, updated, days); - } - sb.append(appleTable); - sb.append("\n"); - } - - if (!nonUpdatedGoogleApps.isEmpty()) { - sb.append("%d Google Apps:\n".formatted(nonUpdatedGoogleApps.size())); - sb.append("\n"); - var googleTable = new Table("#", "AppId", "Updated", "Days"); - int i = 0; - for (var app : nonUpdatedGoogleApps) { - i++; - var appId = app.appId(); - var updated = app.updated(); - long days = app.days(); - googleTable.addRow(i, appId, updated, days); - } - sb.append(googleTable); - sb.append(""); - } - - var dayOfWeek = LocalDate.now(VIETNAM_ZONE_ID).getDayOfWeek(); - boolean mute = WEEKENDS.contains(dayOfWeek); - try { - var sendMessage = - SendMessage.builder() - .parseMode(ParseMode.HTML) - .chatId(groupId) - .disableNotification(mute) - .text(sb.toString()) - .build(); - StoreScrapeBotTelegramClient.INSTANCE.execute(sendMessage); - } catch (Exception e) { - log.error("sendMessage error", e); - } - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotTelegramClient.java b/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotTelegramClient.java deleted file mode 100644 index 6703f47..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotTelegramClient.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.miti99.storescraperbot.bot; - -import com.miti99.storescraperbot.env.Environment; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.client.okhttp.OkHttpTelegramClient; -import org.telegram.telegrambots.meta.api.methods.ParseMode; -import org.telegram.telegrambots.meta.api.methods.send.SendMessage; - -@Log4j2 -public class StoreScrapeBotTelegramClient extends OkHttpTelegramClient { - public static final StoreScrapeBotTelegramClient INSTANCE = new StoreScrapeBotTelegramClient(); - - public StoreScrapeBotTelegramClient() { - super(Environment.TELEGRAM_BOT_TOKEN); - } - - public void sendMessage(long chatId, String text) { - try { - var sendMessage = - SendMessage.builder().parseMode(ParseMode.HTML).chatId(chatId).text(text).build(); - execute(sendMessage); - } catch (Exception e) { - log.error("sendMessage error", e); - } - } - - public void sendMessage(long chatId, int threadId, String text) { - try { - var sendMessage = - SendMessage.builder() - .parseMode(ParseMode.HTML) - .chatId(chatId) - .messageThreadId(threadId) - .text(text) - .build(); - execute(sendMessage); - } catch (Exception e) { - log.error("sendMessage error", e); - } - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotUsernameSupplier.java b/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotUsernameSupplier.java deleted file mode 100644 index 8d3ea74..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/StoreScrapeBotUsernameSupplier.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.miti99.storescraperbot.bot; - -import com.miti99.storescraperbot.env.Environment; -import java.util.function.Supplier; - -public class StoreScrapeBotUsernameSupplier implements Supplier { - public static final StoreScrapeBotUsernameSupplier INSTANCE = - new StoreScrapeBotUsernameSupplier(); - - @Override - public String get() { - return Environment.TELEGRAM_BOT_USERNAME; - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/AddAppleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/AddAppleAppCommand.java deleted file mode 100644 index 6c355d4..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/AddAppleAppCommand.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.apple.AppStoreScraper; -import com.miti99.storescraperbot.api.apple.request.AppleAppRequest; -import com.miti99.storescraperbot.api.apple.response.AppleAppResponse; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.model.entity.AppleAppInfo; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -@Log4j2 -public class AddAppleAppCommand extends BaseStoreScraperBotCommand { - public static final AddAppleAppCommand INSTANCE = new AddAppleAppCommand(); - - AddAppleAppCommand() { - super( - "addapple", - " [country]. Thêm Apple app vào danh sách theo dõi của nhóm. Một số app cần country để hoạt động đúng, country mặc định là 'vn'"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length < 1 || arguments.length > 2) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - long id = -1; - var country = arguments.length == 2 ? arguments[1] : "vn"; - AppleAppResponse response = null; - try { - try { - id = Long.parseLong(appId); - } catch (Exception e) { - // Input không phải id, bỏ qua - } - if (id != -1) { - response = AppStoreScraper.app(new AppleAppRequest(id, country)); - } else { - response = AppStoreScraper.app(new AppleAppRequest(appId, country)); - } - } catch (Exception e) { - log.error("request app error for appId: '{}', id: '{}'", appId, id, e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Error when request app info"); - return; - } - appId = response.appId(); - - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - var finalAppId = appId; - if (group.getAppleApps().stream().anyMatch(app -> finalAppId.equals(app.appId()))) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Apple app %s is already added".formatted(appId)); - return; - } - - group.getAppleApps().add(new AppleAppInfo(appId, country)); - GroupRepository.INSTANCE.save(groupId, group); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), - "Apple app %s, country %s added successfully" - .formatted(appId, country)); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/AddGoogleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/AddGoogleAppCommand.java deleted file mode 100644 index cffd917..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/AddGoogleAppCommand.java +++ /dev/null @@ -1,68 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.google.GooglePlayScraper; -import com.miti99.storescraperbot.api.google.request.GoogleAppRequest; -import com.miti99.storescraperbot.api.google.response.GoogleAppResponse; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.model.entity.GoogleAppInfo; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -@Log4j2 -public class AddGoogleAppCommand extends BaseStoreScraperBotCommand { - public static final AddGoogleAppCommand INSTANCE = new AddGoogleAppCommand(); - - AddGoogleAppCommand() { - super( - "addgoogle", - " [country]. Thêm Google app vào danh sách theo dõi của nhóm. Một số app cần country để hoạt động đúng, country mặc định là 'vn'"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length < 1 || arguments.length > 2) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - var country = arguments.length == 2 ? arguments[1] : "vn"; - GoogleAppResponse response = null; - try { - response = GooglePlayScraper.app(new GoogleAppRequest(appId, country)); - } catch (Exception e) { - log.error("request app error for appId: '{}'", appId, e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Error when request app info"); - return; - } - - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - if (group.getGoogleApps().stream().anyMatch(app -> appId.equals(app.appId()))) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Google app %s is already added".formatted(appId)); - return; - } - - group.getGoogleApps().add(new GoogleAppInfo(appId, country)); - GroupRepository.INSTANCE.save(groupId, group); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), - "Google app %s, country %s added successfully" - .formatted(appId, country)); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/AddGroupCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/AddGroupCommand.java deleted file mode 100644 index 2e61d74..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/AddGroupCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.env.Environment; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class AddGroupCommand extends BaseStoreScraperBotCommand { - public static final AddGroupCommand INSTANCE = new AddGroupCommand(); - - AddGroupCommand() { - super("addgroup", ". Thêm group vào list group cho phép sử dụng bot"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - if (!Environment.ADMIN_IDS.contains(user.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "You are not admin"); - return; - } - - if (arguments.length > 1) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId; - if (arguments.length == 1) { - try { - groupId = Long.parseLong(arguments[0]); - } catch (NumberFormatException e) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid groupId"); - return; - } - } else { - groupId = chat.getId(); - } - - var admin = AdminRepository.INSTANCE.load(); - if (admin.getGroups().contains(groupId)) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Group is already added"); - return; - } - - GroupRepository.INSTANCE.init(groupId); - admin.getGroups().add(groupId); - AdminRepository.INSTANCE.save(admin); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Group added successfully"); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/BaseStoreScraperBotCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/BaseStoreScraperBotCommand.java deleted file mode 100644 index 8edfa27..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/BaseStoreScraperBotCommand.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.extensions.bots.commandbot.commands.BotCommand; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -@Log4j2 -public abstract class BaseStoreScraperBotCommand extends BotCommand { - - public BaseStoreScraperBotCommand(String commandIdentifier, String description) { - super(commandIdentifier, description); - } - - @Override - public void execute(TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - try { - executeCommand(telegramClient, user, chat, arguments); - } catch (Exception e) { - log.error("execute error", e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Internal server error"); - } - } - - protected abstract void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments); -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppCommand.java deleted file mode 100644 index 594b6a0..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppCommand.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.apple.AppStoreScraper; -import com.miti99.storescraperbot.api.google.GooglePlayScraper; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.bot.table.Table; -import com.miti99.storescraperbot.constant.Constant; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import java.time.LocalDate; -import java.time.temporal.ChronoUnit; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class CheckAppCommand extends BaseStoreScraperBotCommand { - public static final CheckAppCommand INSTANCE = new CheckAppCommand(); - - CheckAppCommand() { - super("checkapp", "Kiểm tra cập nhật các app"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length != 0) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - var now = LocalDate.now(); - - var sb = new StringBuilder(); - sb.append("Apple Apps:\n"); - sb.append("\n"); - var appleTable = new Table("AppId", "Updated", "Days", "OK"); - for (var app : group.getAppleApps()) { - var appId = app.appId(); - var updated = AppStoreScraper.getAppUpdated(appId, app.country()); - long days = ChronoUnit.DAYS.between(updated, now); - boolean passed = days <= Constant.NUM_DAYS_WARNING_NOT_UPDATED; - var icon = passed ? "✅" : "❌"; - appleTable.addRow(appId, updated, days, icon); - } - sb.append(appleTable); - sb.append("\n"); - - sb.append("Google Apps:\n"); - sb.append("\n"); - var googleTable = new Table("AppId", "Updated", "Days", "OK"); - for (var app : group.getGoogleApps()) { - var appId = app.appId(); - var updated = GooglePlayScraper.getLastUpdateOfApp(appId, app.country()); - long days = ChronoUnit.DAYS.between(updated, now); - boolean passed = days <= Constant.NUM_DAYS_WARNING_NOT_UPDATED; - var icon = passed ? "✅" : "❌"; - googleTable.addRow(appId, updated, days, icon); - } - sb.append(googleTable); - sb.append(""); - - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), sb.toString()); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppScoreCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppScoreCommand.java deleted file mode 100644 index 37b40d6..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/CheckAppScoreCommand.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.apple.AppStoreScraper; -import com.miti99.storescraperbot.api.google.GooglePlayScraper; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.bot.table.Table; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import org.apache.commons.math3.util.Precision; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class CheckAppScoreCommand extends BaseStoreScraperBotCommand { - public static final CheckAppScoreCommand INSTANCE = new CheckAppScoreCommand(); - public static final int SCORE_ROUNDING_SCALE = 1; - - CheckAppScoreCommand() { - super("checkappscore", "Kiểm tra điểm đánh giá các app (sao)"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length != 0) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - var sb = new StringBuilder(); - sb.append("Apple Apps:\n"); - sb.append("\n"); - var appleTable = new Table("AppId", "Score", "Ratings"); - for (var app : group.getAppleApps()) { - var appId = app.appId(); - var country = app.country(); - double score = - Precision.round(AppStoreScraper.getAppScore(appId, country), SCORE_ROUNDING_SCALE); - long ratings = AppStoreScraper.getAppRatings(appId, country); - appleTable.addRow(appId, score, ratings); - } - sb.append(appleTable); - sb.append("\n"); - - sb.append("Google Apps:\n"); - sb.append("\n"); - var googleTable = new Table("AppId", "Score", "Ratings"); - for (var app : group.getGoogleApps()) { - var appId = app.appId(); - var country = app.country(); - double score = - Precision.round(GooglePlayScraper.getAppScore(appId, country), SCORE_ROUNDING_SCALE); - long ratings = GooglePlayScraper.getAppRatings(appId, country); - googleTable.addRow(appId, score, ratings); - } - sb.append(googleTable); - sb.append(""); - - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), sb.toString()); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteAppleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/DeleteAppleAppCommand.java deleted file mode 100644 index baa9d1f..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteAppleAppCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class DeleteAppleAppCommand extends BaseStoreScraperBotCommand { - public static final DeleteAppleAppCommand INSTANCE = new DeleteAppleAppCommand(); - - DeleteAppleAppCommand() { - super("delapple", ". Xoá Apple app khỏi danh sách theo dõi của nhóm"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length != 1) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - if (group.getAppleApps().stream().noneMatch(app -> appId.equals(app.appId()))) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Apple app is not added"); - return; - } - - group.getAppleApps().removeIf(app -> appId.equals(app.appId())); - GroupRepository.INSTANCE.save(groupId, group); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Apple app deleted successfully"); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGoogleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGoogleAppCommand.java deleted file mode 100644 index 912e774..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGoogleAppCommand.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class DeleteGoogleAppCommand extends BaseStoreScraperBotCommand { - public static final DeleteGoogleAppCommand INSTANCE = new DeleteGoogleAppCommand(); - - DeleteGoogleAppCommand() { - super("delgoogle", ". Xoá Google app khỏi danh sách theo dõi của nhóm"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length != 1) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - if (group.getGoogleApps().stream().noneMatch(app -> appId.equals(app.appId()))) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Google app is not added"); - return; - } - - group.getGoogleApps().removeIf(app -> appId.equals(app.appId())); - GroupRepository.INSTANCE.save(groupId, group); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Google app deleted successfully"); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGroupCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGroupCommand.java deleted file mode 100644 index 5cfd9a6..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/DeleteGroupCommand.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.env.Environment; -import com.miti99.storescraperbot.repository.AdminRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class DeleteGroupCommand extends BaseStoreScraperBotCommand { - public static final DeleteGroupCommand INSTANCE = new DeleteGroupCommand(); - - DeleteGroupCommand() { - super("delgroup", ". Xoá group khỏi list group cho phép sử dụng bot"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - if (!Environment.ADMIN_IDS.contains(user.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "You are not admin"); - return; - } - - if (arguments.length > 1) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId; - if (arguments.length == 1) { - try { - groupId = Long.parseLong(arguments[0]); - } catch (NumberFormatException e) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid groupId"); - return; - } - } else { - groupId = chat.getId(); - } - - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(groupId)) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Group is not added"); - return; - } - - admin.getGroups().remove(groupId); - AdminRepository.INSTANCE.save(admin); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Group deleted successfully"); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/InfoCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/InfoCommand.java deleted file mode 100644 index c71ade9..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/InfoCommand.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class InfoCommand extends BaseStoreScraperBotCommand { - public static final InfoCommand INSTANCE = new InfoCommand(); - - InfoCommand() { - super("info", "Lấy thông tin của nhóm (chatId, threadId,...)"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - if (arguments.length != 0) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId = chat.getId(); - - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Id của nhóm là %s\n".formatted(groupId)); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/ListAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/ListAppCommand.java deleted file mode 100644 index 138fc77..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/ListAppCommand.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.bot.table.Table; -import com.miti99.storescraperbot.repository.AdminRepository; -import com.miti99.storescraperbot.repository.GroupRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class ListAppCommand extends BaseStoreScraperBotCommand { - public static final ListAppCommand INSTANCE = new ListAppCommand(); - - ListAppCommand() { - super("listapp", ". Lấy danh sách app đang theo dõi của nhóm"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length != 0) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - long groupId = chat.getId(); - var group = GroupRepository.INSTANCE.load(groupId); - - var sb = new StringBuilder(); - sb.append("Apple Apps:\n"); - sb.append("\n"); - var appleTable = new Table("#", "AppId", "Country"); - int i = 0; - for (var app : group.getAppleApps()) { - i++; - appleTable.addRow(i, app.appId(), app.country()); - } - sb.append(appleTable); - sb.append("\n"); - - sb.append("Google Apps:\n"); - sb.append("\n"); - var googleTable = new Table("#", "AppId", "Country"); - i = 0; - for (var app : group.getGoogleApps()) { - i++; - googleTable.addRow(i, app.appId(), app.country()); - } - sb.append(googleTable); - sb.append(""); - - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), sb.toString()); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/ListGroupCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/ListGroupCommand.java deleted file mode 100644 index bf1fe52..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/ListGroupCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.env.Environment; -import com.miti99.storescraperbot.repository.AdminRepository; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -public class ListGroupCommand extends BaseStoreScraperBotCommand { - public static final ListGroupCommand INSTANCE = new ListGroupCommand(); - - ListGroupCommand() { - super("listgroup", "Lấy danh sách group được phép sử dụng bot hiện tại"); - } - - @Override - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - if (!Environment.ADMIN_IDS.contains(user.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "You are not admin"); - return; - } - - if (arguments.length != 0) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var admin = AdminRepository.INSTANCE.load(); - var groups = admin.getGroups(); - var sb = new StringBuilder(); - sb.append("Groups:\n"); - for (var groupId : groups) { - sb.append("- %s\n".formatted(groupId)); - } - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), sb.toString()); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/RawAppleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/RawAppleAppCommand.java deleted file mode 100644 index 8bceae0..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/RawAppleAppCommand.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.apple.AppStoreScraper; -import com.miti99.storescraperbot.api.apple.request.AppleAppRequest; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.repository.AdminRepository; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.meta.api.methods.send.SendDocument; -import org.telegram.telegrambots.meta.api.objects.InputFile; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -@Log4j2 -public class RawAppleAppCommand extends BaseStoreScraperBotCommand { - public static final RawAppleAppCommand INSTANCE = new RawAppleAppCommand(); - - RawAppleAppCommand() { - super( - "rawappleapp", - " [country]. Lấy raw response khi request lên service. id: iTunes 'trackId', appId: iTunes 'bundleId'. Một số app cần country để hoạt động đúng, country mặc định là 'vn'"); - } - - @Override - @SneakyThrows - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length < 1 || arguments.length > 2) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - long id = -1; - var country = arguments.length == 2 ? arguments[1] : "vn"; - String response = ""; - try { - try { - id = Long.parseLong(appId); - } catch (Exception e) { - // Input không phải id, bỏ qua - } - if (id != -1) { - response = AppStoreScraper.rawApp(new AppleAppRequest(id, country)); - } else { - response = AppStoreScraper.rawApp(new AppleAppRequest(appId, country)); - } - } catch (Exception e) { - log.error("request app error for appId: '{}', id: '{}'", appId, id, e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Error when request app info"); - return; - } - - if (response == null) response = ""; - - var inputStream = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8)); - - var file = new InputFile(inputStream, "%s.json".formatted(appId)); - - var sendDocument = - SendDocument.builder() - .chatId(chat.getId()) - .document(file) - // .caption("raw") - .build(); - - StoreScrapeBotTelegramClient.INSTANCE.execute(sendDocument); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/command/RawGoogleAppCommand.java b/src/main/java/com/miti99/storescraperbot/bot/command/RawGoogleAppCommand.java deleted file mode 100644 index 7407d58..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/command/RawGoogleAppCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package com.miti99.storescraperbot.bot.command; - -import com.miti99.storescraperbot.api.google.GooglePlayScraper; -import com.miti99.storescraperbot.api.google.request.GoogleAppRequest; -import com.miti99.storescraperbot.bot.StoreScrapeBotTelegramClient; -import com.miti99.storescraperbot.repository.AdminRepository; -import java.io.ByteArrayInputStream; -import java.nio.charset.StandardCharsets; -import lombok.SneakyThrows; -import lombok.extern.log4j.Log4j2; -import org.telegram.telegrambots.meta.api.methods.send.SendDocument; -import org.telegram.telegrambots.meta.api.objects.InputFile; -import org.telegram.telegrambots.meta.api.objects.User; -import org.telegram.telegrambots.meta.api.objects.chat.Chat; -import org.telegram.telegrambots.meta.generics.TelegramClient; - -@Log4j2 -public class RawGoogleAppCommand extends BaseStoreScraperBotCommand { - public static final RawGoogleAppCommand INSTANCE = new RawGoogleAppCommand(); - - RawGoogleAppCommand() { - super( - "rawgoogleapp", - " [country]. Lấy raw response khi request lên service. Một số app cần country để hoạt động đúng, country mặc định là 'vn'"); - } - - @Override - @SneakyThrows - protected void executeCommand( - TelegramClient telegramClient, User user, Chat chat, String[] arguments) { - var admin = AdminRepository.INSTANCE.load(); - if (!admin.getGroups().contains(chat.getId())) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Group is not allowed to use bot"); - return; - } - - if (arguments.length < 1 || arguments.length > 2) { - StoreScrapeBotTelegramClient.INSTANCE.sendMessage(chat.getId(), "Invalid arguments"); - return; - } - - var appId = arguments[0]; - var country = arguments.length == 2 ? arguments[1] : "vn"; - String response = ""; - try { - response = GooglePlayScraper.rawApp(new GoogleAppRequest(appId, country)); - } catch (Exception e) { - log.error("request app error for appId: '{}'", appId, e); - StoreScrapeBotTelegramClient.INSTANCE.sendMessage( - chat.getId(), "Error when request app info"); - return; - } - if (response == null) response = ""; - - var inputStream = new ByteArrayInputStream(response.getBytes(StandardCharsets.UTF_8)); - - var file = new InputFile(inputStream, "%s.json".formatted(appId)); - - var sendDocument = - SendDocument.builder() - .chatId(chat.getId()) - .document(file) - // .caption("raw") - .build(); - - StoreScrapeBotTelegramClient.INSTANCE.execute(sendDocument); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/bot/entity/NonUpdatedApp.java b/src/main/java/com/miti99/storescraperbot/bot/entity/NonUpdatedApp.java deleted file mode 100644 index c3ba838..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/entity/NonUpdatedApp.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.miti99.storescraperbot.bot.entity; - -import java.time.LocalDate; - -public record NonUpdatedApp(String appId, LocalDate updated, long days) {} diff --git a/src/main/java/com/miti99/storescraperbot/bot/table/Table.java b/src/main/java/com/miti99/storescraperbot/bot/table/Table.java deleted file mode 100644 index 5350721..0000000 --- a/src/main/java/com/miti99/storescraperbot/bot/table/Table.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.miti99.storescraperbot.bot.table; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import kotlin.collections.ArrayDeque; - -public class Table { - private final String[] headers; - private final List rows = new ArrayDeque<>(); - - public Table(String... headers) { - this.headers = headers; - } - - public void addRow(Object... objs) { - if (objs.length != headers.length) { - throw new IllegalArgumentException( - "objs.length (%d) != headers.length (%d)".formatted(objs.length, headers.length)); - } - var row = new String[objs.length]; - for (int i = 0; i < objs.length; i++) { - row[i] = String.valueOf(objs[i]); - } - rows.add(row); - } - - @Override - public String toString() { - int[] maxWidths = new int[headers.length]; - for (int i = 0; i < headers.length; i++) { - maxWidths[i] = headers[i].length(); - } - for (var row : rows) { - for (int i = 0; i < row.length; i++) { - maxWidths[i] = Math.max(maxWidths[i], row[i].length()); - } - } - var formater = - Arrays.stream(maxWidths) - .mapToObj(width -> "%-" + width + "s") - .collect(Collectors.joining(" │ ", "", "\n")); - var sb = new StringBuilder(); - sb.append(formater.formatted((Object[]) headers)); - var rule = - Arrays.stream(maxWidths).mapToObj("─"::repeat).collect(Collectors.joining("─┼─", "", "\n")); - int i = 0; - for (var row : rows) { - if (i % 5 == 0) { - sb.append(rule); - } - sb.append(formater.formatted((Object[]) row)); - i++; - } - return sb.toString(); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/constant/Constant.java b/src/main/java/com/miti99/storescraperbot/constant/Constant.java deleted file mode 100644 index 0b8cad5..0000000 --- a/src/main/java/com/miti99/storescraperbot/constant/Constant.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.miti99.storescraperbot.constant; - -import java.time.DayOfWeek; -import java.time.LocalTime; -import java.time.ZoneId; -import java.time.temporal.ChronoUnit; -import java.util.Set; - -public class Constant { - public static final long APP_CACHE_SECONDS = 600; - public static final long APP_CACHE_MILLIS = APP_CACHE_SECONDS * 1000; - public static final long NUM_DAYS_WARNING_NOT_UPDATED = 30; - public static final LocalTime SCHEDULE_CHECK_APP_TIME = LocalTime.of(7, 0); - - public static final String VIETNAM_ZONE_ID_STRING = "Asia/Ho_Chi_Minh"; - public static final ZoneId VIETNAM_ZONE_ID = ZoneId.of(VIETNAM_ZONE_ID_STRING); - public static final long SECONDS_PER_DAY = ChronoUnit.DAYS.getDuration().getSeconds(); - public static final Set WEEKENDS = Set.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY); - - public static final String DEFAULT_DATABASE_NAME = "store-scraper-bot"; -} diff --git a/src/main/java/com/miti99/storescraperbot/env/Environment.java b/src/main/java/com/miti99/storescraperbot/env/Environment.java deleted file mode 100644 index 2c89822..0000000 --- a/src/main/java/com/miti99/storescraperbot/env/Environment.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.miti99.storescraperbot.env; - -import com.google.common.base.Strings; -import com.miti99.storescraperbot.type.Env; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; - -public class Environment { - public static final String MONGODB_CONNECTION_STRING = System.getenv("MONGODB_CONNECTION_STRING"); - - public static final String TELEGRAM_BOT_TOKEN = System.getenv("TELEGRAM_BOT_TOKEN"); - public static final String TELEGRAM_BOT_USERNAME = System.getenv("TELEGRAM_BOT_USERNAME"); - - public static final Env ENV = Env.valueOf(System.getenv("ENV")); - public static final List ADMIN_IDS = - Optional.ofNullable(System.getenv("ADMIN_IDS")) - .map( - v -> - Arrays.stream(v.split(",")) - .map(String::trim) - .filter(s -> !s.isEmpty()) - .map(Long::parseLong) - .collect(Collectors.toList())) - .orElse(Collections.emptyList()); - public static final long CREATOR_ID = ADMIN_IDS.getFirst(); - - public static final String SOURCE_COMMIT = - Strings.isNullOrEmpty(System.getenv("SOURCE_COMMIT")) - ? "unknown" - : System.getenv("SOURCE_COMMIT"); -} diff --git a/src/main/java/com/miti99/storescraperbot/model/AbstractModel.java b/src/main/java/com/miti99/storescraperbot/model/AbstractModel.java deleted file mode 100644 index 1b816af..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/AbstractModel.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.miti99.storescraperbot.model; - -import com.google.gson.annotations.SerializedName; -import lombok.Getter; -import lombok.NoArgsConstructor; -import lombok.Setter; - -@Getter -@NoArgsConstructor -@Setter -public abstract class AbstractModel { - @SerializedName("_id") - protected String id; - - @SerializedName("class") - protected String clazz = getClass().getSimpleName(); - - public void setId(Object id) { - this.id = String.valueOf(id); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/model/Admin.java b/src/main/java/com/miti99/storescraperbot/model/Admin.java deleted file mode 100644 index a61b652..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/Admin.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.miti99.storescraperbot.model; - -import java.util.HashSet; -import java.util.Set; -import lombok.Getter; - -@Getter -public class Admin extends AbstractModel { - final Set groups = new HashSet<>(); -} diff --git a/src/main/java/com/miti99/storescraperbot/model/AppleApp.java b/src/main/java/com/miti99/storescraperbot/model/AppleApp.java deleted file mode 100644 index 7c9b2e3..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/AppleApp.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.miti99.storescraperbot.model; - -import com.miti99.storescraperbot.api.apple.response.AppleAppResponse; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class AppleApp extends AbstractModel { - AppleAppResponse app; - long millis; -} diff --git a/src/main/java/com/miti99/storescraperbot/model/GoogleApp.java b/src/main/java/com/miti99/storescraperbot/model/GoogleApp.java deleted file mode 100644 index a2d8fcc..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/GoogleApp.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.miti99.storescraperbot.model; - -import com.miti99.storescraperbot.api.google.response.GoogleAppResponse; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class GoogleApp extends AbstractModel { - GoogleAppResponse app; - long millis; -} diff --git a/src/main/java/com/miti99/storescraperbot/model/Group.java b/src/main/java/com/miti99/storescraperbot/model/Group.java deleted file mode 100644 index fd151e7..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/Group.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.miti99.storescraperbot.model; - -import com.miti99.storescraperbot.model.entity.AppleAppInfo; -import com.miti99.storescraperbot.model.entity.GoogleAppInfo; -import java.util.ArrayList; -import java.util.List; -import lombok.Getter; -import lombok.Setter; - -@Getter -@Setter -public class Group extends AbstractModel { - List appleApps = new ArrayList<>(); - List googleApps = new ArrayList<>(); -} diff --git a/src/main/java/com/miti99/storescraperbot/model/entity/AppleAppInfo.java b/src/main/java/com/miti99/storescraperbot/model/entity/AppleAppInfo.java deleted file mode 100644 index 5c10556..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/entity/AppleAppInfo.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.miti99.storescraperbot.model.entity; - -public record AppleAppInfo(String appId, String country) {} diff --git a/src/main/java/com/miti99/storescraperbot/model/entity/GoogleAppInfo.java b/src/main/java/com/miti99/storescraperbot/model/entity/GoogleAppInfo.java deleted file mode 100644 index 0b01dd0..0000000 --- a/src/main/java/com/miti99/storescraperbot/model/entity/GoogleAppInfo.java +++ /dev/null @@ -1,3 +0,0 @@ -package com.miti99.storescraperbot.model.entity; - -public record GoogleAppInfo(String appId, String country) {} diff --git a/src/main/java/com/miti99/storescraperbot/repository/AbstractCollectionRepository.java b/src/main/java/com/miti99/storescraperbot/repository/AbstractCollectionRepository.java deleted file mode 100644 index 53a9dd0..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/AbstractCollectionRepository.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.AbstractModel; -import lombok.extern.log4j.Log4j2; - -/** - * Các repository tương ứng với 1 MongoDB collection, public các method protected ở class - * AbstractRepository để các nơi khác gọi - */ -@Log4j2 -public abstract class AbstractCollectionRepository - extends AbstractRepository { - - @Override - public void init(K key) { - super.init(key); - } - - @Override - public void save(K key, V data) { - super.save(key, data); - } - - @Override - public boolean exist(K key) { - return super.exist(key); - } - - @Override - public V load(K key) { - return super.load(key); - } - - @Override - public void delete(K key) { - super.delete(key); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/AbstractRepository.java b/src/main/java/com/miti99/storescraperbot/repository/AbstractRepository.java deleted file mode 100644 index cd5c13a..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/AbstractRepository.java +++ /dev/null @@ -1,119 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import static com.miti99.storescraperbot.repository.AbstractSingletonRepository.COMMON_COLLECTION_NAME; - -import com.google.common.base.CaseFormat; -import com.miti99.storescraperbot.model.AbstractModel; -import com.miti99.storescraperbot.util.GsonUtil; -import com.miti99.storescraperbot.util.MongoDBUtil; -import com.mongodb.client.MongoCollection; -import com.mongodb.client.model.Filters; -import com.mongodb.client.model.ReplaceOptions; -import java.lang.reflect.ParameterizedType; -import lombok.extern.log4j.Log4j2; -import org.bson.Document; - -/** - * @param class Key - * @param class Value - */ -@Log4j2 -public abstract class AbstractRepository { - protected final Class classV = getDataClass(); - protected final String collectionName; - protected final MongoCollection collection; - - protected AbstractRepository(String collectionName) { - this.collectionName = collectionName; - MongoDBUtil.createCollectionIfNotExists(collectionName); - collection = MongoDBUtil.DATABASE.getCollection(collectionName, Document.class); - } - - protected AbstractRepository() { - collectionName = CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, classV.getSimpleName()); - if (COMMON_COLLECTION_NAME.equals(collectionName)) { - throw new RuntimeException( - "Collection named '%s' is reserved".formatted(COMMON_COLLECTION_NAME)); - } - MongoDBUtil.createCollectionIfNotExists(collectionName); - collection = MongoDBUtil.DATABASE.getCollection(collectionName, Document.class); - } - - /** - * Lấy ra class của V. Khi tạo 1 abstract class extends AbstractRepository mà không phải final thì - * sẽ cần override hàm này phù hợp - * - * @return Class<V> - */ - protected Class getDataClass() { - return (Class) - ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[1]; - } - - protected String encode(V data) { - return GsonUtil.toJson(data); - } - - protected V decode(String json) { - return GsonUtil.fromJson(json, classV); - } - - protected void init(K key) { - try { - if (exist(key)) { - return; - } - V data = classV.getDeclaredConstructor().newInstance(); - data.setId(key); - save(key, data); - } catch (Exception e) { - log.error("Error while initializing data", e); - } - } - - protected String getDatabaseKey(K key) { - return String.valueOf(key); - } - - protected void save(K key, V data) { - var databaseKey = getDatabaseKey(key); - try { - var json = encode(data); - var doc = Document.parse(json); - collection.replaceOne(Filters.eq("_id", databaseKey), doc, new ReplaceOptions().upsert(true)); - } catch (Exception e) { - log.error("save error - key {}, databaseKey {}", key, databaseKey, e); - } - } - - protected boolean exist(K key) { - var databaseKey = getDatabaseKey(key); - try { - return collection.countDocuments(Filters.eq("_id", databaseKey)) > 0; - } catch (Exception e) { - log.error("exist error - key {}, databaseKey {}", key, databaseKey, e); - return false; - } - } - - protected V load(K key) { - var databaseKey = getDatabaseKey(key); - try { - var doc = collection.find(Filters.eq("_id", databaseKey)).first(); - if (doc == null) return null; - return decode(doc.toJson()); - } catch (Exception e) { - log.error("load error - key {}, databaseKey {}", key, databaseKey, e); - return null; - } - } - - protected void delete(K key) { - var databaseKey = getDatabaseKey(key); - try { - collection.deleteOne(Filters.eq("_id", databaseKey)); - } catch (Exception e) { - log.error("delete error", e); - } - } -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/AbstractSingletonRepository.java b/src/main/java/com/miti99/storescraperbot/repository/AbstractSingletonRepository.java deleted file mode 100644 index 97cda57..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/AbstractSingletonRepository.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.AbstractModel; -import lombok.extern.log4j.Log4j2; - -/** - * Repository chỉ chứa 1 key duy nhất, public các method liên quan nhưng không cho truyền params - * vào. Các repository loại này được lưu trong 1 collection duy nhất là "common" - */ -@Log4j2 -public abstract class AbstractSingletonRepository - extends AbstractRepository { - - public static final String COMMON_COLLECTION_NAME = "common"; - protected final K key = getKey(); - - protected AbstractSingletonRepository() { - super(COMMON_COLLECTION_NAME); - } - - protected abstract K getKey(); - - public void init() { - init(key); - } - - public void save(V data) { - save(key, data); - } - - public boolean exist() { - return exist(key); - } - - public V load() { - return load(key); - } - - public void delete() { - delete(key); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/AdminRepository.java b/src/main/java/com/miti99/storescraperbot/repository/AdminRepository.java deleted file mode 100644 index 420cf6f..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/AdminRepository.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.Admin; - -public class AdminRepository extends AbstractSingletonRepository { - public static final AdminRepository INSTANCE = new AdminRepository(); - public static final String KEY = "admin"; - - @Override - protected String getKey() { - return KEY; - } -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/AppleAppRepository.java b/src/main/java/com/miti99/storescraperbot/repository/AppleAppRepository.java deleted file mode 100644 index 4f703a8..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/AppleAppRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.AppleApp; - -public class AppleAppRepository extends AbstractCollectionRepository { - public static final AppleAppRepository INSTANCE = new AppleAppRepository(); -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/GoogleAppRepository.java b/src/main/java/com/miti99/storescraperbot/repository/GoogleAppRepository.java deleted file mode 100644 index dcdc7bb..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/GoogleAppRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.GoogleApp; - -public class GoogleAppRepository extends AbstractCollectionRepository { - public static final GoogleAppRepository INSTANCE = new GoogleAppRepository(); -} diff --git a/src/main/java/com/miti99/storescraperbot/repository/GroupRepository.java b/src/main/java/com/miti99/storescraperbot/repository/GroupRepository.java deleted file mode 100644 index 157f697..0000000 --- a/src/main/java/com/miti99/storescraperbot/repository/GroupRepository.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.miti99.storescraperbot.repository; - -import com.miti99.storescraperbot.model.Group; - -public class GroupRepository extends AbstractCollectionRepository { - public static final GroupRepository INSTANCE = new GroupRepository(); -} diff --git a/src/main/java/com/miti99/storescraperbot/type/Env.java b/src/main/java/com/miti99/storescraperbot/type/Env.java deleted file mode 100644 index 545fd01..0000000 --- a/src/main/java/com/miti99/storescraperbot/type/Env.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.miti99.storescraperbot.type; - -public enum Env { - DEVELOPMENT, - PRODUCTION -} diff --git a/src/main/java/com/miti99/storescraperbot/util/GsonUtil.java b/src/main/java/com/miti99/storescraperbot/util/GsonUtil.java deleted file mode 100644 index d8e5718..0000000 --- a/src/main/java/com/miti99/storescraperbot/util/GsonUtil.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.miti99.storescraperbot.util; - -import com.google.gson.Gson; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class GsonUtil { - public static final Gson GSON = new Gson(); - - public static T fromJson(String input, Class valueType) { - return GSON.fromJson(input, valueType); - } - - public static String toJson(Object input) { - return GSON.toJson(input); - } -} diff --git a/src/main/java/com/miti99/storescraperbot/util/MongoDBUtil.java b/src/main/java/com/miti99/storescraperbot/util/MongoDBUtil.java deleted file mode 100644 index 261acec..0000000 --- a/src/main/java/com/miti99/storescraperbot/util/MongoDBUtil.java +++ /dev/null @@ -1,67 +0,0 @@ -package com.miti99.storescraperbot.util; - -import static com.miti99.storescraperbot.env.Environment.MONGODB_CONNECTION_STRING; - -import com.miti99.storescraperbot.constant.Constant; -import com.mongodb.ConnectionString; -import com.mongodb.MongoClientSettings; -import com.mongodb.MongoException; -import com.mongodb.ServerApi; -import com.mongodb.ServerApiVersion; -import com.mongodb.client.MongoClient; -import com.mongodb.client.MongoClients; -import com.mongodb.client.MongoDatabase; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; -import lombok.extern.log4j.Log4j2; -import org.bson.Document; - -@Log4j2 -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MongoDBUtil { - public static final MongoClient MONGO_CLIENT; - public static final MongoDatabase DATABASE; - - static { - var serverApi = ServerApi.builder().version(ServerApiVersion.V1).build(); - var connectionString = new ConnectionString(MONGODB_CONNECTION_STRING); - var settings = - MongoClientSettings.builder() - .applyConnectionString(connectionString) - .serverApi(serverApi) - .build(); - MONGO_CLIENT = MongoClients.create(settings); - var databaseName = - connectionString.getDatabase() != null - ? connectionString.getDatabase() - : Constant.DEFAULT_DATABASE_NAME; - DATABASE = MONGO_CLIENT.getDatabase(databaseName); - try { - DATABASE.runCommand(new Document("ping", 1)); - log.info("Pinged your deployment. You successfully connected to MongoDB!"); - } catch (MongoException e) { - log.error(e); - } - } - - public static void createCollectionIfNotExists(String collectionName) { - try { - boolean collectionExists = false; - for (var name : DATABASE.listCollectionNames()) { - if (name.equals(collectionName)) { - collectionExists = true; - break; - } - } - - if (!collectionExists) { - DATABASE.createCollection(collectionName); - log.info("Collection created: {}", collectionName); - } else { - log.info("Collection existed: {}", collectionName); - } - } catch (Exception e) { - log.error("createCollectionIfNotExists error - collectionName: '{}'", collectionName, e); - } - } -} diff --git a/src/main/java/com/miti99/storescraperbot/util/SchedulerUtil.java b/src/main/java/com/miti99/storescraperbot/util/SchedulerUtil.java deleted file mode 100644 index 3eac3af..0000000 --- a/src/main/java/com/miti99/storescraperbot/util/SchedulerUtil.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.miti99.storescraperbot.util; - -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; - -@NoArgsConstructor(access = AccessLevel.PRIVATE) -public class SchedulerUtil { - public static final ScheduledExecutorService SCHEDULER = - Executors.newSingleThreadScheduledExecutor(); -} diff --git a/src/main/java/com/miti99/storescraperbot/util/Time.java b/src/main/java/com/miti99/storescraperbot/util/Time.java deleted file mode 100644 index 72a4369..0000000 --- a/src/main/java/com/miti99/storescraperbot/util/Time.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.miti99.storescraperbot.util; - -import java.time.Clock; -import java.time.Instant; -import java.time.LocalDate; -import java.time.LocalDateTime; -import java.time.LocalTime; -import java.time.OffsetDateTime; -import java.time.ZoneId; -import java.time.ZonedDateTime; -import java.util.TimeZone; - -public class Time { - private static final TimeZone TIME_ZONE = TimeZone.getDefault(); - private static final ZoneId ZONE_ID = TIME_ZONE.toZoneId(); - private static long deltaMillis = 0L; - - public static LocalDate currentDate() { - return LocalDate.ofInstant(currentInstant(), ZONE_ID); - } - - public static LocalTime currentTime() { - return LocalTime.ofInstant(currentInstant(), ZONE_ID); - } - - public static LocalDateTime currentDateTime() { - return LocalDateTime.ofInstant(currentInstant(), ZONE_ID); - } - - public static OffsetDateTime currentOffsetDateTime() { - return OffsetDateTime.ofInstant(currentInstant(), ZONE_ID); - } - - public static ZonedDateTime currentZonedDateTime() { - return ZonedDateTime.ofInstant(currentInstant(), ZONE_ID); - } - - public static Instant currentInstant() { - return Instant.ofEpochMilli(currentTimeMillis()); - } - - public static long currentTimeMillis() { - return System.currentTimeMillis() + deltaMillis; - } - - public static void useMockTime(LocalDateTime dateTime, ZoneId zoneId) { - deltaMillis = dateTime.atZone(zoneId).toInstant().toEpochMilli() - System.currentTimeMillis(); - } - - public static void useSystemDefaultZoneClock() { - deltaMillis = 0L; - } - - private static Clock getClock() { - return Clock.fixed(currentInstant(), ZONE_ID); - } -} diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml deleted file mode 100644 index 059bfeb..0000000 --- a/src/main/resources/log4j2.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - %d{HH:mm:ss.SSS} %5p --- [%t] %c : %m%n - UTF-8 - - - - - - - - - - - - ${env:LOKI_HOST} - ${env:LOKI_PORT} - - ${env:LOKI_USERNAME} - ${env:LOKI_PASSWORD} - - - - - - - - - - - - diff --git a/src/test/java/com/miti99/storescraperbot/api/apple/AppStoreScraperTest.java b/src/test/java/com/miti99/storescraperbot/api/apple/AppStoreScraperTest.java deleted file mode 100644 index 11ec689..0000000 --- a/src/test/java/com/miti99/storescraperbot/api/apple/AppStoreScraperTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.miti99.storescraperbot.api.apple; - -import com.miti99.storescraperbot.api.apple.request.AppleAppRequest; -import com.miti99.storescraperbot.util.GsonUtil; -import org.junit.jupiter.api.Test; - -class AppStoreScraperTest { - @Test - void testComMptKvtm() { - var request = new AppleAppRequest("com.mpt.kvtm", "vn"); - var response = AppStoreScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } - - @Test - void testComMptBuraco() { - var request = new AppleAppRequest("com.mpt.buraco", "mx"); - var response = AppStoreScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } - - @Test - void testComMptDoudizhu() { - var request = new AppleAppRequest("com.mpt.doudizhu", "hk"); - var response = AppStoreScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } -} diff --git a/src/test/java/com/miti99/storescraperbot/api/google/GooglePlayScraperTest.java b/src/test/java/com/miti99/storescraperbot/api/google/GooglePlayScraperTest.java deleted file mode 100644 index 35a10d9..0000000 --- a/src/test/java/com/miti99/storescraperbot/api/google/GooglePlayScraperTest.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.miti99.storescraperbot.api.google; - -import com.miti99.storescraperbot.api.google.request.GoogleAppRequest; -import com.miti99.storescraperbot.util.GsonUtil; -import org.junit.jupiter.api.Test; - -class GooglePlayScraperTest { - @Test - void testPoolUs() { - var request = new GoogleAppRequest("pool.us"); - var response = GooglePlayScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } - - @Test - void testComZingplayBuracoMx() { - var request = new GoogleAppRequest("com.zingplay.buraco.mx", "mx"); - var response = GooglePlayScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } - - @Test - void testComZingplayDoudizhu() { - var request = new GoogleAppRequest("com.zingplay.doudizhu", "hk"); - var response = GooglePlayScraper.app(request); - System.out.println(GsonUtil.toJson(response)); - } -}