Compare commits

...

105 commits

Author SHA1 Message Date
3a4cb20c95 chore: progress commit
Some checks failed
Build Gradle project / build-gradle-project (push) Failing after 3m44s
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-19 16:42:07 +02:00
5bf19e578b chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m59s
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-06 09:43:32 +02:00
982212ddf3 fix: fixed issue with time in the match extension
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-06 09:43:21 +02:00
95f6772581 fix: fixed api schedulers
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-06 09:42:50 +02:00
e9babd0d74 chore: bump version
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 15:09:58 +02:00
50df374564 chore: updated comment
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 15:09:45 +02:00
2a34d15687 fix: StatusUpdater now starts after the bot is online
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 15:09:30 +02:00
85602038e9 feat: removed the not needed status refreshes
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:53:18 +02:00
b13c2e5f5f feat: made the status refresh every time it updates
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:52:42 +02:00
84f0176ba4 feat: registered new jobs and features
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:41:46 +02:00
5b4b3c9828 feat: added StatusUpdater to update the status of the bot
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:40:45 +02:00
e354ed9143 feat: added JSON deformatter to TimeUtil
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:40:16 +02:00
cc41445d2f feat: added NetUtil for web requests
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:39:46 +02:00
b08779546d feat: added cacheUpdateJobs
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:39:23 +02:00
7f173e4bc2 chore: added credits for the provided data
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:38:34 +02:00
93223fa0ab feat: added Splatoon3.ink API
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 11:38:14 +02:00
cd37bd1242 fix: fixed issues with timestamps
Signed-off-by: moonleay <contact@moonleay.net>
2023-10-05 10:29:27 +02:00
4a0792af08 chore: upgrade crontab
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-26 07:43:56 +02:00
9a134c691f chore: bump version
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-26 07:43:37 +02:00
935af908f7 chore: moved Database stuff in /database package
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-18 16:07:55 +02:00
f762e18b1f chore: update names in action.yml
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m41s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 13:24:46 +02:00
c7b03d49c9 Update .forgejo/workflows/action.yml 2023-09-17 13:23:13 +02:00
55fafa29c5 chore: update names in action.yml
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 13:22:34 +02:00
d789b5ee64 chore: update README.md
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 4m13s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 13:20:41 +02:00
967492685a chore: update README.md
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 4m16s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 13:17:14 +02:00
e9fac0d687 fix: fixed removed functions
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 4m16s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 12:59:54 +02:00
d2af0fce94 chore!: upgrade dependencies & gradle (7.4.2 -> 8.3)
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-17 12:58:15 +02:00
672982ef37 chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m52s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-15 23:37:06 +02:00
95c22c6bd0 feat: moved all transactions into one package for reuse and simplicity
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m52s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-15 22:50:16 +02:00
e27efe094c chore: removed unused comment
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-15 22:49:12 +02:00
b77271517d chore: fixed naming in data objects
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m49s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 18:31:45 +02:00
99c607efd4 feat: added TimePlanningChannelsData
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 18:30:12 +02:00
fdf63c4605 chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m55s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 12:42:49 +02:00
caa5d49bad fix!: Changed all colors to EmbedColor
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m42s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 12:36:19 +02:00
8d14597a38 feat: make embed helper functions use EmbedColor instead of color
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 12:34:27 +02:00
dcdb5c6e56 feat: added EmbedColor
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 12:27:53 +02:00
af15f7eb73 chore: removed unused open modifier in IEditButton
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m35s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 09:46:19 +02:00
36f931b919 feat: improved UpdateRolesExtension
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m37s
chore: updated UpdateRolesExtension Documentation

Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 09:43:36 +02:00
39fb3ba7d6 chore: updated SendPlannerExtension documentation
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 09:42:29 +02:00
99964d7981 !feat: removed TestExtension.kt
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 09:41:43 +02:00
8a77b275dc feat: Bot now skips Bot Users
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 09:41:27 +02:00
3d1f2c7d8f chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m54s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 07:46:07 +02:00
7e0c8e5a9f feat: moved update logic into "updateInChannel" function, updated the function in Timeplanner buttons
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-14 07:44:43 +02:00
de1d8cd3a6 fix: fixed grammar
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m54s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 14:46:40 +02:00
990387fed2 chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m52s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 14:26:43 +02:00
4f8924fb1a Merge pull request 'chore: moved to proper data types in columns' (#3) from chore/cleanup-db into master
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m57s
Reviewed-on: #3
2023-09-11 13:49:47 +02:00
1424e31e2a chore: moved to proper data types in columns
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m45s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 13:35:17 +02:00
d97511eb8b chore: bump version
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m53s
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:48:33 +02:00
63fb1c0c8f feat: added DeclineEditButton
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:47:31 +02:00
308da65105 feat: improved function of AcceptEditButton
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:47:06 +02:00
9400a21403 feat: added Unavailable to MatchExtension table
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:46:33 +02:00
f7b701de20 feat: improved replaceXWithYinValuesAtTable function, edited MatchButtons
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:45:51 +02:00
165e1d342c feat: improved getAClonedEmbed function, added an equivalent using a EmbedBuilder
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-11 12:44:34 +02:00
883940c8fd Merge remote-tracking branch 'origin/master'
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 4m13s
2023-09-06 22:10:39 +02:00
18cd26c456 chore: bump version
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 22:10:17 +02:00
a3c1344f1a feat: Roles now update on button press
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 22:09:59 +02:00
f552ea4faa chore: improved readability
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 22:06:14 +02:00
d10f8901c9 fix: fixed AvailabilityManager
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 22:05:29 +02:00
925398db65 fix: fixed weekstamp
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 22:03:50 +02:00
b258747086 chore: improved imports
Signed-off-by: moonleay <contact@moonleay.net>
2023-09-06 21:59:41 +02:00
500ad1a912 Update .forgejo/workflows/action.yml
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m37s
2023-08-18 11:44:43 +02:00
862206e1d5 Update .forgejo/workflows/action.yml
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 2m30s
2023-08-18 11:40:51 +02:00
9f28aecd57 Update .forgejo/workflows/action.yml
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 3m46s
2023-08-18 11:25:30 +02:00
7bf0f8d56e Update .forgejo/workflows/action.yml 2023-08-18 11:24:48 +02:00
91e4dfde60 Update .forgejo/workflows/action.yml
All checks were successful
Build Gradle project / build-gradle-project (push) Successful in 3m17s
2023-08-18 11:16:47 +02:00
9305118f4a Update .forgejo/workflows/action.yml
Some checks failed
Build Gradle project / build-gradle-project (push) Failing after 1m16s
2023-08-18 11:13:03 +02:00
c638021326 Update .forgejo/workflows/action.yml
Some checks reported warnings
Build Gradle project / build-gradle-project (push) Has been cancelled
2023-08-18 09:20:31 +02:00
937541cf61 Update .forgejo/workflows/action.yml
Some checks failed
Build Gradle project / build-gradle-project (push) Failing after 8s
2023-08-18 09:00:23 +02:00
81d248bfb7 Update .forgejo/workflows/action.yml
Some checks reported warnings
Build Gradle project / build-gradle-project (push) Has been cancelled
2023-08-18 08:56:42 +02:00
3018918bff Update .forgejo/workflows/action.yml 2023-08-18 08:55:04 +02:00
9c1842d4f7 Update .forgejo/workflows/action.yml
Some checks failed
Build Gradle project / build-gradle-project (push) Failing after 7s
2023-08-18 08:53:44 +02:00
cf1fed51c3 Update .forgejo/workflows/action.yml
Some checks failed
Build Gradle project / build-gradle-project (push) Failing after 1m9s
2023-08-12 14:12:10 +02:00
9847192074 Update .forgejo/workflows/action.yml 2023-08-12 14:10:43 +02:00
a45d4ae26d Update .forgejo/workflows/action.yml 2023-08-12 14:09:39 +02:00
fc6824cd5e Update .forgejo/workflows/action.yml 2023-08-12 14:09:21 +02:00
1e65e609e1 Update .forgejo/workflows/action.yml
Signed-off-by: moonleay <account@moonleay.net>
2023-08-12 14:06:37 +02:00
a75a70b689 Update .forgejo/workflows/action.yml
Signed-off-by: moonleay <account@moonleay.net>
2023-08-12 14:04:55 +02:00
08b6601663 Update .forgejo/workflows/action.yml
Signed-off-by: moonleay <account@moonleay.net>
2023-08-12 14:02:50 +02:00
619be85353 Update .forgejo/workflows/action.yml
Signed-off-by: moonleay <account@moonleay.net>
2023-08-12 13:47:55 +02:00
c4233a7b6b fix> update ci
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 19:04:47 +02:00
149ce7d5c6 fix> update ci
Some checks failed
/ build_and_publish (push) Failing after 8s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 18:54:14 +02:00
bf8bc013d9 fix> update ci
Some checks failed
/ build_and_publish (push) Failing after 27s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 18:36:48 +02:00
0928d84b9a fix> update ci
Some checks failed
/ build_and_publish (push) Failing after 3s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 18:36:08 +02:00
e215f556e7 fix> update ci
Some checks failed
/ build_and_publish (push) Failing after 1m57s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 18:27:00 +02:00
90f9dd15c9 fix> update ci
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 18:01:12 +02:00
6b0c5058ab feat moved action.yml
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:41:04 +02:00
7d15ef910b feat moved action.yml
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:39:59 +02:00
d9cedb702b fix: fixed build.yml?????????????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:25:08 +02:00
6b391f2e4d fix: fixed build.yml????????????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:23:20 +02:00
4cc3fae4ab fix: fixed build.yml???????????????
Some checks failed
/ build_and_publish (push) Failing after 3s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:20:17 +02:00
9d68e9aebb fix: fixed build.yml??????????????
Some checks failed
/ build_and_publish (push) Failing after 3s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:19:40 +02:00
7dbae9a330 fix: fixed build.yml?????????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:18:42 +02:00
e344c9bd3a fix: fixed build.yml????????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:17:47 +02:00
02d95b7d12 fix: fixed build.yml???????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:15:48 +02:00
f3497f9a2b fix: fixed build.yml??????????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 02:00:07 +02:00
eb7ac71dd5 fix: fixed build.yml?????????
Some checks failed
/ Build (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 01:57:02 +02:00
9273b4b168 fix: fixed build.yml????????
Some checks reported warnings
/ Build (push) Has been cancelled
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 01:55:59 +02:00
c4b00aa9a5 fix: fixed build.yml???????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-05 01:40:41 +02:00
a2436cb002 fix: fixed build.yml??????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:32:45 +02:00
04fa9ad59a fix: fixed build.yml?????
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:30:17 +02:00
cd84d02608 fix: fixed build.yml????
Some checks failed
/ build_and_publish (push) Failing after 5s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:28:10 +02:00
2bfc327ceb fix: fixed build.yml???
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:25:46 +02:00
38832e1c0d fix: fixed build.yml??
Some checks failed
/ build_and_publish (push) Failing after 5s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:23:16 +02:00
7f2e74ff6c fix: fixed build.yml?
Some checks failed
/ build_and_publish (push) Failing after 3s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:22:29 +02:00
a93499cfb8 fix: fixed build.yml
Some checks failed
/ build_and_publish (push) Failing after 2s
Signed-off-by: moonleay <contact@moonleay.net>
2023-08-04 21:17:52 +02:00
70 changed files with 2642 additions and 709 deletions

View file

@ -0,0 +1,25 @@
name: Build Gradle project
on:
push:
jobs:
build-gradle-project:
runs-on: ubuntu-latest
steps:
- name: apt update
run: apt update
- name: apt upgrade
run: apt upgrade -y
- name: install prerequisits
run: apt install openjdk-17-jdk ca-certificates-java ssl-cert openssl ca-certificates -y
- name: Checkout project sources
uses: actions/checkout@v3
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Run build with Gradle Wrapper
run: ./gradlew shadowJar
- uses: actions/upload-artifact@v3
with:
name: lilJudd.jar
path: build/libs/

View file

@ -1,15 +0,0 @@
on: [ push ]
jobs:
build_and_publish:
runs-on: gradle
steps:
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Clean Caches
run: |
rm -f .gradle/caches/modules-2/modules-2.lock
rm -fr .gradle/caches/*/plugin-resolution/
- name: Run shadowJar
run: ./gradlew shadowJar
- name: Run publish
run: ./gradlew publish

View file

@ -2,11 +2,9 @@
"Oh boy, here we go again" ~ me "Oh boy, here we go again" ~ me
A Discord Bot for Splatoon Teams A Discord Bot for Splatoon Teams.
[![Latest Release](https://gitlab.com/moonleay/liljudd/-/badges/release.svg)](https://gitlab.com/moonleay/liljudd/-/releases) More information can be found on the [Homepage](https://moonleay.net/projects/liljudd/).
[![pipeline status](https://gitlab.com/moonleay/liljudd/badges/master/pipeline.svg)](https://gitlab.com/moonleay/liljudd/-/commits/master)
[![License](https://img.shields.io/badge/license-GPL--3.0-brightgreen)](https://gitlab.com/moonleay/liljudd/-/blob/master/LICENSE)
## Contributors ## Contributors
@ -21,9 +19,13 @@ A Discord Bot for Splatoon Teams
- Commands - Commands
- version -- Show the versions of the bot and the most important dependencies - version -- Show the versions of the bot and the most important dependencies
- feature -- Manage bot features - feature -- Manage bot features
- match -- Create a new match
- updateroles -- Update the roles of all users
- sendplanner -- Send the planner message
- Features - Features
- Time Planner -- Make the bot send messages and reactions into a selected channel in order to make planning easier - Time Planner -- Make the bot send messages and reactions into a selected channel in order to make planning easier
- Availability Manager -- Make the bot assign users roles every day, so it is possible to notify available people - Availability Manager -- Make the bot assign users roles every day, so it is possible to notify available people
- Match Planner -- Make a match, for which players can sign up and the bot will assign teams and roles to them
## (Maybe) upcoming features ## (Maybe) upcoming features
@ -33,36 +35,30 @@ A Discord Bot for Splatoon Teams
- Rndm map command - Rndm map command
- Maybe a DSB / DSL API - Maybe a DSB / DSL API
## TODO
- Rewrite the Database connection system (from transactions all over the place to a single package with transactions)
## How to self-host (using the Docker container) ## How to self-host (using the Docker container)
1. Pull the container 1. Pull the container from [Docker Hub](https://hub.docker.com/repository/docker/limiteddev/liljudd/general)
2. Map /data/ to a folder on disk 2. Map /data/ to a folder on disk
3. Run the Bot once 3. Run the Bot once
4. Follow step 4 - 7 of "How to self-host (using the JAR)" 4. follow step 4 and 5 from the JAR section
5. Run the Bot again
6. Profit.
## How to self-host (using the JAR) ## How to self-host (using the JAR)
1. Download the latest release from the Package Registry ("Packages and registries" > "Package Registry") 1. Download the latest release from the Releases page.
1. It should be called something like this: "lilJudd-X.X.X-xxxxxxxx-prod.jar" (replace "X.X.X" with the latest
version and xxxxxxxx" with the commit its based on.)
2. If you want to run an early version, which may be (very) unsable, you can run a development version. Just use an
entry ending in "-dev.jar"
2. Place it anywhere you want. 2. Place it anywhere you want.
3. Run the following command: 3. Run the following command:
> java -jar lilJudd-X.X.X-xxxxxxxx-prod.jar > java -jar lilJudd.jar
4. The bot should start and create a config file named "credentials.nils" in a folder called "data" 4. The bot should start and create a config file named "credentials.nils" in a folder called "data"
5. Open it and put in your credentials. 5. Open it and put in your credentials.
1. token: your Discord bot token 1. token: your Discord bot token
2. dbDomain: the domain and port of your postgresql database (e.g.: 192.168.178.1:5432) 2. dbDomain: the domain and port of your postgresql database (e.g.: 192.168.178.1:5432)
3. dbName: the name of your database 3. dbName: the name of the database
4. dbUser: the username of the database 4. dbUser: the username of the database
5. dbPassword: the password to your user 5. dbPassword: the password to the db user
6. Rerun the command 6. Rerun the command
> java -jar lilJudd-X.X.X-xxxxxxxx-prod.jar > java -jar lilJudd.jar
7. The bot should now be up and running. 7. The bot should now be up and running.
## How to set up workspace ## How to set up workspace

View file

@ -21,9 +21,9 @@ import org.jetbrains.gradle.ext.TaskTriggersConfig
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins { plugins {
kotlin("jvm") version "1.8.20" kotlin("jvm") version "1.9.10"
id("com.github.johnrengelman.shadow") version "7.1.2" id("com.github.johnrengelman.shadow") version "8.1.1"
id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.6" id("org.jetbrains.gradle.plugin.idea-ext") version "1.1.7"
`maven-publish` `maven-publish`
} }
@ -32,14 +32,14 @@ val ownerID = 372703841151614976L
group = "net.moonleay.liljudd" group = "net.moonleay.liljudd"
version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" } version = System.getenv("CI_COMMIT_TAG")?.let { "$it-${System.getenv("CI_COMMIT_SHORT_SHA")}-prod" }
?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" } ?: System.getenv("CI_COMMIT_SHORT_SHA")?.let { "$it-dev" }
?: "2.4.2" ?: "2.6.4"
val kordver = "1.5.6" val kordver = "1.5.9-SNAPSHOT"
val coroutinesver = "1.1.0" val coroutinesver = "1.7.3"
val ktor_version = "2.3.0" val ktorver = "2.3.5"
val exposedver = "0.40.1" val exposedver = "0.43.0"
val postgresver = "42.3.8" val postgresver = "42.6.0"
val krontabver = "2.1.2" val krontabver = "2.2.1"
val mavenArtifact = "lilJudd" val mavenArtifact = "lilJudd"
project.base.archivesName.set(mavenArtifact) project.base.archivesName.set(mavenArtifact)
@ -72,6 +72,14 @@ repositories {
} }
} }
} }
maven {
name = "sonatype"
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots")
}
maven {
name = "sonatype 2"
url = uri("https://oss.sonatype.org/content/repositories/snapshots")
}
} }
val shadow by configurations.getting val shadow by configurations.getting
@ -81,6 +89,8 @@ implementation.extendsFrom(shadow)
dependencies { dependencies {
//Discord //Discord
shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver") shadow("com.kotlindiscord.kord.extensions:kord-extensions:$kordver")
//Coroutines
shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver") shadow("org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutinesver")
//Logging //Logging
@ -93,22 +103,22 @@ dependencies {
shadow("org.jetbrains.exposed:exposed-jdbc:$exposedver") shadow("org.jetbrains.exposed:exposed-jdbc:$exposedver")
shadow("org.postgresql:postgresql:$postgresver") shadow("org.postgresql:postgresql:$postgresver")
//Korntab //Krontab
shadow("dev.inmo:krontab:$krontabver") shadow("dev.inmo:krontab:$krontabver")
"shadow"("io.ktor:ktor-client-core-jvm:2.3.1") shadow("io.ktor:ktor-client-core-jvm:2.3.5")
"shadow"("io.ktor:ktor-client-cio-jvm:2.3.1") shadow("io.ktor:ktor-client-cio-jvm:2.3.5")
} }
val targetJavaVersion = 17 val targetJavaVersion = 17
val templateSrc = project.rootDir.resolve("src/main/templates") val templateSrc = project.rootDir.resolve("src/main/templates")
val templateDest = project.buildDir.resolve("generated/templates") val templateDest = project.projectDir.resolve("build/generated/templates")
val templateProps = mapOf( val templateProps = mapOf(
"version" to project.version as String, "version" to project.version as String,
"ownerID" to ownerID, "ownerID" to ownerID,
"kordversion" to kordver, "kordversion" to kordver,
"coroutinesversion" to coroutinesver, "coroutinesversion" to coroutinesver,
"ktorversion" to ktor_version, "ktorversion" to ktorver,
"exposedversion" to exposedver, "exposedversion" to exposedver,
"postgresversion" to postgresver, "postgresversion" to postgresver,
"krontabversion" to krontabver "krontabversion" to krontabver

Binary file not shown.

View file

@ -18,6 +18,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View file

@ -19,7 +19,6 @@
package net.moonleay.lilJudd package net.moonleay.lilJudd
import com.kotlindiscord.kord.extensions.ExtensibleBot import com.kotlindiscord.kord.extensions.ExtensibleBot
import dev.kord.common.Color
import dev.kord.common.entity.PresenceStatus import dev.kord.common.entity.PresenceStatus
import dev.kord.core.behavior.interaction.response.respond import dev.kord.core.behavior.interaction.response.respond
import dev.kord.core.event.gateway.ReadyEvent import dev.kord.core.event.gateway.ReadyEvent
@ -34,14 +33,18 @@ import kotlinx.coroutines.launch
import net.moonleay.botendo.build.BuildConstants import net.moonleay.botendo.build.BuildConstants
import net.moonleay.lilJudd.buttons.component.EditButtonManager import net.moonleay.lilJudd.buttons.component.EditButtonManager
import net.moonleay.lilJudd.data.CredentialManager import net.moonleay.lilJudd.data.CredentialManager
import net.moonleay.lilJudd.data.DB import net.moonleay.lilJudd.data.api.Splatoon3ApiCache
import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.data.api.type.ApiDataType
import net.moonleay.lilJudd.extensions.MatchExtension import net.moonleay.lilJudd.data.api.type.ApiRequestType
import net.moonleay.lilJudd.extensions.SendPlannerExtension import net.moonleay.lilJudd.data.database.DB
import net.moonleay.lilJudd.extensions.VersionExtension import net.moonleay.lilJudd.extensions.*
import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.features.AvailabilityManager
import net.moonleay.lilJudd.features.MatchManager import net.moonleay.lilJudd.features.MatchManager
import net.moonleay.lilJudd.features.TimeManager import net.moonleay.lilJudd.features.TimeManager
import net.moonleay.lilJudd.jobs.Splatoon3ApiScheduleUpdateScheduler
import net.moonleay.lilJudd.jobs.StatusUpdater
import net.moonleay.lilJudd.jobs.component.JobManager
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.MessageUtil
import kotlin.system.exitProcess import kotlin.system.exitProcess
@ -79,6 +82,9 @@ object Bot {
CredentialManager.dbPassword CredentialManager.dbPassword
) )
// Make sure the database is up-to-date
DB.register()
// Register all the jobs // Register all the jobs
jobs.addAll( jobs.addAll(
listOf( listOf(
@ -99,12 +105,12 @@ object Bot {
} }
extensions { extensions {
add(::VersionExtension) add(::InfoExtension)
add(::FeatureManageExtension) add(::FeatureManageExtension)
add(::SendPlannerExtension) add(::SendPlannerExtension)
add(::MatchExtension) add(::MatchExtension)
//add(::UpdateRolesExtension) // This command is only for debugging purposes add(::UpdateRolesExtension)
//add(::TestExtension) // See comment in TestExtension.kt add(::RotationExtension)
} }
this.presence { this.presence {
@ -121,7 +127,6 @@ object Bot {
sharding { recommended -> sharding { recommended ->
Shards(recommended) Shards(recommended)
} */ } */
// Same goes for a Database table rewrite
} }
// Register button presses // Register button presses
@ -142,13 +147,13 @@ object Bot {
} }
if (inter.componentId.startsWith("public.message.")) { if (inter.componentId.startsWith("public.message.")) {
val response = inter.deferPublicResponse() val response = inter.deferPublicResponse()
val g = this.interaction.getOriginalInteractionResponse().getGuild()
response.respond { response.respond {
this.embeds = mutableListOf( this.embeds = mutableListOf(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"Error", "404: Not Found",
"Could not find button with id \"${inter.componentId}\".\nPlease report this.", "Could not find button with id \"${inter.componentId}\"." +
"\nPlease report this.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
) )
) )
@ -159,8 +164,20 @@ object Bot {
bot.kordRef.on<ReadyEvent> { bot.kordRef.on<ReadyEvent> {
AvailabilityManager.runThread() // Update Availabilities AvailabilityManager.runThread() // Update Availabilities
MatchManager.update() // Update Matches MatchManager.update() // Update Matches
// Make the bot update the status every 6 seconds
JobManager.addJob(StatusUpdater)
} }
// Update the Splatoon 3 api data and make sure it stays up-to-date
Splatoon3ApiCache.updateData(ApiDataType.SCHEDULES, ApiRequestType.AUTOMATIC_CACHE_CREATION_AT_STARTUP)
JobManager.addJob(Splatoon3ApiScheduleUpdateScheduler)
/*
Other caches will be added when implemented
its not used yet in order to reduce load on the api,
which i am using.
*/
//JobManager.addJob(Splatoon3ApiFestivalAndCoopUpdateScheduler)
//JobManager.addJob(Splatoon3ApiSplatnetGearUpdateScheduler)
//Start the bot //Start the bot
bot.start() bot.start()

View file

@ -18,8 +18,9 @@
package net.moonleay.lilJudd.buttons.component package net.moonleay.lilJudd.buttons.component
import net.moonleay.lilJudd.buttons.matchplanner.AcceptEditButton
import net.moonleay.lilJudd.buttons.matchplanner.CancelEditButton import net.moonleay.lilJudd.buttons.matchplanner.CancelEditButton
import net.moonleay.lilJudd.buttons.matchplanner.SignMeUpEditButton import net.moonleay.lilJudd.buttons.matchplanner.DeclineEditButton
import net.moonleay.lilJudd.buttons.timeplanner.IsAvailableEditButton import net.moonleay.lilJudd.buttons.timeplanner.IsAvailableEditButton
import net.moonleay.lilJudd.buttons.timeplanner.MaybeAvailableEditButton import net.moonleay.lilJudd.buttons.timeplanner.MaybeAvailableEditButton
import net.moonleay.lilJudd.buttons.timeplanner.NotAvailableEditButton import net.moonleay.lilJudd.buttons.timeplanner.NotAvailableEditButton
@ -29,7 +30,8 @@ object EditButtonManager {
IsAvailableEditButton(), IsAvailableEditButton(),
MaybeAvailableEditButton(), MaybeAvailableEditButton(),
NotAvailableEditButton(), NotAvailableEditButton(),
SignMeUpEditButton(), AcceptEditButton(),
CancelEditButton() CancelEditButton(),
DeclineEditButton(),
) )
} }

View file

@ -26,7 +26,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction
interface IEditButton { interface IEditButton {
val id: String val id: String
open suspend fun onInteraction( suspend fun onInteraction(
interaction: ButtonInteraction, interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior, response: PublicMessageInteractionResponseBehavior,
guild: Guild, guild: Guild,

View file

@ -0,0 +1,102 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.buttons.matchplanner
import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.channel.MessageChannel
import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.util.EmbedUtil
import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil
class AcceptEditButton() : IEditButton {
override val id: String = "public.edit.btn.matchmanagement.accept"
override suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
val m = interaction.message
val eb = MessageUtil.getAClonedEmbed(m.embeds[0])
var shouldEditButton = false
val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer(
m.id.value.toLong(),
interaction.channelId.value.toLong(),
guild.id.value.toLong()
)
if (mpdd == null) {
Logger.out("mpdd is null")
return
}
val role = guild.getRoleOrNull(Snowflake(mpdd.roleID))
if (role == null) {
Logger.out("role is null")
return
}
val member = interaction.user.asMember(guild.id) ?: return
// do the checks and update
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
if (member.roleIds.contains(Snowflake(mpdd.roleID))) {
Logger.out("Removing role from ${member.username}")
member.removeRole(role.id)
}
// remove the user from the 1st list in the embed
Logger.out("Removing ${user.username} from the 1st list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields
shouldEditButton = true
}
if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
Logger.out("Removing ${user.username} from the 2nd list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields
shouldEditButton = true
}
if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
if (!member.roleIds.contains(Snowflake(mpdd.roleID))) {
Logger.out("Adding role to ${member.username}")
member.addRole(role.id)
}
//Add the user to the list in the embed
Logger.out("Adding ${user.username} to the 1st list in the embed")
eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 1).fields
shouldEditButton = true
}
if (shouldEditButton) {
// update the message
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
this.embed {
this.color = eb.color
this.title = eb.title
this.description = eb.description
this.fields = eb.fields
this.footer = eb.footer
}
}
}
}
}

View file

@ -28,12 +28,9 @@ import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.data.tables.MatchPlanningData
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
import org.jetbrains.exposed.sql.and import net.moonleay.lilJudd.util.Logger
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
class CancelEditButton : IEditButton { class CancelEditButton : IEditButton {
override val id: String = "public.edit.btn.matchmanagement.cancel" override val id: String = "public.edit.btn.matchmanagement.cancel"
@ -46,35 +43,22 @@ class CancelEditButton : IEditButton {
) { ) {
val m = interaction.message val m = interaction.message
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) { if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
lateinit var mpdd: MatchPlanningDataData val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer(
var found = false m.id.value.toLong(),
transaction { interaction.channelId.value.toLong(),
for (pnr in MatchPlanningData.select { guild.id.value.toLong()
MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and ( )
MatchPlanningData.serverid eq (guild.id.value.toString())) and ( if (mpdd == null) {
MatchPlanningData.channelid eq (interaction.channelId.value.toString())) Logger.out("mpdd is null")
}) { return
mpdd = MatchPlanningDataData( }
pnr[MatchPlanningData.id].value, val role = guild.getRoleOrNull(Snowflake(mpdd.roleID))
pnr[MatchPlanningData.serverid], if (role == null) {
pnr[MatchPlanningData.channelid], Logger.out("role is null")
pnr[MatchPlanningData.matchtype],
pnr[MatchPlanningData.registererid],
pnr[MatchPlanningData.roleid],
pnr[MatchPlanningData.opponentName],
pnr[MatchPlanningData.messageid],
pnr[MatchPlanningData.timestamp],
pnr[MatchPlanningData.jobstr]
)
found = true
}
}
if (!found || mpdd == null) {
return return
} }
val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return
val member = interaction.user.asMember(guild.id) val member = interaction.user.asMember(guild.id)
if (member.roleIds.contains(Snowflake(mpdd.roleid))) { if (member.roleIds.contains(Snowflake(mpdd.roleID))) {
member.removeRole(role.id) member.removeRole(role.id)
} }
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit { Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {

View file

@ -0,0 +1,102 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.buttons.matchplanner
import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.channel.MessageChannel
import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.util.EmbedUtil
import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil
class DeclineEditButton : IEditButton {
override val id: String = "public.edit.btn.matchmanagement.decline"
override suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
val m = interaction.message
val eb = MessageUtil.getAClonedEmbed(m.embeds[0])
var shouldEditButton = false
val mpdd = MatchPlanningDataRepository.getFromMessageInChannelInServer(
m.id.value.toLong(),
interaction.channelId.value.toLong(),
guild.id.value.toLong()
)
if (mpdd == null) {
Logger.out("mpdd is null")
return
}
val role = guild.getRoleOrNull(Snowflake(mpdd.roleID))
if (role == null) {
Logger.out("role is null")
return
}
val member = interaction.user.asMember(guild.id) ?: return
if (m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
if (member.roleIds.contains(Snowflake(mpdd.roleID))) {
Logger.out("Removing role from ${member.username}")
member.removeRole(role.id)
}
// remove the user from the 1st list in the embed
Logger.out("Removing ${user.username} from the 1st list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 1).fields
shouldEditButton = true
}
if (!m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
if (member.roleIds.contains(Snowflake(mpdd.roleID))) {
Logger.out("Removing role from ${member.username}")
member.removeRole(role.id)
}
// Add the user to the list in the embed
Logger.out("Adding ${user.username} to the 2nd list in the embed")
eb.fields = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), eb, 2).fields
shouldEditButton = true
}
if (m.embeds[0].fields[1].value.contains(user.id.value.toString())) {
// Remove the user from all tables
Logger.out("Removing ${user.username} from the 2nd list in the embed")
eb.fields = EmbedUtil.replaceXWithYinValuesAtTable(user.id.value.toString(), "", eb, 2).fields
shouldEditButton = true
}
if (shouldEditButton) {
// update the message
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
this.embed {
this.color = eb.color
this.title = eb.title
this.description = eb.description
this.fields = eb.fields
this.footer = eb.footer
}
}
}
}
}

View file

@ -1,94 +0,0 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.buttons.matchplanner
import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.edit
import dev.kord.core.behavior.interaction.response.PublicMessageInteractionResponseBehavior
import dev.kord.core.entity.Guild
import dev.kord.core.entity.User
import dev.kord.core.entity.channel.MessageChannel
import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData
import net.moonleay.lilJudd.data.tables.MatchPlanningData
import net.moonleay.lilJudd.util.EmbedUtil
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
class SignMeUpEditButton() : IEditButton {
override val id: String = "public.edit.btn.matchmanagement.accept"
override suspend fun onInteraction(
interaction: ButtonInteraction,
response: PublicMessageInteractionResponseBehavior,
guild: Guild,
user: User
) {
val m = interaction.message
if (!m.embeds[0].fields[0].value.contains(user.id.value.toString())) {
lateinit var mpdd: MatchPlanningDataData
var found = false
transaction {
for (pnr in MatchPlanningData.select {
MatchPlanningData.messageid eq (interaction.message.id.value.toString()) and (
MatchPlanningData.serverid eq (guild.id.value.toString())) and (
MatchPlanningData.channelid eq (interaction.channelId.value.toString()))
}) {
mpdd = MatchPlanningDataData(
pnr[MatchPlanningData.id].value,
pnr[MatchPlanningData.serverid],
pnr[MatchPlanningData.channelid],
pnr[MatchPlanningData.matchtype],
pnr[MatchPlanningData.registererid],
pnr[MatchPlanningData.roleid],
pnr[MatchPlanningData.opponentName],
pnr[MatchPlanningData.messageid],
pnr[MatchPlanningData.timestamp],
pnr[MatchPlanningData.jobstr]
)
found = true
}
}
if (!found || mpdd == null) {
return
}
val role = guild.getRoleOrNull(Snowflake(mpdd.roleid)) ?: return
val member = interaction.user.asMember(guild.id)
if (!member.roleIds.contains(Snowflake(mpdd.roleid))) {
member.addRole(role.id)
}
//Add the user to the list in the embed
Bot.bot.kordRef.getChannelOf<MessageChannel>(interaction.channelId)!!.getMessage(m.id).edit {
this.embed {
val temp = EmbedUtil.addXToValuesAtTable(user.id.value.toString(), m.embeds[0], 1)
this.color = temp.color
this.title = temp.title
this.description = temp.description
this.fields = temp.fields
this.footer = temp.footer
}
}
}
}
}

View file

@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.features.AvailabilityManager
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
class IsAvailableEditButton : IEditButton { class IsAvailableEditButton : IEditButton {
@ -62,5 +63,6 @@ class IsAvailableEditButton : IEditButton {
} }
} }
} }
AvailabilityManager.updateInChannel(interaction.channelId)
} }
} }

View file

@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.features.AvailabilityManager
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
class MaybeAvailableEditButton : IEditButton { class MaybeAvailableEditButton : IEditButton {
@ -62,5 +63,6 @@ class MaybeAvailableEditButton : IEditButton {
} }
} }
} }
AvailabilityManager.updateInChannel(interaction.channelId)
} }
} }

View file

@ -27,6 +27,7 @@ import dev.kord.core.entity.interaction.ButtonInteraction
import dev.kord.rest.builder.message.modify.embed import dev.kord.rest.builder.message.modify.embed
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.buttons.component.IEditButton import net.moonleay.lilJudd.buttons.component.IEditButton
import net.moonleay.lilJudd.features.AvailabilityManager
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
class NotAvailableEditButton : IEditButton { class NotAvailableEditButton : IEditButton {
@ -62,5 +63,6 @@ class NotAvailableEditButton : IEditButton {
} }
} }
} }
AvailabilityManager.updateInChannel(interaction.channelId)
} }
} }

View file

@ -0,0 +1,117 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api
import net.moonleay.lilJudd.data.api.entry.schedule.ModeData
import net.moonleay.lilJudd.util.TimeUtil
object Splatoon3Api {
fun getRegularMode(timestamp: Long): ModeData {
Splatoon3ApiCache.cachedRegularModeData.map { modeData ->
val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC")
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
if (timestamp in startTime..endTime) {
return modeData
}
}
throw Exception("No current mode found")
}
fun getOpenMode(timestamp: Long): ModeData {
Splatoon3ApiCache.cachedCompetitiveOpenModeData.map { modeData ->
val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC")
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
if (timestamp in startTime..endTime) {
return modeData
}
}
throw Exception("No current mode found")
}
fun getXMode(timestamp: Long): ModeData {
Splatoon3ApiCache.cachedXModeData.map { modeData ->
val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC")
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
if (timestamp in startTime..endTime) {
return modeData
}
}
throw Exception("No current mode found")
}
fun getSeriesMode(timestamp: Long): ModeData {
Splatoon3ApiCache.cachedCompetitiveSeriesModeData.map { modeData ->
val startTime = TimeUtil.deformatJSONTime(modeData.startTime, "UTC")
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
if (timestamp in startTime..endTime) {
return modeData
}
}
throw Exception("No current mode found")
}
fun getRegularMapsFormatted(timestamp: Long): String {
val modeData = getRegularMode(timestamp)
val map1 = modeData.map1!!.name.split(" ")[0]
val map2 = modeData.map2!!.name.split(" ")[0]
return "R: $map1 & $map2"
}
fun getOpenModeFormatted(timestamp: Long): String {
val modeData = getOpenMode(timestamp)
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime)
return "O: ${modeData.ruleSetName} $diffStamp left"
}
fun getOpenMapFormatted(timestamp: Long): String {
val modeData = getOpenMode(timestamp)
val map1 = modeData.map1!!.name.split(" ")[0]
val map2 = modeData.map2!!.name.split(" ")[0]
return "O: $map1 & $map2"
}
fun getSeriesModeFormatted(timestamp: Long): String {
val modeData = getSeriesMode(timestamp)
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime)
return "S: ${modeData.ruleSetName} $diffStamp left"
}
fun getSeriesMapsFormatted(timestamp: Long): String {
val modeData = getSeriesMode(timestamp)
val map1 = modeData.map1!!.name.split(" ")[0]
val map2 = modeData.map2!!.name.split(" ")[0]
return "S: $map1 & $map2"
}
fun getXModeFormatted(timestamp: Long): String {
val modeData = getXMode(timestamp)
val endTime = TimeUtil.deformatJSONTime(modeData.endTime, "UTC")
val diffStamp = TimeUtil.getTimeDifferenceFormatted(System.currentTimeMillis(), endTime)
return "X: ${modeData.ruleSetName} $diffStamp left"
}
fun getXMapFormatted(timestamp: Long): String {
val modeData = getXMode(timestamp)
val map1 = modeData.map1!!.name.split(" ")[0]
val map2 = modeData.map2!!.name.split(" ")[0]
return "X: $map1 & $map2"
}
}

View file

@ -0,0 +1,535 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api
import io.ktor.http.*
import kotlinx.serialization.json.*
import net.moonleay.botendo.build.BuildConstants
import net.moonleay.lilJudd.data.api.entry.coop.CoopGearData
import net.moonleay.lilJudd.data.api.entry.schedule.*
import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestColor
import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestData
import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestTeamData
import net.moonleay.lilJudd.data.api.entry.splatfest.SplatfestTeamResults
import net.moonleay.lilJudd.data.api.entry.splatnet.BrandData
import net.moonleay.lilJudd.data.api.entry.splatnet.GearAbilityData
import net.moonleay.lilJudd.data.api.entry.splatnet.SplatnetItemData
import net.moonleay.lilJudd.data.api.type.ApiDataType
import net.moonleay.lilJudd.data.api.type.ApiRequestType
import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.NetUtil
object Splatoon3ApiCache {
private val user_agent =
"lilJudd/${BuildConstants.version} (${System.getProperty("os.name")}/${System.getProperty("os.version")}) [contact@moonleay.net]"
private val base_url = "https://splatoon3.ink/data/" // Thank god there is an API
internal var cachedSplatfestData = mutableListOf<SplatfestData>()
internal var cachedMapData = mutableMapOf<Int, MapData>()
internal var cachedRegularModeData = mutableListOf<ModeData>()
internal var cachedCompetitiveSeriesModeData = mutableListOf<ModeData>()
internal var cachedCompetitiveOpenModeData = mutableListOf<ModeData>()
internal var cachedXModeData = mutableListOf<ModeData>()
internal var cachedChallengesData = mutableListOf<ChallengeModeData>()
internal var cachedShiftData = mutableListOf<ShiftData>()
internal var cachedBigRunShiftData = mutableListOf<ShiftData>()
internal var cachedCoopRewardsData = mutableListOf<CoopGearData>()
internal var cachedSplatnetItemData = mutableListOf<SplatnetItemData>()
internal var cachedSplatnetLimitedItemData = mutableListOf<SplatnetItemData>()
internal lateinit var splatnetShopBrandData: BrandData
internal lateinit var splatnetShopNextBrandData: BrandData
fun updateData(dataType: ApiDataType, requestType: ApiRequestType) {
Logger.out("Updating data for $dataType with USER-AGENT: $user_agent")
Logger.out("Reason for update: $requestType")
when (dataType) {
ApiDataType.SCHEDULES -> {
updateScheduleCache(user_agent)
}
ApiDataType.SPLATNETGEAR -> {
updateSplatnetGearCache(user_agent)
}
ApiDataType.COOP -> {
updateCOOPCache(user_agent)
}
ApiDataType.SPLATFESTS -> {
updateSplatfestCache(user_agent)
}
ApiDataType.ALL -> {
updateScheduleCache(user_agent)
updateSplatnetGearCache(user_agent)
updateSplatfestCache(user_agent)
updateCOOPCache(user_agent)
}
}
Logger.out("Finished updating data for $dataType")
}
private fun updateSplatnetGearCache(uag: String) {
val apiResponse = NetUtil.GETJsonData("${base_url}gear.json", uag)
if (apiResponse.startsWith("Error")) {
Logger.out("Error getting splatnet data: $apiResponse")
return
}
val json = Json.parseToJsonElement(apiResponse)
val pickupBrandData = json.jsonObject["data"]!!.jsonObject["gesotown"]!!.jsonObject["pickupBrand"]!!.jsonObject
val brand = pickupBrandData["brand"]!!.jsonObject
splatnetShopBrandData =
BrandData(
brand["name"]!!.jsonPrimitive.content,
Url(pickupBrandData["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
GearAbilityData(
brand["usualGearPower"]!!.jsonObject["name"]!!.jsonPrimitive.content,
brand["usualGearPower"]!!.jsonObject["desc"]!!.jsonPrimitive.content,
Url(brand["usualGearPower"]!!.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
pickupBrandData["saleEndTime"]!!.jsonPrimitive.content
)
val nextBrand = pickupBrandData["nextBrand"]!!.jsonObject
splatnetShopNextBrandData =
BrandData(
nextBrand["name"]!!.jsonPrimitive.content,
Url(pickupBrandData["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
null,
null
)
cachedSplatnetItemData = mutableListOf()
val items = pickupBrandData["brandGears"]!!.jsonArray
items.forEach {
val obj = it as JsonObject
val gear = it["gear"]!!.jsonObject
val primaryGearPower = gear["primaryGearPower"]!!.jsonObject
val additionalGearPowers = gear["additionalGearPowers"]!!.jsonArray
val additionalGearPowersList = mutableListOf<GearAbilityData>()
additionalGearPowers.forEach {
val ob = it as JsonObject
additionalGearPowersList.add(
GearAbilityData(
ob["name"]!!.jsonPrimitive.content,
null,
Url(ob["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
)
)
}
cachedSplatnetItemData.add(
SplatnetItemData(
obj["saleEndTime"]!!.jsonPrimitive.content,
obj["price"]!!.jsonPrimitive.int,
gear["__typename"]!!.jsonPrimitive.content,
gear["name"]!!.jsonPrimitive.content,
GearAbilityData(
primaryGearPower["name"]!!.jsonPrimitive.content,
null,
Url(primaryGearPower["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
additionalGearPowersList,
Url(gear["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
splatnetShopBrandData
)
)
}
Logger.out("Updated gear data")
val limitedItemData = json.jsonObject["data"]!!.jsonObject["gesotown"]!!.jsonObject["limitedGears"]!!.jsonArray
cachedSplatnetLimitedItemData = mutableListOf()
limitedItemData.forEach {
val obj = it as JsonObject
val gear = obj["gear"]!!.jsonObject
val additionalGearPowers = gear["additionalGearPowers"]!!.jsonArray
val additionalGearPowersList = mutableListOf<GearAbilityData>()
additionalGearPowers.forEach {
val ob = it as JsonObject
additionalGearPowersList.add(
GearAbilityData(
ob["name"]!!.jsonPrimitive.content,
null,
Url(ob["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
)
)
}
cachedSplatnetLimitedItemData.add(
SplatnetItemData(
obj["saleEndTime"]!!.jsonPrimitive.content,
obj["price"]!!.jsonPrimitive.int,
gear["__typename"]!!.jsonPrimitive.content,
gear["name"]!!.jsonPrimitive.content,
GearAbilityData(
gear["primaryGearPower"]!!.jsonObject["name"]!!.jsonPrimitive.content,
null,
Url(gear["primaryGearPower"]!!.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
additionalGearPowersList,
Url(gear["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
splatnetShopBrandData
)
)
}
}
private fun updateCOOPCache(uag: String) {
val apiResponse = NetUtil.GETJsonData("${base_url}coop.json", uag)
if (apiResponse.startsWith("Error")) {
Logger.out("Error getting coop data: $apiResponse")
return
}
val json = Json.parseToJsonElement(apiResponse)
val data = json.jsonObject["data"]!!.jsonObject["coopResult"]!!.jsonObject["monthlyGear"]!!.jsonObject
cachedCoopRewardsData = mutableListOf()
cachedCoopRewardsData.add(
CoopGearData(
data["name"]!!.jsonPrimitive.content,
Url(data["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
data["__typename"]!!.jsonPrimitive.content
)
)
Logger.out("Updated COOP data")
}
private fun updateScheduleCache(uag: String) {
val apiResponse = NetUtil.GETJsonData("${base_url}schedules.json", uag)
if (apiResponse.startsWith("Error")) {
Logger.out("Error getting schedule data: $apiResponse")
return
}
val json = Json.decodeFromString(apiResponse) as JsonObject
val data = json["data"]!!.jsonObject
val mapList = data["vsStages"]!!.jsonObject["nodes"]!!.jsonArray
cachedMapData = mutableMapOf()
mapList.forEach {
val obj = it as JsonObject
val imageURL = Url(obj.jsonObject["originalImage"]!!.jsonObject["url"]!!.jsonPrimitive.content)
val id = obj.jsonObject["vsStageId"]!!.jsonPrimitive.int
cachedMapData[id] = MapData(
id,
imageURL,
it.jsonObject["name"]!!.jsonPrimitive.content
)
}
Logger.out("Updated maplist data")
val regularMatches = data["regularSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedRegularModeData = mutableListOf()
regularMatches.forEach {
val obj = it as JsonObject
val setting = obj["regularMatchSetting"]!!.jsonObject
cachedRegularModeData.add(
ModeData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
setting["__typename"]!!.jsonPrimitive.content,
cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int],
cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int],
setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content,
setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content,
"TURF_WAR"
)
)
}
Logger.out("Updated Regular match data")
val compMatches = data["bankaraSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedCompetitiveSeriesModeData = mutableListOf()
cachedCompetitiveOpenModeData = mutableListOf()
compMatches.forEach {
val obj = it as JsonObject
val setting = obj["bankaraMatchSettings"]!!.jsonArray
setting.forEach {
val ob = it as JsonObject
val mode = ob["bankaraMode"]!!.jsonPrimitive.content
if (mode == "CHALLENGE") {
cachedCompetitiveSeriesModeData.add(
ModeData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
ob["__typename"]!!.jsonPrimitive.content,
cachedMapData[ob["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int],
cachedMapData[ob["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int],
ob["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content,
ob["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content,
mode
)
)
} else if (mode == "OPEN") {
cachedCompetitiveOpenModeData.add(
ModeData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
ob["__typename"]!!.jsonPrimitive.content,
cachedMapData[ob["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int],
cachedMapData[ob["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int],
ob["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content,
ob["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content,
mode
)
)
}
}
}
Logger.out("Updated Competitive match data")
val xMatches = data["xSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedXModeData = mutableListOf()
xMatches.forEach {
val obj = it as JsonObject
val setting = obj["xMatchSetting"]!!.jsonObject
cachedXModeData.add(
ModeData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
setting["__typename"]!!.jsonPrimitive.content,
cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int],
cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int],
setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content,
setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content,
"X"
)
)
}
Logger.out("Updated X match data")
val challengeData = data["eventSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedChallengesData = mutableListOf()
challengeData.forEach {
val obj = it as JsonObject
val tpd = obj["timePeriods"]!!.jsonArray
val setting = obj["leagueMatchSetting"]!!.jsonObject
val event = setting["leagueMatchEvent"]!!.jsonObject
cachedChallengesData.add(
ChallengeModeData(
event["leagueMatchEventId"]!!.jsonPrimitive.content,
event["name"]!!.jsonPrimitive.content,
event["desc"]!!.jsonPrimitive.content,
event["regulation"]!!.jsonPrimitive.content,
cachedMapData[setting["vsStages"]!!.jsonArray[0].jsonObject["vsStageId"]!!.jsonPrimitive.int],
cachedMapData[setting["vsStages"]!!.jsonArray[1].jsonObject["vsStageId"]!!.jsonPrimitive.int],
setting["__typename"]!!.jsonPrimitive.content,
setting["vsRule"]!!.jsonObject["rule"]!!.jsonPrimitive.content,
setting["vsRule"]!!.jsonObject["name"]!!.jsonPrimitive.content,
TimePeriodData(
tpd[0].jsonObject["startTime"]!!.jsonPrimitive.content,
tpd[0].jsonObject["endTime"]!!.jsonPrimitive.content
),
TimePeriodData(
tpd[1].jsonObject["startTime"]!!.jsonPrimitive.content,
tpd[1].jsonObject["endTime"]!!.jsonPrimitive.content
),
TimePeriodData(
tpd[2].jsonObject["startTime"]!!.jsonPrimitive.content,
tpd[2].jsonObject["endTime"]!!.jsonPrimitive.content
)
)
)
}
Logger.out("Updated Challenge data")
val shiftData = data["coopGroupingSchedule"]!!.jsonObject["regularSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedShiftData = mutableListOf()
shiftData.forEach {
val obj = it as JsonObject
val setting = obj["setting"]!!.jsonObject
val stage = setting["coopStage"]!!.jsonObject
val weapons = setting["weapons"]!!.jsonArray
cachedShiftData.add(
ShiftData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
obj["__splatoon3ink_king_salmonid_guess"]!!.jsonPrimitive.content,
setting["__typename"]!!.jsonPrimitive.content,
stage["name"]!!.jsonPrimitive.content,
Url(stage["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
WeaponData(
weapons[0].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[0].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[1].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[1].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[2].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[2].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[3].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[3].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
)
)
)
}
val bigRunData = data["coopGroupingSchedule"]!!.jsonObject["bigRunSchedules"]!!.jsonObject["nodes"]!!.jsonArray
cachedBigRunShiftData = mutableListOf()
bigRunData.forEach {
val obj = it as JsonObject
val setting = obj["setting"]!!.jsonObject
val stage = setting["coopStage"]!!.jsonObject
val weapons = setting["weapons"]!!.jsonArray
cachedBigRunShiftData.add(
ShiftData(
obj["startTime"]!!.jsonPrimitive.content,
obj["endTime"]!!.jsonPrimitive.content,
obj["__splatoon3ink_king_salmonid_guess"]!!.jsonPrimitive.content,
setting["__typename"]!!.jsonPrimitive.content,
stage["name"]!!.jsonPrimitive.content,
Url(stage["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
WeaponData(
weapons[0].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[0].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[1].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[1].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[2].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[2].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
),
WeaponData(
weapons[3].jsonObject["name"]!!.jsonPrimitive.content,
Url(weapons[3].jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content)
)
)
)
}
Logger.out("Updated big run data")
Logger.out("Updated all Schedules")
}
private fun updateSplatfestCache(uag: String) {
val apiResponse = NetUtil.GETJsonData("${base_url}festivals.json", uag)
if (apiResponse.startsWith("Error")) {
Logger.out("Error getting splatfest data: $apiResponse")
return
}
val json = Json.decodeFromString(apiResponse) as JsonObject
val festivals = json["US"]!!.jsonObject["data"]!!.jsonObject["festRecords"]!!.jsonObject["nodes"]!!.jsonArray
cachedSplatfestData = mutableListOf()
festivals.forEach {
val fest = it as JsonObject
val teams = fest.jsonObject["teams"]!!.jsonArray
val team1 = teams[0].jsonObject
val team1Color = team1["color"]!!.jsonObject
var team1Result: JsonObject? = null
if (team1["result"] !is JsonNull) {
team1Result = team1["result"]!!.jsonObject
}
val team2 = teams[1].jsonObject
val team2Color = team2["color"]!!.jsonObject
var team2Result: JsonObject? = null
if (team2["result"] !is JsonNull) {
team2Result = team2["result"]!!.jsonObject
}
val team3 = teams[2].jsonObject
val team3Color = team3["color"]!!.jsonObject
var team3Result: JsonObject? = null
if (team3["result"] !is JsonNull) {
team3Result = team3["result"]!!.jsonObject
}
cachedSplatfestData.add(
SplatfestData(
fest.jsonObject["id"]!!.jsonPrimitive.content,
fest.jsonObject["state"]!!.jsonPrimitive.content,
fest.jsonObject["startTime"]!!.jsonPrimitive.content,
fest.jsonObject["endTime"]!!.jsonPrimitive.content,
fest.jsonObject["title"]!!.jsonPrimitive.content,
Url(fest.jsonObject["image"]!!.jsonObject["url"]!!.jsonPrimitive.content),
SplatfestTeamData(
team1["teamName"]!!.jsonPrimitive.content,
SplatfestColor(
team1Color["a"]!!.jsonPrimitive.int,
team1Color["b"]!!.jsonPrimitive.double,
team1Color["g"]!!.jsonPrimitive.double,
team1Color["r"]!!.jsonPrimitive.double
),
if (team1Result.isNullOrEmpty() || team1Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null)
null
else SplatfestTeamResults(
team1Result["isWinner"]!!.jsonPrimitive.boolean,
team1Result["horagaiRatio"]!!.jsonPrimitive.double,
team1Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean,
team1Result["voteRatio"]!!.jsonPrimitive.double,
team1Result["isVoteRatioTop"]!!.jsonPrimitive.boolean,
team1Result["regularContributionRatio"]!!.jsonPrimitive.double,
team1Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean,
team1Result["challengeContributionRatio"]!!.jsonPrimitive.double,
team1Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean,
team1Result["tricolorContributionRatio"]!!.jsonPrimitive.double,
team1Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean,
)
),
SplatfestTeamData(
team2["teamName"]!!.jsonPrimitive.content,
SplatfestColor(
team2Color["a"]!!.jsonPrimitive.int,
team2Color["b"]!!.jsonPrimitive.double,
team2Color["g"]!!.jsonPrimitive.double,
team2Color["r"]!!.jsonPrimitive.double
),
if (team2Result.isNullOrEmpty() || team2Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null)
null
else SplatfestTeamResults(
team2Result["isWinner"]!!.jsonPrimitive.boolean,
team2Result["horagaiRatio"]!!.jsonPrimitive.double,
team2Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean,
team2Result["voteRatio"]!!.jsonPrimitive.double,
team2Result["isVoteRatioTop"]!!.jsonPrimitive.boolean,
team2Result["regularContributionRatio"]!!.jsonPrimitive.double,
team2Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean,
team2Result["challengeContributionRatio"]!!.jsonPrimitive.double,
team2Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean,
team2Result["tricolorContributionRatio"]!!.jsonPrimitive.double,
team2Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean,
)
),
SplatfestTeamData(
team3["teamName"]!!.jsonPrimitive.content,
SplatfestColor(
team3Color["a"]!!.jsonPrimitive.int,
team3Color["b"]!!.jsonPrimitive.double,
team3Color["g"]!!.jsonPrimitive.double,
team3Color["r"]!!.jsonPrimitive.double
),
if (team3Result.isNullOrEmpty() || team3Result["tricolorContributionRatio"]!!.jsonPrimitive.doubleOrNull == null)
null
else SplatfestTeamResults(
team3Result["isWinner"]!!.jsonPrimitive.boolean,
team3Result["horagaiRatio"]!!.jsonPrimitive.double,
team3Result["isHoragaiRatioTop"]!!.jsonPrimitive.boolean,
team3Result["voteRatio"]!!.jsonPrimitive.double,
team3Result["isVoteRatioTop"]!!.jsonPrimitive.boolean,
team3Result["regularContributionRatio"]!!.jsonPrimitive.double,
team3Result["isRegularContributionRatioTop"]!!.jsonPrimitive.boolean,
team3Result["challengeContributionRatio"]!!.jsonPrimitive.double,
team3Result["isChallengeContributionRatioTop"]!!.jsonPrimitive.boolean,
team3Result["tricolorContributionRatio"]!!.jsonPrimitive.double,
team3Result["isTricolorContributionRatioTop"]!!.jsonPrimitive.boolean,
)
),
)
)
}
Logger.out("Updated Splatfest data")
}
}

View file

@ -0,0 +1,28 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.coop
import io.ktor.http.*
data class CoopGearData(
val name: String,
val image: Url,
val __typename: String,
)

View file

@ -0,0 +1,34 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
data class ChallengeModeData(
val leagueMatchEventId: String,
val name: String,
val description: String,
val regulation: String,
val map1: MapData?,
val map2: MapData?,
val __typename: String,
val ruleSet: String,
val ruleSetName: String,
val timePeriod1: TimePeriodData,
val timePeriod2: TimePeriodData,
val timePeriod3: TimePeriodData,
)

View file

@ -0,0 +1,27 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
import io.ktor.http.*
data class MapData(
val stageID: Int,
val image: Url,
val name: String,
)

View file

@ -0,0 +1,30 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
data class ModeData(
val startTime: String,
val endTime: String,
val matchType: String,
val map1: MapData?,
val map2: MapData?,
val ruleSetName: String,
val ruleSet: String,
val mode: String,
)

View file

@ -0,0 +1,34 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
import io.ktor.http.*
data class ShiftData(
val startTime: String,
val endTime: String,
val __splatoon3ink_king_salmonid_guess: String,
val __typename: String,
val stageName: String,
val image: Url,
val weapon1: WeaponData,
val weapon2: WeaponData,
val weapon3: WeaponData,
val weapon4: WeaponData,
)

View file

@ -0,0 +1,24 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
data class TimePeriodData(
val startTime: String,
val endTime: String,
)

View file

@ -0,0 +1,26 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.schedule
import io.ktor.http.*
data class WeaponData(
val name: String,
val image: Url,
)

View file

@ -0,0 +1,26 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatfest
data class SplatfestColor(
val a: Int,
val b: Double,
val g: Double,
val r: Double,
)

View file

@ -16,13 +16,18 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.tables package net.moonleay.lilJudd.data.api.entry.splatfest
import org.jetbrains.exposed.dao.id.IntIdTable import io.ktor.http.*
object PlanningNotifierRoles : IntIdTable() { data class SplatfestData(
var serverid = varchar("serverid", 50) val id: String,
var channelid = varchar("channelid", 50) val state: String,
var hastimeroleid = varchar("hastimeroleid", 50) val startTime: String,
var wantstobenotifiedid = varchar("wantstobenotifiedid", 50) val endTime: String,
} val title: String,
val image: Url,
val team1: SplatfestTeamData,
val team2: SplatfestTeamData,
val team3: SplatfestTeamData,
)

View file

@ -0,0 +1,25 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatfest
data class SplatfestTeamData(
val teamName: String,
val color: SplatfestColor,
val results: SplatfestTeamResults?,
)

View file

@ -0,0 +1,33 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatfest
data class SplatfestTeamResults(
val isWinner: Boolean,
val horagaiRatio: Double,
val horagaiRatioTop: Boolean,
val voteRatio: Double,
val voteRatioTop: Boolean,
val regularRatio: Double,
val regularRatioTop: Boolean,
val challengeRatio: Double,
val challengeRatioTop: Boolean,
val tricolorRatio: Double,
val tricolorRatioTop: Boolean,
)

View file

@ -0,0 +1,28 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatnet
import io.ktor.http.*
data class BrandData(
val name: String,
val image: Url,
val usualGearPower: GearAbilityData?,
val saleEndTime: String?,
)

View file

@ -0,0 +1,27 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatnet
import io.ktor.http.*
data class GearAbilityData(
val name: String,
val description: String?,
val image: Url,
)

View file

@ -0,0 +1,32 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.entry.splatnet
import io.ktor.http.*
data class SplatnetItemData(
val saleEndTime: String,
val price: Int,
val typeName: String,
val name: String,
val primaryGearPower: GearAbilityData,
val additionalGearPowers: List<GearAbilityData>,
val image: Url,
val brand: BrandData,
)

View file

@ -0,0 +1,27 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.type
enum class ApiDataType {
SCHEDULES,
SPLATNETGEAR,
COOP,
SPLATFESTS,
ALL
}

View file

@ -0,0 +1,26 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.api.type
enum class ApiRequestType(val nameToDisplay: String) {
AUTOMATIC_CACHE_UPDATE("automatic request to update the cache"),
AUTOMATIC_CACHE_CREATION_AT_STARTUP("automatic request to create cache at startup"),
MANUAL("manual request"),
DEBUG("debug request")
}

View file

@ -16,13 +16,21 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data package net.moonleay.lilJudd.data.database
import net.moonleay.lilJudd.data.database.tables.MatchPlanningData
import net.moonleay.lilJudd.data.database.tables.PlanningNotifierRoles
import net.moonleay.lilJudd.data.database.tables.TimePlanningChannels
import net.moonleay.lilJudd.data.database.tables.TimePlanningMessages
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction
object DB { object DB {
//Connect to the provided DB; trows errors, if the DB is not avalible. private var connected = false
//Connect to the provided DB; trows errors, if the DB is not available.
fun connect(dbDomain: String, dbName: String, dbUser: String, dbPasswd: String) { fun connect(dbDomain: String, dbName: String, dbUser: String, dbPasswd: String) {
Database.connect( Database.connect(
"jdbc:postgresql://$dbDomain/$dbName", "jdbc:postgresql://$dbDomain/$dbName",
@ -30,5 +38,18 @@ object DB {
user = dbUser, user = dbUser,
password = dbPasswd password = dbPasswd
) )
connected = true
}
fun register() {
if (!connected)
return
// Register tables here
transaction {
SchemaUtils.create(TimePlanningChannels)
SchemaUtils.create(TimePlanningMessages)
SchemaUtils.create(MatchPlanningData)
SchemaUtils.create(PlanningNotifierRoles)
}
} }
} }

View file

@ -16,17 +16,17 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.entry package net.moonleay.lilJudd.data.database.entry
data class MatchPlanningDataData( data class MatchPlanningDataData(
val id: Int, val id: Int,
val serverid: String, val serverID: Long,
val channelid: String, val channelID: Long,
val matchtype: String, val matchType: String,
val registererid: String, val registererID: Long,
val roleid: String, val roleID: Long,
val opponentname: String, val opponentName: String,
val messageid: String, val messageID: Long,
val timestamp: String, val timestamp: Long,
val jobstr: String val jobString: String
) )

View file

@ -16,11 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.entry package net.moonleay.lilJudd.data.database.entry
data class PlanningNotifierRolesData( data class PlanningNotifierRolesData(
val serverID: String, // The id of the server val id: Int, // The id of the entry
val channelId: String, // The id of the channel val serverID: Long, // The id of the server
val hastimeroleid: String, // The id of the role that has time today val channelID: Long, // The id of the channel
val wantstobenotifid: String // The id of the role that wants to be notified val hasTimeRoleID: Long, // The id of the role that has time today
val wantsToBeNotifiedID: Long // The id of the role that wants to be notified
) )

View file

@ -0,0 +1,25 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.entry
data class TimePlanningChannelsData(
val id: Int,
val serverID: Long,
val channelID: Long,
)

View file

@ -16,11 +16,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.entry package net.moonleay.lilJudd.data.database.entry
data class TimePlanningMessagesData( data class TimePlanningMessagesData(
val serverid: String, // The discord server id val id: Int, // The id of the entry
val channelid: String, // The discord channel id val serverID: Long, // The discord server id
val weekstamp: String, // The timestamp of the monday of the week at 4am UTC val channelID: Long, // The discord channel id
val messageids: String // IDs are in the following format: "{weekdayNr}:{id};{weekdayNr}:{id};[etc.]" val weekstamp: Long, // The timestamp of the monday of the week at 4am UTC
val messageIDs: String // IDs are in the following format: "{weekdayNr}:{id};{weekdayNr}:{id};[etc.]"
) )

View file

@ -0,0 +1,112 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.repository
import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData
import net.moonleay.lilJudd.data.database.tables.MatchPlanningData
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
object MatchPlanningDataRepository {
fun getAll(): List<MatchPlanningDataData> {
val dataList = mutableListOf<MatchPlanningDataData>()
transaction {
MatchPlanningData.selectAll().forEach {
dataList.add(
MatchPlanningDataData(
it[MatchPlanningData.id],
it[MatchPlanningData.serverid],
it[MatchPlanningData.channelid],
it[MatchPlanningData.matchtype],
it[MatchPlanningData.registererid],
it[MatchPlanningData.roleid],
it[MatchPlanningData.opponentName],
it[MatchPlanningData.messageid],
it[MatchPlanningData.timestamp],
it[MatchPlanningData.jobstr]
)
)
}
}
return dataList
}
fun get(id: Int): MatchPlanningDataData? =
transaction {
MatchPlanningData.select { MatchPlanningData.id eq id }.firstOrNull()?.let {
MatchPlanningDataData(
it[MatchPlanningData.id],
it[MatchPlanningData.serverid],
it[MatchPlanningData.channelid],
it[MatchPlanningData.matchtype],
it[MatchPlanningData.registererid],
it[MatchPlanningData.roleid],
it[MatchPlanningData.opponentName],
it[MatchPlanningData.messageid],
it[MatchPlanningData.timestamp],
it[MatchPlanningData.jobstr]
)
}
}
fun getFromMessageInChannelInServer(messageID: Long, channelID: Long, serverID: Long): MatchPlanningDataData? =
transaction {
MatchPlanningData.select {
MatchPlanningData.messageid eq (messageID) and (
MatchPlanningData.serverid eq (serverID)) and (
MatchPlanningData.channelid eq (channelID))
}.firstOrNull()?.let {
MatchPlanningDataData(
it[MatchPlanningData.id],
it[MatchPlanningData.serverid],
it[MatchPlanningData.channelid],
it[MatchPlanningData.matchtype],
it[MatchPlanningData.registererid],
it[MatchPlanningData.roleid],
it[MatchPlanningData.opponentName],
it[MatchPlanningData.messageid],
it[MatchPlanningData.timestamp],
it[MatchPlanningData.jobstr]
)
}
}
fun delete(id: Int) {
transaction {
MatchPlanningData.deleteWhere { MatchPlanningData.id eq id }
}
}
fun write(data: MatchPlanningDataData): Int =
transaction {
MatchPlanningData.insert {
it[MatchPlanningData.serverid] = data.serverID
it[MatchPlanningData.channelid] = data.channelID
it[MatchPlanningData.matchtype] = data.matchType
it[MatchPlanningData.registererid] = data.registererID
it[MatchPlanningData.roleid] = data.roleID
it[MatchPlanningData.opponentName] = data.opponentName
it[MatchPlanningData.messageid] = data.messageID
it[MatchPlanningData.timestamp] = data.timestamp
it[MatchPlanningData.jobstr] = data.jobString
} get MatchPlanningData.id
}
}

View file

@ -0,0 +1,104 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.repository
import net.moonleay.lilJudd.data.database.entry.PlanningNotifierRolesData
import net.moonleay.lilJudd.data.database.tables.PlanningNotifierRoles
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
object PlanningNotifierRolesRepository {
fun getAll(): List<PlanningNotifierRolesData> {
val dataList = mutableListOf<PlanningNotifierRolesData>()
transaction {
for (pnr in PlanningNotifierRoles.selectAll()) {
dataList.add(
PlanningNotifierRolesData(
pnr[PlanningNotifierRoles.id],
pnr[PlanningNotifierRoles.serverid],
pnr[PlanningNotifierRoles.channelid],
pnr[PlanningNotifierRoles.hastimeroleid],
pnr[PlanningNotifierRoles.wantstobenotifiedid]
)
)
}
}
return dataList
}
fun getForChannel(channelID: Long): PlanningNotifierRolesData? =
transaction {
PlanningNotifierRoles.select {
PlanningNotifierRoles.channelid eq channelID
}.firstOrNull()?.let {
PlanningNotifierRolesData(
it[PlanningNotifierRoles.id],
it[PlanningNotifierRoles.serverid],
it[PlanningNotifierRoles.channelid],
it[PlanningNotifierRoles.hastimeroleid],
it[PlanningNotifierRoles.wantstobenotifiedid]
)
}
}
fun getForChannelInServer(channelID: Long, serverID: Long): PlanningNotifierRolesData? =
transaction {
PlanningNotifierRoles.select {
PlanningNotifierRoles.channelid eq channelID and (PlanningNotifierRoles.serverid eq serverID)
}.firstOrNull()?.let {
PlanningNotifierRolesData(
it[PlanningNotifierRoles.id],
it[PlanningNotifierRoles.serverid],
it[PlanningNotifierRoles.channelid],
it[PlanningNotifierRoles.hastimeroleid],
it[PlanningNotifierRoles.wantstobenotifiedid]
)
}
}
fun existsInChannel(channelID: Long): Boolean =
transaction {
PlanningNotifierRoles.select { PlanningNotifierRoles.channelid eq channelID }.count() > 0
}
fun existsInChannelFromSever(channelID: Long, serverID: Long): Boolean =
transaction {
PlanningNotifierRoles.select { PlanningNotifierRoles.channelid eq channelID and (PlanningNotifierRoles.serverid eq serverID) }
.count() > 0
}
fun write(data: PlanningNotifierRolesData) {
transaction {
PlanningNotifierRoles.insert {
it[PlanningNotifierRoles.serverid] = data.serverID
it[PlanningNotifierRoles.channelid] = data.channelID
it[PlanningNotifierRoles.hastimeroleid] = data.hasTimeRoleID
it[PlanningNotifierRoles.wantstobenotifiedid] = data.wantsToBeNotifiedID
} get PlanningNotifierRoles.id
}
}
fun delete(id: Int) {
transaction {
PlanningNotifierRoles.deleteWhere { PlanningNotifierRoles.id eq id }
}
}
}

View file

@ -0,0 +1,69 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.repository
import net.moonleay.lilJudd.data.database.entry.TimePlanningChannelsData
import net.moonleay.lilJudd.data.database.tables.TimePlanningChannels
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
object TimePlanningChannelsRepository {
fun getAll(): List<TimePlanningChannelsData> {
val dataList = mutableListOf<TimePlanningChannelsData>()
transaction {
for (tp in TimePlanningChannels.selectAll())
dataList.add(
TimePlanningChannelsData(
id = tp[TimePlanningChannels.id],
serverID = tp[TimePlanningChannels.serverid],
channelID = tp[TimePlanningChannels.channelid],
)
)
}
return dataList
}
fun exists(channelID: Long, serverID: Long): Boolean =
transaction {
TimePlanningChannels.select { TimePlanningChannels.channelid eq channelID and (TimePlanningChannels.serverid eq serverID) }
.firstOrNull() != null
}
fun delete(id: Int) {
transaction {
TimePlanningChannels.deleteWhere { TimePlanningChannels.id eq id }
}
}
fun deleteFromChannelInServer(channelID: Long, serverID: Long) {
transaction {
TimePlanningChannels.deleteWhere { TimePlanningChannels.channelid eq channelID and (TimePlanningChannels.serverid eq serverID) }
}
}
fun write(data: TimePlanningChannelsData): Int =
transaction {
TimePlanningChannels.insert {
it[TimePlanningChannels.serverid] = data.serverID
it[TimePlanningChannels.channelid] = data.channelID
} get TimePlanningChannels.id
}
}

View file

@ -0,0 +1,76 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.repository
import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData
import net.moonleay.lilJudd.data.database.tables.TimePlanningMessages
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
object TimePlanningMessagesRepository {
fun write(data: TimePlanningMessagesData): Int =
transaction {
TimePlanningMessages.insert {
it[serverid] = data.serverID
it[channelid] = data.channelID
it[weekstamp] = data.weekstamp
it[messageids] = data.messageIDs
} get TimePlanningMessages.id
}
fun getWeek(stamp: Long): List<TimePlanningMessagesData> {
val dataList = mutableListOf<TimePlanningMessagesData>()
transaction {
for (pnr in TimePlanningMessages.select {
TimePlanningMessages.weekstamp eq (stamp)
}) {
dataList.add(
TimePlanningMessagesData(
pnr[TimePlanningMessages.id],
pnr[TimePlanningMessages.serverid],
pnr[TimePlanningMessages.channelid],
pnr[TimePlanningMessages.weekstamp],
pnr[TimePlanningMessages.messageids]
)
)
}
}
return dataList
}
fun getWeekInChannel(stamp: Long, channelID: Long): TimePlanningMessagesData? =
transaction {
TimePlanningMessages.select {
TimePlanningMessages.weekstamp eq (stamp) and (TimePlanningMessages.channelid eq channelID)
}.firstOrNull()?.let {
TimePlanningMessagesData(
it[TimePlanningMessages.id],
it[TimePlanningMessages.serverid],
it[TimePlanningMessages.channelid],
it[TimePlanningMessages.weekstamp],
it[TimePlanningMessages.messageids]
)
}
}
}

View file

@ -16,18 +16,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.tables package net.moonleay.lilJudd.data.database.tables
import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.Table
object MatchPlanningData : IntIdTable() { object MatchPlanningData : Table(name = "new_matchplanning_data") {
var serverid = varchar("serverid", 50) var id = integer("id").autoIncrement()
var channelid = varchar("channelid", 50) var serverid = long("serverid")
var channelid = long("channelid")
var matchtype = varchar("matchtype", 50) var matchtype = varchar("matchtype", 50)
var registererid = varchar("registererid", 50) var registererid = long("registererid")
var roleid = varchar("roleid", 50) var roleid = long("roleid")
var opponentName = varchar("opponentname", 100) var opponentName = varchar("opponentname", 100)
var messageid = varchar("messageid", 50) var messageid = long("messageid")
var timestamp = varchar("timestamp", 50) var timestamp = long("timestamp")
var jobstr = varchar("jobstr", 50) var jobstr = varchar("jobstr", 50)
} }

View file

@ -0,0 +1,29 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.tables
import org.jetbrains.exposed.sql.Table
object PlanningNotifierRoles : Table(name = "new_planningnotifier_roles") {
var id = integer("id").autoIncrement()
var serverid = long("serverid")
var channelid = long("channelid")
var hastimeroleid = long("hastimeroleid")
var wantstobenotifiedid = long("wantstobenotifiedid")
}

View file

@ -0,0 +1,28 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.data.database.tables
import org.jetbrains.exposed.sql.Table
object TimePlanningChannels : Table(name = "new_timeplanning_channels") {
var id = integer("id").autoIncrement()
var serverid = long("serverid")
val channelid = long("channelid")
}

View file

@ -16,13 +16,14 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.tables package net.moonleay.lilJudd.data.database.tables
import org.jetbrains.exposed.dao.id.IntIdTable import org.jetbrains.exposed.sql.Table
object TimePlanningMessages : IntIdTable() { object TimePlanningMessages : Table(name = "new_timeplanning_messages") {
var serverid = varchar("serverid", 50) var id = integer("id").autoIncrement()
var channelid = varchar("channelid", 50) var serverid = long("serverid")
var weekstamp = varchar("weekstamp", 50) var channelid = long("channelid")
var weekstamp = long("weekstamp")
var messageids = varchar("messageids", 200) var messageids = varchar("messageids", 200)
} }

View file

@ -25,11 +25,11 @@ import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import com.kotlindiscord.kord.extensions.utils.hasPermission import com.kotlindiscord.kord.extensions.utils.hasPermission
import dev.kord.common.Color
import dev.kord.common.entity.Permission import dev.kord.common.entity.Permission
import net.moonleay.lilJudd.extensions.component.EnableOrDisable import net.moonleay.lilJudd.extensions.component.EnableOrDisable
import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.FeatureEnum
import net.moonleay.lilJudd.features.component.FeatureManager import net.moonleay.lilJudd.features.component.FeatureManager
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.MessageUtil
@ -51,7 +51,7 @@ class FeatureManageExtension : Extension() {
this.respond { this.respond {
embeds.add( embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"403: Forbidden", "403: Forbidden",
"You cannot edit features, as you don't have the Administrator permission.", "You cannot edit features, as you don't have the Administrator permission.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -60,8 +60,8 @@ class FeatureManageExtension : Extension() {
} }
return@action return@action
} }
val gID = this.guild!!.id.toString() val gID = this.guild!!.id.value.toLong()
val cID = this.arguments.channel.id.toString() val cID = this.arguments.channel.id.value.toLong()
val channel = this.arguments.channel val channel = this.arguments.channel
val args = this.arguments val args = this.arguments
Logger.out("${args.feature.readableName} ${args.setStatus.readableName} ${channel.data.name.value}") Logger.out("${args.feature.readableName} ${args.setStatus.readableName} ${channel.data.name.value}")
@ -70,7 +70,7 @@ class FeatureManageExtension : Extension() {
this.respond { this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"404: Not Found", "404: Not Found",
"The feature you are trying to edit does not exist.", "The feature you are trying to edit does not exist.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator

View file

@ -20,25 +20,26 @@ package net.moonleay.lilJudd.extensions
import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import dev.kord.common.Color
import net.moonleay.botendo.build.BuildConstants import net.moonleay.botendo.build.BuildConstants
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.MessageUtil
class VersionExtension : Extension() { class InfoExtension : Extension() {
override val name = "version" override val name = "info"
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand { publicSlashCommand {
name = "version" name = "info"
description = "Show infos about the bot" description = "Show infos about the bot"
this.action { this.action {
MessageUtil.sendEmbedForPublicSlashCommand( MessageUtil.sendEmbedForPublicSlashCommand(
this, this,
Color(0x52E01A), EmbedColor.INFO,
"Lil' Judd", "Lil' Judd",
"Lil' Judd ***v." + BuildConstants.version + "***\n" + "Lil' Judd ***v." + BuildConstants.version + "***\n" +
"Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" + "Kord-Extensions ***v." + BuildConstants.kordVersion + "***\n" +
"Coroutines ***v." + BuildConstants.coroutinesVersion + "***\n" + "Coroutines ***v." + BuildConstants.coroutinesVersion + "***\n" +
"Krontab ***v." + BuildConstants.krontabVersion + "***" "Krontab ***v." + BuildConstants.krontabVersion + "***\n\n" +
"Splatoon 3 api data provided by splatoon3.ink"
) )
} }
} }

View file

@ -25,20 +25,18 @@ import com.kotlindiscord.kord.extensions.commands.converters.impl.string
import com.kotlindiscord.kord.extensions.extensions.Extension import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import dev.kord.common.Color
import dev.kord.core.behavior.channel.createMessage import dev.kord.core.behavior.channel.createMessage
import dev.kord.core.behavior.createRole import dev.kord.core.behavior.createRole
import dev.kord.rest.builder.message.create.actionRow import dev.kord.rest.builder.message.create.actionRow
import net.moonleay.lilJudd.data.tables.MatchPlanningData import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData
import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.extensions.component.MatchTypes import net.moonleay.lilJudd.extensions.component.MatchTypes
import net.moonleay.lilJudd.jobs.MatchJob import net.moonleay.lilJudd.jobs.MatchJob
import net.moonleay.lilJudd.jobs.component.JobManager import net.moonleay.lilJudd.jobs.component.JobManager
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.MessageUtil
import net.moonleay.lilJudd.util.TimeUtil import net.moonleay.lilJudd.util.TimeUtil
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.transactions.transaction
class MatchExtension : Extension() { class MatchExtension : Extension() {
@ -54,19 +52,20 @@ class MatchExtension : Extension() {
this.action { this.action {
val args = this.arguments val args = this.arguments
val m = this.member!! val m = this.member!!
val gID = this.guild!!.id.value.toString() val gID = this.guild!!.id.value
val cID = this.channel.id.value.toString() val cID = this.channel.id.value
val opponent = args.opponent ?: "?" val opponent = args.opponent ?: "?"
val msg = this.respond { val msg = this.respond {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithTable( MessageUtil.getEmbedWithTable(
Color(0X4C4645), EmbedColor.INFO,
args.matchType.readableName, args.matchType.readableName,
"***Vs. $opponent***\n" + "***Vs. $opponent***\n" +
"At ${args.timeStamp}\n" + "At ${args.timeStamp}\n" +
"Registered by ${m.mention}", "Registered by ${m.mention}",
mapOf( mapOf(
"Signed up" to listOf(), "Signed up" to listOf(),
"Unavailable" to listOf(),
) )
) )
) )
@ -89,7 +88,7 @@ class MatchExtension : Extension() {
this.channel.createMessage { this.channel.createMessage {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"500: Internal Error", "500: Internal Error",
"Could not find created role.\n" + "Could not find created role.\n" +
"It seems, that said role could not be created.", "It seems, that said role could not be created.",
@ -99,28 +98,28 @@ class MatchExtension : Extension() {
} }
return@action return@action
} }
lateinit var tableID: EntityID<Int> val tID = MatchPlanningDataRepository.write(
transaction { MatchPlanningDataData(
tableID = MatchPlanningData.insert { 0,
it[MatchPlanningData.serverid] = gID gID.toLong(),
it[MatchPlanningData.channelid] = cID cID.toLong(),
it[MatchPlanningData.messageid] = msg.id.value.toString() args.matchType.readableName,
it[MatchPlanningData.matchtype] = args.matchType.readableName m.id.value.toLong(),
it[MatchPlanningData.roleid] = role.id.value.toString() role.id.value.toLong(),
it[MatchPlanningData.registererid] = m.id.value.toString() opponent,
it[MatchPlanningData.opponentName] = opponent msg.id.value.toLong(),
it[MatchPlanningData.timestamp] = (zdt.toEpochSecond() * 1000).toString() (zdt.toEpochSecond() * 1000),
it[MatchPlanningData.jobstr] = jobString jobString
} get MatchPlanningData.id )
} )
if (tableID == null) { if (tID == null || tID <= 0) {
return@action // Not saved to db return@action // Not saved to db
} }
JobManager.addJob( JobManager.addJob(
MatchJob( MatchJob(
jobString, jobString,
tableID.value, tID,
"${args.matchType.readableName}_Vs_${opponent}_[${tableID.value}]-${gID}_${cID}" "${args.matchType.readableName}_Vs_${opponent}_[${tID}]-${gID}_${cID}",
) )
) )
} }

View file

@ -0,0 +1,80 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.extensions
import com.kotlindiscord.kord.extensions.commands.Arguments
import com.kotlindiscord.kord.extensions.commands.application.slash.converters.impl.enumChoice
import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import net.moonleay.lilJudd.extensions.component.SplatoonOnlineMode
import net.moonleay.lilJudd.util.Logger
class RotationExtension : Extension() {
override val name = "rotation"
override val allowApplicationCommandInDMs: Boolean
get() = false
override suspend fun setup() {
publicSlashCommand(::RotationArguments) {
name = "rotation"
description = "Check the current rotations"
this.action {
val mode = this.arguments.mode
when (mode) {
SplatoonOnlineMode.ALL -> {
}
SplatoonOnlineMode.REGULAR -> {
}
SplatoonOnlineMode.SERIES -> {
}
SplatoonOnlineMode.OPEN -> {
}
SplatoonOnlineMode.X -> {
}
SplatoonOnlineMode.SALMON_RUN -> {
}
}
Logger.out("Done")
}
}
}
inner class RotationArguments : Arguments() {
val mode by enumChoice<SplatoonOnlineMode> {
this.name = "mode"
this.description = "The mode you want to check the rotation for"
this.typeName = "en_US"
}
}
}

View file

@ -22,18 +22,13 @@ import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import com.kotlindiscord.kord.extensions.utils.hasPermission import com.kotlindiscord.kord.extensions.utils.hasPermission
import dev.kord.common.Color
import dev.kord.common.entity.Permission import dev.kord.common.entity.Permission
import dev.kord.core.behavior.channel.createMessage import dev.kord.core.behavior.channel.createMessage
import dev.kord.rest.builder.message.create.actionRow import dev.kord.rest.builder.message.create.actionRow
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import net.moonleay.lilJudd.data.tables.TimePlanningMessages import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.*
import net.moonleay.lilJudd.util.MessageUtil
import net.moonleay.lilJudd.util.TimeUtil
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.ZoneId import java.time.ZoneId
import java.time.ZonedDateTime import java.time.ZonedDateTime
@ -47,13 +42,13 @@ class SendPlannerExtension : Extension() {
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand() { publicSlashCommand() {
name = "sendplanner" name = "sendplanner"
description = "Send the planner for the current and x next weeks" description = "Send the planner for the current week"
this.action { this.action {
if (!this.member!!.asMember(this.guild!!.id) if (!this.member!!.asMember(this.guild!!.id)
.hasPermission(Permission.Administrator) .hasPermission(Permission.Administrator)
) { ) {
val res = this.respond { val res = this.respond {
this.content = "no." this.content = "You need to be an administrator to use this command."
} }
res.delete() res.delete()
return@action return@action
@ -71,7 +66,7 @@ class SendPlannerExtension : Extension() {
c.createMessage { c.createMessage {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0X4C4645), EmbedColor.INFO,
"Time Planning Feature", "Time Planning Feature",
"Do you have time on the following Days?", "Do you have time on the following Days?",
"Automated Message" "Automated Message"
@ -83,7 +78,7 @@ class SendPlannerExtension : Extension() {
val msg = c.createMessage { val msg = c.createMessage {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithTable( MessageUtil.getEmbedWithTable(
Color(0X4C4645), EmbedColor.INFO,
"", "",
"${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday",
mapOf( mapOf(
@ -105,14 +100,15 @@ class SendPlannerExtension : Extension() {
} }
// Save the message ids // Save the message ids
transaction { TimePlanningMessagesRepository.write(
TimePlanningMessages.insert { TimePlanningMessagesData(
it[serverid] = c.data.guildId.value.toString() -1,
it[channelid] = c.id.value.toString() c.data.guildId.value?.value!!.toLong(),
it[weekstamp] = (TimeUtil.getWeekStamp().toEpochSecond() * 1000).toString() c.id.value.toLong(),
it[messageids] = msgStr (TimeUtil.getWeekStamp().toEpochSecond()),
} get TimePlanningMessages.id msgStr
} )
)
Logger.out("Finished with ${c.data.guildId.value}") Logger.out("Finished with ${c.data.guildId.value}")
} }
} }

View file

@ -1,62 +0,0 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.extensions
import com.kotlindiscord.kord.extensions.extensions.Extension
import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond
import dev.kord.common.Color
import dev.kord.rest.builder.message.create.actionRow
import net.moonleay.lilJudd.util.EmbedUtil
import net.moonleay.lilJudd.util.MessageUtil
/* This extension has no proper use.
It is used in testing to test stuff, without having to wait for certain events to trigger. */
class TestExtension : Extension() {
override val name = "test"
override val allowApplicationCommandInDMs: Boolean
get() = false
override suspend fun setup() {
publicSlashCommand {
name = "test"
description = "Test game"
this.action {
this.respond {
this.embeds.add(
MessageUtil.getEmbedWithTable(
Color(0X4C4645),
"",
"MONDAY, 22.05.2023",
mapOf(
"Is available" to listOf(),
"May be available" to listOf(),
"Is not available" to listOf()
)
)
)
this.actionRow {
this.components.addAll(EmbedUtil.getTimePlannerButtons().components)
}
}
}
}
}
}

View file

@ -23,16 +23,16 @@ import com.kotlindiscord.kord.extensions.extensions.publicSlashCommand
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import com.kotlindiscord.kord.extensions.utils.hasPermission import com.kotlindiscord.kord.extensions.utils.hasPermission
import dev.kord.common.entity.Permission import dev.kord.common.entity.Permission
import dev.kord.gateway.PrivilegedIntent
import net.moonleay.lilJudd.features.AvailabilityManager import net.moonleay.lilJudd.features.AvailabilityManager
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil
class UpdateRolesExtension : Extension() { class UpdateRolesExtension : Extension() {
override val name = "updateroles" override val name = "updateroles"
override val allowApplicationCommandInDMs: Boolean override val allowApplicationCommandInDMs: Boolean
get() = false get() = false
@OptIn(PrivilegedIntent::class)
override suspend fun setup() { override suspend fun setup() {
publicSlashCommand() { publicSlashCommand() {
name = "updateroles" name = "updateroles"
@ -41,21 +41,34 @@ class UpdateRolesExtension : Extension() {
if (!this.member!!.asMember(this.guild!!.id) if (!this.member!!.asMember(this.guild!!.id)
.hasPermission(Permission.Administrator) .hasPermission(Permission.Administrator)
) { ) {
val res = this.respond { this.respond {
this.content = "no." this.embeds.add(
MessageUtil.getEmbed(
EmbedColor.ERROR,
"403: Forbidden",
"You need to be an administrator to use this command.",
user.asUser().username + "#" + user.asUser().discriminator
)
)
} }
res.delete()
return@action return@action
} }
val res = this.respond { this.respond {
this.content = "OK." this.embeds.add(
MessageUtil.getEmbed(
EmbedColor.SUCCESS,
"200: Success",
"Updating roles.\n" +
"This may take a while, please be patient.",
user.asUser().username + "#" + user.asUser().discriminator
)
)
} }
// -- below here is the code of the cronjob -- // -- below here is the code of the cronjob --
Logger.out("Starting to update roles...") Logger.out("Starting to update roles...")
AvailabilityManager.runThread() AvailabilityManager.updateInChannel(this.channel.id)
} }
} }
} }

View file

@ -0,0 +1,30 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.extensions.component
import com.kotlindiscord.kord.extensions.commands.application.slash.converters.ChoiceEnum
enum class SplatoonOnlineMode(override val readableName: String) : ChoiceEnum {
ALL("All Modes"),
REGULAR("Regular Battle"),
SERIES("Ranked Battle (Series)"),
OPEN("Ranked Battle (Open)"),
X("X Battle"),
SALMON_RUN("Salmon Run"),
}

View file

@ -18,9 +18,9 @@
package net.moonleay.lilJudd.features package net.moonleay.lilJudd.features
import com.kotlindiscord.kord.extensions.utils.isNullOrBot
import dev.inmo.krontab.buildSchedule import dev.inmo.krontab.buildSchedule
import dev.inmo.krontab.doInfinity import dev.inmo.krontab.doInfinity
import dev.kord.common.Color
import dev.kord.common.entity.Snowflake import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.UserBehavior
import dev.kord.core.behavior.createRole import dev.kord.core.behavior.createRole
@ -30,129 +30,133 @@ import dev.kord.core.entity.channel.MessageChannel
import dev.kord.gateway.PrivilegedIntent import dev.kord.gateway.PrivilegedIntent
import dev.kord.rest.builder.message.EmbedBuilder import dev.kord.rest.builder.message.EmbedBuilder
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.data.entry.PlanningNotifierRolesData import net.moonleay.lilJudd.data.database.entry.PlanningNotifierRolesData
import net.moonleay.lilJudd.data.entry.TimePlanningMessagesData import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData
import net.moonleay.lilJudd.data.tables.PlanningNotifierRoles import net.moonleay.lilJudd.data.database.repository.PlanningNotifierRolesRepository
import net.moonleay.lilJudd.data.tables.TimePlanningMessages import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository
import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.extensions.FeatureManageExtension
import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.FeatureEnum
import net.moonleay.lilJudd.features.component.IFeature import net.moonleay.lilJudd.features.component.IFeature
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.*
import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil
import net.moonleay.lilJudd.util.TimeUtil
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.ZonedDateTime import java.time.ZonedDateTime
object AvailabilityManager : IFeature { object AvailabilityManager : IFeature {
// This runs during the cronjob. // This runs during the cronjob.
@OptIn(PrivilegedIntent::class)
suspend fun runThread() { suspend fun runThread() {
Logger.out("Starting to update roles...") Logger.out("Starting to update roles...")
// ChannelID, Data // ChannelID, Data
val messageMap = mutableMapOf<Snowflake, TimePlanningMessagesData>() val messages = TimePlanningMessagesRepository.getWeek(TimeUtil.getWeekStamp().toEpochSecond())
// ChannelID, Data .associateBy { it.channelID }
val roleMap = mutableMapOf<String, PlanningNotifierRolesData>() val targetedRoles = PlanningNotifierRolesRepository.getAll().associateBy { it.channelID }
if (targetedRoles.isEmpty()) {
transaction { Logger.out("No saved roles. Canceling.")
for (pnr in TimePlanningMessages.select { return
TimePlanningMessages.weekstamp eq (TimeUtil.getWeekStamp().toEpochSecond() * 1000).toString()
}) {
messageMap[Snowflake(pnr[TimePlanningMessages.channelid])] =
TimePlanningMessagesData(
pnr[TimePlanningMessages.serverid],
pnr[TimePlanningMessages.channelid],
pnr[TimePlanningMessages.weekstamp],
pnr[TimePlanningMessages.messageids]
)
}
for (pnr in PlanningNotifierRoles.selectAll()) {
roleMap[pnr[PlanningNotifierRoles.channelid]] =
PlanningNotifierRolesData(
pnr[PlanningNotifierRoles.serverid],
pnr[PlanningNotifierRoles.channelid],
pnr[PlanningNotifierRoles.hastimeroleid],
pnr[PlanningNotifierRoles.wantstobenotifiedid]
)
}
} }
val weekday = ZonedDateTime.now().dayOfWeek // The current week day for (id in messages.keys) {
val weekStamp = TimeUtil.getWeekStamp().toEpochSecond() * 1000 // The current week time stamp val snf = Snowflake(id) // snf = Snowflake
Logger.out("It is week ${weekStamp} and day ${weekday}/${TimeUtil.getDayOfMonthInt(weekday)} of the week.") val data = messages[id]!! // this is the data of the table
for (snf in messageMap.keys) { // snf = Snowflake if (Bot.bot.kordRef.getChannel(Snowflake(data.channelID)) == null) {
val data = messageMap[snf]!! // this is the data of the table // This channel does not exist anymore.
if (Bot.bot.kordRef.getChannel(Snowflake(data.channelid)) == null) Logger.out("Warning: Channel ${data.channelID} does not exist anymore. Skipping.")
continue // This channel does not exist anymore. continue
val c =
Bot.bot.kordRef.getChannelOf<MessageChannel>(Snowflake(data.channelid))!! // Get the channel as MessageChannel
if (roleMap.isEmpty()) {
Logger.out("No saved roles. Canceling.")
return
} }
val roleData = roleMap[data.channelid] // Get the role data val roleData = targetedRoles[data.channelID] // Get the role data
if (roleData == null) { if (roleData == null) {
Logger.out("Role for this channel does not exist") Logger.out("Role for channel ${data.channelID} does not exist")
return continue // this took way to long to find out that this was the issue
}
val g = Bot.bot.kordRef.getGuildOrThrow(Snowflake(data.serverid))
// Get all members with the role
val mce = g.requestMembers {
this.requestAllMembers()
}
mce.collect { memberchunkevent ->
memberchunkevent.members.forEach {
Logger.out("Checking member ${it.id.value}")
if (it.roleIds.contains(Snowflake(roleData.hastimeroleid)))
it.removeRole(Snowflake(roleData.hastimeroleid))
}
}
Logger.out("Got through all members")
// This stores the ids of the messages.
// The format is weekdaNR:ID
// The last entry (nr 8) is empty, so we can ignore it
val messageIdSplit = data.messageids.split(";").subList(0, 7)
for (mid in messageIdSplit) {
Logger.out("Checking id $mid")
if (!mid.startsWith((TimeUtil.getDayOfMonthInt(weekday) - 1).toString(), true))
continue // This is not the right message, check the next one
val idFiltered = mid.split(":")[1] // This is the target message id
val message = c.getMessageOrNull(Snowflake(idFiltered)) // Get the message from the channel
if (message == null) {
Logger.out("Could not find message.")
break // This message does not exist anymore. Nothing we can do about that.
}
if (message.data.embeds.isEmpty()) {
Logger.out("There are no embeds.")
break // There are no embeds or there are not enough embeds
}
val targets = EmbedUtil.getAllUsersInTheFirstXTables(2, message.embeds[0])
for (tid in targets) {
Logger.out("Checking id $tid")
if (Bot.bot.kordRef.getGuildOrNull(Snowflake(data.serverid))!!
.getMemberOrNull(Snowflake(tid)) == null
)
continue // This member does not exist anymore.
val member = Bot.bot.kordRef.getGuildOrThrow(Snowflake(data.serverid))
.getMember(Snowflake(tid)) // Get the member
if (member.roleIds.contains(Snowflake(roleData.hastimeroleid)))
continue // This member already has the role
member.addRole(Snowflake(roleData.hastimeroleid)) // Add the role
Logger.out("Added role to ${member.username}")
}
Logger.out("Done with message. Moving on...")
// We found the right message. We don't need to check the others.
break
} }
this.updateInChannel(snf, data, roleData)
} }
Logger.out("Done! Until tomorrow! <3 ") Logger.out("Done! Until tomorrow! <3 ")
} }
suspend fun updateInChannel(snf: Snowflake) {
val stamp = TimeUtil.getWeekStamp().toEpochSecond()
Logger.out("Weekstamp: $stamp")
val messageData = TimePlanningMessagesRepository.getWeekInChannel(
stamp,
snf.value.toLong()
)
if (messageData == null) {
Logger.out("Could not find data for channel ${snf.value}")
return
}
val roleData = PlanningNotifierRolesRepository.getForChannel(snf.value.toLong())
if (roleData == null) {
Logger.out("Role for channel ${messageData.channelID} does not exist")
return // this took way to long to find out that this was the issue
}
updateInChannel(snf, messageData, roleData)
}
@OptIn(PrivilegedIntent::class)
suspend fun updateInChannel(snf: Snowflake, tpmd: TimePlanningMessagesData, pnrd: PlanningNotifierRolesData) {
if (Bot.bot.kordRef.getChannel(snf) == null)
return // This channel does not exist anymore.
val c = Bot.bot.kordRef.getChannelOf<MessageChannel>(snf)!! // Get the channel as MessageChannel
val weekday = ZonedDateTime.now().dayOfWeek // The current week day
val weekStamp = TimeUtil.getWeekStamp().toEpochSecond() // The current week time stamp
Logger.out("It is week ${weekStamp} and day ${weekday}/${TimeUtil.getDayOfMonthInt(weekday)} of the week.")
val g = Bot.bot.kordRef.getGuild(Snowflake(tpmd.serverID))
// Get all members with the role
val mce = g.requestMembers {
this.requestAllMembers()
}
mce.collect { memberchunkevent ->
memberchunkevent.members.forEach {
if (!it.isNullOrBot()) { // Check if the member is a bot
Logger.out("Checking member ${it.id.value} (${it.username})")
if (it.roleIds.contains(Snowflake(pnrd.hasTimeRoleID))) {
it.removeRole(Snowflake(pnrd.hasTimeRoleID))
Logger.out("Removed role from ${it.username}") // Removed the role
}
}
// I cant use continue here, because it does not work with .forEach
}
}
Logger.out("Got through all members")
// This stores the ids of the messages.
// The format is weekdaNR:ID
// The last entry (nr 8) is empty, so we can ignore it
val messageIdSplit = tpmd.messageIDs.split(";").subList(0, 7)
for (mid in messageIdSplit) {
Logger.out("Checking id $mid")
if (!mid.startsWith((TimeUtil.getDayOfMonthInt(weekday) - 1).toString(), true))
continue// This is not the right message, check the next one
val idFiltered = mid.split(":")[1] // This is the target message id
val message = c.getMessageOrNull(Snowflake(idFiltered)) // Get the message from the channel
if (message == null) {
Logger.out("Could not find message.")
return // This message does not exist anymore. Nothing we can do about that.
}
if (message.data.embeds.isEmpty()) {
Logger.out("There are no embeds.")
return // There are no embeds or there are not enough embeds
}
val targets = EmbedUtil.getAllUsersInTheFirstXTables(2, message.embeds[0])
for (tid in targets) {
Logger.out("Checking id $tid")
if (Bot.bot.kordRef.getGuildOrNull(Snowflake(tpmd.serverID))!!
.getMemberOrNull(Snowflake(tid)) == null
)
continue// This member does not exist anymore.
val member = Bot.bot.kordRef.getGuild(Snowflake(tpmd.serverID))
.getMember(Snowflake(tid)) // Get the member
if (member.roleIds.contains(Snowflake(pnrd.hasTimeRoleID)))
continue // This member already has the role
member.addRole(Snowflake(pnrd.hasTimeRoleID)) // Add the role
Logger.out("Added role to ${member.username}")
}
Logger.out("Done with message. Moving on...")
// We found the right message. We don't need to check the others.
break
}
}
override val feat: FeatureEnum override val feat: FeatureEnum
get() = FeatureEnum.PLANNINGROLES get() = FeatureEnum.PLANNINGROLES
@ -167,44 +171,40 @@ object AvailabilityManager : IFeature {
override suspend fun enable( override suspend fun enable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder { ): EmbedBuilder {
var alreadyExists = false var alreadyExists = PlanningNotifierRolesRepository.existsInChannel(cID)
// Check if the channel and guild already exist in the db // Check if the channel and guild already exist in the db
transaction {
alreadyExists = PlanningNotifierRoles.select {
(PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID)
}.count() > 0
}
if (!alreadyExists) { if (!alreadyExists) {
// Create the roles in Discord // Create the roles in Discord
val hasTimeRole = Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)).createRole { val hasTimeRole = Bot.bot.kordRef.getGuild(Snowflake(gID)).createRole {
this.name = "available [${ch.data.name.value}]" this.name = "available [${ch.data.name.value}]"
this.mentionable = true this.mentionable = true
} }
val htr = hasTimeRole.id.toString() val htr = hasTimeRole.id.value.toLong()
val wantsNotifsRole = Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)).createRole { val wantsNotifsRole = Bot.bot.kordRef.getGuild(Snowflake(gID)).createRole {
this.name = "notifications [${ch.data.name.value}]" this.name = "notifications [${ch.data.name.value}]"
this.mentionable = true this.mentionable = true
} }
val wnr = wantsNotifsRole.id.toString() val wnr = wantsNotifsRole.id.value.toLong()
// Save the role ids to db // Save the role ids to db
transaction { PlanningNotifierRolesRepository.write(
PlanningNotifierRoles.insert { PlanningNotifierRolesData(
it[PlanningNotifierRoles.serverid] = gID id = -1,
it[PlanningNotifierRoles.channelid] = cID serverID = gID,
it[PlanningNotifierRoles.hastimeroleid] = htr channelID = cID,
it[PlanningNotifierRoles.wantstobenotifiedid] = wnr hasTimeRoleID = htr,
} get PlanningNotifierRoles.id wantsToBeNotifiedID = wnr
} )
)
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0x52E01A), EmbedColor.SUCCESS,
"200: Success", "200: Success",
"The feature was enabled in channel ${args.channel.data.name.value} with roles ${hasTimeRole.mention} & ${wantsNotifsRole.mention}.", "The feature was enabled in channel ${args.channel.data.name.value} with roles ${hasTimeRole.mention} & ${wantsNotifsRole.mention}.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -213,7 +213,7 @@ object AvailabilityManager : IFeature {
// They exist, do not add them // They exist, do not add them
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"403: Forbidden", "403: Forbidden",
"The feature is already enabled in this channel.", "The feature is already enabled in this channel.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -222,43 +222,24 @@ object AvailabilityManager : IFeature {
override suspend fun disable( override suspend fun disable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder { ): EmbedBuilder {
// Check if entry exists in db // Check if entry exists in db
var alreadyExists = false if (PlanningNotifierRolesRepository.existsInChannelFromSever(cID, gID)) {
transaction { val entry = PlanningNotifierRolesRepository.getForChannelInServer(cID, gID)!!
alreadyExists = PlanningNotifierRoles.select {
(PlanningNotifierRoles.serverid eq gID) and (PlanningNotifierRoles.channelid eq cID)
}.count() > 0
}
if (alreadyExists) {
var matchingEntries: List<ResultRow> = mutableListOf()
transaction {
matchingEntries = PlanningNotifierRoles.select {
(PlanningNotifierRoles.serverid eq gID) and
(PlanningNotifierRoles.channelid eq cID)
}.toList()
}
// delete all entries for this guild and channel combo // delete all entries for this guild and channel combo
for (e in matchingEntries) { Bot.bot.kordRef.getGuild(Snowflake(gID))
Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)) .getRoleOrNull(Snowflake(entry.hasTimeRoleID))?.delete()
.getRoleOrNull(Snowflake(e[PlanningNotifierRoles.hastimeroleid]))?.delete() Bot.bot.kordRef.getGuild(Snowflake(gID))
Bot.bot.kordRef.getGuildOrThrow(Snowflake(gID)) .getRoleOrNull(Snowflake(entry.wantsToBeNotifiedID))?.delete()
.getRoleOrNull(Snowflake(e[PlanningNotifierRoles.wantstobenotifiedid]))
?.delete()
}
// delete all found entries // delete all found entries
transaction { PlanningNotifierRolesRepository.delete(entry.id)
matchingEntries.forEach { entry ->
PlanningNotifierRoles.deleteWhere { id eq entry[id] }
}
}
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0x52E019), EmbedColor.SUCCESS,
"200: Success", "200: Success",
"The feature was disabled.", "The feature was disabled.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -266,7 +247,7 @@ object AvailabilityManager : IFeature {
} }
// not in db, do nothing // not in db, do nothing
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"403: Forbidden", "403: Forbidden",
"The feature is already disabled in this channel.", "The feature is already disabled in this channel.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator

View file

@ -20,47 +20,23 @@ package net.moonleay.lilJudd.features
import dev.kord.common.entity.Snowflake import dev.kord.common.entity.Snowflake
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData import net.moonleay.lilJudd.data.database.entry.MatchPlanningDataData
import net.moonleay.lilJudd.data.tables.MatchPlanningData import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.jobs.MatchJob import net.moonleay.lilJudd.jobs.MatchJob
import net.moonleay.lilJudd.jobs.component.JobManager import net.moonleay.lilJudd.jobs.component.JobManager
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
object MatchManager { object MatchManager {
suspend fun update() { suspend fun update() {
Logger.out("Updating match roles...") Logger.out("Updating match roles...")
val dataList = mutableListOf<MatchPlanningDataData>() val dataList = MatchPlanningDataRepository.getAll()
transaction {
MatchPlanningData.selectAll().forEach {
dataList.add(
MatchPlanningDataData(
it[MatchPlanningData.id].value,
it[MatchPlanningData.serverid],
it[MatchPlanningData.channelid],
it[MatchPlanningData.matchtype],
it[MatchPlanningData.registererid],
it[MatchPlanningData.roleid],
it[MatchPlanningData.opponentName],
it[MatchPlanningData.messageid],
it[MatchPlanningData.timestamp],
it[MatchPlanningData.jobstr]
)
)
}
}
for (data in dataList) { for (data in dataList) {
Logger.out("Checking match role ${data.id}...") Logger.out("Checking match role ${data.id}...")
if (data.timestamp.toLong() < System.currentTimeMillis()) { if (data.timestamp < System.currentTimeMillis()) {
Logger.out("Match role ${data.id} is expired, removing...") Logger.out("Match role ${data.id} is expired, removing...")
this.removeRoleFromGuild(data.serverid, data.roleid) this.removeRoleFromGuild(data.serverID, data.roleID)
transaction { MatchPlanningDataRepository.delete(data.id)
MatchPlanningData.deleteWhere { MatchPlanningData.messageid eq data.messageid }
}
continue continue
} }
this.registerJob(data) this.registerJob(data)
@ -71,17 +47,17 @@ object MatchManager {
private fun registerJob(data: MatchPlanningDataData) { private fun registerJob(data: MatchPlanningDataData) {
JobManager.addJob( JobManager.addJob(
MatchJob( MatchJob(
data.jobstr, data.jobString,
data.id, data.id,
"fromdb-${data.matchtype}_Vs_${data.opponentname}_[${data.id}]-${data.serverid}_${data.channelid}" "fromdb-${data.matchType}_Vs_${data.opponentName}_[${data.id}]-${data.serverID}_${data.channelID}"
) )
) )
Logger.out("Registered job for match ${data.id}...") Logger.out("Registered job for match ${data.id}...")
} }
private suspend fun removeRoleFromGuild(gid: String, rid: String): Boolean { private suspend fun removeRoleFromGuild(gid: Long, rid: Long): Boolean {
val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(gid.toLong())) ?: return false val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(gid)) ?: return false
val role = guild.getRoleOrNull(Snowflake(rid.toLong())) ?: return false val role = guild.getRoleOrNull(Snowflake(rid)) ?: return false
role.delete() role.delete()
return true return true
} }

View file

@ -20,7 +20,6 @@ package net.moonleay.lilJudd.features
import dev.inmo.krontab.buildSchedule import dev.inmo.krontab.buildSchedule
import dev.inmo.krontab.doInfinity import dev.inmo.krontab.doInfinity
import dev.kord.common.Color
import dev.kord.common.entity.Snowflake import dev.kord.common.entity.Snowflake
import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.UserBehavior
import dev.kord.core.behavior.channel.createMessage import dev.kord.core.behavior.channel.createMessage
@ -30,20 +29,18 @@ import dev.kord.rest.builder.message.EmbedBuilder
import dev.kord.rest.builder.message.create.actionRow import dev.kord.rest.builder.message.create.actionRow
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.data.entry.PlanningNotifierRolesData import net.moonleay.lilJudd.data.database.entry.TimePlanningChannelsData
import net.moonleay.lilJudd.data.tables.PlanningNotifierRoles import net.moonleay.lilJudd.data.database.entry.TimePlanningMessagesData
import net.moonleay.lilJudd.data.tables.TimePlanningChannels import net.moonleay.lilJudd.data.database.repository.PlanningNotifierRolesRepository
import net.moonleay.lilJudd.data.tables.TimePlanningMessages import net.moonleay.lilJudd.data.database.repository.TimePlanningChannelsRepository
import net.moonleay.lilJudd.data.database.repository.TimePlanningMessagesRepository
import net.moonleay.lilJudd.extensions.FeatureManageExtension import net.moonleay.lilJudd.extensions.FeatureManageExtension
import net.moonleay.lilJudd.features.component.FeatureEnum import net.moonleay.lilJudd.features.component.FeatureEnum
import net.moonleay.lilJudd.features.component.IFeature import net.moonleay.lilJudd.features.component.IFeature
import net.moonleay.lilJudd.util.EmbedColor
import net.moonleay.lilJudd.util.EmbedUtil import net.moonleay.lilJudd.util.EmbedUtil
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import net.moonleay.lilJudd.util.MessageUtil import net.moonleay.lilJudd.util.MessageUtil
import net.moonleay.lilJudd.util.TimeUtil
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.transactions.transaction
import java.time.ZoneId import java.time.ZoneId
import java.time.ZonedDateTime import java.time.ZonedDateTime
@ -64,43 +61,26 @@ object TimeManager : IFeature {
private suspend fun runThread() { private suspend fun runThread() {
Logger.out("Starting to notify...") Logger.out("Starting to notify...")
// ChannelID -> Data
val targetedChannels = TimePlanningChannelsRepository.getAll().associateBy { it.channelID }
val targetedRoles = PlanningNotifierRolesRepository.getAll().associateBy { it.channelID }
// ChannelID, ServerID lateinit var msgStr: String
val channelList = mutableMapOf<Snowflake, Snowflake>()
// ChannelID, Data
val roleMap = mutableMapOf<Snowflake, PlanningNotifierRolesData>()
var msgStr = "" Logger.out("${targetedChannels.count()} Channels to notify with ${targetedRoles.count()} Roles to ping!")
for (ch2 in targetedChannels.keys) {
transaction { val ch = Snowflake(ch2)
for (tp in TimePlanningChannels.selectAll()) {
channelList[Snowflake(tp[TimePlanningChannels.channelid])] =
Snowflake(tp[TimePlanningChannels.serverid])
Logger.out("Have to notify channel with ID ${tp[TimePlanningChannels.channelid]}.")
}
for (pnr in PlanningNotifierRoles.selectAll()) {
roleMap[Snowflake(pnr[PlanningNotifierRoles.channelid])] = PlanningNotifierRolesData(
pnr[PlanningNotifierRoles.serverid],
pnr[PlanningNotifierRoles.channelid],
pnr[PlanningNotifierRoles.hastimeroleid],
pnr[PlanningNotifierRoles.wantstobenotifiedid]
)
Logger.out("Have to ping roles: ${pnr[PlanningNotifierRoles.wantstobenotifiedid]}}")
}
}
Logger.out("${channelList.count()} Channels to notify with ${roleMap.count()} Roles to ping!")
for (ch in channelList.keys) {
if (Bot.bot.kordRef.getChannel(ch) == null) if (Bot.bot.kordRef.getChannel(ch) == null)
continue // TODO: Check if the channel is valid in another shard continue // TODO: Check if the channel is valid in another shard
val c = Bot.bot.kordRef.getChannelOf<MessageChannel>(ch)!! val c = Bot.bot.kordRef.getChannelOf<MessageChannel>(ch)!!
if (roleMap != null && roleMap.keys.contains(ch) && roleMap[ch] != null) { msgStr = ""
if (targetedRoles != null && targetedRoles.keys.contains(ch2) && targetedRoles[ch2] != null) {
c.createMessage { c.createMessage {
this.content = this.content =
"The weekly planning starts now <@&${Snowflake(roleMap[ch]?.wantstobenotifid!!)}>" "The weekly planning starts now <@&${Snowflake(targetedRoles[ch2]?.wantsToBeNotifiedID!!)}>"
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0X4C4645), EmbedColor.INFO,
"Time Planning Feature", "Time Planning Feature",
"Do you have time on the following Days?", "Do you have time on the following Days?",
"Automated Message" "Automated Message"
@ -111,7 +91,7 @@ object TimeManager : IFeature {
c.createMessage { c.createMessage {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbed( MessageUtil.getEmbed(
Color(0X4C4645), EmbedColor.INFO,
"Time Planning Feature", "Time Planning Feature",
"Do you have time on the following Days?", "Do you have time on the following Days?",
"Automated Message" "Automated Message"
@ -125,7 +105,7 @@ object TimeManager : IFeature {
val msg = c.createMessage { val msg = c.createMessage {
this.embeds.add( this.embeds.add(
MessageUtil.getEmbedWithTable( MessageUtil.getEmbedWithTable(
Color(0X4C4645), EmbedColor.INFO,
"", "",
"${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday", "${then.dayOfWeek.name}, ${then.dayOfMonth}.${then.monthValue}.${then.year} /${it + 1}. weekday",
mapOf( mapOf(
@ -148,14 +128,15 @@ object TimeManager : IFeature {
} }
// Save the message ids // Save the message ids
transaction { TimePlanningMessagesRepository.write(
TimePlanningMessages.insert { TimePlanningMessagesData(
it[TimePlanningMessages.serverid] = c.data.guildId.value.toString() id = -1,
it[TimePlanningMessages.channelid] = c.id.value.toString() serverID = c.data.guildId.value?.value!!.toLong(),
it[TimePlanningMessages.weekstamp] = TimeUtil.getWeekStamp().toOffsetDateTime().toString() channelID = c.data.id.value.toLong(),
it[TimePlanningMessages.messageids] = msgStr weekstamp = then.minusDays(7).toEpochSecond(),
} get TimePlanningMessages.id messageIDs = msgStr
} )
)
Logger.out("Finished with ${c.data.guildId.value}") Logger.out("Finished with ${c.data.guildId.value}")
} }
Logger.out("Done! Until next Monday! <3 ") Logger.out("Done! Until next Monday! <3 ")
@ -163,34 +144,22 @@ object TimeManager : IFeature {
override suspend fun enable( override suspend fun enable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder { ): EmbedBuilder {
var alreadyExists = false if (!TimePlanningChannelsRepository.exists(cID, gID)) {
transaction { TimePlanningChannelsRepository.write(TimePlanningChannelsData(id = -1, serverID = gID, channelID = cID))
alreadyExists = TimePlanningChannels.select {
(TimePlanningChannels.serverid eq gID) and
(TimePlanningChannels.channelid eq cID)
}.count() > 0
}
if (!alreadyExists) {
transaction {
TimePlanningChannels.insert {
it[TimePlanningChannels.serverid] = gID
it[TimePlanningChannels.channelid] = cID
} get TimePlanningChannels.id
}
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0x52E01A), EmbedColor.SUCCESS,
"200: Success", "200: Success",
"The feature was enabled in channel ${args.channel.data.name.value}", "The feature was enabled in channel ${args.channel.data.name.value}",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
) )
} }
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"403: Forbidden", "403: Forbidden",
"The feature is already enabled in this channel.", "The feature is already enabled in this channel.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -199,33 +168,17 @@ object TimeManager : IFeature {
override suspend fun disable( override suspend fun disable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder { ): EmbedBuilder {
// Check if entry exists in db // Check if entry exists in db
var alreadyExists = false if (TimePlanningChannelsRepository.exists(cID, gID)) {
transaction {
alreadyExists = TimePlanningChannels.select {
(TimePlanningChannels.serverid eq gID) and
(TimePlanningChannels.channelid eq cID)
}.count() > 0
}
if (alreadyExists) {
// delete all entrys for this channel // delete all entrys for this channel
transaction { TimePlanningChannelsRepository.deleteFromChannelInServer(cID, gID)
val matchingEntries = TimePlanningChannels.select {
(TimePlanningChannels.serverid eq gID) and
(TimePlanningChannels.channelid eq cID)
}.toList()
matchingEntries.forEach { entry ->
TimePlanningChannels.deleteWhere { id eq entry[id] }
}
}
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0x52E019), EmbedColor.SUCCESS,
"200: Success", "200: Success",
"The feature was disabled.", "The feature was disabled.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator
@ -233,7 +186,7 @@ object TimeManager : IFeature {
} }
// Do nothing; not in db // Do nothing; not in db
return MessageUtil.getEmbed( return MessageUtil.getEmbed(
Color(0xE0311A), EmbedColor.ERROR,
"403: Forbidden", "403: Forbidden",
"The feature is already disabled in this channel.", "The feature is already disabled in this channel.",
u.asUser().username + "#" + u.asUser().discriminator u.asUser().username + "#" + u.asUser().discriminator

View file

@ -29,16 +29,16 @@ interface IFeature {
suspend fun enable( suspend fun enable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder ): EmbedBuilder
suspend fun disable( suspend fun disable(
u: UserBehavior, u: UserBehavior,
gID: String, gID: Long,
cID: String, cID: Long,
ch: Channel, ch: Channel,
args: FeatureManageExtension.FeatureManagerArgs args: FeatureManageExtension.FeatureManagerArgs
): EmbedBuilder ): EmbedBuilder

View file

@ -22,16 +22,11 @@ import dev.inmo.krontab.KronScheduler
import dev.kord.common.entity.Snowflake import dev.kord.common.entity.Snowflake
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import net.moonleay.lilJudd.Bot import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.data.entry.MatchPlanningDataData import net.moonleay.lilJudd.data.database.repository.MatchPlanningDataRepository
import net.moonleay.lilJudd.data.tables.MatchPlanningData
import net.moonleay.lilJudd.jobs.component.CronjobType import net.moonleay.lilJudd.jobs.component.CronjobType
import net.moonleay.lilJudd.jobs.component.ICronjob import net.moonleay.lilJudd.jobs.component.ICronjob
import net.moonleay.lilJudd.jobs.component.JobManager import net.moonleay.lilJudd.jobs.component.JobManager
import net.moonleay.lilJudd.util.Logger import net.moonleay.lilJudd.util.Logger
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
class MatchJob( class MatchJob(
override val jobIncoming: String, override val jobIncoming: String,
@ -48,41 +43,19 @@ class MatchJob(
* */ * */
override suspend fun jobFunction() { override suspend fun jobFunction() {
Logger.out("Running MatchJob \"${this.jobName}\"") Logger.out("Running MatchJob \"${this.jobName}\"")
lateinit var mpdd: MatchPlanningDataData val mpdd = MatchPlanningDataRepository.get(tableId)!!
transaction { val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(mpdd.serverID))
for (pnr in MatchPlanningData.select {
MatchPlanningData.id eq (tableId)
}) {
mpdd = MatchPlanningDataData(
pnr[MatchPlanningData.id].value,
pnr[MatchPlanningData.serverid],
pnr[MatchPlanningData.channelid],
pnr[MatchPlanningData.matchtype],
pnr[MatchPlanningData.registererid],
pnr[MatchPlanningData.roleid],
pnr[MatchPlanningData.opponentName],
pnr[MatchPlanningData.messageid],
pnr[MatchPlanningData.timestamp],
pnr[MatchPlanningData.jobstr]
)
}
}
val guild = Bot.bot.kordRef.getGuildOrNull(Snowflake(mpdd.serverid))
if (guild == null) { if (guild == null) {
Logger.out("Guild not found.") Logger.out("Guild not found.")
return return
} }
val r = guild.getRoleOrNull(Snowflake(mpdd.roleid)) val r = guild.getRoleOrNull(Snowflake(mpdd.roleID))
if (r == null) { if (r == null) {
Logger.out("Role not found.") Logger.out("Role not found.")
return return
} }
r.delete() r.delete()
transaction { MatchPlanningDataRepository.delete(tableId)
MatchPlanningData.deleteWhere {
MatchPlanningData.id eq (tableId)
}
}
Logger.out("MatchJob \"${this.jobName}\" finished.") Logger.out("MatchJob \"${this.jobName}\" finished.")
Logger.out("Killing job \"${this.jobName}\"..") Logger.out("Killing job \"${this.jobName}\"..")
JobManager.killJob(this) JobManager.killJob(this)

View file

@ -0,0 +1,50 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.jobs
import dev.inmo.krontab.KronScheduler
import kotlinx.coroutines.Job
import net.moonleay.lilJudd.data.api.Splatoon3ApiCache
import net.moonleay.lilJudd.data.api.type.ApiDataType
import net.moonleay.lilJudd.data.api.type.ApiRequestType
import net.moonleay.lilJudd.jobs.component.CronjobType
import net.moonleay.lilJudd.jobs.component.ICronjob
import net.moonleay.lilJudd.util.Logger
object Splatoon3ApiFestivalAndCoopUpdateScheduler : ICronjob {
override val jobName: String
get() = "Splatoon3ApiFestivalAndCoopUpdateScheduler"
override val jobIncoming: String
get() = "0 0 0 /1 * * 0o *" // once a day
override val jobType: CronjobType
get() = CronjobType.INFINITE
override val continueJob: Boolean
get() = true
override lateinit var cronjobJob: Job
override lateinit var scheduler: KronScheduler
override suspend fun jobFunction() {
Logger.out("Running Splatoon3ApiFestivalUpdateScheduler.")
Splatoon3ApiCache.updateData(ApiDataType.SPLATFESTS, ApiRequestType.AUTOMATIC_CACHE_UPDATE)
Logger.out("Splatoon3ApiFestivalUpdateScheduler finished.")
Logger.out("Running Splatoon3ApiCoopUpdateScheduler.")
Splatoon3ApiCache.updateData(ApiDataType.COOP, ApiRequestType.AUTOMATIC_CACHE_UPDATE)
Logger.out("Splatoon3ApiCoopUpdateScheduler finished.")
}
}

View file

@ -0,0 +1,47 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.jobs
import dev.inmo.krontab.KronScheduler
import kotlinx.coroutines.Job
import net.moonleay.lilJudd.data.api.Splatoon3ApiCache
import net.moonleay.lilJudd.data.api.type.ApiDataType
import net.moonleay.lilJudd.data.api.type.ApiRequestType
import net.moonleay.lilJudd.jobs.component.CronjobType
import net.moonleay.lilJudd.jobs.component.ICronjob
import net.moonleay.lilJudd.util.Logger
object Splatoon3ApiScheduleUpdateScheduler : ICronjob {
override val jobName: String
get() = "Splatoon3ApiScheduleUpdateScheduler"
override val jobIncoming: String
get() = "0 0 /1 * * * 0o *" //Every hour
override val jobType: CronjobType
get() = CronjobType.INFINITE
override val continueJob: Boolean
get() = true
override lateinit var cronjobJob: Job
override lateinit var scheduler: KronScheduler
override suspend fun jobFunction() {
Logger.out("Running Splatoon3ApiScheduleUpdateScheduler.")
Splatoon3ApiCache.updateData(ApiDataType.SCHEDULES, ApiRequestType.AUTOMATIC_CACHE_UPDATE)
Logger.out("Splatoon3ApiScheduleUpdateScheduler finished.")
}
}

View file

@ -0,0 +1,47 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.jobs
import dev.inmo.krontab.KronScheduler
import kotlinx.coroutines.Job
import net.moonleay.lilJudd.data.api.Splatoon3ApiCache
import net.moonleay.lilJudd.data.api.type.ApiDataType
import net.moonleay.lilJudd.data.api.type.ApiRequestType
import net.moonleay.lilJudd.jobs.component.CronjobType
import net.moonleay.lilJudd.jobs.component.ICronjob
import net.moonleay.lilJudd.util.Logger
object Splatoon3ApiSplatnetGearUpdateScheduler : ICronjob {
override val jobName: String
get() = "Splatoon3ApiSplatnetGearUpdateScheduler"
override val jobIncoming: String
get() = "0 0 /6 * * * 0o *" //Every 6 hours
override val jobType: CronjobType
get() = CronjobType.INFINITE
override val continueJob: Boolean
get() = true
override lateinit var cronjobJob: Job
override lateinit var scheduler: KronScheduler
override suspend fun jobFunction() {
Logger.out("Running Splatoon3ApiSplatnetGearUpdateScheduler.")
Splatoon3ApiCache.updateData(ApiDataType.SPLATNETGEAR, ApiRequestType.AUTOMATIC_CACHE_UPDATE)
Logger.out("Splatoon3ApiSplatnetGearUpdateScheduler finished.")
}
}

View file

@ -0,0 +1,67 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.jobs
import dev.inmo.krontab.KronScheduler
import dev.kord.common.entity.PresenceStatus
import kotlinx.coroutines.Job
import net.moonleay.lilJudd.Bot
import net.moonleay.lilJudd.data.api.Splatoon3Api
import net.moonleay.lilJudd.jobs.component.CronjobType
import net.moonleay.lilJudd.jobs.component.ICronjob
object StatusUpdater : ICronjob {
override val jobName: String
get() = "StatusUpdater"
override val jobIncoming: String
get() = "/5 * * * * * 0o *" //Every 5 seconds
override val jobType: CronjobType
get() = CronjobType.INFINITE
override val continueJob: Boolean
get() = true
override lateinit var cronjobJob: Job
override lateinit var scheduler: KronScheduler
private var statusList = listOf<String>()
private var index = 0
override suspend fun jobFunction() {
refreshStatusList(System.currentTimeMillis())
Bot.bot.kordRef.editPresence {
this.status = PresenceStatus.DoNotDisturb
this.playing(statusList[index])
}
++index
if (index >= statusList.size) {
index = 0
}
}
fun refreshStatusList(timestamp: Long) {
statusList = listOf(
Splatoon3Api.getRegularMapsFormatted(timestamp),
Splatoon3Api.getSeriesModeFormatted(timestamp),
Splatoon3Api.getSeriesMapsFormatted(timestamp),
Splatoon3Api.getOpenModeFormatted(timestamp),
Splatoon3Api.getOpenMapFormatted(timestamp),
Splatoon3Api.getXModeFormatted(timestamp),
Splatoon3Api.getXMapFormatted(timestamp),
)
}
}

View file

@ -16,11 +16,13 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.lilJudd.data.tables package net.moonleay.lilJudd.util
import org.jetbrains.exposed.dao.id.IntIdTable import dev.kord.common.Color
object TimePlanningChannels : IntIdTable() { enum class EmbedColor(val color: Color) {
var serverid = varchar("serverid", 50) ERROR(Color(0xE0311A)),
val channelid = varchar("channelid", 50) WARNING(Color(0xFFA500)),
SUCCESS(Color(0x52E01A)),
INFO(Color(0x4C4645)),
} }

View file

@ -41,17 +41,26 @@ object EmbedUtil {
fun getMatchButtons(): ActionRowBuilder { fun getMatchButtons(): ActionRowBuilder {
val ar = ActionRowBuilder() val ar = ActionRowBuilder()
ar.interactionButton(ButtonStyle.Success, "public.edit.btn.matchmanagement.accept") { ar.interactionButton(ButtonStyle.Success, "public.edit.btn.matchmanagement.accept") {
this.label = "Sign me up!" this.label = "I'm in!"
} }
ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.cancel") { ar.interactionButton(ButtonStyle.Danger, "public.edit.btn.matchmanagement.decline") {
this.label = "Cancel" this.label = "I'm out!"
} }
/*
ar.interactionButton(ButtonStyle.Secondary, "public.edit.btn.matchmanagement.cancel") {
this.label = "Cancel this match..."
} */
return ar return ar
} }
fun replaceXWithYinValuesAtTable(x: String, y: String, e: Embed, table: Int): EmbedBuilder { fun replaceXWithYinValuesAtTable(x: String, y: String, e: Embed, table: Int): EmbedBuilder {
val ebb = MessageUtil.getAClonedEmbedd(e) return replaceXWithYinValuesAtTable(x, y, MessageUtil.getAClonedEmbed(e), table)
for ((i, f) in e.fields.withIndex()) { }
fun replaceXWithYinValuesAtTable(x: String, y: String, ebb: EmbedBuilder, table: Int): EmbedBuilder {
val ebbb = MessageUtil.getAClonedEmbed(ebb)
ebbb.fields = mutableListOf()
for ((i, f) in ebb.fields.withIndex()) {
val fb = EmbedBuilder.Field() val fb = EmbedBuilder.Field()
fb.name = f.name fb.name = f.name
if (i == table - 1) { if (i == table - 1) {
@ -66,9 +75,9 @@ object EmbedUtil {
} else } else
fb.value = f.value fb.value = f.value
fb.inline = true fb.inline = true
ebb.fields.add(fb) ebbb.fields.add(fb)
} }
return ebb return ebbb
} }
fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List<String> { fun getAllUsersInTheFirstXTables(amountOfTables: Int, e: Embed): List<String> {
@ -87,8 +96,13 @@ object EmbedUtil {
} }
fun addXToValuesAtTable(x: String, e: Embed, table: Int): EmbedBuilder { fun addXToValuesAtTable(x: String, e: Embed, table: Int): EmbedBuilder {
val ebb = MessageUtil.getAClonedEmbedd(e) return addXToValuesAtTable(x, MessageUtil.getAClonedEmbed(e), table)
for ((i, f) in e.fields.withIndex()) { }
fun addXToValuesAtTable(x: String, ebb: EmbedBuilder, table: Int): EmbedBuilder {
val ebbb = MessageUtil.getAClonedEmbed(ebb)
ebbb.fields = mutableListOf()
ebb.fields.forEachIndexed { i, f ->
val fb = EmbedBuilder.Field() val fb = EmbedBuilder.Field()
fb.name = f.name fb.name = f.name
if (i == table - 1) if (i == table - 1)
@ -105,9 +119,9 @@ object EmbedUtil {
} }
fb.inline = true fb.inline = true
ebb.fields.add(fb) ebbb.fields.add(fb)
} }
return ebb return ebbb
} }
} }

View file

@ -22,7 +22,6 @@ import com.kotlindiscord.kord.extensions.commands.Arguments
import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext import com.kotlindiscord.kord.extensions.commands.application.slash.PublicSlashCommandContext
import com.kotlindiscord.kord.extensions.components.forms.ModalForm import com.kotlindiscord.kord.extensions.components.forms.ModalForm
import com.kotlindiscord.kord.extensions.types.respond import com.kotlindiscord.kord.extensions.types.respond
import dev.kord.common.Color
import dev.kord.core.entity.Embed import dev.kord.core.entity.Embed
import dev.kord.rest.builder.message.EmbedBuilder import dev.kord.rest.builder.message.EmbedBuilder
import java.time.LocalDateTime import java.time.LocalDateTime
@ -34,7 +33,7 @@ object MessageUtil {
///Send an embedded message as a reply ///Send an embedded message as a reply
suspend fun sendEmbedForPublicSlashCommand( suspend fun sendEmbedForPublicSlashCommand(
ctx: PublicSlashCommandContext<Arguments, ModalForm>, ctx: PublicSlashCommandContext<Arguments, ModalForm>,
color: Color, color: EmbedColor,
title: String, title: String,
description: String description: String
) { ) {
@ -53,7 +52,7 @@ object MessageUtil {
///Send an embedded message with an image as a reply ///Send an embedded message with an image as a reply
suspend fun sendEmbedForPublicSlashCommandWithImage( suspend fun sendEmbedForPublicSlashCommandWithImage(
ctx: PublicSlashCommandContext<Arguments, ModalForm>, ctx: PublicSlashCommandContext<Arguments, ModalForm>,
color: Color, color: EmbedColor,
title: String, title: String,
description: String, description: String,
thumbnailUrl: String thumbnailUrl: String
@ -71,17 +70,39 @@ object MessageUtil {
} }
} }
///Get a cloned embedded message, missing only the fields ///Get a cloned embedded message
fun getAClonedEmbedd(e: Embed): EmbedBuilder { fun getAClonedEmbed(e: Embed): EmbedBuilder {
val ebb = EmbedBuilder() val ebb = EmbedBuilder()
ebb.color = e.color ebb.color = e.color
ebb.title = e.title ebb.title = e.title
e.fields.forEach {
val fb = EmbedBuilder.Field()
fb.name = it.name
fb.value = it.value
fb.inline = it.inline
ebb.fields.add(fb)
}
ebb.description = e.description
return ebb
}
fun getAClonedEmbed(e: EmbedBuilder): EmbedBuilder {
val ebb = EmbedBuilder()
ebb.color = e.color
ebb.title = e.title
e.fields.forEach {
val fb = EmbedBuilder.Field()
fb.name = it.name
fb.value = it.value
fb.inline = it.inline
ebb.fields.add(fb)
}
ebb.description = e.description ebb.description = e.description
return ebb return ebb
} }
fun getEmbedWithTableWithFooter( fun getEmbedWithTableWithFooter(
color: Color, color: EmbedColor,
title: String, title: String,
description: String, description: String,
values: Map<String, List<String>>?, values: Map<String, List<String>>?,
@ -95,7 +116,7 @@ object MessageUtil {
///Get an embedded msg with image, title and description ///Get an embedded msg with image, title and description
fun getEmbedWithTable( fun getEmbedWithTable(
color: Color, color: EmbedColor,
title: String, title: String,
description: String, description: String,
values: Map<String, List<String>>? values: Map<String, List<String>>?
@ -118,20 +139,20 @@ object MessageUtil {
///Get an embedded msg with title and description ///Get an embedded msg with title and description
fun getEmbedSmall( fun getEmbedSmall(
color: Color, color: EmbedColor,
title: String, title: String,
description: String description: String
): EmbedBuilder { ): EmbedBuilder {
val ebb = EmbedBuilder() val ebb = EmbedBuilder()
ebb.title = title ebb.title = title
ebb.description = description ebb.description = description
ebb.color = color ebb.color = color.color
return ebb return ebb
} }
///Get an embedded msg with title, description and a src ///Get an embedded msg with title, description and a src
fun getEmbed( fun getEmbed(
color: Color, color: EmbedColor,
title: String, title: String,
description: String, description: String,
source: String source: String
@ -145,7 +166,7 @@ object MessageUtil {
///Get an embedded msg with image, title, description and a src ///Get an embedded msg with image, title, description and a src
fun getEmbedWithImage( fun getEmbedWithImage(
color: Color, color: EmbedColor,
title: String, title: String,
description: String, description: String,
source: String, source: String,

View file

@ -0,0 +1,45 @@
/*
* lilJudd
* Copyright (C) 2023 moonleay
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package net.moonleay.lilJudd.util
import java.net.URL
import javax.net.ssl.HttpsURLConnection
object NetUtil {
fun GETJsonData(urlIN: String, userAgent: String): String {
val startTime = System.currentTimeMillis()
val url = URL(urlIN)
val connection = url.openConnection() as HttpsURLConnection
connection.requestMethod = "GET"
connection.setRequestProperty("User-Agent", userAgent)
connection.setRequestProperty("Accept", "application/json")
val responseCode = connection.responseCode
val timeDiff = System.currentTimeMillis() - startTime
Logger.out("GET took $timeDiff ms (from: $urlIN, as $userAgent)")
return if (responseCode == HttpsURLConnection.HTTP_OK) {
val inputStream = connection.inputStream
val inputStreamReader = inputStream.reader()
val inputAsString = inputStreamReader.readText()
inputStream.close()
inputAsString
} else {
"Error $responseCode"
}
}
}

View file

@ -29,7 +29,7 @@ import java.util.concurrent.TimeUnit
object TimeUtil { object TimeUtil {
fun getTimeFormatedShortend(time2: Long): String { fun getTimeFormatedShortend(time2: Long, showS: Boolean): String {
var time = time2 var time = time2
val days: Long = TimeUnit.MILLISECONDS val days: Long = TimeUnit.MILLISECONDS
.toDays(time) .toDays(time)
@ -52,7 +52,7 @@ object TimeUtil {
if (minutes >= 1) { if (minutes >= 1) {
s += minutes.toString() + "m " s += minutes.toString() + "m "
} }
if (seconds >= 1 && hours < 1) { if (seconds >= 1 && hours < 1 && showS) {
s += seconds.toString() + "s" s += seconds.toString() + "s"
} }
if (s.isEmpty() || s.isBlank()) { if (s.isEmpty() || s.isBlank()) {
@ -158,4 +158,17 @@ object TimeUtil {
val zdt_ = zdt.minusHours(1) val zdt_ = zdt.minusHours(1)
return "0 ${zdt_.minute} ${zdt_.hour} ${zdt_.dayOfMonth - 1} ${zdt_.month.value - 1} ${zdt_.year}"// 0o *w" return "0 ${zdt_.minute} ${zdt_.hour} ${zdt_.dayOfMonth - 1} ${zdt_.month.value - 1} ${zdt_.year}"// 0o *w"
} }
fun deformatJSONTime(inp: String, zone: String): Long {
// 2023-10-05T08:00:00Z
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'")
val localDateTime = LocalDateTime.parse(inp, formatter)
val zoneId = ZoneId.of(zone) // TODO: Add the possibility to set your timezone
return ZonedDateTime.of(localDateTime, zoneId).toEpochSecond() * 1000
}
fun getTimeDifferenceFormatted(start: Long, end: Long): String {
val diff = end - start
return getTimeFormatedShortend(diff, false)
}
} }

View file

@ -16,7 +16,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package net.moonleay.botendo.build package net.moonleay.lilJudd.build
internal object BuildConstants { internal object BuildConstants {
const val version = "${version}" const val version = "${version}"