Compare commits
38 Commits
v1.0
...
0c2c5954ba
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c2c5954ba | |||
| d49d80af94 | |||
| 68cf337f48 | |||
| 4ecab127af | |||
| 61f8639a67 | |||
| 7f0866cbac | |||
| f2fbeaaa4d | |||
| abf0b9dbde | |||
| c881b8ae49 | |||
| 19eb496d35 | |||
| 156bbdb20f | |||
| 83ffa76f1f | |||
| de6c41d9f8 | |||
| af58b8602a | |||
| f2ca083dde | |||
| 117275043c | |||
| b0ae302c2f | |||
| 05963e9fec | |||
| 914fbb57e2 | |||
| 3f8409f007 | |||
| 8c51ef4da5 | |||
| 44b8e62b5e | |||
| cceae6eadd | |||
| d20d7bbbcf | |||
| c09f5681c2 | |||
| 25349fef02 | |||
| 35eca77223 | |||
| 3317241f86 | |||
| c90ab941df | |||
| eed4104ae3 | |||
| 3b54917551 | |||
| 43c2d31d4f | |||
| df414c37d0 | |||
| 3f405d1723 | |||
| 93ce4e7539 | |||
| 3d86c3b7be | |||
| 2fd314b972 | |||
| 515c51a4bc |
59
.gitea/workflows/compile.yaml
Normal file
59
.gitea/workflows/compile.yaml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
name: Compile and test using leiningen
|
||||||
|
run-name: ${{ gitea.actor }} testing the code
|
||||||
|
on: [push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
clojure:
|
||||||
|
name: Run tests
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
# Checkouts code
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
# Install Java
|
||||||
|
- name: Install java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: '21'
|
||||||
|
|
||||||
|
# Install Leiningen
|
||||||
|
- name: Install Leiningen
|
||||||
|
run: |
|
||||||
|
curl https://raw.githubusercontent.com/technomancy/leiningen/stable/bin/lein > lein
|
||||||
|
chmod +x lein
|
||||||
|
sudo mv lein /usr/local/bin/lein
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
- name: Install dependencies
|
||||||
|
run: lein deps
|
||||||
|
|
||||||
|
# Optional: cache dependencies
|
||||||
|
- name: Cache dependencias
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-m2-${{ hashFiles('**/project.clj') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-m2-
|
||||||
|
|
||||||
|
# Get leiningen's version
|
||||||
|
- name: Get leiningen version
|
||||||
|
run: lein -v
|
||||||
|
|
||||||
|
# Test the code
|
||||||
|
- name: Run tests
|
||||||
|
env:
|
||||||
|
TFT_API: ${{ secrets.DEV_API }}
|
||||||
|
run: lein test
|
||||||
|
|
||||||
|
# Send jar to repository
|
||||||
|
- name: Deploy on Gitea Maven
|
||||||
|
if: github.ref == 'refs/heads/main'
|
||||||
|
env:
|
||||||
|
GITEA_USER: ${{ secrets.DEPLOY_USER }}
|
||||||
|
GITEA_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
lein deploy gitea
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -14,3 +14,5 @@ pom.xml.asc
|
|||||||
.clj-kondo
|
.clj-kondo
|
||||||
.lsp
|
.lsp
|
||||||
.calva
|
.calva
|
||||||
|
*.svg
|
||||||
|
/logs
|
||||||
|
|||||||
5
.idea/.gitignore
generated
vendored
5
.idea/.gitignore
generated
vendored
@@ -1,5 +0,0 @@
|
|||||||
# Default ignored files
|
|
||||||
/shelf/
|
|
||||||
/workspace.xml
|
|
||||||
# Environment-dependent path to Maven home directory
|
|
||||||
/mavenHomeManager.xml
|
|
||||||
6
.idea/ClojureProjectResolveSettings.xml
generated
6
.idea/ClojureProjectResolveSettings.xml
generated
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ClojureProjectResolveSettings">
|
|
||||||
<currentScheme>IDE</currentScheme>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
18
.idea/compiler.xml
generated
18
.idea/compiler.xml
generated
@@ -1,18 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="CompilerConfiguration">
|
|
||||||
<wildcardResourcePatterns>
|
|
||||||
<entry name="!dev-resources:*" />
|
|
||||||
<entry name="!resources:*" />
|
|
||||||
<entry name="!?*.java" />
|
|
||||||
<entry name="!?*.form" />
|
|
||||||
<entry name="!?*.class" />
|
|
||||||
<entry name="!?*.groovy" />
|
|
||||||
<entry name="!?*.scala" />
|
|
||||||
<entry name="!?*.flex" />
|
|
||||||
<entry name="!?*.kt" />
|
|
||||||
<entry name="!?*.clj" />
|
|
||||||
<entry name="!?*.aj" />
|
|
||||||
</wildcardResourcePatterns>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
7
.idea/dictionaries/project.xml
generated
7
.idea/dictionaries/project.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<component name="ProjectDictionaryState">
|
|
||||||
<dictionary name="project">
|
|
||||||
<words>
|
|
||||||
<w>puuid</w>
|
|
||||||
</words>
|
|
||||||
</dictionary>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: buddy/buddy-core:1.12.0-430">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/buddy/buddy-core/1.12.0-430/buddy-core-1.12.0-430.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__cheshire_6_0_0.xml
generated
9
.idea/libraries/Leiningen__cheshire_6_0_0.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: cheshire:6.0.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/cheshire/cheshire/6.0.0/cheshire-6.0.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__cli_matic_0_5_4.xml
generated
9
.idea/libraries/Leiningen__cli_matic_0_5_4.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: cli-matic:0.5.4">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/cli-matic/cli-matic/0.5.4/cli-matic-0.5.4.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__clj_http_2_0_0.xml
generated
9
.idea/libraries/Leiningen__clj_http_2_0_0.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: clj-http:2.0.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/clj-http/clj-http/2.0.0/clj-http-2.0.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__clj_tuple_0_2_2.xml
generated
9
.idea/libraries/Leiningen__clj_tuple_0_2_2.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: clj-tuple:0.2.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/clj-tuple/clj-tuple/0.2.2/clj-tuple-0.2.2.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: com.fasterxml.jackson.core/jackson-core:2.18.3">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/core/jackson-core/2.18.3/jackson-core-2.18.3.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-cbor:2.18.3">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/dataformat/jackson-dataformat-cbor/2.18.3/jackson-dataformat-cbor-2.18.3.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-smile:2.18.3">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/com/fasterxml/jackson/dataformat/jackson-dataformat-smile/2.18.3/jackson-dataformat-smile-2.18.3.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: commons-codec:1.10">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/commons-codec/commons-codec/1.10/commons-codec-1.10.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__commons_io_2_4.xml
generated
9
.idea/libraries/Leiningen__commons_io_2_4.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: commons-io:2.4">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/commons-io/commons-io/2.4/commons-io-2.4.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: commons-logging:1.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/commons-logging/commons-logging/1.2/commons-logging-1.2.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__expound_0_9_0.xml
generated
9
.idea/libraries/Leiningen__expound_0_9_0.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: expound:0.9.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/expound/expound/0.9.0/expound-0.9.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__nrepl_1_0_0.xml
generated
9
.idea/libraries/Leiningen__nrepl_1_0_0.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: nrepl:1.0.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/nrepl/nrepl/1.0.0/nrepl-1.0.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.apache.httpcomponents/httpclient:4.5">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpclient/4.5/httpclient-4.5.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.apache.httpcomponents/httpcore:4.4.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpcore/4.4.1/httpcore-4.4.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.apache.httpcomponents/httpmime:4.5">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/apache/httpcomponents/httpmime/4.5/httpmime-4.5.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.bouncycastle/bcpkix-jdk18on:1.78.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/bouncycastle/bcpkix-jdk18on/1.78.1/bcpkix-jdk18on-1.78.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.bouncycastle/bcprov-jdk18on:1.78.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/bouncycastle/bcprov-jdk18on/1.78.1/bcprov-jdk18on-1.78.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.bouncycastle/bcutil-jdk18on:1.78.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/bouncycastle/bcutil-jdk18on/1.78.1/bcutil-jdk18on-1.78.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/clojure:1.11.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/clojure/1.11.1/clojure-1.11.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/core.specs.alpha:0.2.62">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/core.specs.alpha/0.2.62/core.specs.alpha-0.2.62.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/java.classpath:1.1.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/java.classpath/1.1.0/java.classpath-1.1.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/spec.alpha:0.3.218">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/spec.alpha/0.3.218/spec.alpha-0.3.218.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/test.check:1.1.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/test.check/1.1.1/test.check-1.1.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/tools.cli:1.1.230">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/tools.cli/1.1.230/tools.cli-1.1.230.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/tools.namespace:1.5.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/tools.namespace/1.5.0/tools.namespace-1.5.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.clojure/tools.reader:1.4.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/clojure/tools.reader/1.4.0/tools.reader-1.4.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: org.nrepl/incomplete:0.1.0">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/org/nrepl/incomplete/0.1.0/incomplete-0.1.0.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__potemkin_0_4_1.xml
generated
9
.idea/libraries/Leiningen__potemkin_0_4_1.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: potemkin:0.4.1">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/potemkin/potemkin/0.4.1/potemkin-0.4.1.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__riddley_0_1_10.xml
generated
9
.idea/libraries/Leiningen__riddley_0_1_10.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: riddley:0.1.10">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/riddley/riddley/0.1.10/riddley-0.1.10.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__slingshot_0_12_2.xml
generated
9
.idea/libraries/Leiningen__slingshot_0_12_2.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: slingshot:0.12.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/slingshot/slingshot/0.12.2/slingshot-0.12.2.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
9
.idea/libraries/Leiningen__tigris_0_1_2.xml
generated
9
.idea/libraries/Leiningen__tigris_0_1_2.xml
generated
@@ -1,9 +0,0 @@
|
|||||||
<component name="libraryTable">
|
|
||||||
<library name="Leiningen: tigris:0.1.2">
|
|
||||||
<CLASSES>
|
|
||||||
<root url="jar://$MAVEN_REPOSITORY$/tigris/tigris/0.1.2/tigris-0.1.2.jar!/" />
|
|
||||||
</CLASSES>
|
|
||||||
<JAVADOC />
|
|
||||||
<SOURCES />
|
|
||||||
</library>
|
|
||||||
</component>
|
|
||||||
11
.idea/misc.xml
generated
11
.idea/misc.xml
generated
@@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="LeiningenProjectsManager">
|
|
||||||
<option name="projectFiles">
|
|
||||||
<set>
|
|
||||||
<option value="file://$PROJECT_DIR$/project.clj" />
|
|
||||||
</set>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="21" project-jdk-type="JavaSDK" />
|
|
||||||
</project>
|
|
||||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="ProjectModuleManager">
|
|
||||||
<modules>
|
|
||||||
<module fileurl="file://$PROJECT_DIR$/riot-clojure.iml" filepath="$PROJECT_DIR$/riot-clojure.iml" />
|
|
||||||
</modules>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
7
.idea/vcs.xml
generated
7
.idea/vcs.xml
generated
@@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="VcsDirectoryMappings">
|
|
||||||
<mapping directory="" vcs="Git" />
|
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
134
README.md
134
README.md
@@ -1,79 +1,107 @@
|
|||||||
# riot-clojure
|
# riot-clojure
|
||||||
|
|
||||||
This is a simple tool for using Riot Games public API. Those APIs are HUGE and
|
Riot Games provides a lot of nice endpoints with a lot of data for all their games.
|
||||||
privide a lot of information, but this tool is focused in the time data of matches.
|
This projects provides a library to access those data from Clojure and a small
|
||||||
|
application to quick get some relevant data.
|
||||||
|
|
||||||
The objetive of this tool is extract the playing time of one player. Taking the
|
The library and the CLI application are separated, you can use the library independently.
|
||||||
starting and ending timestams we can create a chronogram with the time spent
|
|
||||||
playing.
|
|
||||||
|
|
||||||
This simple program needs a developer API. You can obtain a key from https://developer.riotgames.com/
|
CLI application should be compatible with [babashka](https://babashka.org/), so
|
||||||
Developer keys are valid for 24 hours only, but you can refresh the key easily
|
will use external libraries compatible with it.
|
||||||
from the developer's web site.
|
|
||||||
|
|
||||||
By default, the application searchs for the API key in the environment variable
|
# The API and the tokens
|
||||||
`RIOT_API`. If you prefer to provide the key via parameter, you must use `-k KEY` or
|
|
||||||
`--key=KEY`.
|
|
||||||
|
|
||||||
## Goals
|
Accessing the API requires one or more API tokens. Each videogame has their own
|
||||||
|
group of endpoints, secured with an API. Development APIs can access to all
|
||||||
|
andpoints, but they must be refreshed every 24 hours.
|
||||||
|
|
||||||
Goals of the project, ordered from easiest to hardest:
|
You can obtain a token for free in the [official developer web](https://developer.riotgames.com/).
|
||||||
|
|
||||||
* [x] Take API key from environment
|
The library and the application will take the API token from environment. CLI application
|
||||||
* [x] Call the API to get basic player data
|
has optional parameters that override the environment variables.
|
||||||
* [x] Make the call to the API flexible
|
|
||||||
* [x] Obtain list of past matches
|
|
||||||
* [x] Obtain list of current matches
|
|
||||||
* [x] Process app parameters
|
|
||||||
* [x] By default, search for player's name and tag
|
|
||||||
* [x] Take API key from parameter
|
|
||||||
* [x] Use PUUID instead of name and tag
|
|
||||||
* [x] Output as simple EDN data with timestamps
|
|
||||||
* [x] Output as simple EDN data with local datetimes
|
|
||||||
* [x] Output as JSON with timestamps
|
|
||||||
* [x] Output as JSON with local datetimes
|
|
||||||
* [x] Output as ASCII table with localdatetimes
|
|
||||||
* [x] By default, output timestamps and local datetimes, and provide parameters
|
|
||||||
to select the output data.
|
|
||||||
* [x] Only checks if it's playing just now
|
|
||||||
* [x] Win / Loss match
|
|
||||||
* [x] Distribution as uberjar
|
|
||||||
* [x] Distribution as native Linux executable
|
|
||||||
* [ ] Unit tests: move "comment" manual tests to real unit tests
|
|
||||||
* [ ] Output as a graphical chronogram or calendar.
|
|
||||||
* [ ] Simple web server
|
|
||||||
* [ ] Universal player search
|
|
||||||
* [ ] Simple API to get JSON data
|
|
||||||
* [ ] Simple endpoint to tell if it's playing just now
|
|
||||||
|
|
||||||
|
| Game | Environment variable | CLI parameter |
|
||||||
|
| ---------- | -------------------- | ------------- |
|
||||||
|
| all | `RIOT_DEV_KEY` | `--dev-key` |
|
||||||
|
| LOL | `RIOT_LOL_KEY` | `--lol-key` |
|
||||||
|
| TFT | `RIOT_TFT_KEY` | `--tft-key` |
|
||||||
|
*more to came*
|
||||||
|
|
||||||
## Installation
|
# Usage
|
||||||
|
## CLI
|
||||||
|
### Installation
|
||||||
|
|
||||||
Download from http://example.com/FIXME.
|
Download release from https://git.rcorral.es/ruben/riot-clojure/releases.
|
||||||
|
|
||||||
## Usage
|
### Example
|
||||||
|
|
||||||
FIXME: explanation
|
Using the Java uberjar
|
||||||
|
|
||||||
$ java -jar riot-clojure-0.1.0-standalone.jar [args]
|
$ java -jar riot-clojure-0.1.0-standalone.jar [args]
|
||||||
|
|
||||||
## Options
|
Using the linux native image:
|
||||||
|
$ ./riot [args]
|
||||||
|
|
||||||
FIXME: listing of options this app accepts.
|
Both are equivalent. In the examples we will use the native image, because is shorter.
|
||||||
|
|
||||||
## Examples
|
### Options
|
||||||
|
|
||||||
...
|
Run the application without params or wich `-?` param to show all options:
|
||||||
|
|
||||||
### Bugs
|
$ ./riot -?
|
||||||
|
|
||||||
...
|
### Tipycal usages
|
||||||
|
|
||||||
### Any Other Sections
|
Show all matches from a march the 1st (in ISO format):
|
||||||
### That You Think
|
|
||||||
### Might be Useful
|
|
||||||
|
|
||||||
## License
|
$ ./riot t <username> <tag> -s "2025-03-01"
|
||||||
|
|
||||||
|
Get te same data in CSV and store it in a file:
|
||||||
|
|
||||||
|
$ ./riot t <username> <tag> -s "2025-03-01" -o csv > results.csv
|
||||||
|
|
||||||
|
Don't format durations, show them in seconds
|
||||||
|
|
||||||
|
$ ./riot t <username> <tag> -s "2025-03-01" --no-format-durations
|
||||||
|
|
||||||
|
|
||||||
|
## Library
|
||||||
|
|
||||||
|
# Version
|
||||||
|
|
||||||
|
**Notes about v2.0:** This is complete rewriting of the project, with all
|
||||||
|
I have learn in the last months. The objetive for this version is to implement
|
||||||
|
all functionality provided by v1.1.
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
### General
|
||||||
|
|
||||||
|
* [ ] Reestructure all project to use `deps.edn`, `tools.clj` and subprojects
|
||||||
|
* [ ] Use babashka compatible libraries and `bb.edn`
|
||||||
|
* [ ] Gitea actions for automatic test executing
|
||||||
|
* [ ] Distribute CLI as self executable (bb, jlink or graal)
|
||||||
|
|
||||||
|
### Library
|
||||||
|
|
||||||
|
* [ ] Read tokens from environment and a function to override them manually
|
||||||
|
* [ ] Fuctions for calling Riot API and read result as clojure data structures (EDN format)
|
||||||
|
* [ ] Get [PUUID](https://developer.riotgames.com/docs/lol#summoner-names-to-riot-ids_obtaining-puuid-and-summonerid-from-riotid) for a player
|
||||||
|
* [ ] Get basic player info
|
||||||
|
* [ ] Format raw data
|
||||||
|
|
||||||
|
### CLI
|
||||||
|
* [ ] Babashka compatible CLI
|
||||||
|
* [ ] Basic parameters for log level and override API tokens
|
||||||
|
* [ ] Obtain basic player info
|
||||||
|
* [ ] Last games for player (LOL, TFT and others)
|
||||||
|
* [ ] Is the player playing just now?
|
||||||
|
* [ ] Format output as fancy table
|
||||||
|
* [ ] Format output as CSV
|
||||||
|
* [ ] Calculte statistics
|
||||||
|
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
# Introduction to riot-clojure
|
|
||||||
|
|
||||||
TODO: write [great documentation](http://jacobian.org/writing/what-to-write/)
|
|
||||||
30
project.clj
30
project.clj
@@ -1,30 +0,0 @@
|
|||||||
(defproject riot-clojure "1.0.0"
|
|
||||||
:description "Utility for getting for Riot APIs in Clojure"
|
|
||||||
:url "https://git.rcorral.es/ruben/riot-clojure"
|
|
||||||
|
|
||||||
:license {:name "MIT"
|
|
||||||
:url "https://mit-license.org/"}
|
|
||||||
|
|
||||||
:dependencies [[org.clojure/clojure "1.11.1"]
|
|
||||||
[clj-http/clj-http "2.0.0"]
|
|
||||||
[cheshire/cheshire "6.0.0"]
|
|
||||||
[slingshot/slingshot "0.12.2"]
|
|
||||||
[org.clojure/tools.cli "1.1.230"]
|
|
||||||
[cli-matic/cli-matic "0.5.4"]
|
|
||||||
[buddy/buddy-core "1.12.0-430"]
|
|
||||||
[org.clojure/tools.namespace "1.5.0"]
|
|
||||||
[lt.tokenmill/timewords "0.5.0"]]
|
|
||||||
|
|
||||||
:plugins [[io.taylorwood/lein-native-image "0.3.1"]]
|
|
||||||
|
|
||||||
:main ^:skip-aot riot.app
|
|
||||||
:target-path "target/%s"
|
|
||||||
|
|
||||||
:native-image {:name "riot" ;; name of output image, optional
|
|
||||||
:graal-bin "/home/ruben/.sdkman/candidates/java/21.0.2-graalce/" ;; path to GraalVM home, optional
|
|
||||||
:opts ["--verbose"]} ;; pass-thru args to GraalVM native-image, optional
|
|
||||||
|
|
||||||
:profiles {:uberjar {:aot :all
|
|
||||||
:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
|
|
||||||
:native-image {:jvm-opts ["-Dclojure.compiler.direct-linking=true"]}
|
|
||||||
:dev {:dependencies [[org.clojure/test.check "1.1.1"]]}})
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module type="JAVA_MODULE" version="4">
|
|
||||||
<component name="BuildSystem">
|
|
||||||
<option name="buildSystemId" value="LEININGEN" />
|
|
||||||
<option name="displayName" value="riot-clojure:1.0.0" />
|
|
||||||
</component>
|
|
||||||
<component name="NewModuleRootManager">
|
|
||||||
<output url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<output-test url="file://$MODULE_DIR$/target/classes" />
|
|
||||||
<exclude-output />
|
|
||||||
<content url="file://$MODULE_DIR$">
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/dev-resources" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
|
||||||
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
|
||||||
</content>
|
|
||||||
<orderEntry type="inheritedJdk" />
|
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
|
||||||
<orderEntry type="library" name="Leiningen: buddy/buddy-core:1.12.0-430" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: cheshire:6.0.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: cli-matic:0.5.4" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: clj-http:2.0.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: clj-tuple:0.2.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.core/jackson-core:2.18.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-cbor:2.18.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: com.fasterxml.jackson.dataformat/jackson-dataformat-smile:2.18.3" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: commons-codec:1.10" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: commons-io:2.4" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: commons-logging:1.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: expound:0.9.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: nrepl:1.0.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.apache.httpcomponents/httpclient:4.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.apache.httpcomponents/httpcore:4.4.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.apache.httpcomponents/httpmime:4.5" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.bouncycastle/bcpkix-jdk18on:1.78.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.bouncycastle/bcprov-jdk18on:1.78.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.bouncycastle/bcutil-jdk18on:1.78.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/clojure:1.11.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/core.specs.alpha:0.2.62" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/java.classpath:1.1.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/spec.alpha:0.3.218" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/test.check:1.1.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/tools.cli:1.1.230" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/tools.namespace:1.5.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.clojure/tools.reader:1.4.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: org.nrepl/incomplete:0.1.0" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: potemkin:0.4.1" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: riddley:0.1.10" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: slingshot:0.12.2" level="project" />
|
|
||||||
<orderEntry type="library" name="Leiningen: tigris:0.1.2" level="project" />
|
|
||||||
</component>
|
|
||||||
</module>
|
|
||||||
386
src/riot/app.clj
386
src/riot/app.clj
@@ -1,386 +0,0 @@
|
|||||||
|
|
||||||
;; Main CLI application
|
|
||||||
|
|
||||||
(ns riot.app
|
|
||||||
(:require [cli-matic.core :refer [run-cmd]]
|
|
||||||
[cli-matic.utils :as U]
|
|
||||||
[clojure.pprint :as pp]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[timewords.core :refer [parse]])
|
|
||||||
(:use [riot.core]
|
|
||||||
[riot.data]
|
|
||||||
[slingshot.slingshot :only [try+]])
|
|
||||||
(:gen-class))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-puuid-from-params
|
|
||||||
[api-key params & {:keys [puuid name tag]}]
|
|
||||||
;(println "get puuid API key" api-key)
|
|
||||||
(cond
|
|
||||||
(= 1 (count params)) (first params)
|
|
||||||
(= 2 (count params)) (get-puuid-from-name (first params) (second params) :api-key api-key)
|
|
||||||
(some? puuid) puuid
|
|
||||||
(and (some? name) (some? tag)) (get-puuid-from-name name tag :api-key api-key)))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(get-puuid-from-params (get-lol-api-key) [] :puuid "annlAfxhJnTwlwRgQZYbGeQpD3jWb-ju7vVKEW_g-EIJf6xQT0eeb-0obARVekrksf8n9XCjcxyHHQ")
|
|
||||||
(get-puuid-from-params (get-lol-api-key) [] :name "Errepunto" :tag "4595")
|
|
||||||
|
|
||||||
(get-puuid-from-params (get-tft-api-key) [] :puuid "annlAfxhJnTwlwRgQZYbGeQpD3jWb-ju7vVKEW_g-EIJf6xQT0eeb-0obARVekrksf8n9XCjcxyHHQ")
|
|
||||||
(get-puuid-from-params (get-tft-api-key) [] :name "Errepunto" :tag "4595"))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn cmd-active
|
|
||||||
"Checks if a player is online at the moment"
|
|
||||||
[& {:keys [lol-api-key tft-api-key debug-http _arguments]
|
|
||||||
:as opts}]
|
|
||||||
(try+
|
|
||||||
;(println "Check online" opts)
|
|
||||||
(let [lol-key (get-lol-api-key lol-api-key)
|
|
||||||
tft-key (get-tft-api-key tft-api-key)
|
|
||||||
lol-id (get-puuid-from-params lol-key _arguments opts)
|
|
||||||
tft-id (get-puuid-from-params tft-key _arguments opts)]
|
|
||||||
;(println "LOL API key" lol-key "TFT API key" tft-key)
|
|
||||||
(if (or (nil? lol-id) (nil? tft-id))
|
|
||||||
(U/exit! "Invalid params" 2)
|
|
||||||
(if (is-playing? lol-id tft-id :lol-api-key lol-key :tft-api-key tft-key :debug debug-http)
|
|
||||||
(println "Yes, it's playing")
|
|
||||||
(println "No, it's not playing right now"))))
|
|
||||||
(catch [:status 401] _
|
|
||||||
(U/exit! "Invalid API key" 3))
|
|
||||||
(catch [:status 404] _
|
|
||||||
(U/exit! "Unknown user or tag" 5))))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(cmd-active :_arguments ["annlAfxhJnTwlwRgQZYbGeQpD3jWb-ju7vVKEW_g-EIJf6xQT0eeb-0obARVekrksf8n9XCjcxyHHQ"])
|
|
||||||
(cmd-active :_arguments ["Errepunto" "4595"]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn format-map
|
|
||||||
"Format result"
|
|
||||||
[output x]
|
|
||||||
(case output
|
|
||||||
"edn" (pp/pprint x)
|
|
||||||
"json" (println (as-json x))
|
|
||||||
"table" (as-ascii-table x)
|
|
||||||
"csv" (println (as-csv x))
|
|
||||||
(pp/pprint x))) ;edn as default
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(format-map "json" riot.test-examples/matches-example)
|
|
||||||
(format-map "csv" riot.test-examples/matches-example2))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn format-dates-cond
|
|
||||||
[format-dates format-durations pattern x]
|
|
||||||
(let [dur (if format-durations
|
|
||||||
(with-parsed-durations x)
|
|
||||||
x)]
|
|
||||||
(if format-dates
|
|
||||||
(if (some? pattern)
|
|
||||||
(with-parsed-dates dur :datetime-format pattern)
|
|
||||||
(with-parsed-dates dur))
|
|
||||||
dur)))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(format-dates-cond false false nil riot.test-examples/matches-example2)
|
|
||||||
(format-dates-cond false true nil riot.test-examples/matches-example2)
|
|
||||||
(format-dates-cond true false nil riot.test-examples/matches-example2)
|
|
||||||
(format-dates-cond true true nil riot.test-examples/matches-example2))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn reverse-cond
|
|
||||||
[rev x] (if rev x (reverse x)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn filter-today-cond
|
|
||||||
[only-today x] (if only-today (filter match-today? x) x))
|
|
||||||
|
|
||||||
|
|
||||||
(defn filter-columns
|
|
||||||
[columns x] (if (= "all" columns)
|
|
||||||
x
|
|
||||||
(map #(select-keys % (map keyword (str/split columns #","))) x)))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(filter-columns "all" riot.test-examples/matches-example2)
|
|
||||||
(filter-columns "start,end" riot.test-examples/matches-example2)
|
|
||||||
|
|
||||||
(map #(select-keys % (map keyword (str/split "start,end" #","))) riot.test-examples/matches-example2))
|
|
||||||
|
|
||||||
(defn get-date
|
|
||||||
[x]
|
|
||||||
(if (nil? x) nil (parse x)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn cmd-timeline
|
|
||||||
"Get match "
|
|
||||||
[& {:keys [lol-api-key tft-api-key output count max-total format-dates format-durations date-format reverse order-by show-columns show-active debug-http only-today since until _arguments]
|
|
||||||
:as opts}]
|
|
||||||
(try+
|
|
||||||
;(println "Get timeline" opts)
|
|
||||||
(let [lol-key (get-lol-api-key lol-api-key)
|
|
||||||
tft-key (get-tft-api-key tft-api-key)
|
|
||||||
lol-id (get-puuid-from-params lol-key _arguments opts)
|
|
||||||
tft-id (get-puuid-from-params tft-key _arguments opts)]
|
|
||||||
;(println "LOL API key" lol-key "TFT API key" tft-key)
|
|
||||||
(if (or (nil? lol-id) (nil? tft-id))
|
|
||||||
(U/exit! "Invalid params" 2)
|
|
||||||
(->> (get-last-matches lol-id tft-id :lol-api-key lol-key :tft-api-key tft-key :count count :include-current show-active :debug debug-http :order-by (keyword order-by) :since (get-date since) :until (get-date until))
|
|
||||||
(filter-today-cond only-today)
|
|
||||||
(reverse-cond reverse)
|
|
||||||
(take count)
|
|
||||||
(format-dates-cond format-dates format-durations date-format)
|
|
||||||
(filter-columns show-columns)
|
|
||||||
(map)
|
|
||||||
(format-map output))))
|
|
||||||
(catch [:status 401] _
|
|
||||||
(U/exit! "Invalid API key" 3))
|
|
||||||
(catch [:status 404] _
|
|
||||||
(U/exit! "Unknown user or tag" 5))
|
|
||||||
(catch [:status 429] _
|
|
||||||
(U/exit! "Rate limit exceeded, please wait some minutes and try again" 4))))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(cmd-timeline :_arguments ["dMNR4Aj5OW9jrGj0RUVBRuzfu77p3iO5y1W16ASNp1PI7pxuJWLz14b2pJiUn16DCPlyeREoi0MJ7Q"])
|
|
||||||
(cmd-timeline :_arguments ["Sarinailo" "EUW"]))
|
|
||||||
|
|
||||||
|
|
||||||
(defn cmd-bulk
|
|
||||||
"Get all matches"
|
|
||||||
[& {:keys [lol-api-key tft-api-key output format-dates format-durations date-format reverse order-by show-columns debug-http since until _arguments]
|
|
||||||
:as opts}]
|
|
||||||
(try+
|
|
||||||
;(println "Get timeline" opts)
|
|
||||||
(let [lol-key (get-lol-api-key lol-api-key)
|
|
||||||
tft-key (get-tft-api-key tft-api-key)
|
|
||||||
lol-id (get-puuid-from-params lol-key _arguments opts)
|
|
||||||
tft-id (get-puuid-from-params tft-key _arguments opts)]
|
|
||||||
;(println "LOL API key" lol-key "TFT API key" tft-key)
|
|
||||||
(if (or (nil? lol-id) (nil? tft-id))
|
|
||||||
(U/exit! "Invalid params" 2)
|
|
||||||
(->> (get-matches-info-batch lol-id tft-id :lol-api-key lol-key :tft-api-key tft-key :debug debug-http :order-by (keyword order-by) :since (get-date since) :until (get-date until))
|
|
||||||
(reverse-cond reverse)
|
|
||||||
(format-dates-cond format-dates format-durations date-format)
|
|
||||||
(filter-columns show-columns)
|
|
||||||
(format-map output))))
|
|
||||||
(catch [:status 401] _
|
|
||||||
(U/exit! "Invalid API key" 3))
|
|
||||||
(catch [:status 404] _
|
|
||||||
(U/exit! "Unknown user or tag" 5))
|
|
||||||
(catch [:status 429] _
|
|
||||||
(U/exit! "Rate limit exceeded, please wait some minutes and try again" 4))
|
|
||||||
(catch [:status 503] _
|
|
||||||
(U/exit! "Server timeout, please wait some minutes and try again" 6))))
|
|
||||||
|
|
||||||
|
|
||||||
;; More info: https://github.com/l3nz/cli-matic/blob/master/README.md
|
|
||||||
(def CONFIGURATION
|
|
||||||
{:app {:command "riot"
|
|
||||||
:description ["Get how much time have you spent on LoL or FTF"
|
|
||||||
""
|
|
||||||
"Posible error codes:"
|
|
||||||
" 0: OK"
|
|
||||||
" 1: player not playing"
|
|
||||||
" 2: Invalid params"
|
|
||||||
" 3: Invalid API key, please, get an updated one"
|
|
||||||
" 4: Rate limit exceeded, please wait some minutes and try again"
|
|
||||||
" 5: Unknown user and tag"
|
|
||||||
" 6: Server error. Please, try again"]
|
|
||||||
:version "1.0.0"}
|
|
||||||
:global-opts [{:option "lol-api-key"
|
|
||||||
:as "API key for LOL data"
|
|
||||||
:type :string :default nil
|
|
||||||
:env "LOL_API"}
|
|
||||||
{:option "tft-api-key"
|
|
||||||
:as "API key for TFT data"
|
|
||||||
:type :string :default nil
|
|
||||||
:env "TFT_API"}
|
|
||||||
{:option "debug-http"
|
|
||||||
:as "Show debug for HTTP connections. I'ts very verbose!"
|
|
||||||
:type :flag
|
|
||||||
:default false}]
|
|
||||||
:commands [{:command "active" :short "a"
|
|
||||||
:description ["Shows if the player currently playing"
|
|
||||||
"You can search by PUUID or name and tagline, but not both."
|
|
||||||
""
|
|
||||||
"You can set the PUUID passing only one argument or using -p param."
|
|
||||||
"You can set the name and tag passing two arguments, or using -n and -t."]
|
|
||||||
:opts [{:option "puuid" :short "p"
|
|
||||||
:type :string
|
|
||||||
:as "Summonner's unique PUUID."}
|
|
||||||
{:option "name" :short "n"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner name (Riot ID)"}
|
|
||||||
{:option "tag" :short "t"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner tagline"}]
|
|
||||||
:runs cmd-active}
|
|
||||||
{:command "last" :short "l"
|
|
||||||
:description ["Gets time info from last matches."
|
|
||||||
"You can search by PUUID or name and tagline, but not both."
|
|
||||||
""
|
|
||||||
"You can set the PUUID passing only one argument or using -p param."
|
|
||||||
"You can set the name and tag passing two arguments, or using -n and -t."]
|
|
||||||
:opts [{:option "puuid" :short "p"
|
|
||||||
:type :string
|
|
||||||
:as "Summonner's unique PUUID."}
|
|
||||||
{:option "name" :short "n"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner name (Riot ID)"}
|
|
||||||
{:option "tag" :short "t"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner tagline"}
|
|
||||||
{:option "output" :short "o"
|
|
||||||
:type #{"edn" "json" "table" "csv"} :default "table"
|
|
||||||
:as ["Output type. It can be one of:"
|
|
||||||
" - edn: Clojure's internal EDN format"
|
|
||||||
" - json: Classic JSON"
|
|
||||||
" - table: ASCII table (by default)"
|
|
||||||
" - csv: CSV data, using ',' as field separator"]}
|
|
||||||
{:option "count" :short "c"
|
|
||||||
:type :int :default 10
|
|
||||||
:as "Max number of matches retrieved for each type of game (max value: 100)"}
|
|
||||||
;{:option "max-total" :short "m"
|
|
||||||
; :type :int :default 10
|
|
||||||
; :as "Max number of matches of all types, including current match"}
|
|
||||||
{:option "order-by"
|
|
||||||
:type #{"start" "end" "duration"} :default "start"
|
|
||||||
:as "Order by field"}
|
|
||||||
{:option "reverse" :short "r"
|
|
||||||
:type :with-flag :default false
|
|
||||||
:as "If true, newer matches are shown last in list"}
|
|
||||||
{:option "show-active" :short "a"
|
|
||||||
:type :with-flag :default true
|
|
||||||
:as "Include current playing match"}
|
|
||||||
{:option "format-dates"
|
|
||||||
:type :with-flag :default true
|
|
||||||
:as "Show formatted dates"}
|
|
||||||
{:option "format-durations"
|
|
||||||
:type :with-flag :default true
|
|
||||||
:as "Show formatted durations"}
|
|
||||||
{:option "date-format"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "If format-dates is enabled, specifies the formatter's string"}
|
|
||||||
{:option "show-columns"
|
|
||||||
:type :string :default "all"
|
|
||||||
:as ["Show only selected columns, separated by comma. Supported columns:"
|
|
||||||
" - all: All columns"
|
|
||||||
" - start: Start timestamp"
|
|
||||||
" - end: End timestamp"
|
|
||||||
" - duration: Duration in seconds"
|
|
||||||
" - active: Match is in course"
|
|
||||||
" - game-type: lol or tft"
|
|
||||||
" - id: Game unique id"
|
|
||||||
" - winner: Winner of the match"]}
|
|
||||||
{:option "only-today"
|
|
||||||
:type :flag :default false
|
|
||||||
:as "If true, only shows today played matches"}
|
|
||||||
{:option "since" :short "s"
|
|
||||||
:type :string :default nil
|
|
||||||
:as ["Starting date (included) in 'yyyy-MM-dd' format."
|
|
||||||
"Other valid values: today, yesterday"]}
|
|
||||||
{:option "until" :short "u"
|
|
||||||
:type :string :default nil
|
|
||||||
:as ["Ending date (not included) in 'yyyy-MM-dd' format."
|
|
||||||
"Other valid values: today, yesterday, tomorrow"]}]
|
|
||||||
:runs cmd-timeline}
|
|
||||||
{:command "timeline" :short "t"
|
|
||||||
:description ["Get info from LOL and TFT matches in a time range."
|
|
||||||
"Warning: it can take several minutes to obtain all data, due to api restrictions."
|
|
||||||
"You can search by PUUID or name and tagline, but not both."
|
|
||||||
""
|
|
||||||
"You can set the PUUID passing only one argument or using -p param."
|
|
||||||
"You can set the name and tag passing two arguments, or using -n and -t."]
|
|
||||||
:opts [{:option "puuid" :short "p"
|
|
||||||
:type :string
|
|
||||||
:as "Summonner's unique PUUID."}
|
|
||||||
{:option "name" :short "n"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner name (Riot ID)"}
|
|
||||||
{:option "tag" :short "t"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "Summoner tagline"}
|
|
||||||
{:option "output" :short "o"
|
|
||||||
:type #{"edn" "json" "table" "csv"} :default "table"
|
|
||||||
:as ["Output type. It can be one of:"
|
|
||||||
" - edn: Clojure's internal EDN format"
|
|
||||||
" - json: Classic JSON"
|
|
||||||
" - table: ASCII table (by default)"
|
|
||||||
" - csv: CSV data, using ',' as field separator"]}
|
|
||||||
{:option "order-by"
|
|
||||||
:type #{"start" "end" "duration"} :default "start"
|
|
||||||
:as "Order by field"}
|
|
||||||
{:option "reverse" :short "r"
|
|
||||||
:type :with-flag :default false
|
|
||||||
:as "If true, newer matches are shown last in list"}
|
|
||||||
{:option "format-dates"
|
|
||||||
:type :with-flag :default true
|
|
||||||
:as "Show formatted dates"}
|
|
||||||
{:option "format-durations"
|
|
||||||
:type :with-flag :default true
|
|
||||||
:as "Show formatted durations"}
|
|
||||||
{:option "date-format"
|
|
||||||
:type :string :default nil
|
|
||||||
:as "If format-dates is enabled, specifies the formatter's string"}
|
|
||||||
{:option "show-columns"
|
|
||||||
:type :string :default "all"
|
|
||||||
:as ["Show only selected columns, separated by comma. Supported columns:"
|
|
||||||
" - all: All columns"
|
|
||||||
" - start: Start timestamp"
|
|
||||||
" - end: End timestamp"
|
|
||||||
" - duration: Duration in seconds"
|
|
||||||
" - game-type: lol or tft"
|
|
||||||
" - id: Game unique id"
|
|
||||||
" - winner: Winner of the match"]}
|
|
||||||
{:option "only-today"
|
|
||||||
:type :flag :default false
|
|
||||||
:as "If true, only shows today played matches"}
|
|
||||||
{:option "since" :short "s"
|
|
||||||
:type :string :default nil
|
|
||||||
:as ["Starting date (included) in 'yyyy-MM-dd' format."
|
|
||||||
"Other valid values: today, yesterday, etc"]}
|
|
||||||
{:option "until" :short "u"
|
|
||||||
:type :string :default nil
|
|
||||||
:as ["Ending date (not included) in 'yyyy-MM-dd' format."
|
|
||||||
"Other valid values: today, yesterday, tomorrow, etc"]}]
|
|
||||||
:runs cmd-bulk}]})
|
|
||||||
|
|
||||||
|
|
||||||
(defn -main
|
|
||||||
"Main entry point"
|
|
||||||
[& args]
|
|
||||||
(run-cmd args CONFIGURATION))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn old-main
|
|
||||||
"Testing some basic things"
|
|
||||||
[& args]
|
|
||||||
(let [player "RdNVioNKYzvFuXI00zurL_8QvaU0E8P61NU0SzwIfbbHHk9HFvxLtSWiDHKuJ9iXb4UC0UUZ3ltLxw"]
|
|
||||||
;(println "API Key: " (get-lol-api-key))
|
|
||||||
(println "Last matches:")
|
|
||||||
(println "Player PUUID: " player)
|
|
||||||
;(as-json
|
|
||||||
;(as-ascii-table
|
|
||||||
; (with-parsed-dates
|
|
||||||
; (take 10
|
|
||||||
; (reverse
|
|
||||||
; (get-last-matches player :count 10 :print-not-active true)))))
|
|
||||||
(as-ascii-table
|
|
||||||
(with-parsed-dates-durations
|
|
||||||
; (filter match-today? ; Only today
|
|
||||||
(reverse (get-last-matches player :count 10 :print-not-active true))))
|
|
||||||
;)
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
(comment
|
|
||||||
; Launch manually
|
|
||||||
(-main)
|
|
||||||
|
|
||||||
(old-main))
|
|
||||||
@@ -1,488 +0,0 @@
|
|||||||
|
|
||||||
;; Core functions to get data from server
|
|
||||||
|
|
||||||
(ns riot.core
|
|
||||||
(:require [clj-http.client :as client]
|
|
||||||
[buddy.core.crypto :as crypto]
|
|
||||||
[buddy.core.codecs :as codecs])
|
|
||||||
(:use [slingshot.slingshot :only [try+]])
|
|
||||||
(:gen-class))
|
|
||||||
|
|
||||||
|
|
||||||
(def API-HOST "api.riotgames.com")
|
|
||||||
|
|
||||||
(def secret-key (codecs/b64->bytes "//EaEeKElZDJSLLJaydGQDKw5DiqUCZ5DdnLvpE6dbo="))
|
|
||||||
(def iv (codecs/b64->bytes "cMN8rAwUoYHk7YwJ7HawFw=="))
|
|
||||||
|
|
||||||
|
|
||||||
;; Keys aren't in plain
|
|
||||||
|
|
||||||
(defn encrypt-data
|
|
||||||
([text] (encrypt-data text secret-key iv))
|
|
||||||
([text key iv]
|
|
||||||
(-> (codecs/str->bytes text)
|
|
||||||
(crypto/encrypt key iv)
|
|
||||||
(codecs/bytes->b64-str))))
|
|
||||||
|
|
||||||
(defn decrypt-data
|
|
||||||
([b64] (decrypt-data b64 secret-key iv))
|
|
||||||
([b64 key iv]
|
|
||||||
(-> (codecs/b64->bytes b64)
|
|
||||||
(crypto/decrypt key iv)
|
|
||||||
(codecs/bytes->str))))
|
|
||||||
|
|
||||||
;;;; API KEYS
|
|
||||||
|
|
||||||
(def DEV_KEY "RGAPI-fc8c6d88-2c13-4a43-b53f-3465bb564acc")
|
|
||||||
(def LOL_KEY "jXL+gA3LIeBPBvrOhLOYSZCiURC7eOtwMXahkxtwpdj6JDtT5NMu25zMz+UY2+9MuHBADjUJh46jSanrV5OBag==")
|
|
||||||
(def TFT_KEY (encrypt-data DEV_KEY secret-key iv))
|
|
||||||
|
|
||||||
(defn get-lol-api-key
|
|
||||||
"Get the API key from the LOL_API environment variable"
|
|
||||||
([key]
|
|
||||||
(if (some? key) key (get-lol-api-key)))
|
|
||||||
([]
|
|
||||||
(let [k (System/getenv "LOL_API")]
|
|
||||||
(if (some? k) k (decrypt-data LOL_KEY secret-key iv)))))
|
|
||||||
|
|
||||||
(defn get-tft-api-key
|
|
||||||
"Get the API key from the TFT_API environment variable"
|
|
||||||
([key]
|
|
||||||
(if (some? key) key (get-tft-api-key)))
|
|
||||||
([]
|
|
||||||
(let [k (System/getenv "TFT_API")]
|
|
||||||
(if (some? k) k (decrypt-data TFT_KEY secret-key iv)))))
|
|
||||||
|
|
||||||
|
|
||||||
;;;; MATCH DATA RESPONSE PARSER
|
|
||||||
|
|
||||||
;; Parsers takes data from a response, and builds a map with standardized keys
|
|
||||||
|
|
||||||
;; Builds a json-data object
|
|
||||||
(defn make-json-data
|
|
||||||
[json-key hash-key & [fn-value]]
|
|
||||||
(if (some? fn-value)
|
|
||||||
{:json-key json-key :hash-key hash-key :fn-value fn-value}
|
|
||||||
{:json-key json-key :hash-key hash-key :fn-value #(identity %)}))
|
|
||||||
|
|
||||||
;; Postprocess functions
|
|
||||||
(defn post-calculate-end
|
|
||||||
[match & _]
|
|
||||||
(assoc match :end
|
|
||||||
(+ (:start match) (* 1000 (int (:duration match))))))
|
|
||||||
|
|
||||||
; Winner?
|
|
||||||
|
|
||||||
(defn pos-in-col
|
|
||||||
"Find the indexes of an element inside a collection.
|
|
||||||
If there are multiple ocurrences, there will be multiple indexes in the result.
|
|
||||||
If the collection is a map, keys are returned"
|
|
||||||
[col x]
|
|
||||||
(reduce-kv (fn [m k v]
|
|
||||||
(if (= v x)
|
|
||||||
(conj m k)
|
|
||||||
m))
|
|
||||||
[] col))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-player-info
|
|
||||||
[match-resp puuid]
|
|
||||||
(let [participants (get-in match-resp [:metadata :participants])
|
|
||||||
idx (first (pos-in-col participants puuid))
|
|
||||||
player-info (get-in match-resp [:info :participants idx])]
|
|
||||||
player-info))
|
|
||||||
|
|
||||||
|
|
||||||
(defn winner?
|
|
||||||
[match-resp puuid]
|
|
||||||
(:win (get-player-info match-resp puuid)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn post-calculate-win
|
|
||||||
[data response puuid]
|
|
||||||
(assoc data :winner (winner? response puuid)))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(get-in riot.test-examples/response-lol-match [:metadata :participants])
|
|
||||||
(get-in riot.test-examples/response-lol-match [:info :participants 3])
|
|
||||||
|
|
||||||
(get-player-info riot.test-examples/response-lol-match riot.test-examples/example-lol-puuid)
|
|
||||||
(winner? riot.test-examples/response-lol-match riot.test-examples/example-lol-puuid))
|
|
||||||
|
|
||||||
|
|
||||||
(defn with-winner-status
|
|
||||||
"Takes the original list of matches and parses durations"
|
|
||||||
[matches puuid]
|
|
||||||
(map #(assoc % :winner (winner? % puuid)) matches))
|
|
||||||
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(with-winner-status riot.test-examples/matches-example riot.test-examples/example-lol-puuid))
|
|
||||||
|
|
||||||
|
|
||||||
;; json adapters
|
|
||||||
(def player-info-parser {:parser [(make-json-data [:puuid] :puuid)]})
|
|
||||||
|
|
||||||
(def lol-match-parser {:parser [(make-json-data [:info :gameCreation] :start)
|
|
||||||
(make-json-data [:info :gameEndTimestamp] :end)
|
|
||||||
(make-json-data [:info :gameDuration] :duration)
|
|
||||||
(make-json-data [:none] :active (constantly false))
|
|
||||||
(make-json-data [:none] :game-type (constantly "lol"))
|
|
||||||
(make-json-data [:metadata :matchId] :id)
|
|
||||||
(make-json-data [:none] :winner (constantly false))]
|
|
||||||
:post post-calculate-win})
|
|
||||||
|
|
||||||
(def tft-match-parser {:parser [(make-json-data [:info :gameCreation] :start)
|
|
||||||
(make-json-data [:none] :end (constantly -1))
|
|
||||||
(make-json-data [:info :game_length] :duration #(int %)) ; rounds to integer
|
|
||||||
(make-json-data [:none] :active (constantly false))
|
|
||||||
(make-json-data [:none] :game-type (constantly "ftf"))
|
|
||||||
(make-json-data [:metadata :match_id] :id)
|
|
||||||
(make-json-data [:none] :winner (constantly false))]
|
|
||||||
:post #(post-calculate-win
|
|
||||||
(post-calculate-end %1 %2 %3) %2 %3)}) ; end = start + (duration * 1000)
|
|
||||||
|
|
||||||
(def lol-current-parser {:parser [(make-json-data [:gameStartTime] :start)
|
|
||||||
(make-json-data [:none] :end (constantly nil))
|
|
||||||
(make-json-data [:gameLength] :duration)
|
|
||||||
(make-json-data [:none] :active (constantly true))
|
|
||||||
(make-json-data [:none] :game-type (constantly "lol"))
|
|
||||||
(make-json-data [:gameId] :id)
|
|
||||||
(make-json-data [:none] :winner (constantly nil))]})
|
|
||||||
|
|
||||||
(def tft-current-parser {:parser [(make-json-data [:gameStartTime] :start)
|
|
||||||
(make-json-data [:none] :end (constantly nil))
|
|
||||||
(make-json-data [:gameLength] :duration)
|
|
||||||
(make-json-data [:none] :active (constantly true))
|
|
||||||
(make-json-data [:none] :game-type (constantly "ftf"))
|
|
||||||
(make-json-data [:gameId] :id)
|
|
||||||
(make-json-data [:none] :winner (constantly nil))]})
|
|
||||||
|
|
||||||
|
|
||||||
(defn parse-response
|
|
||||||
"Takes a parser and a response and resturns a hasmap with known keys"
|
|
||||||
[parser response puuid]
|
|
||||||
(let [data (into {} (map
|
|
||||||
#(vector
|
|
||||||
(:hash-key %)
|
|
||||||
((:fn-value %) (get-in response (:json-key %))))
|
|
||||||
(:parser parser)))
|
|
||||||
postfn (:post parser)]
|
|
||||||
(if (some? postfn)
|
|
||||||
(postfn data response puuid)
|
|
||||||
data)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn create-endpoint
|
|
||||||
"Create a URL for the API"
|
|
||||||
[server & parts]
|
|
||||||
(apply str "https://" server "." API-HOST parts))
|
|
||||||
|
|
||||||
|
|
||||||
(defn raw-get-query
|
|
||||||
"Send a query to the API and parsers the result"
|
|
||||||
[url & {:keys [api-key params debug]
|
|
||||||
:or {params nil
|
|
||||||
debug false}}]
|
|
||||||
(when debug (println "** SENDING REQUEST **"))
|
|
||||||
;; (println "Params: " params)
|
|
||||||
(:body (client/get url
|
|
||||||
{:debug debug
|
|
||||||
:save-request? true
|
|
||||||
:headers {:X-Riot-Token api-key}
|
|
||||||
:query-params (when (map? params) params)
|
|
||||||
:as :json})))
|
|
||||||
|
|
||||||
|
|
||||||
(defn query
|
|
||||||
"Send a query to the API and parsers the result"
|
|
||||||
[url parser & {:keys [puuid api-key params debug]
|
|
||||||
:or {api-key nil
|
|
||||||
params nil
|
|
||||||
debug false}}]
|
|
||||||
(parse-response parser (raw-get-query url :api-key api-key :params params :debug debug) puuid))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;;; MAIN QUERY FUNCTIONS
|
|
||||||
|
|
||||||
(defn get-puuid-from-name
|
|
||||||
"Get player's PUUID from its name and tag"
|
|
||||||
[playername tag & {:keys [api-key debug server]
|
|
||||||
:or {debug false
|
|
||||||
server "europe"}}]
|
|
||||||
(:puuid (raw-get-query
|
|
||||||
(create-endpoint server "/riot/account/v1/accounts/by-riot-id/" playername "/" tag)
|
|
||||||
:api-key api-key
|
|
||||||
:debug debug)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn date-to-seconds
|
|
||||||
([] (date-to-seconds (java.util.Date.)))
|
|
||||||
([d]
|
|
||||||
(when (some? d) (quot (.getTime d) 1000))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn query-params
|
|
||||||
"Calculate query params"
|
|
||||||
[& {:keys [count start since until]
|
|
||||||
:or {count 100}}]
|
|
||||||
(cond-> {"count" count}
|
|
||||||
(some? start) (assoc "start" start)
|
|
||||||
(some? since) (assoc "startTime" (date-to-seconds since))
|
|
||||||
(some? until) (assoc "endTime" (date-to-seconds until))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-lol-matches
|
|
||||||
"Get last LoL match-ids for a given PUUID"
|
|
||||||
[puuid & {:keys [api-key debug server count start since until]
|
|
||||||
:or {api-key (get-lol-api-key)
|
|
||||||
debug false
|
|
||||||
server "europe"
|
|
||||||
count 20
|
|
||||||
start 0}}]
|
|
||||||
;; (println "get lol start: " start)
|
|
||||||
(raw-get-query
|
|
||||||
(create-endpoint server "/lol/match/v5/matches/by-puuid/" puuid "/ids")
|
|
||||||
:api-key api-key
|
|
||||||
:params (query-params :count count :start start :since since :until until)
|
|
||||||
:debug debug))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-tft-matches
|
|
||||||
"Get last TFT match-ids for a given PUUID"
|
|
||||||
[puuid & {:keys [api-key debug server count start since until]
|
|
||||||
:or {api-key (get-tft-api-key)
|
|
||||||
debug false
|
|
||||||
server "europe"
|
|
||||||
count 20
|
|
||||||
start 0}}]
|
|
||||||
(raw-get-query
|
|
||||||
(create-endpoint server "/tft/match/v1/matches/by-puuid/" puuid "/ids")
|
|
||||||
:api-key api-key
|
|
||||||
:params (query-params :count count :start start :since since :until until)
|
|
||||||
:debug debug))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-lol-match-info
|
|
||||||
"Get info for a LoL match"
|
|
||||||
[match-id & {:keys [api-key debug server puuid]
|
|
||||||
:or {api-key (get-lol-api-key)
|
|
||||||
debug false
|
|
||||||
server "europe"}}]
|
|
||||||
;; (println "get-lol-match-info match:" match-id)
|
|
||||||
(query
|
|
||||||
(create-endpoint server "/lol/match/v5/matches/" match-id)
|
|
||||||
lol-match-parser
|
|
||||||
:api-key api-key
|
|
||||||
:debug debug
|
|
||||||
:puuid puuid))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-tft-match-info
|
|
||||||
"Get info for a TFT match"
|
|
||||||
[match-id & {:keys [api-key debug server puuid]
|
|
||||||
:or {api-key (get-tft-api-key)
|
|
||||||
debug false
|
|
||||||
server "europe"}}]
|
|
||||||
;; (println "get-tft-match-info match:" match-id)
|
|
||||||
(query
|
|
||||||
(create-endpoint server "/tft/match/v1/matches/" match-id)
|
|
||||||
tft-match-parser
|
|
||||||
:api-key api-key
|
|
||||||
:debug debug
|
|
||||||
:puuid puuid))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-lol-current-info
|
|
||||||
"Get current LoL match, if any"
|
|
||||||
[puuid & {:keys [api-key debug print-not-active server]
|
|
||||||
:or {api-key (get-lol-api-key)
|
|
||||||
debug false
|
|
||||||
print-not-active false
|
|
||||||
server "euw1"}}]
|
|
||||||
(try+
|
|
||||||
(query
|
|
||||||
(create-endpoint server "/lol/spectator/v5/active-games/by-summoner/" puuid)
|
|
||||||
lol-current-parser
|
|
||||||
:api-key api-key
|
|
||||||
:debug debug)
|
|
||||||
(catch [:status 404] _
|
|
||||||
(when print-not-active (println "No active LoL match")))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-tft-current-info
|
|
||||||
"Get current TFT match, if any"
|
|
||||||
[puuid & {:keys [api-key debug print-not-active server]
|
|
||||||
:or {api-key (get-tft-api-key)
|
|
||||||
debug false
|
|
||||||
print-not-active false
|
|
||||||
server "euw1"}}]
|
|
||||||
(try+
|
|
||||||
(query
|
|
||||||
(create-endpoint server "/lol/spectator/tft/v5/active-games/by-puuid/" puuid)
|
|
||||||
tft-current-parser
|
|
||||||
:api-key api-key
|
|
||||||
:debug debug)
|
|
||||||
(catch [:status 404] _
|
|
||||||
(when print-not-active (println "No active FTF match")))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn is-playing?
|
|
||||||
"Checks if player is in and active LoL or TFT match"
|
|
||||||
[lol-puuid tft-puuid & {:keys [lol-api-key tft-api-key debug server print-not-active]
|
|
||||||
:or {lol-api-key (get-lol-api-key)
|
|
||||||
tft-api-key (get-tft-api-key)
|
|
||||||
debug false
|
|
||||||
print-not-active false
|
|
||||||
server "euw1"}}]
|
|
||||||
(or (some? (get-lol-current-info lol-puuid :api-key lol-api-key :server server :debug debug :print-not-active print-not-active))
|
|
||||||
(some? (get-tft-current-info tft-puuid :api-key tft-api-key :server server :debug debug :print-not-active print-not-active))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-last-matches
|
|
||||||
"Get info for last LoL or FTF matches"
|
|
||||||
[lol-puuid tft-puuid & {:keys [lol-api-key tft-api-key include-current print-not-active debug server1 server2 count start order-by since until]
|
|
||||||
:or {lol-api-key (get-lol-api-key)
|
|
||||||
tft-api-key (get-tft-api-key)
|
|
||||||
include-current true
|
|
||||||
print-not-active false
|
|
||||||
debug false
|
|
||||||
server1 "europe"
|
|
||||||
server2 "euw1"
|
|
||||||
count 20
|
|
||||||
start 0
|
|
||||||
order-by :start}}]
|
|
||||||
(sort-by order-by
|
|
||||||
(filter some?
|
|
||||||
(concat
|
|
||||||
(map
|
|
||||||
#(get-lol-match-info % :api-key lol-api-key :debug debug :server server1 :puuid lol-puuid)
|
|
||||||
(get-lol-matches lol-puuid :api-key lol-api-key :debug debug :server server1 :count count :start start :since since :until until))
|
|
||||||
(map
|
|
||||||
#(get-tft-match-info % :api-key tft-api-key :debug debug :server server1 :puuid tft-puuid)
|
|
||||||
(get-tft-matches tft-puuid :api-key tft-api-key :debug debug :server server1 :count count :start start :since since :until until))
|
|
||||||
(when include-current [(get-lol-current-info lol-puuid :api-key lol-api-key :server server2 :debug debug :print-not-active print-not-active)])
|
|
||||||
(when include-current [(get-tft-current-info tft-puuid :api-key tft-api-key :server server2 :debug debug :print-not-active print-not-active)])))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;;;; Get data bulk
|
|
||||||
|
|
||||||
(defn get-with-wait
|
|
||||||
"Calls a getter and waits for response. If rate limit has been exceeded, waits for some
|
|
||||||
seconds and retries."
|
|
||||||
[getter & {:keys [wait-limit-exceeded]
|
|
||||||
:or {wait-limit-exceeded 15}}]
|
|
||||||
(try+
|
|
||||||
(getter)
|
|
||||||
(catch [:status 429] _
|
|
||||||
(println "Rate limit exceeded, waiting for" wait-limit-exceeded "seconds")
|
|
||||||
(Thread/sleep (* 1000 wait-limit-exceeded))
|
|
||||||
(get-with-wait getter))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-batch-range
|
|
||||||
"Gets data in batches. Getter should be a function with one argument"
|
|
||||||
[getter & {:keys [wait-limit-exceeded first-batch max-batches]
|
|
||||||
:or {wait-limit-exceeded 15
|
|
||||||
first-batch 0
|
|
||||||
max-batches 10}}]
|
|
||||||
;; (println "Obtaining bulk data - range")
|
|
||||||
(doall (flatten (concat
|
|
||||||
(map
|
|
||||||
#(get-with-wait (partial getter %) :wait-limit-exceeded wait-limit-exceeded)
|
|
||||||
(range first-batch max-batches))))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-batch-seq
|
|
||||||
"Gets data from a secquence. The getter should be a function with one argument"
|
|
||||||
[getter seq & {:keys [wait-limit-exceeded]
|
|
||||||
:or {wait-limit-exceeded 15}}]
|
|
||||||
;; (println "Obtaining bulk data - seq")
|
|
||||||
(doall (flatten (concat
|
|
||||||
(map
|
|
||||||
#(get-with-wait (partial getter %) :wait-limit-exceeded wait-limit-exceeded)
|
|
||||||
seq)))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-matches-batch-lol
|
|
||||||
"Get a lot of LOL match IDs"
|
|
||||||
[puuid api-key & {:keys [server since until wait-limit-exceeded first-batch max-batches count debug]
|
|
||||||
:or {server "europe"
|
|
||||||
wait-limit-exceeded 15
|
|
||||||
first-batch 0
|
|
||||||
max-batches 10
|
|
||||||
count 100
|
|
||||||
debug false}}]
|
|
||||||
(when (every? some? [puuid api-key])
|
|
||||||
(get-batch-range #(get-lol-matches puuid :api-key api-key :start (* count %) :since since :until until :server server :wait-limit-exceeded wait-limit-exceeded :debug debug :count count)
|
|
||||||
:wait-limit-exceeded wait-limit-exceeded
|
|
||||||
:first-batch first-batch
|
|
||||||
:max-batches max-batches)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-matches-batch-tft
|
|
||||||
"Get a lot of TFT match IDs"
|
|
||||||
[puuid api-key & {:keys [server since until wait-limit-exceeded first-batch max-batches count debug]
|
|
||||||
:or {server "europe"
|
|
||||||
wait-limit-exceeded 15
|
|
||||||
first-batch 0
|
|
||||||
max-batches 10
|
|
||||||
count 100
|
|
||||||
debug false}}]
|
|
||||||
(when (every? some? [puuid api-key])
|
|
||||||
(get-batch-range #(get-tft-matches puuid :api-key api-key :start (* count %) :since since :until until :server server :wait-limit-exceeded wait-limit-exceeded :debug debug :count count)
|
|
||||||
:wait-limit-exceeded wait-limit-exceeded
|
|
||||||
:first-batch first-batch
|
|
||||||
:max-batches max-batches)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-matches-info-batch-lol
|
|
||||||
"Get a lot of LOL matches info"
|
|
||||||
[matches-id puuid api-key & {:keys [server wait-limit-exceeded debug]
|
|
||||||
:or {server "europe"
|
|
||||||
wait-limit-exceeded 15
|
|
||||||
debug false}}]
|
|
||||||
;; (println "Matches: " matches-id)
|
|
||||||
(when (every? some? [matches-id puuid api-key])
|
|
||||||
(get-batch-seq #(get-lol-match-info % :puuid puuid :api-key api-key :server server :wait-limit-exceeded wait-limit-exceeded :debug debug)
|
|
||||||
matches-id
|
|
||||||
:wait-limit-exceeded wait-limit-exceeded)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-matches-info-batch-tft
|
|
||||||
"Get a lot of TFT matches info"
|
|
||||||
[matches-id puuid api-key & {:keys [server wait-limit-exceeded debug]
|
|
||||||
:or {server "europe"
|
|
||||||
wait-limit-exceeded 15
|
|
||||||
debug false}}]
|
|
||||||
(when (every? some? [matches-id puuid api-key])
|
|
||||||
(get-batch-seq #(get-tft-match-info % :puuid puuid :api-key api-key :server server :wait-limit-exceeded wait-limit-exceeded :debug debug)
|
|
||||||
matches-id
|
|
||||||
:wait-limit-exceeded wait-limit-exceeded)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn get-matches-info-batch
|
|
||||||
"Get a lot of LOL and TFT matches info"
|
|
||||||
[lol-puuid tft-puuid & {:keys [lol-api-key tft-api-key wait-limit-exceeded debug server count order-by since until]
|
|
||||||
:or {lol-api-key (get-lol-api-key)
|
|
||||||
tft-api-key (get-tft-api-key)
|
|
||||||
wait-limit-exceeded 15
|
|
||||||
debug false
|
|
||||||
server "europe"
|
|
||||||
count 100
|
|
||||||
order-by :start}}]
|
|
||||||
(sort-by order-by
|
|
||||||
(filter some?
|
|
||||||
(concat
|
|
||||||
(get-matches-info-batch-lol (get-matches-batch-lol lol-puuid lol-api-key :wait-limit-exceeded wait-limit-exceeded :debug debug :server server :count count :since since :until until)
|
|
||||||
lol-puuid lol-api-key :debug debug :server server :puuid lol-puuid)
|
|
||||||
(get-matches-info-batch-tft (get-matches-batch-tft tft-puuid tft-api-key :wait-limit-exceeded wait-limit-exceeded :debug debug :server server :count count :since since :until until)
|
|
||||||
tft-puuid tft-api-key :debug debug :server server :puuid lol-puuid)))))
|
|
||||||
@@ -1,173 +0,0 @@
|
|||||||
|
|
||||||
;; Parsing data
|
|
||||||
|
|
||||||
(ns riot.data
|
|
||||||
(:import [java.time Instant LocalDate ZoneId Duration]
|
|
||||||
[java.time.format DateTimeFormatter])
|
|
||||||
(:require [clojure.pprint :as pp]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[cheshire.core :refer :all])
|
|
||||||
(:use [riot.core :refer :all])
|
|
||||||
(:gen-class))
|
|
||||||
|
|
||||||
|
|
||||||
(def DEFAULT_DATE_TIME_FORMAT "yyyy-MM-dd HH:mm:ss")
|
|
||||||
(def DEFAULT_DATE_FORMAT "yyyy-MM-dd")
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse UNIX time
|
|
||||||
|
|
||||||
(defn unix-to-datetime
|
|
||||||
"Conver from UNIX time in millis, to a ZonedDateTime"
|
|
||||||
[millis]
|
|
||||||
(when (some? millis)
|
|
||||||
(.atZone (Instant/ofEpochMilli millis) (ZoneId/systemDefault))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn localdate-to-date
|
|
||||||
"Converts a java.time.LocalDate to an ancient java.util.Date"
|
|
||||||
[localdate]
|
|
||||||
(when (some? localdate)
|
|
||||||
(java.util.Date/from (.toInstant (.atZone (.atStartOfDay localdate) (ZoneId/systemDefault))))))
|
|
||||||
|
|
||||||
(defn parse-localdate
|
|
||||||
"Parse a yyyy-MM-dd date to java.time.LocalDate"
|
|
||||||
[s]
|
|
||||||
(java.time.LocalDate/parse s (DateTimeFormatter/ofPattern DEFAULT_DATE_FORMAT)))
|
|
||||||
|
|
||||||
(defn parse-date-str
|
|
||||||
[s]
|
|
||||||
(localdate-to-date (parse-localdate s)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn parse-date-epoch
|
|
||||||
[millis]
|
|
||||||
(localdate-to-date (unix-to-datetime millis)))
|
|
||||||
|
|
||||||
|
|
||||||
(defn format-datetime
|
|
||||||
"Converts a LocalDateTime to its string representation"
|
|
||||||
([dtime] (format-datetime dtime DEFAULT_DATE_TIME_FORMAT))
|
|
||||||
([dtime pattern]
|
|
||||||
(when (and (some? dtime) (some? pattern))
|
|
||||||
(.format (DateTimeFormatter/ofPattern pattern) dtime))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn format-datetime-millis
|
|
||||||
"Converts a UNIX time in millis to a string representation"
|
|
||||||
([millis] (format-datetime-millis millis DEFAULT_DATE_TIME_FORMAT))
|
|
||||||
([millis pattern]
|
|
||||||
(when (and (some? millis) (some? pattern))
|
|
||||||
(format-datetime (unix-to-datetime millis) pattern))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse durations
|
|
||||||
(defn format-duration-seconds
|
|
||||||
"Converts a duration in seconds to a string with hours and seconds"
|
|
||||||
[seconds]
|
|
||||||
(when (some? seconds)
|
|
||||||
(if (< seconds 3600)
|
|
||||||
(format "%02d:%02d" (quot seconds 60) (rem seconds 60))
|
|
||||||
(format "%02d:%02d:%02d" (quot seconds 3600) (- (quot seconds 60) 60) (rem seconds 60)))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn today-millis
|
|
||||||
"Epoch time in millis for 00:00:00 of today"
|
|
||||||
[]
|
|
||||||
(* 1000 (. (. (LocalDate/now) atStartOfDay (ZoneId/systemDefault)) toEpochSecond)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn match-today?
|
|
||||||
"Predicate that is true if the match has been played today.
|
|
||||||
|
|
||||||
A match has been played today if its start date or end date is from today"
|
|
||||||
[match]
|
|
||||||
(or
|
|
||||||
(>= (or (:start match) 0) (today-millis))
|
|
||||||
(>= (or (:end match) 0) (today-millis))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse hashmaps
|
|
||||||
|
|
||||||
(defn with-parsed-dates
|
|
||||||
"Takes the original list of matches and parses dates"
|
|
||||||
[matches & {:keys [datetime-format]
|
|
||||||
:or {datetime-format DEFAULT_DATE_TIME_FORMAT}}]
|
|
||||||
(->> matches
|
|
||||||
(map #(update % :start (fn [x] (format-datetime-millis x datetime-format))))
|
|
||||||
(map #(update % :end (fn [x] (format-datetime-millis x datetime-format))))))
|
|
||||||
(comment
|
|
||||||
(with-parsed-dates riot.test-examples/matches-example))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn with-parsed-durations
|
|
||||||
"Takes the original list of matches and parses durations"
|
|
||||||
[matches]
|
|
||||||
(map #(update % :duration format-duration-seconds) matches))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn with-parsed-dates-durations
|
|
||||||
"Takes the original list of matches and parses dates and durations"
|
|
||||||
[matches & {:keys [datetime-format]
|
|
||||||
:or {datetime-format DEFAULT_DATE_TIME_FORMAT}}]
|
|
||||||
(-> matches
|
|
||||||
(with-parsed-durations)
|
|
||||||
(with-parsed-dates :datetime-format datetime-format)))
|
|
||||||
|
|
||||||
|
|
||||||
;;; Export to other formats
|
|
||||||
|
|
||||||
(def headers [[:game-type "Type"]
|
|
||||||
[:start "Start"]
|
|
||||||
[:end "End"]
|
|
||||||
[:duration "Duration"]
|
|
||||||
[:active "Now playing?"]])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn as-json
|
|
||||||
"Take a list with matches and parse it as a JSON string"
|
|
||||||
[matches & {:keys [pretty]
|
|
||||||
:or {pretty true}}]
|
|
||||||
|
|
||||||
(generate-string matches {:pretty pretty}))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(println (as-json (with-parsed-dates-durations riot.test-examples/matches-example
|
|
||||||
:pretty false))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn as-ascii-table
|
|
||||||
"Export as ascii table"
|
|
||||||
[matches]
|
|
||||||
(pp/print-table matches))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(as-ascii-table riot.test-examples/matches-example)
|
|
||||||
(as-ascii-table (with-parsed-dates-durations riot.test-examples/matches-example)))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
(defn as-csv
|
|
||||||
"Export as CSV"
|
|
||||||
([matches] (as-csv matches ","))
|
|
||||||
([matches separator]
|
|
||||||
(str/join (System/lineSeparator) ; Local EOL characteres
|
|
||||||
(concat
|
|
||||||
[(clojure.string/join separator (map name (keys (first matches))))] ; header
|
|
||||||
(map #(clojure.string/join separator %)
|
|
||||||
(map vals matches))))))
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(as-csv riot.test-examples/matches-example)
|
|
||||||
(as-csv riot.test-examples/matches-example2)
|
|
||||||
(as-csv (with-parsed-dates-durations riot.test-examples/matches-example))
|
|
||||||
(as-csv (with-parsed-dates-durations riot.test-examples/matches-example2)))
|
|
||||||
@@ -1,299 +0,0 @@
|
|||||||
(ns riot.core-test
|
|
||||||
(:require [clojure.test :refer :all]
|
|
||||||
[riot.test-examples :refer :all]
|
|
||||||
[riot.core :refer :all]
|
|
||||||
[timewords.core :refer [parse]]
|
|
||||||
[clojure.pprint :as pp])
|
|
||||||
(:use [slingshot.slingshot :only [try+]]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Tests encryption and decryption of data
|
|
||||||
(deftest test-encryption
|
|
||||||
(println "* Testing encryption *")
|
|
||||||
(let [orig "secret"
|
|
||||||
enc "Dbokabdn7We5iisgONMlfQZKCjqTaGKmuThA8PaNeO8="]
|
|
||||||
(testing "Cypher a text"
|
|
||||||
(is (= "Dbokabdn7We5iisgONMlfQZKCjqTaGKmuThA8PaNeO8=" (encrypt-data orig))))
|
|
||||||
(testing "Decypher a text"
|
|
||||||
(is (= "secret" (decrypt-data enc))))
|
|
||||||
(testing "Cypher and decypher"
|
|
||||||
(is (= orig (decrypt-data (encrypt-data orig)))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; NOTE: we can't test getting API from environment
|
|
||||||
;; Please, unset LOL_KEY or TFT_KEY from your environment before launch tests
|
|
||||||
(deftest test-get-apis
|
|
||||||
(println "* Testing how to get apis *")
|
|
||||||
(testing "Get LOL API key"
|
|
||||||
(is (= (decrypt-data LOL_KEY) (get-lol-api-key)))
|
|
||||||
(is (= (decrypt-data LOL_KEY) (get-lol-api-key nil)))
|
|
||||||
(is (= "abc" (get-lol-api-key "abc"))))
|
|
||||||
(testing "Get TFT API key"
|
|
||||||
(is (= (decrypt-data TFT_KEY) (get-tft-api-key)))
|
|
||||||
(is (= (decrypt-data TFT_KEY) (get-tft-api-key nil)))
|
|
||||||
(is (= "abc" (get-tft-api-key "abc")))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Make JSON data
|
|
||||||
(deftest test-make-json-data
|
|
||||||
(println "* Testing make-json-data *")
|
|
||||||
(testing "Default fn-value"
|
|
||||||
(are [exp res]
|
|
||||||
(= (select-keys [:json-key :hash-key] exp) (select-keys [:json-key :hash-key] res))
|
|
||||||
{:json-key "key1" :hash-key "key2"} (make-json-data "key1" "key2")
|
|
||||||
{:json-key :key1 :hash-key :key2} (make-json-data :key1 :key2)
|
|
||||||
{:json-key nil :hash-key nil} (make-json-data nil nil)))
|
|
||||||
(testing "With fn-value"
|
|
||||||
(are [exp res] (= exp res)
|
|
||||||
{:json-key "key1" :hash-key "key2" :fn-value +} (make-json-data "key1" "key2" +)
|
|
||||||
{:json-key :key1 :hash-key :key2 :fn-value +} (make-json-data :key1 :key2 +)
|
|
||||||
{:json-key nil :hash-key nil :fn-value +} (make-json-data nil nil +))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse a response
|
|
||||||
(deftest test-parse-response
|
|
||||||
(println "* Parse resonse from a query *")
|
|
||||||
(is (= (select-keys response-player-info [:puuid]) (parse-response player-info-parser response-player-info nil))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Find the index of an element inside a collection
|
|
||||||
(deftest test-pos-in-col
|
|
||||||
(println "* Testin index inside a collection *")
|
|
||||||
(testing "Nil values"
|
|
||||||
(is (= [] (pos-in-col nil "abc")))
|
|
||||||
(is (= [] (pos-in-col ["a" "b" "c"] nil))))
|
|
||||||
(testing "Vectors"
|
|
||||||
(is (= [2] (pos-in-col [3 1 2 4 1 5] 2)))
|
|
||||||
(is (= [1 4] (pos-in-col [3 1 2 4 1 5] 1)))
|
|
||||||
(is (= [] (pos-in-col [3 1 2 4 1 5] 9))))
|
|
||||||
(testing "Secuences"
|
|
||||||
(is (= [2] (pos-in-col (clojure.string/split "3 1 2 4 1 5" #" ") "2")))
|
|
||||||
(is (= [1 4] (pos-in-col (clojure.string/split "3 1 2 4 1 5" #" ") "1")))
|
|
||||||
(is (= [] (pos-in-col (clojure.string/split "3 1 2 4 1 5" #" ") "9"))))
|
|
||||||
(testing "Maps"
|
|
||||||
(is (= [:c] (pos-in-col {:a 3 :b 1 :c 2 :d 4 :e 1 :f 5} 2)))
|
|
||||||
(is (= [:b :e] (pos-in-col {:a 3 :b 1 :c 2 :d 4 :e 1 :f 5} 1)))
|
|
||||||
(is (= [] (pos-in-col {:a 3 :b 1 :c 2 :d 4 :e 1 :f 5} 9)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Create a URL
|
|
||||||
(deftest test-create-endpoint
|
|
||||||
(println "* Testing create URL for a remote endpoint *")
|
|
||||||
(testing "Simple URL"
|
|
||||||
(are [exp res] (= exp res)
|
|
||||||
"https://test.api.riotgames.com" (create-endpoint "test")
|
|
||||||
"https://.api.riotgames.com" (create-endpoint "")
|
|
||||||
"https://.api.riotgames.com" (create-endpoint nil)))
|
|
||||||
(println "* Testing create URL for a remote endpoint *")
|
|
||||||
(testing "Complex URL"
|
|
||||||
(are [exp res] (= exp res)
|
|
||||||
"https://test.api.riotgames.compath" (create-endpoint "test" "path")
|
|
||||||
"https://test.api.riotgames.com/path" (create-endpoint "test" "/path")
|
|
||||||
"https://.api.riotgames.com" (create-endpoint "" "")
|
|
||||||
"https://.api.riotgames.com" (create-endpoint nil nil)
|
|
||||||
"https://test.api.riotgames.com/path/id?query" (create-endpoint "test" "/path/" "id" "?query"))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Make a raw HTML GET query
|
|
||||||
(deftest test-raw-get-query
|
|
||||||
(println "* Testing get raw data from Riot API *")
|
|
||||||
(testing "Get user data raw"
|
|
||||||
(is (= response-player-info (raw-get-query "https://europe.api.riotgames.com/riot/account/v1/accounts/by-riot-id/Errepunto/4595" :api-key (get-lol-api-key))))
|
|
||||||
(is (some? (raw-get-query "https://europe.api.riotgames.com/lol/match/v5/matches/EUW1_7434497430" :api-key (get-lol-api-key))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Make a query and parse result with a parser
|
|
||||||
(deftest test-query
|
|
||||||
(println "* Testing get parsed data from Riot API *")
|
|
||||||
(testing "Get user data parsed"
|
|
||||||
(is (= (select-keys response-player-info [:puuid]) (query "https://europe.api.riotgames.com/riot/account/v1/accounts/by-riot-id/Errepunto/4595" player-info-parser :api-key (get-lol-api-key))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get PUUID
|
|
||||||
(deftest test-get-puuid-from-name
|
|
||||||
(println "* Get PUUID from user name and tag *")
|
|
||||||
(testing "Get PUUID using lol api"
|
|
||||||
(is (= (:puuid response-player-info) (get-puuid-from-name "Errepunto" "4595" :api-key (get-lol-api-key))))
|
|
||||||
; THROWS EXCEPTION ;(is (= nil (get-puuid-from-name "Not_existing" "" :api-key (decrypt-data LOL_KEY))))
|
|
||||||
))
|
|
||||||
|
|
||||||
(comment (get-puuid-from-name example-name example-tag :api-key (get-tft-api-key)))
|
|
||||||
|
|
||||||
;; From java.util.Date to seconds since 1970
|
|
||||||
(deftest test-date-to-seconds
|
|
||||||
(println "* Date to epoch seconds *")
|
|
||||||
(testing "Some dates"
|
|
||||||
(is (nil? (date-to-seconds nil)))
|
|
||||||
(is (some? (date-to-seconds)))
|
|
||||||
(is (= 1738364400 (date-to-seconds (java.util.Date. 125 1 1))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get parameter for querying data
|
|
||||||
(deftest test-query-params
|
|
||||||
(println "* Generate query params *")
|
|
||||||
(testing "None params"
|
|
||||||
(is (= {"count" 100} (query-params))))
|
|
||||||
(testing "Start and count"
|
|
||||||
(is (= {"count" 5 "start" 2} (query-params :count 5 :start 2))))
|
|
||||||
(testing "Times"
|
|
||||||
(is (= {"count" 100 "startTime" 1743631200} (query-params :since (java.util.Date. 125 3 3))))
|
|
||||||
(is (= {"count" 100 "startTime" 1743631200 "endTime" 1744236000} (query-params :since (java.util.Date. 125 3 3) :until (java.util.Date. 125 3 10))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get LOL matches from PUUID
|
|
||||||
(deftest test-get-lol-matches
|
|
||||||
(println "* Getting LOL matches *")
|
|
||||||
(testing "Famous player"
|
|
||||||
(let [res (get-lol-matches example-lol-puuid :count 5)]
|
|
||||||
(is (seq? res))
|
|
||||||
(is (= 5 (count res)))
|
|
||||||
(is (some? (get-lol-matches example-lol-puuid :since (java.util.Date. 2025 1 1) :until (java.util.Date. 2025 1 31))))))
|
|
||||||
(testing "Never played"
|
|
||||||
(let [res (get-lol-matches example-lol-never-played :count 5)]
|
|
||||||
(is (seq? res))
|
|
||||||
(is (= 0 (count res))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get TFT matches from PUUID
|
|
||||||
;; I NEED A PRODUCTION KEY FIRST
|
|
||||||
(comment
|
|
||||||
(deftest test-get-tft-matches
|
|
||||||
(println "* Getting FTF matches *")
|
|
||||||
(testing "Famous player"
|
|
||||||
(let [res (get-tft-matches example-tft-puuid :count 5)]
|
|
||||||
(is (seq? res))
|
|
||||||
(is (= 5 (count res)))))
|
|
||||||
(testing "Never played"
|
|
||||||
(let [res (get-tft-matches example-tft-never-played :count 5)]
|
|
||||||
(is (seq? res))
|
|
||||||
(is (= 0 (count res)))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get info from one LOL match
|
|
||||||
(deftest test-get-lol-match-info
|
|
||||||
(println "* Getting one LOL match info *")
|
|
||||||
(let [res (get-lol-match-info "EUW1_7434497430" :puuid example-lol-puuid)]
|
|
||||||
(is (some? res))
|
|
||||||
(is (= example-lol-match res))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get info from one TFT match
|
|
||||||
;; I NEED A PRODUCTION KEY FIRST
|
|
||||||
(comment
|
|
||||||
(deftest test-get-tft-match-info
|
|
||||||
(println "* Getting one TFT match info *")
|
|
||||||
(let [res (get-tft-match-info "EUW1_7420994275")]
|
|
||||||
(is (some? res))
|
|
||||||
(is (= example-tft-match res)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get current LOL playing info
|
|
||||||
;; RESULTS DEPENDS ON PLAYER IS ACTIVE OR NOT
|
|
||||||
(deftest test-get-lol-current-info
|
|
||||||
(println "* Get info from current LOL match *")
|
|
||||||
(let [res (get-lol-current-info example-lol-puuid)]
|
|
||||||
(is (nil? res) (str "Oh, well, the player is playing: " res))) ;; Data only when player is playing.
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
;; Get current LOL playing info
|
|
||||||
;; RESULTS DEPENDS ON PLAYER IS ACTIVE OR NOT
|
|
||||||
;; I NEED A PRODUCTION KEY FIRST
|
|
||||||
(comment
|
|
||||||
(deftest test-get-tft-current-info
|
|
||||||
(println "* Get info from current TFT match *")
|
|
||||||
(let [res (get-tft-current-info example-tft-puuid)]
|
|
||||||
(is (nil? res) (str "Oh, well, the player is playing: " res))) ;; Data only when player is playing.
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
;; Check if the player is currently in a match
|
|
||||||
;; RESULTS DEPENDS ON PLAYER IS ACTIVE OR NOT
|
|
||||||
;; I NEED A PRODUCTION KEY FIRST
|
|
||||||
(comment
|
|
||||||
(deftest test-is-playing?
|
|
||||||
(println "* Check player is playing *")
|
|
||||||
(let [res (is-playing? example-lol-puuid example-tft-puuid)]
|
|
||||||
(is (not res) (str "Oh, well, the player is playing: " res))) ;; Data only when player is playing.
|
|
||||||
))
|
|
||||||
|
|
||||||
|
|
||||||
;; Get last LOL and TFT matches
|
|
||||||
;; RESULTS DEPENDS ON PLAYER IS ACTIVE OR NOT
|
|
||||||
(comment
|
|
||||||
(deftest test-get-last-matches
|
|
||||||
(println "* Get last mateches *")
|
|
||||||
(testing "Don't include current"
|
|
||||||
(let [res (is-playing? example-lol-puuid example-tft-puuid :include-current false)]
|
|
||||||
(is (not res) (str "Oh, well, the player is playing: " res))))
|
|
||||||
(testing "Include current"
|
|
||||||
(let [res (is-playing? example-lol-puuid example-tft-puuid)]
|
|
||||||
(is (not res) (str "Oh, well, the player is playing: " res))))))
|
|
||||||
|
|
||||||
|
|
||||||
(deftest test-get-matches-batch-lol
|
|
||||||
(println "* Get lol matches batch *")
|
|
||||||
(testing "Invalid data"
|
|
||||||
(is (= nil (get-matches-batch-lol nil nil)))
|
|
||||||
(is (= nil (get-matches-batch-lol example-lol-puuid nil)))
|
|
||||||
(is (= nil (get-matches-batch-lol nil (get-lol-api-key)))))
|
|
||||||
(testing "Get LOL matches"
|
|
||||||
(is (= 10 (count (get-matches-batch-lol example-lol-puuid (get-lol-api-key) :count 5 :max-batches 2))))))
|
|
||||||
|
|
||||||
(deftest test-get-matches-batch-tft
|
|
||||||
(println "* Get tft matches batch *")
|
|
||||||
(testing "Invalid data"
|
|
||||||
(is (= nil (get-matches-batch-tft nil nil)))
|
|
||||||
(is (= nil (get-matches-batch-tft example-tft-puuid nil)))
|
|
||||||
(is (= nil (get-matches-batch-tft nil (get-tft-api-key)))))
|
|
||||||
(testing "Get LOL matches"
|
|
||||||
(is (= 10 (count (get-matches-batch-tft example-tft-puuid (get-tft-api-key) :count 5 :max-batches 2))))))
|
|
||||||
|
|
||||||
|
|
||||||
(deftest test-get-matches-info-batch-lol
|
|
||||||
(println "* Get lol matches info batch *")
|
|
||||||
(testing "Invalid data"
|
|
||||||
(is (= nil (get-matches-info-batch-lol nil nil nil)))
|
|
||||||
(is (= nil (get-matches-info-batch-lol nil example-lol-puuid nil)))
|
|
||||||
(is (= nil (get-matches-info-batch-lol nil nil (get-lol-api-key)))))
|
|
||||||
(testing "Get LOL matches"
|
|
||||||
(is (= 10 (count (get-matches-info-batch-lol
|
|
||||||
(get-matches-batch-lol example-lol-puuid (get-lol-api-key) :count 5 :max-batches 2)
|
|
||||||
example-lol-puuid
|
|
||||||
(get-lol-api-key)))))))
|
|
||||||
|
|
||||||
|
|
||||||
(deftest test-get-matches-info-batch-tft
|
|
||||||
(println "* Get tft matches info batch *")
|
|
||||||
(testing "Invalid data"
|
|
||||||
(is (= nil (get-matches-info-batch-tft nil nil nil)))
|
|
||||||
(is (= nil (get-matches-info-batch-tft nil example-tft-puuid nil)))
|
|
||||||
(is (= nil (get-matches-info-batch-tft nil nil (get-tft-api-key)))))
|
|
||||||
(testing "Get tft matches"
|
|
||||||
(is (= 10 (count (get-matches-info-batch-tft
|
|
||||||
(get-matches-batch-tft example-tft-puuid (get-tft-api-key) :count 5 :max-batches 2)
|
|
||||||
example-tft-puuid
|
|
||||||
(get-tft-api-key)))))))
|
|
||||||
|
|
||||||
|
|
||||||
(comment
|
|
||||||
(def matches-lol (get-matches-batch-lol
|
|
||||||
example-lol-puuid
|
|
||||||
(get-lol-api-key)
|
|
||||||
:since (parse "since 5 days") :debug false :count 100 :max-batches 20))
|
|
||||||
|
|
||||||
(count matches-lol) ;; Todos los obtenidos
|
|
||||||
|
|
||||||
(count (set matches-lol)) ;; Esto cuenta sólo los únicos
|
|
||||||
|
|
||||||
(def matches-info (get-matches-info-batch-lol (take 200 matches-lol) example-lol-puuid (get-lol-api-key) :debug false))
|
|
||||||
|
|
||||||
(count matches-info)
|
|
||||||
(count (set matches-info))
|
|
||||||
|
|
||||||
(try+
|
|
||||||
(get-matches-info-batch example-lol-puuid example-tft-puuid)
|
|
||||||
(catch [:status 404] {:keys [request-time headers body] :as excp}
|
|
||||||
(println "NOT Found 404")
|
|
||||||
(pp/pprint excp))))
|
|
||||||
@@ -1,119 +0,0 @@
|
|||||||
(ns riot.data-test
|
|
||||||
(:require [clojure.test :refer :all]
|
|
||||||
[riot.test-examples :refer :all]
|
|
||||||
[riot.data :refer :all]
|
|
||||||
[riot.core :refer :all])
|
|
||||||
(:import [java.time Instant LocalDate ZoneId Duration ZonedDateTime]
|
|
||||||
[java.time.format DateTimeFormatter]))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
;; Convert from epoch in millis (1970-01-01 00:00:00) to ZonedDateTime
|
|
||||||
(deftest test-unix-to-datetime
|
|
||||||
(println "* Epoch millis to java.util.Datetime *")
|
|
||||||
(testing "Get LOL API key"
|
|
||||||
(is (= (ZonedDateTime/of 2025 4 3 0 0 0 0 (ZoneId/systemDefault))
|
|
||||||
(unix-to-datetime 1743631200000)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Format a LocalDateTime o ZonedDateTime as a String
|
|
||||||
(deftest test-format-datetime
|
|
||||||
(println "* DateTime to String *")
|
|
||||||
(testing "Null"
|
|
||||||
(is (nil? (format-datetime-millis nil))))
|
|
||||||
(testing "Default format"
|
|
||||||
(is (= "2025-04-03 00:00:00"
|
|
||||||
(format-datetime (unix-to-datetime 1743631200000)))))
|
|
||||||
(testing "Personalized time formats"
|
|
||||||
(is (= "2025-04-03"
|
|
||||||
(format-datetime (unix-to-datetime 1743631200000) "yyyy-MM-dd")))
|
|
||||||
(is (= "00:00"
|
|
||||||
(format-datetime (unix-to-datetime 1743631200000) "HH:00")))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Format a epoch in millis as a String
|
|
||||||
(deftest test-datetime-millis
|
|
||||||
(println "* DateTime to String *")
|
|
||||||
(testing "Null"
|
|
||||||
(is (nil? (format-datetime-millis nil))))
|
|
||||||
(testing "Default format"
|
|
||||||
(is (= "2025-04-03 00:00:00"
|
|
||||||
(format-datetime-millis 1743631200000))))
|
|
||||||
(testing "Personalized time formats"
|
|
||||||
(is (= "2025-04-03"
|
|
||||||
(format-datetime-millis 1743631200000 "yyyy-MM-dd")))
|
|
||||||
(is (= "00:00"
|
|
||||||
(format-datetime-millis 1743631200000 "HH:00")))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Format a duration in seconds to minutes and seconds
|
|
||||||
(deftest test-format-duration-seconds
|
|
||||||
(println "* Duration in seconds to string *")
|
|
||||||
(testing "Nil duration"
|
|
||||||
(is (nil? (format-duration-seconds nil))))
|
|
||||||
(testing "Short durations"
|
|
||||||
(is (= "00:01" (format-duration-seconds 1)))
|
|
||||||
(is (= "01:01" (format-duration-seconds 61)))
|
|
||||||
(is (= "59:59" (format-duration-seconds 3599))))
|
|
||||||
(testing "Long durations"
|
|
||||||
(is (= "01:00:00" (format-duration-seconds 3600)))
|
|
||||||
(is (= "01:00:01" (format-duration-seconds 3601)))
|
|
||||||
(is (= "01:01:01" (format-duration-seconds 3661)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Epoch in millis for today at 00:00:00 hours. Difficult to test
|
|
||||||
(deftest test-today-millis
|
|
||||||
(println "* Epoch for today *")
|
|
||||||
(testing "Epoch for today"
|
|
||||||
(is (some? (today-millis)))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Match has been played today
|
|
||||||
(deftest test-match-today?
|
|
||||||
(println "* Has the match been played today? *")
|
|
||||||
(testing "Start date today"
|
|
||||||
(is (match-today? {:start (today-millis)}))
|
|
||||||
(is (match-today? {:start (+ 5000 (today-millis))})))
|
|
||||||
(testing "End date today"
|
|
||||||
(is (match-today? {:end (today-millis)}))
|
|
||||||
(is (match-today? {:end (+ 5000 (today-millis))}))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse dates inside a lis of matches
|
|
||||||
(deftest test-with-parsed-dates
|
|
||||||
(println "* Parse dates in a match list*")
|
|
||||||
(testing "Empty or invalid lists"
|
|
||||||
(is (= '() (with-parsed-dates '())))
|
|
||||||
(is (= '({:start nil, :end nil}) (with-parsed-dates '({}))))
|
|
||||||
(is (= '({:a "AAA" :b 2 :start nil, :end nil}) (with-parsed-dates '({:a "AAA" :b 2})))))
|
|
||||||
(testing "Valid list"
|
|
||||||
(is (= '({:start "2025-06-11 19:00:54", :end nil, :duration 1288, :active true, :game-type "lol", :id "EUW1_111111"})
|
|
||||||
(with-parsed-dates (take 1 matches-example))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse durations
|
|
||||||
(deftest test-with-parsed-dates
|
|
||||||
(println "* Parse durations in a match list *")
|
|
||||||
(testing "Empty or invalid lists"
|
|
||||||
(is (= '() (with-parsed-durations '())))
|
|
||||||
(is (= '({:duration nil}) (with-parsed-durations '({}))))
|
|
||||||
(is (= '({:a "AAA" :b 2 :duration nil}) (with-parsed-durations '({:a "AAA" :b 2})))))
|
|
||||||
(testing "Valid list"
|
|
||||||
(is (= '({:start 1749661254854, :end nil, :duration "21:28", :active true, :game-type "lol", :id "EUW1_111111"})
|
|
||||||
(with-parsed-durations (take 1 matches-example))))))
|
|
||||||
|
|
||||||
|
|
||||||
;; Parse dates and durations
|
|
||||||
(deftest test-with-parsed-dates
|
|
||||||
(println "* Parse dates and durations in a match list *")
|
|
||||||
(testing "Empty or invalid lists"
|
|
||||||
(is (= '() (with-parsed-dates-durations '())))
|
|
||||||
(is (= '({:duration nil, :start nil, :end nil})
|
|
||||||
(with-parsed-dates-durations '({}))))
|
|
||||||
(is (= '({:a "AAA" :b 2 :duration nil, :start nil, :end nil})
|
|
||||||
(with-parsed-dates-durations '({:a "AAA" :b 2})))))
|
|
||||||
(testing "Valid list"
|
|
||||||
(is (= '({:start "2025-06-11 19:00:54", :end nil, :duration "21:28", :active true, :game-type "lol", :id "EUW1_111111"})
|
|
||||||
(with-parsed-dates-durations (take 1 matches-example))))))
|
|
||||||
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user