Compare commits
46 Commits
Author | SHA1 | Date | |
---|---|---|---|
eb2bdf34e8 | |||
7604489d29 | |||
29196585ab | |||
6e0842b4f9 | |||
2708918862 | |||
73189203f3 | |||
ce584fd292 | |||
a6f4d4616e | |||
50a42f91f0 | |||
9797bbb9d9 | |||
c5005680b4 | |||
99ef0c40de | |||
cab4709463 | |||
82b864946b | |||
b43139bcbb | |||
81274707d3 | |||
f2ed75e4c8 | |||
dc5f4a03de | |||
8496747ac8 | |||
a637e66258 | |||
0fbea77850 | |||
0d034710b5 | |||
998deef3aa | |||
a740a589be | |||
8bffd2647b | |||
af3fffae43 | |||
a2fb6425a0 | |||
93fa246f14 | |||
fc9d1be2fe | |||
aaabe449d5 | |||
ac571326c3 | |||
cceeb270c4 | |||
f94fd27432 | |||
1ddcbb66ed | |||
d099601b69 | |||
ff364a93ea | |||
f38e3d6954 | |||
2bfc8b1c84 | |||
c2fd244639 | |||
e69cf46abe | |||
56944664ac | |||
0427e0dd60 | |||
a6a68cd530 | |||
4bd12132f9 | |||
d66e2de08d | |||
00397f0aaf |
2
.env
|
@ -1 +1 @@
|
||||||
TWHELP_API_BASE_URL=https://tribalwarshelp.com
|
TWHELP_API_BASE_URL=https://twhelp.app/api
|
||||||
|
|
|
@ -5,3 +5,4 @@ k8s
|
||||||
.prettierrc.js
|
.prettierrc.js
|
||||||
commitlint.config.js
|
commitlint.config.js
|
||||||
postbuild.js
|
postbuild.js
|
||||||
|
src/lib/twhelp
|
||||||
|
|
|
@ -1,4 +1 @@
|
||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
npx --no -- commitlint --edit ${1}
|
npx --no -- commitlint --edit ${1}
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
module.exports = {
|
|
||||||
singleQuote: true,
|
|
||||||
};
|
|
4
.prettierrc.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "es5"
|
||||||
|
}
|
|
@ -4,31 +4,31 @@ when:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
deploy:
|
deploy:
|
||||||
image: alpine/k8s:1.26.9
|
image: alpine/k8s:1.27.11
|
||||||
secrets:
|
secrets:
|
||||||
- kubeconfig
|
- kubeconfig
|
||||||
commands:
|
commands:
|
||||||
- "mkdir ~/.kube && echo \"$KUBECONFIG\" > ~/.kube/twhelp"
|
- "mkdir ~/.kube && echo \"$KUBECONFIG\" > ~/.kube/twhelp"
|
||||||
- "cd ./k8s/overlays/prod && kustomize edit set image scripts=gitea.dwysokinski.me/twhelp-packages/scripts:${CI_COMMIT_TAG##v} && cd ../../.."
|
- "cd ./k8s/overlays/prod && kustomize edit set image scripts=gitea.dwysokinski.me/twhelp-packages/scripts:${CI_COMMIT_TAG##v} && cd ../../.."
|
||||||
- kustomize build ./k8s/overlays/prod | kubectl --kubeconfig ~/.kube/twhelp apply -n twhelp -f -
|
- kustomize build ./k8s/overlays/prod | kubectl --kubeconfig ~/.kube/twhelp apply -n twhelp -f -
|
||||||
notify:
|
|
||||||
|
email:
|
||||||
image: deblan/woodpecker-email
|
image: deblan/woodpecker-email
|
||||||
settings:
|
settings:
|
||||||
|
dsn:
|
||||||
|
from_secret: email_dsn
|
||||||
from:
|
from:
|
||||||
from_secret: email_from
|
address:
|
||||||
from.name: Woodpecker
|
from_secret: email_from_address
|
||||||
host:
|
name: Woodpecker
|
||||||
from_secret: email_host
|
|
||||||
username:
|
|
||||||
from_secret: email_username
|
|
||||||
password:
|
|
||||||
from_secret: email_password
|
|
||||||
recipients:
|
recipients:
|
||||||
- notifications@dwysokinski.me
|
- notifications@twhelp.app
|
||||||
recipients_only: true
|
recipients_only: true
|
||||||
subject: "[deploy - {{ build.status }}] {{ repo.owner }}/{{ repo.name }} ({{ build.branch }} - {{ truncate build.commit 8 }})"
|
content:
|
||||||
|
subject:
|
||||||
|
"[deployment - {{ pipeline.status }}] {{ repo.full_name }} ({{ commit.tag }})"
|
||||||
when:
|
when:
|
||||||
status: [failure]
|
status: [success, failure]
|
||||||
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- docker
|
- docker
|
|
@ -6,7 +6,7 @@ steps:
|
||||||
publish:
|
publish:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
settings:
|
settings:
|
||||||
platforms: linux/amd64
|
platforms: linux/amd64,linux/arm64
|
||||||
repo: gitea.dwysokinski.me/twhelp-packages/scripts
|
repo: gitea.dwysokinski.me/twhelp-packages/scripts
|
||||||
registry: gitea.dwysokinski.me
|
registry: gitea.dwysokinski.me
|
||||||
auto_tag: true
|
auto_tag: true
|
||||||
|
@ -14,20 +14,3 @@ steps:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
notify:
|
|
||||||
image: deblan/woodpecker-email
|
|
||||||
settings:
|
|
||||||
from:
|
|
||||||
from_secret: email_from
|
|
||||||
from.name: Woodpecker
|
|
||||||
host:
|
|
||||||
from_secret: email_host
|
|
||||||
username:
|
|
||||||
from_secret: email_username
|
|
||||||
password:
|
|
||||||
from_secret: email_password
|
|
||||||
recipients:
|
|
||||||
- notifications@dwysokinski.me
|
|
||||||
recipients_only: true
|
|
||||||
when:
|
|
||||||
status: [failure]
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ when:
|
||||||
- ${CI_REPO_DEFAULT_BRANCH}
|
- ${CI_REPO_DEFAULT_BRANCH}
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
- &node_image 'node:18'
|
- &node_image 'node:20'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
test-build:
|
test-build:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
:80 {
|
:80 {
|
||||||
root * /var/www
|
root * /var/www
|
||||||
file_server
|
file_server browse
|
||||||
header -Server
|
header -Server
|
||||||
header Cache-Control max-age=3600
|
header Cache-Control max-age=3600
|
||||||
header *.js Content-type "text/javascript; charset=UTF-8"
|
header *.js Content-type "text/javascript; charset=UTF-8"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM node:18.18-alpine as build-deps
|
FROM --platform=$BUILDPLATFORM node:20.14-alpine as build-deps
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json yarn.lock ./
|
COPY package.json yarn.lock ./
|
||||||
|
@ -8,7 +8,7 @@ COPY . ./
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
RUN yarn build
|
RUN yarn build
|
||||||
|
|
||||||
FROM caddy:2.7.5-alpine
|
FROM caddy:2.8.1-alpine
|
||||||
|
|
||||||
COPY --from=build-deps /app/dist /var/www
|
COPY --from=build-deps /app/dist /var/www
|
||||||
COPY Caddyfile /etc/caddy/Caddyfile
|
COPY Caddyfile /etc/caddy/Caddyfile
|
||||||
|
|
62
README.md
|
@ -1,6 +1,31 @@
|
||||||
# Tribal Wars - scripts
|
<div align="center">
|
||||||
|
<picture>
|
||||||
|
<img alt="TWHelp logo" src="assets/white_logo_full.png" width="50%">
|
||||||
|
</picture>
|
||||||
|
</div>
|
||||||
|
|
||||||
This repo contains a variety of scripts for [Tribal Wars](https://www.tribalwars.net/en-dk/).
|
<br>
|
||||||
|
|
||||||
|
<h1 align="center"><a href="https://www.tribalwars.net/en-dk/">Tribal Wars</a> scripts to enhance your gameplay</h1>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[![License](https://img.shields.io/badge/License-MIT-green)](#license)
|
||||||
|
[![CI/CD](https://woodpecker.dwysokinski.me/api/badges/10/status.svg)](https://woodpecker.dwysokinski.me/repos/10)
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://twhelp.app/api/v2/swagger/">API</a>
|
||||||
|
·
|
||||||
|
<a href="https://gitea.dwysokinski.me/twhelp/scripts">Scripts</a>
|
||||||
|
·
|
||||||
|
<a href="https://gitea.dwysokinski.me/twhelp/dcbot">Discord Bot</a>
|
||||||
|
·
|
||||||
|
<a href="mailto:contact@twhelp.app">Report Bug</a>
|
||||||
|
·
|
||||||
|
<a href="mailto:contact@twhelp.app">Request Feature</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
## Scripts
|
## Scripts
|
||||||
|
|
||||||
|
@ -8,70 +33,71 @@ This repo contains a variety of scripts for [Tribal Wars](https://www.tribalwars
|
||||||
|
|
||||||
This script adds additional info and actions on a player overview.
|
This script adds additional info and actions on a player overview.
|
||||||
|
|
||||||
![img.png](docs/extended-player-profile.png)
|
![img.png](assets/extended-player-profile.png)
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
[User script](https://scripts.tribalwarshelp.com/extended-player-profile.user.js)
|
[User script](https://scripts.twhelp.app/extended-player-profile.user.js)
|
||||||
|
|
||||||
Quick bar:
|
Quick bar:
|
||||||
```javascript
|
```javascript
|
||||||
javascript:
|
javascript:
|
||||||
$.getScript('https://scripts.tribalwarshelp.com/extended-player-profile.quickbar.js')
|
$.getScript('https://scripts.twhelp.app/extended-player-profile.quickbar.js?_='+~~(Date.now()/9e6))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Extended tribe profile
|
### Extended tribe profile
|
||||||
|
|
||||||
This script adds additional info and actions on a tribe overview.
|
This script adds additional info and actions on a tribe overview.
|
||||||
|
|
||||||
![img.png](docs/extended-tribe-profile.png)
|
![img.png](assets/extended-tribe-profile.png)
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
[User script](https://scripts.tribalwarshelp.com/extended-tribe-profile.user.js)
|
[User script](https://scripts.twhelp.app/extended-tribe-profile.user.js)
|
||||||
|
|
||||||
Quick bar:
|
Quick bar:
|
||||||
```javascript
|
```javascript
|
||||||
javascript:
|
javascript:
|
||||||
$.getScript('https://scripts.tribalwarshelp.com/extended-tribe-profile.quickbar.js')
|
$.getScript('https://scripts.twhelp.app/extended-tribe-profile.quickbar.js?_='+~~(Date.now()/9e6))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Extended map popup
|
### Extended map popup
|
||||||
|
|
||||||
This script extends the map popup with additional info.
|
This script extends the map popup with additional info.
|
||||||
|
|
||||||
![img.png](docs/extended-map-popup.png)
|
![img.png](assets/extended-map-popup.png)
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
[User script](https://scripts.tribalwarshelp.com/extended-map-popup.user.js)
|
[User script](https://scripts.twhelp.app/extended-map-popup.user.js)
|
||||||
|
|
||||||
Quick bar:
|
Quick bar:
|
||||||
```javascript
|
```javascript
|
||||||
javascript:
|
javascript:
|
||||||
$.getScript('https://scripts.tribalwarshelp.com/extended-map-popup.quickbar.js')
|
$.getScript('https://scripts.twhelp.app/extended-map-popup.quickbar.js?_='+~~(Date.now()/9e6))
|
||||||
```
|
```
|
||||||
|
|
||||||
### Extended village profile
|
### Extended village profile
|
||||||
|
|
||||||
This script adds additional info and actions on a village overview.
|
This script adds additional info and actions on a village overview.
|
||||||
|
|
||||||
![img.png](docs/extended-village-profile.png)
|
![img.png](assets/extended-village-profile.png)
|
||||||
|
|
||||||
#### Installation
|
#### Installation
|
||||||
|
|
||||||
[User script](https://scripts.tribalwarshelp.com/extended-village-profile.user.js)
|
[User script](https://scripts.twhelp.app/extended-village-profile.user.js)
|
||||||
|
|
||||||
Quick bar:
|
Quick bar:
|
||||||
```javascript
|
```javascript
|
||||||
javascript:
|
javascript:
|
||||||
$.getScript('https://scripts.tribalwarshelp.com/extended-village-profile.quickbar.js')
|
$.getScript('https://scripts.twhelp.app/extended-village-profile.quickbar.js?_='+~~(Date.now()/9e6))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
If you would like to contribute to the software, please contact me via [email](mailto:contact@twhelp.app).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Distributed under the MIT License. See ``LICENSE`` for more information.
|
This project is licensed under the MIT license. See the [LICENSE](LICENSE) file for the full license text.
|
||||||
|
|
||||||
## Contact
|
|
||||||
|
|
||||||
Dawid Wysokiński - [contact@dwysokinski.me](mailto:contact@dwysokinski.me)
|
|
||||||
|
|
Before Width: | Height: | Size: 204 KiB After Width: | Height: | Size: 204 KiB |
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 196 KiB |
Before Width: | Height: | Size: 452 KiB After Width: | Height: | Size: 452 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
BIN
assets/white_logo_full.png
Normal file
After Width: | Height: | Size: 124 KiB |
|
@ -18,3 +18,13 @@ spec:
|
||||||
name: scripts-caddy-service
|
name: scripts-caddy-service
|
||||||
port:
|
port:
|
||||||
number: 80
|
number: 80
|
||||||
|
- host: scripts.twhelp.app
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: scripts-caddy-service
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
image: gitea.dwysokinski.me/twhelp-packages/scripts:{{#if build.tag}}{{trimPrefix "v" build.tag}}{{else}}latest{{/if}}
|
|
||||||
{{#if build.tags}}
|
|
||||||
tags:
|
|
||||||
{{#each build.tags}}
|
|
||||||
- {{this}}
|
|
||||||
{{/each}}
|
|
||||||
{{/if}}
|
|
||||||
manifests:
|
|
||||||
-
|
|
||||||
image: gitea.dwysokinski.me/twhelp-packages/scripts:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64
|
|
||||||
platform:
|
|
||||||
architecture: amd64
|
|
||||||
os: linux
|
|
26
package.json
|
@ -3,9 +3,10 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"prepare": "husky install",
|
"prepare": "husky",
|
||||||
"build": "rm -rf dist && parcel build ./src/*.user.ts ./src/*.quickbar.ts",
|
"generate-client": "openapi --input src/lib/twhelp/openapi3.json --output src/lib/twhelp/generated --name TWHelpClient --useOptions --client axios",
|
||||||
"postbuild": "PUBLIC_URL=https://scripts.tribalwarshelp.com node postbuild.js",
|
"build": "rm -rf dist && yarn generate-client && parcel build ./src/*.user.ts ./src/*.quickbar.ts",
|
||||||
|
"postbuild": "PUBLIC_URL=https://scripts.twhelp.app node postbuild.js",
|
||||||
"lint": "eslint src/**/*.ts"
|
"lint": "eslint src/**/*.ts"
|
||||||
},
|
},
|
||||||
"targets": {
|
"targets": {
|
||||||
|
@ -20,29 +21,30 @@
|
||||||
"url": "https://dwysokinski.me/"
|
"url": "https://dwysokinski.me/"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"since 2017-06"
|
"since 2020-01"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "^17.4.4",
|
"@commitlint/cli": "^19.0.0",
|
||||||
"@commitlint/config-conventional": "^17.4.4",
|
"@commitlint/config-conventional": "^19.0.0",
|
||||||
"@parcel/validator-eslint": "^2.9.1",
|
"@parcel/validator-eslint": "^2.12.0",
|
||||||
"@parcel/validator-typescript": "^2.9.1",
|
"@parcel/validator-typescript": "^2.12.0",
|
||||||
"@types/jquery": "^3.5.14",
|
"@types/jquery": "^3.5.14",
|
||||||
"@types/lodash": "^4.14.191",
|
"@types/lodash": "^4.14.191",
|
||||||
"@types/node": "^18.11.17",
|
"@types/node": "^20.0.0",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.50.0",
|
"@typescript-eslint/eslint-plugin": "^5.50.0",
|
||||||
"@typescript-eslint/parser": "^5.50.0",
|
"@typescript-eslint/parser": "^5.50.0",
|
||||||
"buffer": "^5.5.0",
|
"buffer": "^5.5.0",
|
||||||
"eslint": "^7.32.0",
|
"eslint": "^7.32.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.0.0",
|
||||||
"husky": "^8.0.3",
|
"husky": "^9.0.0",
|
||||||
"parcel": "^2.9.1",
|
"openapi-typescript-codegen": "^0.28.0",
|
||||||
|
"parcel": "^2.12.0",
|
||||||
"prettier": "^3.0.0",
|
"prettier": "^3.0.0",
|
||||||
"typescript": "^5.0.0"
|
"typescript": "^5.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^1.2.2",
|
"axios": "^1.2.2",
|
||||||
"date-fns": "^2.29.3",
|
"date-fns": "^3.0.0",
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
16
postbuild.js
|
@ -7,9 +7,9 @@ const DIST_DIR = 'dist';
|
||||||
const metadata = {
|
const metadata = {
|
||||||
'extended-player-profile': `// ==UserScript==
|
'extended-player-profile': `// ==UserScript==
|
||||||
// @name Extended player profile
|
// @name Extended player profile
|
||||||
// @version 1.1.6
|
// @version 1.2.0
|
||||||
// @description Adds additional info and actions on a player overview.
|
// @description Adds additional info and actions on a player overview.
|
||||||
// @author Dawid Wysokiński - Kichiyaki - contact@dwysokinski.me
|
// @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app
|
||||||
// @match https://*/game.php?*screen=info_player*
|
// @match https://*/game.php?*screen=info_player*
|
||||||
// @downloadURL ${process.env.PUBLIC_URL}/extended-player-profile.user.js
|
// @downloadURL ${process.env.PUBLIC_URL}/extended-player-profile.user.js
|
||||||
// @updateURL ${process.env.PUBLIC_URL}/extended-player-profile.user.js
|
// @updateURL ${process.env.PUBLIC_URL}/extended-player-profile.user.js
|
||||||
|
@ -19,9 +19,9 @@ const metadata = {
|
||||||
// ==/UserScript==`,
|
// ==/UserScript==`,
|
||||||
'extended-map-popup': `// ==UserScript==
|
'extended-map-popup': `// ==UserScript==
|
||||||
// @name Extended map popup
|
// @name Extended map popup
|
||||||
// @version 1.0.5
|
// @version 1.1.0
|
||||||
// @description Extends the map popup with additional info.
|
// @description Extends the map popup with additional info.
|
||||||
// @author Dawid Wysokiński - Kichiyaki - contact@dwysokinski.me
|
// @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app
|
||||||
// @match https://*/game.php?*screen=map*
|
// @match https://*/game.php?*screen=map*
|
||||||
// @downloadURL ${process.env.PUBLIC_URL}/extended-map-popup.user.js
|
// @downloadURL ${process.env.PUBLIC_URL}/extended-map-popup.user.js
|
||||||
// @updateURL ${process.env.PUBLIC_URL}/extended-map-popup.user.js
|
// @updateURL ${process.env.PUBLIC_URL}/extended-map-popup.user.js
|
||||||
|
@ -31,9 +31,9 @@ const metadata = {
|
||||||
// ==/UserScript==`,
|
// ==/UserScript==`,
|
||||||
'extended-village-profile': `// ==UserScript==
|
'extended-village-profile': `// ==UserScript==
|
||||||
// @name Extended village profile
|
// @name Extended village profile
|
||||||
// @version 1.0.4
|
// @version 1.1.0
|
||||||
// @description Adds additional info and actions on a village overview.
|
// @description Adds additional info and actions on a village overview.
|
||||||
// @author Dawid Wysokiński - Kichiyaki - contact@dwysokinski.me
|
// @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app
|
||||||
// @match https://*/game.php?*screen=info_village*
|
// @match https://*/game.php?*screen=info_village*
|
||||||
// @downloadURL ${process.env.PUBLIC_URL}/extended-village-profile.user.js
|
// @downloadURL ${process.env.PUBLIC_URL}/extended-village-profile.user.js
|
||||||
// @updateURL ${process.env.PUBLIC_URL}/extended-village-profile.user.js
|
// @updateURL ${process.env.PUBLIC_URL}/extended-village-profile.user.js
|
||||||
|
@ -43,9 +43,9 @@ const metadata = {
|
||||||
// ==/UserScript==`,
|
// ==/UserScript==`,
|
||||||
'extended-tribe-profile': `// ==UserScript==
|
'extended-tribe-profile': `// ==UserScript==
|
||||||
// @name Extended tribe profile
|
// @name Extended tribe profile
|
||||||
// @version 1.0.4
|
// @version 1.1.0
|
||||||
// @description Adds additional info and actions on a tribe overview.
|
// @description Adds additional info and actions on a tribe overview.
|
||||||
// @author Dawid Wysokiński - Kichiyaki - contact@dwysokinski.me
|
// @author Dawid Wysokiński - Kichiyaki - contact@twhelp.app
|
||||||
// @match https://*/game.php?*screen=info_ally*
|
// @match https://*/game.php?*screen=info_ally*
|
||||||
// @downloadURL ${process.env.PUBLIC_URL}/extended-tribe-profile.user.js
|
// @downloadURL ${process.env.PUBLIC_URL}/extended-tribe-profile.user.js
|
||||||
// @updateURL ${process.env.PUBLIC_URL}/extended-tribe-profile.user.js
|
// @updateURL ${process.env.PUBLIC_URL}/extended-tribe-profile.user.js
|
||||||
|
|
|
@ -15,48 +15,54 @@ export type DialogTableColumn<T> = {
|
||||||
accessor: (row: T, index: number, rows: T[]) => string;
|
accessor: (row: T, index: number, rows: T[]) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type Cursor = {
|
||||||
|
next?: string;
|
||||||
|
self?: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type LoadDataResult<T> = {
|
export type LoadDataResult<T> = {
|
||||||
|
cursor?: Cursor;
|
||||||
data: T[];
|
data: T[];
|
||||||
total: number;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export class DialogTable<T> {
|
export class DialogTable<T> {
|
||||||
prevPageId: string;
|
private readonly prevPageId: string;
|
||||||
selectId: string;
|
private readonly nextPageId: string;
|
||||||
nextPageId: string;
|
|
||||||
|
private readonly prevCursors: Cursor[] = [];
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly id: string,
|
private readonly id: string,
|
||||||
private readonly columns: DialogTableColumn<T>[],
|
private readonly columns: DialogTableColumn<T>[],
|
||||||
private readonly limit: number,
|
private readonly limit: number,
|
||||||
private readonly loadData: (
|
private readonly loadData: (
|
||||||
page: number,
|
cursor: string | undefined,
|
||||||
limit: number
|
limit: number
|
||||||
) => Promise<LoadDataResult<T>>
|
) => Promise<LoadDataResult<T>>
|
||||||
) {
|
) {
|
||||||
this.prevPageId = `${this.id}_page_prev`;
|
this.prevPageId = `${this.id}_page_prev`;
|
||||||
this.selectId = `${this.id}_page_select`;
|
|
||||||
this.nextPageId = `${this.id}_page_next`;
|
this.nextPageId = `${this.id}_page_next`;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async render() {
|
public async render() {
|
||||||
await this.renderPage(1);
|
await this.renderPage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async renderPage(page: number) {
|
private async renderPage(pageCursor?: string) {
|
||||||
window.Dialog.show(`${this.id}_loading`, `<p>${t('Loading')}...</p>`);
|
window.Dialog.show(this.id, `<p>${t('Loading')}...</p>`);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { data, total } = await this.loadData(page, this.limit);
|
const { data, cursor } = await this.loadData(pageCursor, this.limit);
|
||||||
|
|
||||||
window.Dialog.show(
|
window.Dialog.show(
|
||||||
this.id,
|
this.id,
|
||||||
`
|
`
|
||||||
${this.buildPagination(page, total)}
|
${this.buildPagination(cursor)}
|
||||||
${this.buildTable(data)}
|
${this.buildTable(data)}
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
|
||||||
this.addEventListeners(page);
|
this.addEventListeners(cursor);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
window.Dialog.close();
|
window.Dialog.close();
|
||||||
|
@ -64,31 +70,17 @@ export class DialogTable<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private buildPagination(page: number, total: number): string {
|
private buildPagination(cursor?: Cursor): string {
|
||||||
const maxPage = Math.ceil(total / this.limit);
|
|
||||||
|
|
||||||
const pageOpts = [];
|
|
||||||
for (let i = 1; i <= (page > maxPage ? page : maxPage); i++) {
|
|
||||||
pageOpts.push(
|
|
||||||
`<option${
|
|
||||||
i === page ? ' disabled selected' : ''
|
|
||||||
} value="${i}">${i}</option>`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px">
|
<div style="display: flex; flex-direction: row; align-items: center; justify-content: center; margin-bottom: 10px">
|
||||||
<button title="${t(
|
<button title="${t(
|
||||||
'Previous page'
|
'Previous page'
|
||||||
)}" style="margin-right: 5px" class="btn" id="${this.prevPageId}"${
|
)}" style="margin-right: 5px" class="btn" id="${this.prevPageId}"${
|
||||||
page <= 1 ? ' disabled' : ''
|
this.prevCursors.length === 0 ? ' disabled' : ''
|
||||||
}><</button>
|
}><</button>
|
||||||
<select style="margin-right: 5px" id="${this.selectId}">
|
|
||||||
${pageOpts.join('')}
|
|
||||||
</select>
|
|
||||||
<button title="${t('Next page')}" class="btn" id="${
|
<button title="${t('Next page')}" class="btn" id="${
|
||||||
this.nextPageId
|
this.nextPageId
|
||||||
}"${page >= maxPage ? ' disabled' : ''}>></button>
|
}"${!cursor?.next ? ' disabled' : ''}>></button>
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
@ -116,27 +108,25 @@ export class DialogTable<T> {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addEventListeners(page: number) {
|
private addEventListeners(cursor?: Cursor) {
|
||||||
document
|
document
|
||||||
.querySelector('#' + this.prevPageId)
|
.querySelector('#' + this.prevPageId)
|
||||||
?.addEventListener('click', () => {
|
?.addEventListener('click', () => {
|
||||||
this.renderPage(page - 1);
|
const prev = this.prevCursors.pop();
|
||||||
});
|
if (!prev) {
|
||||||
|
|
||||||
document
|
|
||||||
.querySelector('#' + this.selectId)
|
|
||||||
?.addEventListener('change', (e: Event) => {
|
|
||||||
if (!(e.currentTarget instanceof HTMLSelectElement)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
this.renderPage(prev.self);
|
||||||
this.renderPage(parseInt(e.currentTarget.value));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
document
|
document
|
||||||
.querySelector('#' + this.nextPageId)
|
.querySelector('#' + this.nextPageId)
|
||||||
?.addEventListener('click', () => {
|
?.addEventListener('click', () => {
|
||||||
this.renderPage(page + 1);
|
if (!cursor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.prevCursors.push(cursor);
|
||||||
|
this.renderPage(cursor.next);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
import addSeconds from 'date-fns/addSeconds';
|
import { addSeconds } from 'date-fns/addSeconds';
|
||||||
import {
|
|
||||||
Ennoblement,
|
|
||||||
ServerConfig,
|
|
||||||
TWHelpClient,
|
|
||||||
UnitInfo,
|
|
||||||
} from './lib/twhelp';
|
|
||||||
import { Cache, InMemoryStorage } from './lib/cache';
|
import { Cache, InMemoryStorage } from './lib/cache';
|
||||||
import { calcDistance, calcLoyalty } from './lib/tw';
|
import { calcDistance, calcLoyalty } from './lib/tw';
|
||||||
import { createTranslationFunc } from './utils';
|
import { createTranslationFunc } from './utils';
|
||||||
|
import {
|
||||||
|
TWHelpClient,
|
||||||
|
Ennoblement,
|
||||||
|
UnitInfo,
|
||||||
|
ServerConfig,
|
||||||
|
AxiosHttpRequestWithTimeout,
|
||||||
|
} from './lib/twhelp';
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
|
@ -43,25 +44,41 @@ const t = createTranslationFunc({
|
||||||
|
|
||||||
class TWHelpConnector {
|
class TWHelpConnector {
|
||||||
private static readonly SERVER_CONFIG_CACHE_KEY =
|
private static readonly SERVER_CONFIG_CACHE_KEY =
|
||||||
'extended_map_popup_server_config';
|
'extended_map_popup_server_config_v2';
|
||||||
private static readonly UNIT_INFO_CACHE_KEY = 'extended_map_popup_unit_info';
|
private static readonly UNIT_INFO_CACHE_KEY =
|
||||||
|
'extended_map_popup_unit_info_v2';
|
||||||
private static readonly VILLAGE_CACHE_KEY_PREFIX =
|
private static readonly VILLAGE_CACHE_KEY_PREFIX =
|
||||||
'extended_map_popup_village_';
|
'extended_map_popup_village_v2_';
|
||||||
|
|
||||||
private readonly localStorageCache = new Cache(localStorage);
|
private readonly localStorageCache = new Cache(localStorage);
|
||||||
private readonly inMemoryCache = new Cache(new InMemoryStorage());
|
private readonly inMemoryCache = new Cache(new InMemoryStorage());
|
||||||
|
|
||||||
|
private readonly client: TWHelpClient;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly client: TWHelpClient,
|
readonly baseUrl: string,
|
||||||
private readonly version: string,
|
private readonly version: string,
|
||||||
private readonly server: string
|
private readonly server: string
|
||||||
) {}
|
) {
|
||||||
|
this.client = new TWHelpClient(
|
||||||
|
{
|
||||||
|
BASE: baseUrl,
|
||||||
|
},
|
||||||
|
AxiosHttpRequestWithTimeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
serverConfig() {
|
serverConfig() {
|
||||||
return this.localStorageCache.load(
|
return this.localStorageCache.load(
|
||||||
TWHelpConnector.SERVER_CONFIG_CACHE_KEY,
|
TWHelpConnector.SERVER_CONFIG_CACHE_KEY,
|
||||||
3600,
|
3600,
|
||||||
() => {
|
async () => {
|
||||||
return this.client.serverConfig(this.version, this.server);
|
return (
|
||||||
|
await this.client.servers.getServerConfig({
|
||||||
|
serverKey: this.server,
|
||||||
|
versionCode: this.version,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -70,8 +87,13 @@ class TWHelpConnector {
|
||||||
return this.localStorageCache.load(
|
return this.localStorageCache.load(
|
||||||
TWHelpConnector.UNIT_INFO_CACHE_KEY,
|
TWHelpConnector.UNIT_INFO_CACHE_KEY,
|
||||||
3600,
|
3600,
|
||||||
() => {
|
async () => {
|
||||||
return this.client.unitInfo(this.version, this.server);
|
return (
|
||||||
|
await this.client.servers.getUnitInfo({
|
||||||
|
serverKey: this.server,
|
||||||
|
versionCode: this.version,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -84,15 +106,14 @@ class TWHelpConnector {
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.inMemoryCache.load(key, 86400, async () => {
|
return this.inMemoryCache.load(key, 86400, async () => {
|
||||||
const ennoblements = await this.client.villageEnnoblements(
|
const ennoblements =
|
||||||
this.version,
|
await this.client.ennoblements.listVillageEnnoblements({
|
||||||
this.server,
|
versionCode: this.version,
|
||||||
id,
|
serverKey: this.server,
|
||||||
{
|
|
||||||
limit: 1,
|
|
||||||
sort: ['createdAt:DESC'],
|
sort: ['createdAt:DESC'],
|
||||||
}
|
villageId: id,
|
||||||
);
|
limit: 1,
|
||||||
|
});
|
||||||
return ennoblements.data.length > 0 ? ennoblements.data[0] : null;
|
return ennoblements.data.length > 0 ? ennoblements.data[0] : null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -245,9 +266,9 @@ class Popup {
|
||||||
|
|
||||||
class ExtendedMapPopup {
|
class ExtendedMapPopup {
|
||||||
connector: TWHelpConnector;
|
connector: TWHelpConnector;
|
||||||
constructor(client: TWHelpClient) {
|
constructor(baseApiUrl: string) {
|
||||||
this.connector = new TWHelpConnector(
|
this.connector = new TWHelpConnector(
|
||||||
client,
|
baseApiUrl,
|
||||||
window.game_data.market,
|
window.game_data.market,
|
||||||
window.game_data.world
|
window.game_data.world
|
||||||
);
|
);
|
||||||
|
@ -273,9 +294,7 @@ class ExtendedMapPopup {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await new ExtendedMapPopup(
|
await new ExtendedMapPopup(process.env.TWHELP_API_BASE_URL ?? '')
|
||||||
new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '')
|
|
||||||
)
|
|
||||||
.run()
|
.run()
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
|
@ -1,10 +1,16 @@
|
||||||
// Extended player profile
|
// Extended player profile
|
||||||
|
|
||||||
import { Player, PlayerSnapshot, TWHelpClient } from './lib/twhelp';
|
|
||||||
import { DialogTable } from './common/dialog-table';
|
|
||||||
import { InADayClient } from './lib/tw';
|
import { InADayClient } from './lib/tw';
|
||||||
import { createTranslationFunc } from './utils';
|
import { createTranslationFunc } from './utils';
|
||||||
import { buildURL } from './lib/twstats';
|
import { buildURL } from './lib/twstats';
|
||||||
|
import {
|
||||||
|
TWHelpClient,
|
||||||
|
PlayerSnapshot,
|
||||||
|
Player,
|
||||||
|
AxiosHttpRequestWithTimeout,
|
||||||
|
} from './lib/twhelp';
|
||||||
|
import { DialogTable } from './common/dialog-table';
|
||||||
|
import { Cache } from './lib/cache';
|
||||||
|
|
||||||
const t = createTranslationFunc({
|
const t = createTranslationFunc({
|
||||||
pl_PL: {
|
pl_PL: {
|
||||||
|
@ -59,62 +65,98 @@ const t = createTranslationFunc({
|
||||||
});
|
});
|
||||||
|
|
||||||
class TWHelpConnector {
|
class TWHelpConnector {
|
||||||
|
private readonly client: TWHelpClient;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly client: TWHelpClient,
|
readonly baseUrl: string,
|
||||||
private readonly version: string,
|
private readonly version: string,
|
||||||
private readonly server: string,
|
private readonly server: string,
|
||||||
private readonly id: number
|
private readonly id: number
|
||||||
) {}
|
) {
|
||||||
|
this.client = new TWHelpClient(
|
||||||
|
{
|
||||||
|
BASE: baseUrl,
|
||||||
|
},
|
||||||
|
AxiosHttpRequestWithTimeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
player() {
|
async player() {
|
||||||
return this.client.player(this.version, this.server, this.id);
|
return (
|
||||||
|
await this.client.players.getPlayer({
|
||||||
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
playerId: this.id,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
}
|
}
|
||||||
|
|
||||||
async latestSnapshot() {
|
async latestSnapshot() {
|
||||||
const snapshot = await this.playerSnapshots(1, 1);
|
const snapshot = await this.playerSnapshots(undefined, 1);
|
||||||
return snapshot.data.length > 0 ? snapshot.data[0] : null;
|
return snapshot.data.length > 0 ? snapshot.data[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
playerTribeChanges(page: number, limit: number) {
|
playerTribeChanges(cursor: string | undefined, limit: number) {
|
||||||
return this.client.playerTribeChanges(this.version, this.server, this.id, {
|
return this.client.tribeChanges.listPlayerTribeChanges({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
playerId: this.id,
|
||||||
limit,
|
limit,
|
||||||
sort: ['createdAt:desc', 'id:asc'],
|
cursor,
|
||||||
|
sort: ['createdAt:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
playerEnnoblements(page: number, limit: number) {
|
playerEnnoblements(cursor: string | undefined, limit: number) {
|
||||||
return this.client.playerEnnoblements(this.version, this.server, this.id, {
|
return this.client.ennoblements.listPlayerEnnoblements({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
playerId: this.id,
|
||||||
limit,
|
limit,
|
||||||
sort: ['createdAt:desc'],
|
cursor,
|
||||||
|
sort: ['createdAt:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
playerSnapshots(page: number, limit: number) {
|
playerSnapshots(cursor: string | undefined, limit: number) {
|
||||||
return this.client.playerSnapshots(this.version, this.server, this.id, {
|
return this.client.snapshots.listPlayerPlayerSnapshots({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
playerId: this.id,
|
||||||
limit,
|
limit,
|
||||||
sort: ['date:desc'],
|
cursor,
|
||||||
|
sort: ['date:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
playerOtherServers(page: number, limit: number) {
|
playerOtherServers(cursor: string | undefined, limit: number) {
|
||||||
return this.client.playerOtherServers(this.version, this.server, this.id, {
|
return this.client.players.listVersionPlayers({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
limit,
|
limit,
|
||||||
|
cursor,
|
||||||
|
id: [this.id],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class InADayConnector {
|
class InADayConnector {
|
||||||
constructor(
|
private static readonly CACHE_KEY_PREFIX =
|
||||||
private readonly client: InADayClient,
|
'extended_player_profile_in_a_day_';
|
||||||
private readonly name: string
|
|
||||||
) {}
|
private readonly cache = new Cache(localStorage);
|
||||||
|
|
||||||
|
private readonly client = new InADayClient();
|
||||||
|
|
||||||
|
constructor(private readonly name: string) {}
|
||||||
|
|
||||||
player() {
|
player() {
|
||||||
return this.client.player(this.name);
|
return this.cache.load(
|
||||||
|
InADayConnector.CACHE_KEY_PREFIX + this.name,
|
||||||
|
600,
|
||||||
|
() => {
|
||||||
|
return this.client.player(this.name);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,20 +202,20 @@ class UI {
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Best rank')}:</td>
|
<td>${t('Best rank')}:</td>
|
||||||
<td>${this.player.bestRank} (${new Date(
|
<td>${this.player.bestRank} (${new Date(
|
||||||
this.player.bestRankAt
|
this.player.bestRankAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Most points')}:</td>
|
<td>${t('Most points')}:</td>
|
||||||
<td>${this.player.mostPoints.toLocaleString()} (${new Date(
|
<td>${this.player.mostPoints.toLocaleString()} (${new Date(
|
||||||
this.player.mostPointsAt
|
this.player.mostPointsAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Most villages')}:</td>
|
<td>${t('Most villages')}:</td>
|
||||||
<td>${this.player.mostVillages.toLocaleString()} (${new Date(
|
<td>${this.player.mostVillages.toLocaleString()} (${new Date(
|
||||||
this.player.mostVillagesAt
|
this.player.mostVillagesAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
@ -204,38 +246,54 @@ class UI {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA'),
|
header: t('ODA'),
|
||||||
value: this.player.scoreAtt - (this.latestSnapshot?.scoreAtt ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.scoreAtt -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreAtt ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA - rank'),
|
header: t('ODA - rank'),
|
||||||
value: this.player.rankAtt - (this.latestSnapshot?.rankAtt ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.rankAtt -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankAtt ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD'),
|
header: t('ODD'),
|
||||||
value: this.player.scoreDef - (this.latestSnapshot?.scoreDef ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.scoreDef -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreDef ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD - rank'),
|
header: t('ODD - rank'),
|
||||||
value: this.player.rankDef - (this.latestSnapshot?.rankDef ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.rankDef -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankDef ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODS'),
|
header: t('ODS'),
|
||||||
value: this.player.scoreSup - (this.latestSnapshot?.scoreSup ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.scoreSup -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreSup ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODS - rank'),
|
header: t('ODS - rank'),
|
||||||
value: this.player.rankSup - (this.latestSnapshot?.rankSup ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.rankSup -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankSup ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('OD'),
|
header: t('OD'),
|
||||||
value: this.player.scoreTotal - (this.latestSnapshot?.scoreTotal ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.scoreTotal -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreTotal ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('OD - rank'),
|
header: t('OD - rank'),
|
||||||
value: this.player.rankTotal - (this.latestSnapshot?.rankTotal ?? 0),
|
value:
|
||||||
|
this.player.opponentsDefeated.rankTotal -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankTotal ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -364,8 +422,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.playerOtherServers(page, limit);
|
return this.twhelpConnector.playerOtherServers(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -454,8 +512,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.playerTribeChanges(page, limit);
|
return this.twhelpConnector.playerTribeChanges(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -473,8 +531,8 @@ class UI {
|
||||||
{
|
{
|
||||||
header: t('Tribe'),
|
header: t('Tribe'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
s.tribe
|
s.player.tribe
|
||||||
? `<a href="${s.tribe.profileUrl}">${s.tribe.tag}</a>`
|
? `<a href="${s.player.tribe.profileUrl}">${s.player.tribe.tag}</a>`
|
||||||
: '-',
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -489,29 +547,29 @@ class UI {
|
||||||
{
|
{
|
||||||
header: t('OD'),
|
header: t('OD'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreTotal.toLocaleString()} (<strong>${
|
`${s.opponentsDefeated.scoreTotal.toLocaleString()} (<strong>${
|
||||||
s.rankTotal
|
s.opponentsDefeated.rankTotal
|
||||||
}</strong>)`,
|
}</strong>)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA'),
|
header: t('ODA'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreAtt.toLocaleString()} (<strong>${s.rankAtt}</strong>)`,
|
`${s.opponentsDefeated.scoreAtt.toLocaleString()} (<strong>${s.opponentsDefeated.rankAtt}</strong>)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD'),
|
header: t('ODD'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreDef.toLocaleString()} (<strong>${s.rankDef}</strong>)`,
|
`${s.opponentsDefeated.scoreDef.toLocaleString()} (<strong>${s.opponentsDefeated.rankDef}</strong>)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODS'),
|
header: t('ODS'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreSup.toLocaleString()} (<strong>${s.rankSup}</strong>)`,
|
`${s.opponentsDefeated.scoreSup.toLocaleString()} (<strong>${s.opponentsDefeated.rankSup}</strong>)`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.playerSnapshots(page, limit);
|
return this.twhelpConnector.playerSnapshots(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -563,8 +621,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.playerEnnoblements(page, limit);
|
return this.twhelpConnector.playerEnnoblements(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -574,18 +632,15 @@ class ExtendedPlayerProfile {
|
||||||
private readonly twhelpConnector: TWHelpConnector;
|
private readonly twhelpConnector: TWHelpConnector;
|
||||||
private readonly inADayConnector: InADayConnector;
|
private readonly inADayConnector: InADayConnector;
|
||||||
|
|
||||||
constructor(twhelpClient: TWHelpClient, inADayClient: InADayClient) {
|
constructor(apiBaseUrl: string) {
|
||||||
this.twhelpConnector = new TWHelpConnector(
|
this.twhelpConnector = new TWHelpConnector(
|
||||||
twhelpClient,
|
apiBaseUrl,
|
||||||
window.game_data.market,
|
window.game_data.market,
|
||||||
window.game_data.world,
|
window.game_data.world,
|
||||||
this.getPlayerId()
|
this.getPlayerId()
|
||||||
);
|
);
|
||||||
|
|
||||||
this.inADayConnector = new InADayConnector(
|
this.inADayConnector = new InADayConnector(this.getPlayerName());
|
||||||
inADayClient,
|
|
||||||
this.getPlayerName()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async run() {
|
async run() {
|
||||||
|
@ -627,10 +682,7 @@ class ExtendedPlayerProfile {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await new ExtendedPlayerProfile(
|
await new ExtendedPlayerProfile(process.env.TWHELP_API_BASE_URL ?? '')
|
||||||
new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? ''),
|
|
||||||
new InADayClient()
|
|
||||||
)
|
|
||||||
.run()
|
.run()
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
import { Player, Tribe, TribeSnapshot, TWHelpClient } from './lib/twhelp';
|
import {
|
||||||
|
AxiosHttpRequestWithTimeout,
|
||||||
|
Player,
|
||||||
|
Tribe,
|
||||||
|
TribeSnapshot,
|
||||||
|
TWHelpClient,
|
||||||
|
} from './lib/twhelp';
|
||||||
import { createTranslationFunc } from './utils';
|
import { createTranslationFunc } from './utils';
|
||||||
import { DialogTable } from './common/dialog-table';
|
|
||||||
import { buildURL } from './lib/twstats';
|
import { buildURL } from './lib/twstats';
|
||||||
|
import { DialogTable } from './common/dialog-table';
|
||||||
|
|
||||||
const t = createTranslationFunc({
|
const t = createTranslationFunc({
|
||||||
pl_PL: {
|
pl_PL: {
|
||||||
|
@ -44,47 +50,75 @@ const t = createTranslationFunc({
|
||||||
});
|
});
|
||||||
|
|
||||||
class TWHelpConnector {
|
class TWHelpConnector {
|
||||||
|
private readonly client: TWHelpClient;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly client: TWHelpClient,
|
baseUrl: string,
|
||||||
private readonly version: string,
|
private readonly version: string,
|
||||||
private readonly server: string,
|
private readonly server: string,
|
||||||
private readonly id: number
|
private readonly id: number
|
||||||
) {}
|
) {
|
||||||
|
this.client = new TWHelpClient(
|
||||||
|
{
|
||||||
|
BASE: baseUrl,
|
||||||
|
},
|
||||||
|
AxiosHttpRequestWithTimeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
tribe() {
|
async tribe() {
|
||||||
return this.client.tribe(this.version, this.server, this.id);
|
return (
|
||||||
|
await this.client.tribes.getTribe({
|
||||||
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
tribeId: this.id,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
}
|
}
|
||||||
|
|
||||||
tribeMembers() {
|
tribeMembers() {
|
||||||
return this.client.tribeMembers(this.version, this.server, this.id);
|
return this.client.tribes.listTribeMembers({
|
||||||
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
tribeId: this.id,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async latestSnapshot() {
|
async latestSnapshot() {
|
||||||
const snapshot = await this.tribeSnapshots(1, 1);
|
const snapshot = await this.tribeSnapshots(undefined, 1);
|
||||||
return snapshot.data.length > 0 ? snapshot.data[0] : null;
|
return snapshot.data.length > 0 ? snapshot.data[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
tribeSnapshots(page: number, limit: number) {
|
tribeSnapshots(cursor: string | undefined, limit: number) {
|
||||||
return this.client.tribeSnapshots(this.version, this.server, this.id, {
|
return this.client.snapshots.listTribeTribeSnapshots({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
tribeId: this.id,
|
||||||
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
sort: ['date:desc'],
|
sort: ['date:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tribeTribeChanges(page: number, limit: number) {
|
memberChanges(cursor: string | undefined, limit: number) {
|
||||||
return this.client.tribeTribeChanges(this.version, this.server, this.id, {
|
return this.client.tribeChanges.listTribeMemberChanges({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
tribeId: this.id,
|
||||||
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
sort: ['createdAt:desc'],
|
sort: ['createdAt:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
tribeEnnoblements(page: number, limit: number) {
|
tribeEnnoblements(cursor: string | undefined, limit: number) {
|
||||||
return this.client.tribeEnnoblements(this.version, this.server, this.id, {
|
return this.client.ennoblements.listTribeEnnoblements({
|
||||||
offset: (page - 1) * limit,
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
tribeId: this.id,
|
||||||
|
cursor,
|
||||||
limit,
|
limit,
|
||||||
sort: ['createdAt:desc'],
|
sort: ['createdAt:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,20 +167,20 @@ class UI {
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Best rank')}:</td>
|
<td>${t('Best rank')}:</td>
|
||||||
<td>${this.tribe.bestRank} (${new Date(
|
<td>${this.tribe.bestRank} (${new Date(
|
||||||
this.tribe.bestRankAt
|
this.tribe.bestRankAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Most points')}:</td>
|
<td>${t('Most points')}:</td>
|
||||||
<td>${this.tribe.mostPoints.toLocaleString()} (${new Date(
|
<td>${this.tribe.mostPoints.toLocaleString()} (${new Date(
|
||||||
this.tribe.mostPointsAt
|
this.tribe.mostPointsAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>${t('Most villages')}:</td>
|
<td>${t('Most villages')}:</td>
|
||||||
<td>${this.tribe.mostVillages.toLocaleString()} (${new Date(
|
<td>${this.tribe.mostVillages.toLocaleString()} (${new Date(
|
||||||
this.tribe.mostVillagesAt
|
this.tribe.mostVillagesAt
|
||||||
).toLocaleString()})</td>
|
).toLocaleString()})</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
|
@ -185,29 +219,41 @@ class UI {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA'),
|
header: t('ODA'),
|
||||||
value: this.tribe.scoreAtt - (this.latestSnapshot?.scoreAtt ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.scoreAtt -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreAtt ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA - rank'),
|
header: t('ODA - rank'),
|
||||||
value: this.tribe.rankAtt - (this.latestSnapshot?.rankAtt ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.rankAtt -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankAtt ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD'),
|
header: t('ODD'),
|
||||||
value: this.tribe.scoreDef - (this.latestSnapshot?.scoreDef ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.scoreDef -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreDef ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD - rank'),
|
header: t('ODD - rank'),
|
||||||
value: this.tribe.rankDef - (this.latestSnapshot?.rankDef ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.rankDef -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankDef ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('OD'),
|
header: t('OD'),
|
||||||
value: this.tribe.scoreTotal - (this.latestSnapshot?.scoreTotal ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.scoreTotal -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.scoreTotal ?? 0),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('OD - rank'),
|
header: t('OD - rank'),
|
||||||
value: this.tribe.rankTotal - (this.latestSnapshot?.rankTotal ?? 0),
|
value:
|
||||||
|
this.tribe.opponentsDefeated.rankTotal -
|
||||||
|
(this.latestSnapshot?.opponentsDefeated.rankTotal ?? 0),
|
||||||
rank: true,
|
rank: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -231,10 +277,10 @@ class UI {
|
||||||
r.value,
|
r.value,
|
||||||
r.rank
|
r.rank
|
||||||
)}">${
|
)}">${
|
||||||
r.customFormat
|
r.customFormat
|
||||||
? r.customFormat(r.value)
|
? r.customFormat(r.value)
|
||||||
: Math.abs(r.value).toLocaleString()
|
: Math.abs(r.value).toLocaleString()
|
||||||
}</td>
|
}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
@ -323,8 +369,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.tribeTribeChanges(page, limit);
|
return this.twhelpConnector.memberChanges(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -359,24 +405,24 @@ class UI {
|
||||||
{
|
{
|
||||||
header: t('OD'),
|
header: t('OD'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreTotal.toLocaleString()} (<strong>${
|
`${s.opponentsDefeated.scoreTotal.toLocaleString()} (<strong>${
|
||||||
s.rankTotal
|
s.opponentsDefeated.rankTotal
|
||||||
}</strong>)`,
|
}</strong>)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODA'),
|
header: t('ODA'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreAtt.toLocaleString()} (<strong>${s.rankAtt}</strong>)`,
|
`${s.opponentsDefeated.scoreAtt.toLocaleString()} (<strong>${s.opponentsDefeated.rankAtt}</strong>)`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: t('ODD'),
|
header: t('ODD'),
|
||||||
accessor: (s) =>
|
accessor: (s) =>
|
||||||
`${s.scoreDef.toLocaleString()} (<strong>${s.rankDef}</strong>)`,
|
`${s.opponentsDefeated.scoreDef.toLocaleString()} (<strong>${s.opponentsDefeated.rankDef}</strong>)`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.tribeSnapshots(page, limit);
|
return this.twhelpConnector.tribeSnapshots(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -428,8 +474,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
(cursor: string | undefined, limit: number) => {
|
||||||
return this.twhelpConnector.tribeEnnoblements(page, limit);
|
return this.twhelpConnector.tribeEnnoblements(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -477,10 +523,10 @@ class UI {
|
||||||
const member = this.members.find((m) => m.id === id);
|
const member = this.members.find((m) => m.id === id);
|
||||||
|
|
||||||
[
|
[
|
||||||
(member?.rankAtt ?? 0).toString(),
|
(member?.opponentsDefeated.rankAtt ?? 0).toString(),
|
||||||
(member?.rankDef ?? 0).toString(),
|
(member?.opponentsDefeated.rankDef ?? 0).toString(),
|
||||||
(member?.rankSup ?? 0).toString(),
|
(member?.opponentsDefeated.rankSup ?? 0).toString(),
|
||||||
(member?.rankTotal ?? 0).toString(),
|
(member?.opponentsDefeated.rankTotal ?? 0).toString(),
|
||||||
member?.lastActivityAt
|
member?.lastActivityAt
|
||||||
? new Date(member.lastActivityAt).toLocaleString()
|
? new Date(member.lastActivityAt).toLocaleString()
|
||||||
: '-',
|
: '-',
|
||||||
|
@ -501,9 +547,9 @@ class UI {
|
||||||
class ExtendedTribeProfile {
|
class ExtendedTribeProfile {
|
||||||
private readonly twhelpConnector: TWHelpConnector;
|
private readonly twhelpConnector: TWHelpConnector;
|
||||||
|
|
||||||
constructor(twhelpClient: TWHelpClient) {
|
constructor(apiBaseUrl: string) {
|
||||||
this.twhelpConnector = new TWHelpConnector(
|
this.twhelpConnector = new TWHelpConnector(
|
||||||
twhelpClient,
|
apiBaseUrl,
|
||||||
window.game_data.market,
|
window.game_data.market,
|
||||||
window.game_data.world,
|
window.game_data.world,
|
||||||
this.getTribeId()
|
this.getTribeId()
|
||||||
|
@ -543,9 +589,7 @@ class ExtendedTribeProfile {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await new ExtendedTribeProfile(
|
await new ExtendedTribeProfile(process.env.TWHELP_API_BASE_URL ?? '')
|
||||||
new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '')
|
|
||||||
)
|
|
||||||
.run()
|
.run()
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
import { Ennoblement, ServerConfig, TWHelpClient } from './lib/twhelp';
|
|
||||||
import { createTranslationFunc } from './utils';
|
import { createTranslationFunc } from './utils';
|
||||||
import { DialogTable } from './common/dialog-table';
|
|
||||||
import { calcLoyalty } from './lib/tw';
|
import { calcLoyalty } from './lib/tw';
|
||||||
import { Cache } from './lib/cache';
|
import { Cache } from './lib/cache';
|
||||||
|
import {
|
||||||
|
TWHelpClient,
|
||||||
|
Ennoblement,
|
||||||
|
ServerConfig,
|
||||||
|
AxiosHttpRequestWithTimeout,
|
||||||
|
} from './lib/twhelp';
|
||||||
|
import { DialogTable } from './common/dialog-table';
|
||||||
|
|
||||||
const t = createTranslationFunc({
|
const t = createTranslationFunc({
|
||||||
pl_PL: {
|
pl_PL: {
|
||||||
|
@ -22,32 +27,47 @@ const t = createTranslationFunc({
|
||||||
|
|
||||||
class TWHelpConnector {
|
class TWHelpConnector {
|
||||||
private static SERVER_CONFIG_CACHE_KEY =
|
private static SERVER_CONFIG_CACHE_KEY =
|
||||||
'extended_village_profile_server_config';
|
'extended_village_profile_server_config_v2';
|
||||||
|
|
||||||
private cache = new Cache(localStorage);
|
private cache = new Cache(localStorage);
|
||||||
|
|
||||||
|
private client: TWHelpClient;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly client: TWHelpClient,
|
readonly baseUrl: string,
|
||||||
private readonly version: string,
|
private readonly version: string,
|
||||||
private readonly server: string,
|
private readonly server: string,
|
||||||
private readonly id: number
|
private readonly id: number
|
||||||
) {}
|
) {
|
||||||
|
this.client = new TWHelpClient(
|
||||||
|
{
|
||||||
|
BASE: baseUrl,
|
||||||
|
},
|
||||||
|
AxiosHttpRequestWithTimeout
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
serverConfig() {
|
serverConfig() {
|
||||||
return this.cache.load(
|
return this.cache.load(
|
||||||
TWHelpConnector.SERVER_CONFIG_CACHE_KEY,
|
TWHelpConnector.SERVER_CONFIG_CACHE_KEY,
|
||||||
3600,
|
3600,
|
||||||
() => {
|
async () => {
|
||||||
return this.client.serverConfig(this.version, this.server);
|
return (
|
||||||
|
await this.client.servers.getServerConfig({
|
||||||
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
})
|
||||||
|
).data;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async latestEnnoblement() {
|
async latestEnnoblement() {
|
||||||
const ennoblements = await this.client.villageEnnoblements(
|
const ennoblements = await this.client.ennoblements.listVillageEnnoblements(
|
||||||
this.version,
|
|
||||||
this.server,
|
|
||||||
this.id,
|
|
||||||
{
|
{
|
||||||
|
versionCode: this.version,
|
||||||
|
serverKey: this.server,
|
||||||
|
villageId: this.id,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
sort: ['createdAt:DESC'],
|
sort: ['createdAt:DESC'],
|
||||||
}
|
}
|
||||||
|
@ -55,11 +75,14 @@ class TWHelpConnector {
|
||||||
return ennoblements.data.length > 0 ? ennoblements.data[0] : null;
|
return ennoblements.data.length > 0 ? ennoblements.data[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
villageEnnoblements(page: number, limit: number) {
|
villageEnnoblements(cursor: string | undefined, limit: number) {
|
||||||
return this.client.villageEnnoblements(this.version, this.server, this.id, {
|
return this.client.ennoblements.listVillageEnnoblements({
|
||||||
offset: (page - 1) * limit,
|
cursor,
|
||||||
limit,
|
versionCode: this.version,
|
||||||
sort: ['createdAt:desc'],
|
serverKey: this.server,
|
||||||
|
villageId: this.id,
|
||||||
|
limit: limit,
|
||||||
|
sort: ['createdAt:DESC'],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,7 +161,7 @@ class UI {
|
||||||
private async showEnnoblements(e: Event) {
|
private async showEnnoblements(e: Event) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
await new DialogTable(
|
await new DialogTable<Ennoblement>(
|
||||||
DialogId.ENNOBLEMENTS,
|
DialogId.ENNOBLEMENTS,
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
@ -182,8 +205,8 @@ class UI {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
30,
|
30,
|
||||||
(page: number, limit: number) => {
|
async (cursor, limit) => {
|
||||||
return this.connector.villageEnnoblements(page, limit);
|
return this.connector.villageEnnoblements(cursor, limit);
|
||||||
}
|
}
|
||||||
).render();
|
).render();
|
||||||
}
|
}
|
||||||
|
@ -191,9 +214,9 @@ class UI {
|
||||||
|
|
||||||
class ExtendedVillageProfile {
|
class ExtendedVillageProfile {
|
||||||
connector: TWHelpConnector;
|
connector: TWHelpConnector;
|
||||||
constructor(client: TWHelpClient) {
|
constructor(apiBaseUrl: string) {
|
||||||
this.connector = new TWHelpConnector(
|
this.connector = new TWHelpConnector(
|
||||||
client,
|
apiBaseUrl,
|
||||||
window.game_data.market,
|
window.game_data.market,
|
||||||
window.game_data.world,
|
window.game_data.world,
|
||||||
this.getVillageId()
|
this.getVillageId()
|
||||||
|
@ -226,9 +249,7 @@ class ExtendedVillageProfile {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await new ExtendedVillageProfile(
|
await new ExtendedVillageProfile(process.env.TWHELP_API_BASE_URL ?? '')
|
||||||
new TWHelpClient(process.env.TWHELP_API_BASE_URL ?? '')
|
|
||||||
)
|
|
||||||
.run()
|
.run()
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import addSeconds from 'date-fns/addSeconds';
|
import { addSeconds } from 'date-fns/addSeconds';
|
||||||
import isAfter from 'date-fns/isAfter';
|
import { isAfter } from 'date-fns/isAfter';
|
||||||
|
|
||||||
export interface Storage {
|
export interface Storage {
|
||||||
getItem(key: string): string | null;
|
getItem(key: string): string | null;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import differenceInMinutes from 'date-fns/differenceInMinutes';
|
import { differenceInMinutes } from 'date-fns/differenceInMinutes';
|
||||||
import { LOYALTY_AFTER_CONQUER, MAX_LOYALTY } from './constants';
|
import { LOYALTY_AFTER_CONQUER, MAX_LOYALTY } from './constants';
|
||||||
|
|
||||||
export const calcLoyalty = (
|
export const calcLoyalty = (
|
||||||
|
|
|
@ -1,424 +0,0 @@
|
||||||
import axios, {
|
|
||||||
AxiosInstance,
|
|
||||||
AxiosResponseHeaders,
|
|
||||||
RawAxiosResponseHeaders,
|
|
||||||
} from 'axios';
|
|
||||||
|
|
||||||
export type ServerMeta = {
|
|
||||||
key: string;
|
|
||||||
open: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Tribe = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
tag: string;
|
|
||||||
numMembers: number;
|
|
||||||
numVillages: number;
|
|
||||||
points: number;
|
|
||||||
allPoints: number;
|
|
||||||
rank: number;
|
|
||||||
dominance: number;
|
|
||||||
rankAtt: number;
|
|
||||||
scoreAtt: number;
|
|
||||||
rankDef: number;
|
|
||||||
scoreDef: number;
|
|
||||||
rankTotal: number;
|
|
||||||
scoreTotal: number;
|
|
||||||
profileUrl: string;
|
|
||||||
bestRank: number;
|
|
||||||
bestRankAt: string;
|
|
||||||
mostPoints: number;
|
|
||||||
mostPointsAt: string;
|
|
||||||
mostVillages: number;
|
|
||||||
mostVillagesAt: string;
|
|
||||||
createdAt: string;
|
|
||||||
deletedAt: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TribeMeta = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
tag: string;
|
|
||||||
profileUrl: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Player = {
|
|
||||||
id: number;
|
|
||||||
points: number;
|
|
||||||
rank: number;
|
|
||||||
numVillages: number;
|
|
||||||
scoreAtt: number;
|
|
||||||
rankAtt: number;
|
|
||||||
scoreDef: number;
|
|
||||||
rankDef: number;
|
|
||||||
scoreSup: number;
|
|
||||||
rankSup: number;
|
|
||||||
scoreTotal: number;
|
|
||||||
rankTotal: number;
|
|
||||||
bestRank: number;
|
|
||||||
bestRankAt: string;
|
|
||||||
mostPoints: number;
|
|
||||||
mostPointsAt: string;
|
|
||||||
mostVillages: number;
|
|
||||||
mostVillagesAt: string;
|
|
||||||
lastActivityAt: string;
|
|
||||||
createdAt: string;
|
|
||||||
tribe: TribeMeta | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PlayerWithServer = Player & {
|
|
||||||
server: ServerMeta;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PlayerMeta = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
profileUrl: string;
|
|
||||||
tribe: TribeMeta | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type VillageMeta = {
|
|
||||||
id: number;
|
|
||||||
fullName: string;
|
|
||||||
profileUrl: string;
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
continent: string;
|
|
||||||
player: PlayerMeta | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TribeChange = {
|
|
||||||
id: number;
|
|
||||||
newTribe: TribeMeta | null;
|
|
||||||
player: PlayerMeta;
|
|
||||||
createdAt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Ennoblement = {
|
|
||||||
id: number;
|
|
||||||
points: number;
|
|
||||||
newOwner: PlayerMeta | null;
|
|
||||||
village: VillageMeta;
|
|
||||||
createdAt: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type TribeSnapshot = {
|
|
||||||
id: number;
|
|
||||||
numMembers: number;
|
|
||||||
numVillages: number;
|
|
||||||
points: number;
|
|
||||||
allPoints: number;
|
|
||||||
rank: number;
|
|
||||||
dominance: number;
|
|
||||||
rankAtt: number;
|
|
||||||
scoreAtt: number;
|
|
||||||
rankDef: number;
|
|
||||||
scoreDef: number;
|
|
||||||
rankTotal: number;
|
|
||||||
scoreTotal: number;
|
|
||||||
date: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PlayerSnapshot = {
|
|
||||||
id: number;
|
|
||||||
tribe: TribeMeta | null;
|
|
||||||
points: number;
|
|
||||||
numVillages: number;
|
|
||||||
rank: number;
|
|
||||||
rankAtt: number;
|
|
||||||
rankDef: number;
|
|
||||||
rankSup: number;
|
|
||||||
rankTotal: number;
|
|
||||||
scoreAtt: number;
|
|
||||||
scoreDef: number;
|
|
||||||
scoreSup: number;
|
|
||||||
scoreTotal: number;
|
|
||||||
date: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ServerConfig = {
|
|
||||||
speed: number;
|
|
||||||
unitSpeed: number;
|
|
||||||
snob: {
|
|
||||||
maxDist: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export type Unit = {
|
|
||||||
speed: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UnitInfo = {
|
|
||||||
archer: Unit;
|
|
||||||
axe: Unit;
|
|
||||||
catapult: Unit;
|
|
||||||
heavy: Unit;
|
|
||||||
knight: Unit;
|
|
||||||
light: Unit;
|
|
||||||
marcher: Unit;
|
|
||||||
militia: Unit;
|
|
||||||
ram: Unit;
|
|
||||||
snob: Unit;
|
|
||||||
spear: Unit;
|
|
||||||
spy: Unit;
|
|
||||||
sword: Unit;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListResult<T> = {
|
|
||||||
data: T[];
|
|
||||||
total: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListTribeChangesQueryParams = {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
sort?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListEnnoblementsParams = {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
sort?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListTribeMembers = {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
sort?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListSnapshotsParams = {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
sort?: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export type ListPlayerOtherServersParams = {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export class TWHelpClient {
|
|
||||||
client: AxiosInstance;
|
|
||||||
|
|
||||||
constructor(url: string, timeout = 10000) {
|
|
||||||
this.client = axios.create({
|
|
||||||
baseURL: url,
|
|
||||||
timeout,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public async serverConfig(
|
|
||||||
version: string,
|
|
||||||
server: string
|
|
||||||
): Promise<ServerConfig> {
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/config`
|
|
||||||
);
|
|
||||||
return resp.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async unitInfo(version: string, server: string): Promise<UnitInfo> {
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/unit-info`
|
|
||||||
);
|
|
||||||
return resp.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async tribe(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number
|
|
||||||
): Promise<Tribe> {
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/tribes/${id}`
|
|
||||||
);
|
|
||||||
return resp.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async tribeSnapshots(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListSnapshotsParams
|
|
||||||
): Promise<ListResult<TribeSnapshot>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/tribes/${id}/snapshots?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async tribeTribeChanges(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListTribeChangesQueryParams
|
|
||||||
): Promise<ListResult<TribeChange>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/tribes/${id}/tribe-changes?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async tribeEnnoblements(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListEnnoblementsParams
|
|
||||||
): Promise<ListResult<Ennoblement>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/tribes/${id}/ennoblements?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async tribeMembers(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListTribeMembers
|
|
||||||
): Promise<ListResult<Player>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/tribes/${id}/members?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async player(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number
|
|
||||||
): Promise<Player> {
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/players/${id}`
|
|
||||||
);
|
|
||||||
return resp.data.data;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async playerTribeChanges(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListTribeChangesQueryParams
|
|
||||||
): Promise<ListResult<TribeChange>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/players/${id}/tribe-changes?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async playerEnnoblements(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListEnnoblementsParams
|
|
||||||
): Promise<ListResult<Ennoblement>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/players/${id}/ennoblements?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async playerSnapshots(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListSnapshotsParams
|
|
||||||
): Promise<ListResult<PlayerSnapshot>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/players/${id}/snapshots?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async playerOtherServers(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListPlayerOtherServersParams
|
|
||||||
): Promise<ListResult<PlayerWithServer>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/players/${id}/other-servers?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public async villageEnnoblements(
|
|
||||||
version: string,
|
|
||||||
server: string,
|
|
||||||
id: number,
|
|
||||||
queryParams?: ListEnnoblementsParams
|
|
||||||
): Promise<ListResult<Ennoblement>> {
|
|
||||||
const queryString = queryParams ? this.buildQueryString(queryParams) : '';
|
|
||||||
const resp = await this.client.get(
|
|
||||||
`/api/v1/versions/${version}/servers/${server}/villages/${id}/ennoblements?${queryString}`
|
|
||||||
);
|
|
||||||
return {
|
|
||||||
data: resp.data.data,
|
|
||||||
total: this.parseTotal(resp.headers),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private buildQueryString(
|
|
||||||
queryParams: Record<string, string | boolean | number | Date | string[]>
|
|
||||||
): string {
|
|
||||||
const params = new URLSearchParams();
|
|
||||||
|
|
||||||
for (const [name, val] of Object.entries(queryParams)) {
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
val.forEach((s) => {
|
|
||||||
params.append(name, s);
|
|
||||||
});
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (val instanceof Date) {
|
|
||||||
params.set(name, val.toISOString());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
params.set(name, val.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return params.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private parseTotal(
|
|
||||||
headers: RawAxiosResponseHeaders | AxiosResponseHeaders
|
|
||||||
): number {
|
|
||||||
return parseInt(headers['x-total-count'] ?? '0');
|
|
||||||
}
|
|
||||||
}
|
|
1
src/lib/twhelp/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
generated
|
2
src/lib/twhelp/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export * from './generated';
|
||||||
|
export * from './timeout';
|
1
src/lib/twhelp/openapi3.json
Normal file
20
src/lib/twhelp/timeout.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
import { request as __request } from './generated/core/request';
|
||||||
|
import { CancelablePromise } from './generated/core/CancelablePromise';
|
||||||
|
import { BaseHttpRequest } from './generated/core/BaseHttpRequest';
|
||||||
|
import { ApiRequestOptions } from './generated/core/ApiRequestOptions';
|
||||||
|
import type { OpenAPIConfig } from './generated/core/OpenAPI';
|
||||||
|
|
||||||
|
export class AxiosHttpRequestWithTimeout extends BaseHttpRequest {
|
||||||
|
axiosInstance = axios.create({
|
||||||
|
timeout: 5000,
|
||||||
|
});
|
||||||
|
|
||||||
|
constructor(config: OpenAPIConfig) {
|
||||||
|
super(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override request<T>(options: ApiRequestOptions): CancelablePromise<T> {
|
||||||
|
return __request(this.config, options, this.axiosInstance);
|
||||||
|
}
|
||||||
|
}
|