123 Commits

Author SHA1 Message Date
1c0e3d5eb4 fix(deps): update dependency @types/node to v22 2024-10-29 00:05:02 +00:00
Lee
c7853d4153 Merge pull request 'fix(deps): update dependency @types/node to v20.16.9' (#32) from renovate/node-20.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Successful in 43s
Reviewed-on: #32
2024-09-26 15:15:27 +00:00
1481bd1d00 fix(deps): update dependency @types/node to v20.16.9 2024-09-26 13:01:56 +00:00
Lee
1bf3c86a4c Merge pull request 'fix(deps): update dependency @types/node to v20.16.9' (#28) from renovate/node-20.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 26s
Publish Docker Image / docker (push) Successful in 44s
Reviewed-on: #28
2024-09-26 12:39:42 +00:00
Lee
6727e1177c Merge pull request 'fix(deps): update dependency tsup to v8.3.0' (#30) from renovate/tsup-8.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #30
2024-09-26 12:39:37 +00:00
47f3f8b1e0 fix(deps): update dependency tsup to v8.3.0 2024-09-17 05:01:52 +00:00
27703ff009 fix(deps): update dependency @types/node to v20.16.4 2024-09-04 01:01:53 +00:00
Lee
f788f574c0 Merge pull request 'fix(deps): update dependency @types/node to v20.16.3' (#27) from renovate/node-20.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Successful in 46s
Reviewed-on: #27
2024-09-02 08:12:28 +00:00
Lee
6c19559964 Merge pull request 'fix(deps): update dependency @influxdata/influxdb-client to v1.35.0' (#26) from renovate/influxdata-influxdb-client-1.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Failing after 5s
Reviewed-on: #26
2024-09-02 08:12:23 +00:00
Lee
f83ff0a7a6 Merge pull request 'fix(deps): update dependency axios to v1.7.7' (#25) from renovate/axios-1.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #25
2024-09-02 08:12:15 +00:00
ee69ce3c8d fix(deps): update dependency @types/node to v20.16.3 2024-09-01 16:01:58 +00:00
8f47e210d5 fix(deps): update dependency @influxdata/influxdb-client to v1.35.0 2024-09-01 15:02:01 +00:00
8c1055b468 fix(deps): update dependency axios to v1.7.7 2024-09-01 15:01:56 +00:00
Lee
42558f3500 Merge pull request 'fix(deps): update dependency @influxdata/influxdb-client to v1.35.0' (#14) from renovate/influxdata-influxdb-client-1.x-lockfile into master
All checks were successful
Publish Docker Image / docker (push) Successful in 48s
Deploy CI / deploy (push) Successful in 27s
Reviewed-on: #14
2024-09-01 14:19:32 +00:00
Lee
0a3e8f28ba Merge pull request 'fix(deps): update dependency winston to v3.14.2' (#22) from renovate/winston-3.x-lockfile into master
Some checks failed
Deploy CI / deploy (push) Failing after 6s
Publish Docker Image / docker (push) Has been cancelled
Reviewed-on: #22
2024-09-01 14:19:21 +00:00
Lee
419b2b0286 Merge pull request 'fix(deps): update dependency @types/node to v20.16.3' (#23) from renovate/node-20.x-lockfile into master
Some checks failed
Deploy CI / deploy (push) Failing after 5s
Publish Docker Image / docker (push) Has been cancelled
Reviewed-on: #23
2024-09-01 14:19:12 +00:00
Lee
59816d7410 Merge pull request 'fix(deps): update dependency axios to v1.7.7' (#24) from renovate/axios-1.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #24
2024-09-01 14:19:03 +00:00
cdb7dbf18f fix(deps): update dependency axios to v1.7.5 2024-08-23 14:01:43 +00:00
4696d512eb fix(deps): update dependency @types/node to v20.15.0 2024-08-16 19:01:44 +00:00
3793071c2d fix(deps): update dependency winston to v3.14.2 2024-08-14 18:01:48 +00:00
Lee
43e9492a47 Merge pull request 'fix(deps): update dependency axios to v1.7.4' (#21) from renovate/axios-1.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 50s
Publish Docker Image / docker (push) Successful in 1m13s
Reviewed-on: #21
2024-08-14 08:45:43 +00:00
745e4e6fe5 fix(deps): update dependency axios to v1.7.4 2024-08-13 20:01:35 +00:00
Lee
3274e3bc2d Merge pull request 'fix(deps): update dependency @types/node to v20.14.15' (#16) from renovate/node-20.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 23s
Publish Docker Image / docker (push) Successful in 1m5s
Reviewed-on: #16
2024-08-13 17:28:40 +00:00
c463cdff0a fix(deps): update dependency @types/node to v20.14.15 2024-08-11 07:01:33 +00:00
Lee
4c7a46e493 Merge pull request 'fix(deps): update dependency tsup to v8.2.4' (#18) from renovate/tsup-8.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 51s
Publish Docker Image / docker (push) Successful in 54s
Reviewed-on: #18
2024-08-11 06:41:40 +00:00
01df7d1e13 fix(deps): update dependency tsup to v8.2.4 2024-08-10 12:01:33 +00:00
Lee
dc06a3877d Merge pull request 'fix(deps): update dependency axios to v1.7.3' (#17) from renovate/axios-1.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 19s
Publish Docker Image / docker (push) Successful in 40s
Reviewed-on: #17
2024-08-10 11:37:31 +00:00
Lee
c816304a71 Merge pull request 'fix(deps): update dependency typescript to v5.5.4' (#19) from renovate/typescript-5.x-lockfile into master
Some checks failed
Deploy CI / deploy (push) Failing after 5s
Publish Docker Image / docker (push) Has been cancelled
Reviewed-on: #19
2024-08-10 11:37:20 +00:00
Lee
32a50e9de4 Merge pull request 'fix(deps): update dependency winston to v3.14.1' (#20) from renovate/winston-3.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #20
2024-08-10 11:37:12 +00:00
2bfe562269 fix(deps): update dependency winston to v3.14.1 2024-08-10 11:36:38 +00:00
c381d82e2a fix(deps): update dependency typescript to v5.5.4 2024-08-10 11:36:32 +00:00
d12287a13a fix(deps): update dependency axios to v1.7.3 2024-08-10 11:36:21 +00:00
f193dacd14 fix(deps): update dependency @influxdata/influxdb-client to v1.34.0 2024-08-10 11:34:45 +00:00
Lee
6a9ccad31c Update renovate.json
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 1m2s
2024-08-10 11:34:03 +00:00
cf49d249bd chore(deps): update docker/build-push-action action to v6
All checks were successful
Publish Docker Image / docker (push) Successful in 48s
2024-08-10 11:33:00 +00:00
Lee
85b5b7cbce Merge pull request 'fix(deps): update dependency axios to v1.6.8' (#9) from renovate/axios-1.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Successful in 41s
Reviewed-on: #9
2024-08-10 11:30:57 +00:00
Lee
71239fa078 Merge pull request 'fix(deps): update dependency typescript to v5.4.5' (#10) from renovate/typescript-5.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #10
2024-08-10 11:30:52 +00:00
Lee
66f067990b Merge pull request 'fix(deps): update dependency winston to v3.13.0' (#11) from renovate/winston-3.x-lockfile into master
Some checks failed
Publish Docker Image / docker (push) Waiting to run
Deploy CI / deploy (push) Has been cancelled
Reviewed-on: #11
2024-08-10 11:30:43 +00:00
Lee
9701ecdcd7 Update data/servers.json
Some checks failed
Deploy CI / deploy (push) Successful in 54s
Publish Docker Image / docker (push) Has been cancelled
2024-08-10 11:29:01 +00:00
Lee
adf46b9cb8 Update data/servers.json
All checks were successful
Deploy CI / deploy (push) Successful in 1m2s
Publish Docker Image / docker (push) Successful in 59s
2024-06-02 18:56:39 +00:00
9f40efa75a fix(deps): update dependency winston to v3.13.0 2024-04-05 23:47:40 +00:00
6984c35710 fix(deps): update dependency typescript to v5.4.3 2024-03-23 20:51:03 +00:00
f395b66d77 fix(deps): update dependency axios to v1.6.8 2024-03-23 20:50:56 +00:00
Lee
627fe5f38f Update data/servers.json
All checks were successful
Deploy CI / deploy (push) Successful in 28s
Publish Docker Image / docker (push) Successful in 1m16s
2024-03-20 05:54:51 +00:00
Lee
ba4807f33f Update .gitea/workflows/publish.yml
All checks were successful
Publish Docker Image / docker (push) Successful in 59s
2024-03-17 00:52:56 +00:00
Lee
3f791ad52a Merge pull request 'fix(deps): update dependency winston to v3.12.0' (#8) from renovate/winston-3.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 50s
Reviewed-on: #8
2024-03-13 20:11:09 +00:00
Lee
bfe26c2250 Merge pull request 'fix(deps): update dependency tsup to v8.0.2' (#6) from renovate/tsup-8.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 45s
Reviewed-on: #6
2024-03-13 19:55:57 +00:00
Lee
b1451f9e88 Merge pull request 'fix(deps): update dependency axios to v1.6.7' (#5) from renovate/axios-1.x-lockfile into master
All checks were successful
Deploy CI / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Successful in 1m15s
Reviewed-on: #5
2024-03-13 19:54:11 +00:00
Lee
d8fafec1ba server: remove Rainpixel
All checks were successful
Deploy CI / deploy (push) Successful in 29s
Publish Docker Image / docker (push) Successful in 1m7s
2024-03-13 19:50:27 +00:00
666036ef2e fix(deps): update dependency winston to v3.12.0 2024-03-06 01:14:15 +00:00
7f457497e3 fix(deps): update dependency tsup to v8.0.2 2024-03-06 00:19:18 +00:00
7ea96c5cc3 fix(deps): update dependency axios to v1.6.7 2024-03-06 00:19:11 +00:00
Lee
e208b99192 Update grafana-dashboard.json 2024-02-09 10:08:45 +00:00
Lee
58696a9566 Update grafana-dashboard.json 2024-02-08 01:08:01 +00:00
Lee
908e9e1618 Merge pull request 'chore(deps): update actions/cache action to v4' (#4) from renovate/actions-cache-4.x into master
All checks were successful
Publish Docker Image / docker (push) Successful in 1m1s
Reviewed-on: #4
2024-01-23 06:16:38 +00:00
3496865c2e chore(deps): update actions/cache action to v4 2024-01-17 17:01:29 +00:00
21c3677d0e server: add Stray
All checks were successful
Deploy CI / deploy (push) Successful in 14s
Publish Docker Image / docker (push) Successful in 43s
2024-01-16 17:18:27 +00:00
466f96b649 server: add Shotbow
All checks were successful
Deploy CI / deploy (push) Successful in 14s
Publish Docker Image / docker (push) Successful in 43s
2024-01-16 17:05:40 +00:00
4b2a428646 server: add Monumenta
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 46s
2024-01-16 17:01:36 +00:00
20acbfd7f4 server: add Complex Gaming
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 47s
2024-01-16 16:31:45 +00:00
d2d1597b72 Merge branch 'master' of https://git.fascinated.cc/mc-tracker/backend
All checks were successful
Deploy CI / deploy (push) Successful in 14s
Publish Docker Image / docker (push) Successful in 55s
2024-01-13 17:37:26 +00:00
d468e2b070 server: remove tubnet 2024-01-13 17:37:25 +00:00
4a81455f96 meow
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 1m12s
2024-01-13 12:34:20 +00:00
6221a58062 update influx err msg
All checks were successful
Deploy CI / deploy (push) Successful in 14s
Publish Docker Image / docker (push) Successful in 43s
2024-01-10 14:21:30 +00:00
98cb26e310 feat: add server latency to the influx points
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 45s
2024-01-10 10:47:25 +00:00
ab53e24978 server: add cubecraft bedrock
All checks were successful
Deploy CI / deploy (push) Successful in 15s
Publish Docker Image / docker (push) Successful in 47s
2024-01-09 14:59:47 +00:00
3f399bec10 organize server config
All checks were successful
Deploy CI / deploy (push) Successful in 16s
Publish Docker Image / docker (push) Successful in 48s
2024-01-09 14:51:15 +00:00
cf72d4886a update readme 2024-01-09 02:31:10 +00:00
3bed998640 fix dockerfile file
All checks were successful
Deploy CI / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 45s
2024-01-06 09:28:06 +00:00
4b7b43c036 add finisheding msg
Some checks failed
Deploy CI / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Has been cancelled
2024-01-06 09:27:09 +00:00
d15f1613f0 cleanup
All checks were successful
Deploy CI / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 42s
2024-01-06 06:03:30 +00:00
1bd47d2b60 update actions
All checks were successful
Deploy CI / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 48s
2024-01-06 05:13:53 +00:00
a8bc162d8b server: add rainpixel
All checks were successful
deploy / deploy (push) Successful in 22s
Publish Docker Image / docker (push) Successful in 46s
2024-01-06 05:01:32 +00:00
cf66e8c488 fix: update grafana dashboard
All checks were successful
deploy / deploy (push) Successful in 20s
2024-01-04 07:44:44 +00:00
2b8af4050b Merge branch 'master' of https://git.fascinated.cc/mc-tracker/backend
All checks were successful
deploy / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Successful in 41s
2024-01-04 07:26:03 +00:00
3568e195b9 server: add InvadedLands 2024-01-04 07:26:02 +00:00
2d0f4ddca1 server: add manacube 2024-01-04 07:24:08 +00:00
9ffa0c549c server: add minecadia 2024-01-04 07:24:00 +00:00
4543309fd1 server: add op legends 2024-01-04 07:23:45 +00:00
Lee
2780f4f5f6 Delete package-lock.json
All checks were successful
deploy / deploy (push) Successful in 23s
Publish Docker Image / docker (push) Successful in 43s
2024-01-04 04:14:46 +00:00
169d53f2cf server: add Tubnet
All checks were successful
deploy / deploy (push) Successful in 19s
Publish Docker Image / docker (push) Successful in 43s
2024-01-04 04:04:20 +00:00
74ccee0381 server: add Minemen Club 2024-01-04 04:04:03 +00:00
Lee
6880cd30ce server: add Hoplite
All checks were successful
deploy / deploy (push) Successful in 21s
Publish Docker Image / docker (push) Successful in 42s
2024-01-04 04:00:04 +00:00
d9d6d2b3bb fix: warn not error in a log
All checks were successful
deploy / deploy (push) Successful in 19s
Publish Docker Image / docker (push) Successful in 43s
2024-01-04 01:22:14 +00:00
3b33e7f9ae fix: fix time format in logger
Some checks failed
deploy / deploy (push) Successful in 20s
Publish Docker Image / docker (push) Has been cancelled
2024-01-04 01:21:54 +00:00
0f62409e88 fix: remove minecraft.net
All checks were successful
deploy / deploy (push) Successful in 19s
Publish Docker Image / docker (push) Successful in 45s
2024-01-04 01:11:38 +00:00
ff11240334 add website tracking
All checks were successful
deploy / deploy (push) Successful in 22s
Publish Docker Image / docker (push) Successful in 46s
2024-01-04 00:57:21 +00:00
358bb6272c update ci ip
Some checks failed
Publish Docker Image / docker (push) Successful in 43s
deploy / deploy (push) Failing after 29s
2024-01-03 20:56:40 +00:00
9540a03366 update grafana file
All checks were successful
deploy / deploy (push) Successful in 35s
Publish Docker Image / docker (push) Successful in 41s
2024-01-03 10:39:14 +00:00
0781d74067 update example config
All checks were successful
deploy / deploy (push) Successful in 32s
Publish Docker Image / docker (push) Successful in 42s
2024-01-03 09:48:23 +00:00
88472c81e9 add auto invalidation of dns cache
Some checks failed
Publish Docker Image / docker (push) Successful in 42s
deploy / deploy (push) Has been cancelled
2024-01-03 09:46:46 +00:00
d841900cfb add useful stuff
All checks were successful
deploy / deploy (push) Successful in 32s
Publish Docker Image / docker (push) Successful in 41s
2024-01-03 09:36:23 +00:00
404fc5b267 fix: fix gtm name
All checks were successful
deploy / deploy (push) Successful in 32s
Publish Docker Image / docker (push) Successful in 41s
2024-01-03 09:25:27 +00:00
5fd535a19c update grafana dashboard
All checks were successful
deploy / deploy (push) Successful in 34s
Publish Docker Image / docker (push) Successful in 42s
2024-01-03 09:21:42 +00:00
899aac977f add storage tracker script 2024-01-03 09:21:24 +00:00
d76c5a9131 ci stuff
All checks were successful
Publish Docker Image / docker (push) Successful in 42s
deploy / deploy (push) Successful in 27s
2024-01-03 08:59:02 +00:00
31176e4025 fix: cleanup
All checks were successful
Publish Docker Image / docker (push) Successful in 52s
2024-01-03 08:48:16 +00:00
7369ad4d7b fix: update wild ip
All checks were successful
Publish Docker Image / docker (push) Successful in 44s
2024-01-03 08:37:48 +00:00
0d0c3aca71 Merge branch 'master' of https://git.fascinated.cc/mc-tracker/backend
All checks were successful
Publish Docker Image / docker (push) Successful in 1m21s
2024-01-03 08:34:41 +00:00
f71e423d6c fix: update image name 2024-01-03 08:34:40 +00:00
Lee
103f96d5bd Merge pull request 'chore: Configure Renovate' (#1) from renovate/configure into master
All checks were successful
Publish Docker Image / docker (push) Successful in 42s
Reviewed-on: #1
2024-01-03 08:33:51 +00:00
Lee
2cee3d9c7f Merge pull request 'influx-only' (#2) from influx-only into master
All checks were successful
Publish Docker Image / docker (push) Successful in 41s
Reviewed-on: #2
2024-01-03 08:32:27 +00:00
b0f3d8532f dont include ip in the influx data
All checks were successful
Publish Docker Image / docker (push) Successful in 42s
2024-01-03 08:32:04 +00:00
4095d70722 update wild
All checks were successful
Publish Docker Image / docker (push) Successful in 41s
2024-01-03 08:31:21 +00:00
8826a2530a use name to identify servers not ip
All checks were successful
Publish Docker Image / docker (push) Successful in 43s
2024-01-03 08:27:33 +00:00
53ae4dbd89 chore(deps): add renovate.json 2024-01-03 08:01:51 +00:00
56a75560e8 update compose file
All checks were successful
Publish Docker Image / docker (push) Successful in 43s
2024-01-03 08:00:05 +00:00
9c6966f180 remove old log
All checks were successful
Publish Docker Image / docker (push) Successful in 1m0s
2024-01-03 07:52:43 +00:00
8383445898 dont need u either
All checks were successful
Publish Docker Image / docker (push) Successful in 53s
2024-01-03 07:50:03 +00:00
29e3696be3 dont create .d.ts files for prod (rlly slow to make them)
All checks were successful
Publish Docker Image / docker (push) Successful in 1m17s
2024-01-03 07:47:41 +00:00
8f344d246f dont ping servers on startup
All checks were successful
Publish Docker Image / docker (push) Successful in 43s
2024-01-03 07:42:39 +00:00
d4bba5426e fix deps
All checks were successful
Publish Docker Image / docker (push) Successful in 43s
2024-01-03 07:40:43 +00:00
dba6aa8bef 7
All checks were successful
Publish Docker Image / docker (push) Successful in 44s
2024-01-03 07:39:03 +00:00
2ff05f9255 e
Some checks failed
Publish Docker Image / docker (push) Failing after 44s
2024-01-03 07:37:37 +00:00
fb6dbc3b5d helps when you build frfr
Some checks failed
Publish Docker Image / docker (push) Failing after 30s
2024-01-03 07:36:10 +00:00
663f997ee7 root
All checks were successful
Publish Docker Image / docker (push) Successful in 1m26s
2024-01-03 07:33:41 +00:00
00deb93193 im tired okay
Some checks failed
Publish Docker Image / docker (push) Failing after 31s
2024-01-03 07:32:49 +00:00
fd4ef15fae Merge branch 'influx-only' of https://git.fascinated.cc/mc-tracker/backend into influx-only
Some checks failed
Publish Docker Image / docker (push) Failing after 16s
2024-01-03 07:30:31 +00:00
9453ef59d3 for reel 2024-01-03 07:30:29 +00:00
Lee
d2a2bdacd5 Update .gitea/workflows/publish.yaml
All checks were successful
Publish Docker Image / docker (push) Successful in 1m20s
2024-01-03 07:27:35 +00:00
Lee
4f3a9ea9dd Update .gitea/workflows/publish.yaml 2024-01-03 07:27:10 +00:00
e603f65fdc meow 2024-01-03 07:25:17 +00:00
4ed5d2af84 meow 2024-01-03 07:25:17 +00:00
33 changed files with 2950 additions and 4946 deletions

24
.dockerignore Normal file
View File

@ -0,0 +1,24 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md

28
.gitea/workflows/ci.yml Normal file
View File

@ -0,0 +1,28 @@
name: "Deploy CI"
on:
push:
branches:
- master
paths-ignore: # Files in here will not trigger a build
- "README.md"
- "LICENSE"
- "grafana-dashboard.json"
- "storage-tracker.sh"
- "useful-stuff.md"
- ".gitea/workflows/publish.yml"
jobs:
deploy:
runs-on: ubuntu-22.04
steps:
- name: Cloning repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Push to dokku
uses: dokku/github-action@master
with:
git_remote_url: "ssh://dokku@51.158.63.74:22/mc-tracker"
ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}

View File

@ -0,0 +1,53 @@
name: Publish Docker Image
on:
push:
branches:
- "master"
paths-ignore: # Files in here will not trigger a build
- "README.md"
- "LICENSE"
- "grafana-dashboard.json"
- "storage-tracker.sh"
- "useful-stuff.md"
- ".gitea/workflows/ci.yml"
jobs:
docker:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Restore Docker Cache
uses: actions/cache@v4
id: docker-cache
with:
path: /usr/bin/docker
key: ${{ runner.os }}-docker
- name: Install Docker (if not cached)
if: steps.docker-cache.outputs.cache-hit != 'true'
run: |
wget -q -O /tmp/docker.tgz https://download.docker.com/linux/static/stable/x86_64/docker-20.10.23.tgz \
&& tar --extract --file /tmp/docker.tgz --directory /usr/bin --strip-components 1 --no-same-owner docker/docker \
&& rm -rf /tmp/* &&
echo "Done"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Repo
uses: docker/login-action@v3
with:
username: ${{ secrets.REPO_USERNAME }}
password: ${{ secrets.REPO_TOKEN }}
- name: Build and Push (Latest)
uses: docker/build-push-action@v6
with:
push: true
context: .
tags: fascinated/mc-tracker:latest
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache

4
.gitignore vendored
View File

@ -227,4 +227,6 @@ fabric.properties
data/db.sqlite data/db.sqlite
data/db.sqlite-shm data/db.sqlite-shm
data/db.sqlite-wal data/db.sqlite-wal
data/database-backups data/database-backups
data/config.json

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"configurations": [
{
"name": "Docker Node.js Launch",
"type": "docker",
"request": "launch",
"preLaunchTask": "docker-run: debug",
"platform": "node"
}
]
}

35
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,35 @@
{
"version": "2.0.0",
"tasks": [
{
"type": "docker-build",
"label": "docker-build",
"platform": "node",
"dockerBuild": {
"dockerfile": "${workspaceFolder}/Dockerfile",
"context": "${workspaceFolder}",
"pull": true
}
},
{
"type": "docker-run",
"label": "docker-run: release",
"dependsOn": ["docker-build"],
"platform": "node"
},
{
"type": "docker-run",
"label": "docker-run: debug",
"dependsOn": ["docker-build"],
"dockerRun": {
"env": {
"DEBUG": "*",
"NODE_ENV": "development"
}
},
"node": {
"enableDebugging": true
}
}
]
}

12
Dockerfile Normal file
View File

@ -0,0 +1,12 @@
FROM fascinated/docker-images:node-pnpm-latest AS base
ENV NODE_ENV=production
WORKDIR /usr/src/app
COPY ["package.json", "pnpm-lock.yaml", "./"]
RUN pnpm install --production --silent
COPY . .
CMD pnpm run build && pnpm run start

View File

@ -1,2 +1,9 @@
# backend # Mc Tracker
You can view the live instance of this project [here](https://mc-tracker.fascinated.cc).
## Features
- Track Minecraft server's player count over time
- See player count peaks (all time)
- Minecraft Java and Bedrock support

View File

@ -1,12 +0,0 @@
{
"websocket": {
"port": 3000
},
"scanner": {
"updateCron": "*/1 * * * *",
"timeout": 2000
},
"backup": {
"cron": "0 0 * * *"
}
}

13
data/config.json-example Normal file
View File

@ -0,0 +1,13 @@
{
"influx": {
"url": "http://localhost:8086",
"token": "setme",
"org": "setme",
"bucket": "mc-tracker"
},
"pinger": {
"pingCron": "*/1 * * * *",
"dnsInvalidationCron": "0 */6 * * *",
"timeout": 2000
}
}

View File

@ -1,74 +1,132 @@
[ [
{ {
"name": "WildPrison", "name": "HiveMC",
"ip": "wildprison.net", "ip": "geo.hivebedrock.network",
"type": "PC", "type": "PE"
"id": 0 },
{
"name": "Cubecraft - Bedrock",
"ip": "play.cubecraft.net",
"type": "PE"
},
{
"name": "WildNetwork",
"ip": "play.wildnetwork.net",
"type": "PC"
}, },
{ {
"name": "Hypixel", "name": "Hypixel",
"ip": "mc.hypixel.net", "ip": "mc.hypixel.net",
"type": "PC", "type": "PC"
"id": 1
}, },
{ {
"name": "CubeCraft", "name": "Cubecraft",
"ip": "play.cubecraft.net", "ip": "play.cubecraft.net",
"type": "PC", "type": "PC"
"id": 2
}, },
{ {
"name": "Mineplex", "name": "Mineplex",
"ip": "mineplex.com", "ip": "mineplex.com",
"type": "PC", "type": "PC"
"id": 3
}, },
{ {
"name": "2b2t", "name": "2b2t",
"ip": "2b2t.org", "ip": "2b2t.org",
"type": "PC", "type": "PC"
"id": 4
}, },
{ {
"name": "AkumaMC", "name": "AkumaMC",
"ip": "akumamc.net", "ip": "akumamc.net",
"type": "PC", "type": "PC"
"id": 5
}, },
{ {
"name": "Wynncraft", "name": "Wynncraft",
"ip": "play.wynncraft.com", "ip": "play.wynncraft.com",
"type": "PC", "type": "PC"
"id": 6
}, },
{ {
"name": "Minehut", "name": "Minehut",
"ip": "minehut.com", "ip": "minehut.com",
"type": "PC", "type": "PC"
"id": 7
}, },
{ {
"name": "Grand Theft Minecraft", "name": "Grand Theft Minecart",
"ip": "gtm.network", "ip": "gtm.network",
"type": "PC", "type": "PC"
"id": 8
},
{
"name": "HiveMC",
"ip": "geo.hivebedrock.network",
"type": "PE",
"id": 9
}, },
{ {
"name": "Purple Prison", "name": "Purple Prison",
"ip": "MCSL.PURPLE.WTF", "ip": "MCSL.PURPLE.WTF",
"type": "PC", "type": "PC"
"id": 10
}, },
{ {
"name": "MinecraftOnline", "name": "MinecraftOnline",
"ip": "minecraftonline.com", "ip": "minecraftonline.com",
"type": "PC", "type": "PC"
"id": 11 },
{
"name": "Hoplite",
"ip": "hoplite.gg",
"type": "PC"
},
{
"name": "Minemen Club",
"ip": "minemen.club",
"type": "PC"
},
{
"name": "OPLegends",
"ip": "play.oplegends.com",
"type": "PC"
},
{
"name": "Minecadia",
"ip": "play.minecadia.com",
"type": "PC"
},
{
"name": "Manacube",
"ip": "play.manacube.com",
"type": "PC"
},
{
"name": "InvadedLands",
"ip": "invadedlands.net",
"type": "PC"
},
{
"name": "Complex Gaming",
"ip": "hub.mc-complex.com",
"type": "PC"
},
{
"name": "Monumenta",
"ip": "server.playmonumenta.com",
"type": "PC"
},
{
"name": "Shotbow",
"ip": "play.shotbow.net",
"type": "PC"
},
{
"name": "Stray",
"ip": "stray.gg",
"type": "PC"
},
{
"name": "Aetheria Anarchy",
"ip": "aetheria.cc",
"type": "PC"
},
{
"name": "VexedMC",
"ip": "play.vexedmc.com",
"type": "PC"
},
{
"name": "AzureMC",
"ip": "play.azuremc.org",
"type": "PC"
} }
] ]

10
data/websites.json Normal file
View File

@ -0,0 +1,10 @@
[
{
"name": "Minecraft Textures",
"url": "https://textures.minecraft.net"
},
{
"name": "Minecraft Session Server",
"url": "https://session.minecraft.net"
}
]

34
docker-compose.yml Normal file
View File

@ -0,0 +1,34 @@
version: "3"
services:
tracker:
restart: always
image: fascinated/mc-tracker:latest
volumes:
- ./data:/usr/src/app/data
grafana:
image: grafana/grafana:latest
environment:
- GF_ANALYTICS_REPORTING_ENABLED=false
- GF_SERVER_DOMAIN=mc-tracker.fascinated.cc
- GF_AUTH_ANONYMOUS_ENABLED=true
ports:
- 3000:3000
volumes:
- /home/grafana/data:/var/lib/grafana
restart: always
influxdb:
image: influxdb:latest
container_name: influxdb
networks:
- default
security_opt:
- no-new-privileges:true
restart: always
ports:
- "8086:8086"
volumes:
- ./influx/config:/etc/influxdb2
- ./influx/db:/var/lib/influxdb2

1282
grafana-dashboard.json Normal file

File diff suppressed because it is too large Load Diff

4084
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,26 +4,26 @@
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"dev": "nodemon --exec ts-node src/index.ts" "dev": "nodemon --exec ts-node src/index.ts",
"build": "tsup src/index.ts --format cjs",
"start": "node dist/index.js"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@types/better-sqlite3": "^7.6.8", "@influxdata/influxdb-client": "^1.33.2",
"@types/mcping-js": "^1.5.4", "@types/mcping-js": "^1.5.4",
"@types/node": "^22.0.0",
"@types/node-cron": "^3.0.11", "@types/node-cron": "^3.0.11",
"better-sqlite3": "^9.2.2", "axios": "^1.6.4",
"dns": "^0.2.2", "dns": "^0.2.2",
"mcpe-ping-fixed": "^0.0.3", "mcpe-ping-fixed": "^0.0.3",
"mcping-js": "^1.5.0", "mcping-js": "^1.5.0",
"node-cron": "^3.0.3", "node-cron": "^3.0.3",
"socket.io": "^4.7.2",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"tsup": "^8.0.1",
"typescript": "^5.3.3", "typescript": "^5.3.3",
"winston": "^3.11.0" "winston": "^3.11.0"
},
"devDependencies": {
"@types/node": "^20.10.6"
} }
} }

1440
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

3
renovate.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": ["config:recommended", ":dependencyDashboard"]
}

View File

@ -1,158 +0,0 @@
import SQLiteDatabase from "better-sqlite3";
import cron from "node-cron";
import Server from "../server/server";
import { logger } from "../utils/logger";
import { getFormattedDate } from "../utils/timeUtils";
import Config from "../../data/config.json";
import { Ping } from "../types/ping";
import { createDirectory } from "../utils/fsUtils";
const DATA_DIR = "data";
const BACKUP_DIR = `${DATA_DIR}/database-backups`;
const PINGS_TABLE = "pings";
const RECORD_TABLE = "record";
/**
* SQL Queries
*/
const CREATE_PINGS_TABLE = `
CREATE TABLE IF NOT EXISTS pings (
id INTEGER NOT NULL,
timestamp BIGINT NOT NULL,
ip TINYTEXT NOT NULL,
playerCount MEDIUMINT NOT NULL
);
`;
const CREATE_RECORD_TABLE = `
CREATE TABLE IF NOT EXISTS record (
id INTEGER PRIMARY KEY,
timestamp BIGINT NOT NULL,
ip TINYTEXT NOT NULL,
playerCount MEDIUMINT NOT NULL
);
`;
const CREATE_PINGS_INDEX = `CREATE INDEX IF NOT EXISTS ip_index ON pings (id, ip, playerCount)`;
const CREATE_TIMESTAMP_INDEX = `CREATE INDEX IF NOT EXISTS timestamp_index on PINGS (id, timestamp)`;
const INSERT_PING = `
INSERT INTO ${PINGS_TABLE} (id, timestamp, ip, playerCount)
VALUES (?, ?, ?, ?)
`;
const INSERT_RECORD = `
INSERT INTO ${RECORD_TABLE} (id, timestamp, ip, playerCount)
VALUES (?, ?, ?, ?)
ON CONFLICT(id) DO UPDATE SET
timestamp = excluded.timestamp,
playerCount = excluded.playerCount,
ip = excluded.ip
`;
const SELECT_PINGS = `
SELECT * FROM ${PINGS_TABLE} WHERE id = ? AND timestamp >= ? AND timestamp <= ?
`;
const SELECT_RECORD = `
SELECT playerCount, timestamp FROM ${RECORD_TABLE} WHERE {} = ?
`;
const SELECT_RECORD_BY_ID = SELECT_RECORD.replace("{}", "id");
const SELECT_RECORD_BY_IP = SELECT_RECORD.replace("{}", "ip");
export default class Database {
private db: SQLiteDatabase.Database;
constructor() {
this.db = new SQLiteDatabase(`${DATA_DIR}/db.sqlite`);
this.db.pragma("journal_mode = WAL"); // Enable WAL mode for better performance
logger.info("Ensuring tables exist");
this.db.exec(CREATE_PINGS_TABLE); // Ensure the pings table exists
this.db.exec(CREATE_RECORD_TABLE); // Ensure the record table exists
logger.info("Ensuring indexes exist");
this.db.exec(CREATE_PINGS_INDEX); // Ensure the pings index exists
this.db.exec(CREATE_TIMESTAMP_INDEX); // Ensure the timestamp index exists
cron.schedule(Config.backup.cron, () => {
this.createBackup();
});
}
/**
* Gets the pings for a server.
*
* @param id the server ID
* @param startTime the start time
* @param endTime the end time
* @returns the pings for the server
*/
public getPings(id: number, startTime: number, endTime: number): Ping[] | [] {
return this.db.prepare(SELECT_PINGS).all(id, startTime, endTime) as
| Ping[]
| [];
}
/**
* Gets the record player count for a server.
*
* @param value the server ID or IP
* @returns the record for the server
*/
public getRecord(value: any): Ping | undefined {
if (typeof value === "number") {
return this.db.prepare(SELECT_RECORD_BY_ID).get(value) as
| Ping
| undefined;
}
return this.db.prepare(SELECT_RECORD_BY_IP).get(value) as Ping | undefined;
}
/**
* Creates a full backup of the database.
*/
public async createBackup() {
logger.info("Creating database backup");
createDirectory(BACKUP_DIR);
await this.db.backup(`${BACKUP_DIR}/${getFormattedDate()}.sqlite`);
logger.info("Finished creating database backup");
}
/**
* Inserts a ping into the database.
*
* @param timestamp the timestamp of the ping
* @param ip the IP address of the server
* @param playerCount the number of players online
*/
public insertPing(server: Server, response: Ping) {
const { timestamp, playerCount } = response;
const id = server.getID();
const ip = server.getIP();
const statement = this.db.prepare(INSERT_PING);
statement.run(id, timestamp, ip, playerCount); // Insert the ping into the database
}
/**
* Inserts a record into the database.
*
* @param server the server to insert
* @param response the response to insert
* @returns true if the a new record was set, false otherwise
*/
public insertRecord(server: Server, response: Ping): boolean {
const { timestamp, playerCount } = response;
const id = server.getID();
const ip = server.getIP();
const oldRecord = this.getRecord(id);
if (oldRecord && oldRecord.playerCount >= playerCount) {
return false; // Don't update the record if the player count is lower
}
const statement = this.db.prepare(INSERT_RECORD);
statement.run(id, timestamp, ip, playerCount); // Insert the record into the database
return true;
}
}

View File

@ -1,43 +1,14 @@
import Database from "./database/database"; import Influx from "./influx/influx";
import Scanner from "./scanner/scanner";
import ServerManager from "./server/serverManager"; import ServerManager from "./server/serverManager";
import WebsocketServer from "./websocket/websocket"; import WebsiteManager from "./website/websiteManager";
import {logger} from "./utils/logger";
import Config from "../data/config.json";
/** /**
* The database instance. * The influx database instance.
*/ */
export const database = new Database(); export const influx = new Influx();
/** new ServerManager();
* The server manager instance. new WebsiteManager();
*/
export const serverManager = new ServerManager();
/** logger.info("Done loading!");
* The websocket server instance.
*/
export const websocketServer = new WebsocketServer(Config.websocket.port);
(async () => {
await serverManager.init();
// The scanner is responsible for scanning all servers
new Scanner();
})();
// The websocket server is responsible for
// sending data to the client in real time
// serverManager.getServers().forEach((server) => {
// const record = database.getRecord(server.getID());
// if (!record) {
// return;
// }
// console.log(
// `Record for "${server.getName()}": ${record.playerCount} (${formatTimestamp(
// record.timestamp
// )})`
// );
// });

34
src/influx/influx.ts Normal file
View File

@ -0,0 +1,34 @@
import { InfluxDB, Point, WriteApi } from "@influxdata/influxdb-client";
import Config from "../../data/config.json";
import { logger } from "../utils/logger";
export default class Influx {
private influx: InfluxDB;
private writeApi: WriteApi;
constructor() {
logger.info("Loading influx database");
this.influx = new InfluxDB({
url: Config.influx.url,
token: Config.influx.token,
});
this.writeApi = this.influx.getWriteApi(
Config.influx.org,
Config.influx.bucket,
"ms"
);
logger.info("InfluxDB initialized");
}
/**
* Write a point to the database.
*
* @param point the point to write
*/
public writePoint(point: Point) {
this.writeApi.writePoint(point);
}
}

View File

@ -1,64 +0,0 @@
import cron from "node-cron";
import { database, serverManager, websocketServer } from "..";
import Server, { ServerStatus } from "../server/server";
import Config from "../../data/config.json";
import { logger } from "../utils/logger";
export default class Scanner {
constructor() {
logger.info("Loading scanner database");
cron.schedule(Config.scanner.updateCron, () => {
this.scanServers();
});
}
/**
* Start a server scan to ping all servers.
*/
private async scanServers(): Promise<void> {
logger.info(`Scanning servers ${serverManager.getServers().length}`);
// ping all servers in parallel
await Promise.all(
serverManager.getServers().map((server) => this.scanServer(server))
);
logger.info("Finished scanning servers");
}
/**
* Scans a server and inserts the ping into the database.
*
* @param server the server to scan
* @returns a promise that resolves when the server has been scanned
*/
async scanServer(server: Server): Promise<void> {
//logger.info(`Scanning server ${server.getIP()} - ${server.getType()}`);
let response;
let online = false;
try {
response = await server.pingServer();
if (response == undefined) {
return; // Server is offline
}
online = true;
} catch (err) {
logger.info(`Failed to ping ${server.getIP()}`, err);
websocketServer.sendServerError(server, ServerStatus.OFFLINE);
return;
}
if (!online || !response) {
return; // Server is offline
}
database.insertPing(server, response);
const isNewRecord = database.insertRecord(server, response);
// todo: send all server pings at once
websocketServer.sendNewPing(server, response, isNewRecord);
}
}

View File

@ -2,8 +2,11 @@ import javaPing from "mcping-js";
import { ResolvedServer, resolveDns } from "../utils/dnsResolver"; import { ResolvedServer, resolveDns } from "../utils/dnsResolver";
const bedrockPing = require("mcpe-ping-fixed"); // Doesn't have typescript definitions const bedrockPing = require("mcpe-ping-fixed"); // Doesn't have typescript definitions
import { Point } from "@influxdata/influxdb-client";
import { influx } from "..";
import Config from "../../data/config.json"; import Config from "../../data/config.json";
import { Ping } from "../types/ping"; import { Ping } from "../types/ping";
import { logger } from "../utils/logger";
/** /**
* The type of server. * The type of server.
@ -12,12 +15,7 @@ import { Ping } from "../types/ping";
*/ */
export type ServerType = "PC" | "PE"; export type ServerType = "PC" | "PE";
export enum ServerStatus {
OFFLINE = "Unable to reach host",
}
type ServerOptions = { type ServerOptions = {
id: number;
name: string; name: string;
ip: string; ip: string;
port?: number; port?: number;
@ -30,35 +28,25 @@ type DnsInfo = {
}; };
export default class Server { export default class Server {
/**
* The ID of the server.
*/
private id: number;
/** /**
* The name of the server. * The name of the server.
*/ */
private name: string; private readonly name: string;
/** /**
* The IP address of the server. * The IP address of the server.
*/ */
private ip: string; private readonly ip: string;
/** /**
* The port of the server. * The port of the server.
*/ */
private port: number | undefined; private readonly port: number | undefined;
/** /**
* The type of server. * The type of server.
*/ */
private type: ServerType; private readonly type: ServerType;
/**
* The favicon of the server.
*/
private favicon: string | undefined;
/** /**
* The resolved server information from * The resolved server information from
@ -68,8 +56,7 @@ export default class Server {
hasResolved: false, hasResolved: false,
}; };
constructor({ id, name, ip, port, type }: ServerOptions) { constructor({ name, ip, port, type }: ServerOptions) {
this.id = id;
this.name = name; this.name = name;
this.ip = ip; this.ip = ip;
this.port = port; this.port = port;
@ -79,23 +66,47 @@ export default class Server {
/** /**
* Pings a server and gets the response. * Pings a server and gets the response.
* *
* @param server the server to ping
* @param insertPing whether to insert the ping into the database
* @returns the ping response or undefined if the server is offline * @returns the ping response or undefined if the server is offline
*/ */
public pingServer(): Promise<Ping | undefined> { public async pingServer(): Promise<Ping | undefined> {
switch (this.getType()) { const before = Date.now();
case "PC": { try {
return this.pingPCServer(); let response;
switch (this.getType()) {
case "PC": {
response = await this.pingPCServer();
break;
}
case "PE": {
response = await this.pingPEServer();
break;
}
} }
case "PE": {
return this.pingPEServer(); if (!response) {
return Promise.resolve(undefined);
} }
default: {
throw new Error( try {
`Unknown server type ${this.getType()} for ${this.getName()}` influx.writePoint(
new Point("playerCount")
.tag("name", this.getName())
.intField("playerCount", response.playerCount)
.intField("latency", Date.now() - before)
.timestamp(response.timestamp)
);
} catch (err) {
logger.warn(
`Failed to write point to Influx for ${this.getName()} - ${this.getIP()}`,
err
); );
} }
return Promise.resolve(response);
} catch (err) {
logger.warn(`Failed to ping ${this.getIP()}`, err);
return Promise.resolve(undefined);
} }
} }
@ -132,15 +143,14 @@ export default class Server {
const serverPing = new javaPing.MinecraftServer(ip, port); const serverPing = new javaPing.MinecraftServer(ip, port);
// todo: do something to get the latest protocol? (is this even needed??)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
serverPing.ping(Config.scanner.timeout, 700, (err, res) => { serverPing.ping(Config.pinger.timeout, 765, (err, res) => {
if (err || res == undefined) { if (err || res == undefined) {
return reject(err); return reject(err);
} }
this.favicon = res.favicon; // Set the favicon
resolve({ resolve({
id: this.getID(),
timestamp: Date.now(), timestamp: Date.now(),
ip: ip, ip: ip,
playerCount: res.players.online, playerCount: res.players.online,
@ -166,7 +176,6 @@ export default class Server {
} }
resolve({ resolve({
id: this.getID(),
timestamp: Date.now(), timestamp: Date.now(),
ip: this.getIP(), ip: this.getIP(),
playerCount: res.currentPlayers, playerCount: res.currentPlayers,
@ -177,12 +186,12 @@ export default class Server {
} }
/** /**
* Returns the ID of the server. * Invalidates the DNS cache for the server.
*
* @returns the ID
*/ */
public getID(): number { public invalidateDns() {
return this.id; this.dnsInfo = {
hasResolved: false,
};
} }
/** /**
@ -220,13 +229,4 @@ export default class Server {
public getType(): ServerType { public getType(): ServerType {
return this.type; return this.type;
} }
/**
* Returns the favicon of the server.
*
* @returns the favicon
*/
public getFavicon(): string | undefined {
return this.favicon;
}
} }

View File

@ -1,36 +1,46 @@
import cron from "node-cron";
import { logger } from "../utils/logger";
import Server, { ServerType } from "./server"; import Server, { ServerType } from "./server";
import Config from "../../data/config.json";
import Servers from "../../data/servers.json"; import Servers from "../../data/servers.json";
export default class ServerManager { export default class ServerManager {
private servers: Server[] = []; private servers: Server[] = [];
constructor() {} constructor() {
logger.info("Loading servers...");
/**
* Loads the servers from the config file.
*/
async init() {
for (const configServer of Servers) { for (const configServer of Servers) {
const server = new Server({ const server = new Server({
id: configServer.id,
ip: configServer.ip, ip: configServer.ip,
name: configServer.name, name: configServer.name,
type: configServer.type as ServerType, type: configServer.type as ServerType,
}); });
try {
await server.pingServer();
} catch (err) {}
this.servers.push(server); this.servers.push(server);
} }
logger.info(`Loaded ${this.servers.length} servers!`);
cron.schedule(Config.pinger.pingCron, async () => {
await this.pingServers();
});
cron.schedule(Config.pinger.dnsInvalidationCron, () => {
logger.info("Invalidating DNS cache for all servers");
for (const server of this.servers) {
server.invalidateDns();
}
});
} }
/** /**
* Returns the servers. * Ping all servers to update their status.
*
* @returns the servers
*/ */
public getServers(): Server[] { private async pingServers(): Promise<void> {
return this.servers; logger.info(`Pinging servers ${this.servers.length}`);
// ping all servers in parallel
await Promise.all(this.servers.map((server) => server.pingServer()));
logger.info("Finished pinging servers!");
} }
} }

View File

@ -1,5 +1,4 @@
export type Ping = { export type Ping = {
id: number;
timestamp: number; timestamp: number;
ip: string; ip: string;
playerCount: number; playerCount: number;

View File

@ -1,41 +0,0 @@
import fs from "fs";
/**
* Creates a directory at the given path.
*
* @param path the path to the file
* @param recursive whether to create the directory tree if it doesn't exist (defaults to true)
* @returns a promise that resolves when the file is created
*/
export async function createDirectory(
path: string,
recursive?: boolean
): Promise<void> {
if (recursive == undefined) {
recursive = true; // Set to true by default
}
return new Promise((resolve, reject) => {
fs.mkdir(path, { recursive: recursive }, (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
/**
* Checks if a file exists at the given path.
*
* @param path the path to the file
* @returns a promise that returns true if the file exists, false otherwise
*/
export async function exists(path: string): Promise<boolean> {
return new Promise((resolve) => {
fs.exists(path, (exists) => {
resolve(exists);
});
});
}

View File

@ -9,7 +9,7 @@ interface LogInfo {
} }
const customFormat = format.combine( const customFormat = format.combine(
timestamp({ format: "YY-MM-DD HH:MM:SS" }), timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
printf((info: LogInfo) => { printf((info: LogInfo) => {
return `[${info.timestamp}] ${info.level}: ${info.message}`; return `[${info.timestamp}] ${info.level}: ${info.message}`;
}) })

View File

@ -1,18 +0,0 @@
/**
* Gets the current date as YYYY-MM-DD.
*
* @returns the date
*/
export function getFormattedDate() {
return new Date().toISOString().slice(0, 10);
}
/**
* Formats a timestamp as YYYY-MM-DD.
*
* @param timestamp the timestamp
* @returns the formatted timestamp
*/
export function formatTimestamp(timestamp: number) {
return new Date(timestamp).toISOString().slice(0, 10);
}

64
src/website/website.ts Normal file
View File

@ -0,0 +1,64 @@
import { Point } from "@influxdata/influxdb-client";
import axios from "axios";
import { influx } from "..";
import { logger } from "../utils/logger";
import Config from "../../data/config.json";
type WebsiteOptions = {
name: string;
url: string;
};
export default class Website {
/**
* The name of the website.
*/
private readonly name: string;
/**
* The url of the website.
*/
private readonly url: string;
constructor({ name, url }: WebsiteOptions) {
this.name = name;
this.url = url;
}
/**
* Pings a website and gets the response.
*
* @returns the response
*/
public async pingWebsite(): Promise<void> {
try {
const before = Date.now();
const response = await axios.get(this.url, {
validateStatus: () => true, // Don't throw a error on non-200 status codes
timeout: Config.pinger.timeout,
});
if (response.status === 500) {
throw new Error("Server returned 500 status code");
}
const responseTime = Date.now() - before;
influx.writePoint(
new Point("websiteStatus")
.tag("name", this.name)
.booleanField("online", true)
.intField("responseTime", responseTime)
.timestamp(Date.now())
);
} catch (err) {
logger.warn(`Failed to ping ${this.name}:`, err);
influx.writePoint(
new Point("websiteStatus")
.tag("name", this.name)
.booleanField("online", false)
.timestamp(Date.now())
);
}
}
}

View File

@ -0,0 +1,38 @@
import cron from "node-cron";
import { logger } from "../utils/logger";
import Config from "../../data/config.json";
import Websites from "../../data/websites.json";
import Website from "./website";
export default class WebsiteManager {
private websites: Website[] = [];
constructor() {
logger.info("Loading websites...");
for (const configWebsite of Websites) {
const website = new Website({
name: configWebsite.name,
url: configWebsite.url,
});
this.websites.push(website);
}
logger.info(`Loaded ${this.websites.length} websites!`);
cron.schedule(Config.pinger.pingCron, async () => {
await this.pingWebsites();
});
}
/**
* Ping all websites to update their status.
*/
private async pingWebsites(): Promise<void> {
logger.info(`Pinging websites ${this.websites.length}`);
// ping all websites in parallel
await Promise.all(this.websites.map((website) => website.pingWebsite()));
logger.info("Finished pinging websites!");
}
}

View File

@ -1,82 +0,0 @@
import { Socket, Server as SocketServer } from "socket.io";
import { serverManager } from "..";
import Server, { ServerStatus } from "../server/server";
import { Ping } from "../types/ping";
import { logger } from "../utils/logger";
export default class WebsocketServer {
private server: SocketServer;
constructor(port: number) {
logger.info(`Starting websocket server on port ${port}`);
this.server = new SocketServer(port);
this.server.on("connection", (socket) => {
logger.debug("ws: Client connected");
this.sendServerList(socket);
});
}
/**
* Sends the server list to the given socket.
*
* @param socket the socket to send the server list to
*/
public sendServerList(socket: Socket): void {
logger.debug(`ws: Sending server list to ${socket.id}`);
const servers = [];
for (const server of serverManager.getServers()) {
servers.push({
id: server.getID(),
name: server.getName(),
ip: server.getIP(),
port: server.getPort(),
favicon: server.getFavicon(),
});
}
socket.emit("serverList", servers);
}
/**
* Sends the latest ping data for the given server to all clients.
*
* @param server the server to send the ping for
* @param pingResponse the ping data to send
* @param isNewRecord whether a new record has been set
*/
public sendNewPing(
server: Server,
pingResponse: Ping,
isNewRecord: boolean
): void {
logger.debug(`ws: Sending new ping for ${server.getName()}`);
this.server.emit("newPing", {
server: server.getID(),
timestamp: pingResponse.timestamp,
playerCount: pingResponse.playerCount,
});
if (isNewRecord) {
logger.debug(`ws: Sending new record for ${server.getName()}`);
this.server.emit("newRecord", {
server: server.getID(),
timestamp: pingResponse.timestamp,
playerCount: pingResponse.playerCount,
});
}
}
/**
* Sends the server status for the given server to all clients.
*
* @param server the server to send the status for
* @param status the status to send
*/
public sendServerError(server: Server, status: ServerStatus): void {
logger.debug(`ws: Sending server status for ${server.getName()}`);
this.server.emit("serverStatus", {
server: server.getID(),
status: status,
});
}
}

12
storage-tracker.sh Normal file
View File

@ -0,0 +1,12 @@
usage_engine=$(du -s /home/tracker/influx/db/engine/data/setme/ | cut -f1)
usage_wal=$(du -s /home/tracker/influx/db/engine/wal/setme/ | cut -f1)
# Calculate the sum of usage_engine and usage_wal
total_usage=$((usage_engine + usage_wal))
docker exec influxdb influx write \
--org homelab \
--bucket influx_metrics \
--token setme \
--precision s \
"storage_usage,db=mc-tracker value=$total_usage"

7
useful-stuff.md Normal file
View File

@ -0,0 +1,7 @@
# Useful stuff
## Deleteing a specific server from influx
```bash
influx delete --bucket mc-tracker --start 2024-01-01T00:00:00Z --stop 2024-01-05T00:00:00Z --org homelab --token nou --predicate '_measurement="playerCount" AND "name"="Grand Theft Minecraft"'
```