Compare commits

...

159 Commits

Author SHA1 Message Date
release-bot
45516f2458 [maven-release-plugin] prepare release sissi-1.5.4 2025-04-01 12:07:28 +00:00
Sheldan
9d9c8beb88 [SIS-xxx] upgrading abstracto version 2025-04-01 14:04:17 +02:00
Sheldan
427250e0bc [SIS-xxx] adding ability to select multiple decisions for meetup notify
making meetup notify slash command only
2025-03-31 22:32:04 +02:00
Sheldan
35d20be13b [SIS-xxx] updating privacy policy 2025-02-23 23:18:18 +01:00
Sheldan
693bc2cd2c [SIS-xxx] creating privacy policy 2025-02-23 23:08:24 +01:00
release-bot
c62757590a Commit from GitHub Actions (Publishes a new version of Sissi) 2025-02-23 20:37:20 +00:00
release-bot
1b2d326655 [maven-release-plugin] prepare for next development iteration 2025-02-23 20:32:54 +00:00
release-bot
180c2681e0 [maven-release-plugin] prepare release sissi-1.5.3 2025-02-23 20:32:53 +00:00
Sheldan
80d0552d65 [SIS-xxx] updating abstracto version to 1.6.4 2025-02-23 21:30:03 +01:00
release-bot
f76f8afef5 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-02-15 19:14:59 +00:00
release-bot
8bf9fe6c45 [maven-release-plugin] prepare for next development iteration 2025-02-15 19:10:33 +00:00
release-bot
de8301750a [maven-release-plugin] prepare release sissi-1.5.2 2025-02-15 19:10:32 +00:00
Sheldan
555c60caad [SIS-xxx] updating abstracto version and setting default permissions for commands 2025-02-15 20:07:27 +01:00
release-bot
0481deae4a Commit from GitHub Actions (Publishes a new version of Sissi) 2025-02-04 22:53:36 +00:00
release-bot
edb887f51a [maven-release-plugin] prepare for next development iteration 2025-02-04 22:49:03 +00:00
release-bot
4dc424b87a [maven-release-plugin] prepare release sissi-1.5.1 2025-02-04 22:49:01 +00:00
Sheldan
290e59f8da [SIS-xxx] properly upgrading abstracto version 2025-02-04 23:46:16 +01:00
Sheldan
aca7e3449c [SIS-xxx] updating abstracto version to 1.6.2 and abstracto templates to 1.4.53 2025-02-04 23:45:22 +01:00
release-bot
aa1a7344de [maven-release-plugin] prepare for next development iteration 2025-02-04 21:06:14 +00:00
release-bot
faa85173cc [maven-release-plugin] prepare release sissi-1.5.0 2025-02-04 21:06:10 +00:00
Sheldan
2ee2907c72 [SIS-xxx] version re-set after failed release 2025-02-04 22:01:45 +01:00
release-bot
51d9ec2931 [maven-release-plugin] prepare for next development iteration 2025-02-04 20:37:22 +00:00
release-bot
dc801dc220 [maven-release-plugin] prepare release sissi-1.5.0 2025-02-04 20:37:20 +00:00
Sheldan
71aaa31fa1 [SIS-xxx] reducing size of bot image 2025-02-04 21:34:05 +01:00
Sheldan
80a56f4426 [SIS-xxx] preparing for minor release 2025-02-04 21:31:11 +01:00
Sheldan
9f3d1a0080 [SIS-xxx] updating to abstracto 1.6.0 for user installable commands support and general fixes 2025-02-04 21:29:03 +01:00
release-bot
ecf30513b1 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-01-31 20:08:32 +00:00
release-bot
4f9369ce22 [maven-release-plugin] prepare for next development iteration 2025-01-31 20:04:02 +00:00
release-bot
c0369d6cf3 [maven-release-plugin] prepare release sissi-1.4.76 2025-01-31 20:04:01 +00:00
Sheldan
0bd4082f72 [SIS-xxx] updating login action version 2025-01-31 21:01:00 +01:00
release-bot
cda1b2d61c [maven-release-plugin] prepare for next development iteration 2025-01-31 19:34:55 +00:00
release-bot
e9d2ceb2af [maven-release-plugin] prepare release sissi-1.4.75 2025-01-31 19:34:53 +00:00
Sheldan
3c9e8606fa [SIS-xxx] year bump 2025-01-31 20:32:11 +01:00
release-bot
f726a4ca95 [maven-release-plugin] prepare for next development iteration 2025-01-31 18:22:30 +00:00
release-bot
311eb7d3fa [maven-release-plugin] prepare release sissi-1.4.74 2025-01-31 18:22:28 +00:00
Sheldan
7c47159508 [SIS-xxx] updating abstracto version for nicer emote stats output 2025-01-31 19:19:46 +01:00
release-bot
5edba2c037 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-01-27 20:32:40 +00:00
release-bot
e6b35af78a [maven-release-plugin] prepare for next development iteration 2025-01-27 20:28:11 +00:00
release-bot
f11f74507d [maven-release-plugin] prepare release sissi-1.4.73 2025-01-27 20:28:09 +00:00
Sheldan
9bdc023e99 [SIS-xxx] updating abstracto version for emote stats output always showing all emotes 2025-01-27 21:25:23 +01:00
release-bot
f343a5a280 Commit from GitHub Actions (Publishes a new version of Sissi) 2025-01-27 00:56:04 +00:00
release-bot
2312892f0a [maven-release-plugin] prepare for next development iteration 2025-01-27 00:50:42 +00:00
release-bot
d69c4b5b79 [maven-release-plugin] prepare release sissi-1.4.72 2025-01-27 00:50:41 +00:00
Sheldan
2ffa0feb3f [SIS-xxx] updating abstracto version for reaction emote tracking 2025-01-27 01:47:06 +01:00
release-bot
5a3b7216fc Commit from GitHub Actions (Publishes a new version of Sissi) 2025-01-15 21:38:25 +00:00
release-bot
5676d7291c [maven-release-plugin] prepare for next development iteration 2025-01-15 21:34:09 +00:00
release-bot
f6452077f0 [maven-release-plugin] prepare release sissi-1.4.71 2025-01-15 21:34:08 +00:00
Sheldan
2602d073d3 [SIS-xxx] updating abstracto version to contain the currency conversion
adding configuration necessary for currency conversion
2025-01-15 22:31:12 +01:00
Sheldan
d85ebedfcc [SIS-xxx] updating appeal invite link 2025-01-03 08:50:30 +01:00
Sheldan
841bfc19ac [SIS-xxx] allowing an orf news post to have no title 2024-12-27 23:12:00 +01:00
release-bot
d02f2d3088 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-12-26 00:13:20 +00:00
release-bot
c164969afb [maven-release-plugin] prepare for next development iteration 2024-12-26 00:08:18 +00:00
release-bot
af37454918 [maven-release-plugin] prepare release sissi-1.4.70 2024-12-26 00:08:16 +00:00
Sheldan
5e915713e2 [SIS-xxx] upgrading abstracto version to 1.5.56 2024-12-26 01:04:24 +01:00
release-bot
1f7ffc16e2 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-12-25 19:46:27 +00:00
release-bot
3734d271f0 [maven-release-plugin] prepare for next development iteration 2024-12-25 19:42:25 +00:00
release-bot
f219c4ab54 [maven-release-plugin] prepare release sissi-1.4.69 2024-12-25 19:42:24 +00:00
Sheldan
2c984cd183 [SIS-xxx] properly upgrading abstracto version 2024-12-25 20:39:37 +01:00
release-bot
d06a1db108 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-12-25 19:38:01 +00:00
release-bot
6125f39670 [maven-release-plugin] prepare for next development iteration 2024-12-25 19:33:46 +00:00
release-bot
c020a3a0f2 [maven-release-plugin] prepare release sissi-1.4.68 2024-12-25 19:33:45 +00:00
Sheldan
91a0265e6e [SIS-xxx] updating abstracto version to contain the giveaway key features
adding template for custom giveaway winner notification
2024-12-25 20:30:34 +01:00
release-bot
a822c5486f Commit from GitHub Actions (Publishes a new version of Sissi) 2024-12-01 12:55:53 +00:00
release-bot
fd50050870 [maven-release-plugin] prepare for next development iteration 2024-12-01 12:51:45 +00:00
release-bot
9a5e6e1df2 [maven-release-plugin] prepare release sissi-1.4.67 2024-12-01 12:51:44 +00:00
Sheldan
423bf33402 [SIS-xxx] updating debra texts and handling to 2024 2024-12-01 13:48:40 +01:00
release-bot
f9b193a95b Commit from GitHub Actions (Publishes a new version of Sissi) 2024-11-26 23:34:37 +00:00
release-bot
b46c8a1348 [maven-release-plugin] prepare for next development iteration 2024-11-26 23:30:10 +00:00
release-bot
109a770524 [maven-release-plugin] prepare release sissi-1.4.66 2024-11-26 23:30:09 +00:00
Sheldan
3001b14782 [SIS-xxx] updating abstracto version 2024-11-27 00:27:02 +01:00
release-bot
49932641b3 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-11-26 23:00:20 +00:00
release-bot
829d6cc136 [maven-release-plugin] prepare for next development iteration 2024-11-26 22:55:43 +00:00
release-bot
c28a864a47 [maven-release-plugin] prepare release sissi-1.4.65 2024-11-26 22:55:42 +00:00
Sheldan
fae50c2914 [SIS-xxx] updating abstracto version 2024-11-26 23:52:26 +01:00
Sheldan
8f80df1484 [SIS-xxx] updating abstracto version 2024-11-26 23:24:24 +01:00
release-bot
1b5ed0d70d Commit from GitHub Actions (Publishes a new version of Sissi) 2024-11-22 22:18:06 +00:00
release-bot
098d748b96 [maven-release-plugin] prepare for next development iteration 2024-11-22 22:13:04 +00:00
release-bot
075f3b3201 [maven-release-plugin] prepare release sissi-1.4.64 2024-11-22 22:13:03 +00:00
Sheldan
d5e996e1d0 [SIS-xxx] properly updating abstracto version 2024-11-22 23:08:51 +01:00
release-bot
198054ecfe Commit from GitHub Actions (Publishes a new version of Sissi) 2024-11-22 22:05:56 +00:00
release-bot
efcf93492b [maven-release-plugin] prepare for next development iteration 2024-11-22 22:01:30 +00:00
release-bot
564e22d948 [maven-release-plugin] prepare release sissi-1.4.63 2024-11-22 22:01:29 +00:00
Sheldan
29a1473073 [SIS-xxx] adaption to new abstracto version
removing not needed template
adding suffix to template for level action
2024-11-22 22:58:17 +01:00
Sheldan
208dd8c893 [SIS-xxx] updating abstracto version to 1.5.51
adjusting template names to not use a locale
2024-11-22 22:30:34 +01:00
release-bot
752be470e8 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-11-05 22:35:57 +00:00
release-bot
b9cee83afd [maven-release-plugin] prepare for next development iteration 2024-11-05 22:31:48 +00:00
release-bot
ed9bf49e19 [maven-release-plugin] prepare release sissi-1.4.62 2024-11-05 22:31:46 +00:00
Sheldan
8fe46f6172 [SIS-xxx] updating abstracto version to 1.5.50 2024-11-05 23:28:38 +01:00
release-bot
1bc47d962e Commit from GitHub Actions (Publishes a new version of Sissi) 2024-10-29 22:07:11 +00:00
release-bot
b9ce6f22a7 [maven-release-plugin] prepare for next development iteration 2024-10-29 22:03:06 +00:00
release-bot
45b8c3c588 [maven-release-plugin] prepare release sissi-1.4.61 2024-10-29 22:03:05 +00:00
Sheldan
ba5f34d667 [SIS-xxx] updating abstracto version to 1.5.48 2024-10-29 22:59:22 +01:00
Sheldan
1f5ed1b623 [SIS-xxx] updating abstracto version to 1.5.48 2024-10-29 22:57:32 +01:00
Sheldan
170588d638 [SIS-xxx] adding weekly text feature specific to miepscord server 2024-10-29 22:20:57 +01:00
release-bot
4d69a90d5d Commit from GitHub Actions (Publishes a new version of Sissi) 2024-09-29 20:09:45 +00:00
release-bot
19ed221329 [maven-release-plugin] prepare for next development iteration 2024-09-29 20:05:51 +00:00
release-bot
5ba3036e1d [maven-release-plugin] prepare release sissi-1.4.60 2024-09-29 20:05:50 +00:00
Sheldan
25a4d47dc0 [SIS-xxx] upgrading abstracto version 1.5.47 2024-09-29 22:02:52 +02:00
release-bot
3347fdd8f1 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-09-29 19:32:27 +00:00
release-bot
47eef33850 [maven-release-plugin] prepare for next development iteration 2024-09-29 19:28:19 +00:00
release-bot
583a49df5b [maven-release-plugin] prepare release sissi-1.4.59 2024-09-29 19:28:18 +00:00
Sheldan
ca938a0164 [SIS-xxx] upgrading abstracto version 1.5.46 2024-09-29 21:25:25 +02:00
Sheldan
e22f94ff1e [SIS-xxx] adding text to meetup topic parameter about optionally adding a city 2024-08-19 21:40:49 +02:00
release-bot
307c9eac67 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-08-06 21:10:39 +00:00
release-bot
6002c979d9 [maven-release-plugin] prepare for next development iteration 2024-08-06 21:06:11 +00:00
release-bot
df49c313a4 [maven-release-plugin] prepare release sissi-1.4.58 2024-08-06 21:06:09 +00:00
Sheldan
68bf6b5062 [SIS-xxx] upgrading to abstracto 1.5.44 2024-08-06 23:03:07 +02:00
Sheldan
29eb743c35 [SIS-xxx] upgrading to abstracto 1.5.41 2024-08-02 22:47:52 +02:00
Sheldan
03f9b64db2 [SIS-xxx] changing github actions image version to a concrete version and upgrading to docker compose 2024-08-02 22:37:04 +02:00
Sheldan
212bc09d90 [SIS-xxx] upgrading to abstracto snapshot version
adding template for sending message level action
2024-07-27 19:53:27 +02:00
release-bot
e1f327a687 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-07-12 22:58:34 +00:00
release-bot
7af0d2db1c [maven-release-plugin] prepare for next development iteration 2024-07-12 22:54:33 +00:00
release-bot
b4f740fcf6 [maven-release-plugin] prepare release sissi-1.4.57 2024-07-12 22:54:31 +00:00
Sheldan
dda7ed7db8 [SIS-xxx] making quote attachment URL column larger
changing migration script for starboard/quotes
2024-07-13 00:51:41 +02:00
Sheldan
af006ee880 [SIS-xxx] adding missed starboard sync feature template 2024-07-12 23:05:32 +02:00
release-bot
125febc02a Commit from GitHub Actions (Publishes a new version of Sissi) 2024-07-12 20:55:49 +00:00
release-bot
13f92247cf [maven-release-plugin] prepare for next development iteration 2024-07-12 20:50:49 +00:00
release-bot
79ed55d988 [maven-release-plugin] prepare release sissi-1.4.56 2024-07-12 20:50:47 +00:00
Sheldan
7bc04a7906 [SIS-xxx] adding sync of starboard posts and quotes, including migration script 2024-07-12 22:45:17 +02:00
Sheldan
89d743987d [SIS-xxx] fixing not escaping notification message for meetup participant notification 2024-07-03 19:19:27 +02:00
release-bot
32ddd4e6f0 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-06-13 16:42:12 +00:00
release-bot
68afc31b2e [maven-release-plugin] prepare for next development iteration 2024-06-13 16:37:16 +00:00
release-bot
d0ba46c440 [maven-release-plugin] prepare release sissi-1.4.55 2024-06-13 16:37:14 +00:00
Sheldan
554d197ca4 [SIS-xxx] upgrading to new abstracto version 2024-06-13 18:23:36 +02:00
Sheldan
8826796fcb [SIS-xxx] changing text for ban notification to contain translation 2024-06-02 23:11:07 +02:00
Sheldan
c8ed0e2195 [SIS-xxx] changing text for ban notification to contain the new invite link 2024-05-31 09:32:48 +02:00
release-bot
25d19bfa26 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-05-31 07:18:27 +00:00
release-bot
f7e19b580e [maven-release-plugin] prepare for next development iteration 2024-05-31 07:14:21 +00:00
release-bot
5f6bd0d88e [maven-release-plugin] prepare release sissi-1.4.54 2024-05-31 07:14:20 +00:00
Sheldan
a110c54411 [SIS-xxx] upgrading abstracto version 2024-05-31 09:11:12 +02:00
release-bot
a4a729dfc2 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-05-05 22:32:21 +00:00
release-bot
85eee4835f [maven-release-plugin] prepare for next development iteration 2024-05-05 22:28:20 +00:00
release-bot
cab11140fa [maven-release-plugin] prepare release sissi-1.4.53 2024-05-05 22:28:19 +00:00
Sheldan
5854ca2ba7 [SIS-xxx] upgrading abstracto version 2024-05-06 00:23:34 +02:00
release-bot
3f613eeddf Commit from GitHub Actions (Publishes a new version of Sissi) 2024-04-05 13:34:58 +00:00
release-bot
5fda777a62 [maven-release-plugin] prepare for next development iteration 2024-04-05 13:30:23 +00:00
release-bot
e447eca9dd [maven-release-plugin] prepare release sissi-1.4.52 2024-04-05 13:30:20 +00:00
Sheldan
17e2e09541 [SIS-xxx] upgrading abstracto version 2024-04-05 15:24:39 +02:00
Sheldan
1ea2cc02c8 [SIS-xxx] renaming frontend environment variable 2024-04-05 01:59:12 +02:00
Sheldan
3a1071b65e [SIS-xxx] adding variable to make frontend host available 2024-04-05 01:48:47 +02:00
release-bot
32274561e9 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-03-27 21:46:01 +00:00
release-bot
b3550549de [maven-release-plugin] prepare for next development iteration 2024-03-27 21:41:57 +00:00
release-bot
eef245ede0 [maven-release-plugin] prepare release sissi-1.4.51 2024-03-27 21:41:55 +00:00
Sheldan
6ac950358f [SIS-xxx] upgrading abstracto version 2024-03-27 22:26:42 +01:00
release-bot
01c59f5059 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-03-26 23:19:10 +00:00
release-bot
be0325deb9 [maven-release-plugin] prepare for next development iteration 2024-03-26 23:13:55 +00:00
release-bot
f8d84ff943 [maven-release-plugin] prepare release sissi-1.4.50 2024-03-26 23:13:53 +00:00
Sheldan
5ec3b3a1f4 [SIS-xxx] upgrading abstracto version 2024-03-27 00:10:17 +01:00
release-bot
fef1a5f0ae Commit from GitHub Actions (Publishes a new version of Sissi) 2024-03-26 21:59:12 +00:00
release-bot
db89b59600 [maven-release-plugin] prepare for next development iteration 2024-03-26 21:54:04 +00:00
release-bot
3ca37c448d [maven-release-plugin] prepare release sissi-1.4.49 2024-03-26 21:54:01 +00:00
Sheldan
b6a416135a [SIS-xxx] upgrading abstracto version 2024-03-26 22:49:11 +01:00
release-bot
ed181a2bc3 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-03-26 01:29:46 +00:00
release-bot
2ee2cb18f5 [maven-release-plugin] prepare for next development iteration 2024-03-26 01:23:50 +00:00
release-bot
d0908e7315 [maven-release-plugin] prepare release sissi-1.4.48 2024-03-26 01:23:48 +00:00
Sheldan
7c6809500a [SIS-xxx] upgrading abstracto version 2024-03-26 02:09:17 +01:00
release-bot
a6e3f2df17 Commit from GitHub Actions (Publishes a new version of Sissi) 2024-03-26 00:56:10 +00:00
release-bot
6b35a75539 [maven-release-plugin] prepare for next development iteration 2024-03-26 00:52:03 +00:00
release-bot
32ed3bff5d [maven-release-plugin] prepare release sissi-1.4.47 2024-03-26 00:52:01 +00:00
377 changed files with 1915 additions and 169 deletions

4
.env
View File

@@ -1,4 +1,4 @@
REGISTRY_PREFIX=harbor.sheldan.dev/sissi/
ABSTRACTO_PREFIX=harbor.sheldan.dev/abstracto/
VERSION=1.4.46
ABSTRACTO_VERSION=1.5.28
VERSION=1.5.3
ABSTRACTO_VERSION=1.6.7

View File

@@ -14,7 +14,7 @@ on:
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v3

View File

@@ -5,7 +5,7 @@ permissions:
contents: write
jobs:
publish:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
with:
@@ -38,7 +38,7 @@ jobs:
maven-args: "-Dmaven.javadoc.skip=true -s settings.xml -DskipTests"
access-token: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Harbor
uses: docker/login-action@v2
uses: docker/login-action@v3
with:
registry: harbor.sheldan.dev
username: ${{ secrets.HARBOR_USERNAME }}
@@ -72,7 +72,7 @@ jobs:
with:
path: .env
- name: Build and push Docker containers
run: docker-compose build && docker-compose push
run: docker compose build && docker compose push
env:
REGISTRY_PREFIX: ${{ steps.dotenv.outputs.registry_prefix }}
VERSION: ${{ steps.dotenv.outputs.version }}

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2023 Sheldan
Copyright (c) 2025 Sheldan
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

164
PRIVACY_POLICY.md Normal file
View File

@@ -0,0 +1,164 @@
# Sissi Discord bot privacy policy
Last updated: 23.02.2025
## Description
The bot requires some information to function properly and in a reasonable way. These features heavily depend which features are enabled for which server, and this list just presents ALL of the features available.
The detailed list of what information is stored and processed is the following:
### General
* your Discord user ID (in combination with the server ID) is used to uniquely identify you and associate various properties, such as experience, level, opened modmail threads etc
* the IDs of the servers this bot is in
* the IDs of the channel in the servers this bot is in
* the names of channel groups which were given by their creator
* the server aliases which were created for commands
* the name of emotes which are used in the bot for convenience, if they are customized
* towards which channel (identified by ID) certain messages by the bot are posted. e.g. logging, news, starboard
* **no message content, username, channel name or role name is stored, except at the places where its mentioned**
* most of the stored records have a 'created' and 'updated' timestamp, in order to assist in examining bugs and malfunctions
* which commands have which cooldown in which channel group and in which channel group they are disabled
* which channel is in which channel group
* which role is allowed to execute which command
* which features are enabled
* which feature modes are enabled
* **aliases** created for the commands
* **information** necessary to handle components (buttons, select menus). This information is of varying nature and can be user identifiable information
* **emotes** which should be used for varying places (assignable roles, particular emotes which are overwriten, such as star board)
### Moderation
* **mute reason**, duration, mute date, who muted whom and in which message was the mute executed
* the names of filtered invite link servers in order to find out if it would be valid to allow the invite
* any configured allowed invite links the server ID and the actually used invite
* this is necessary in order to determine the server via its ID and allow other unknown invite links. The invite link is necessary as there is no way to map server ID to actual server
* configured profanity regexes
* reported profanities, including which message contains the profanity, and the message which was used to report the profanity, and whether it was identified as a true profanity
* **the text of notes regarding users**
* this is used to enable taking notes about users, and the content is stored directly
* meta information regarding warnings
* **reason for the warning**
* date of the warning
* the user who warned a user
* whether the warning was decayed and when
* the infractions of each user accompanied with **reason** (if available): warns, mutes, bans, kicks
### Giveaway
* the give away information: **description**, provider, manager, target date, winners and participants
### Embedded messages
* embedded message information
* this information includes who embedded which message in which channel and is deleted after a few days
### Emote usage tracking
* the name of emotes which are being tracked in the emote usage tracking system for purely convenience reasons
* **who** used which emote is **not** tracked
* at which day an emote was used how many times
* whether the emote was a reaction
### Reminder
* **the message content** in order to provide you with the reminder text
* the date it was created, and the date it is due
* the id of the message which contained the command
* whether you have been reminded
* the users who have joined the reminders
### Modmail
* the information that a modmail thread existed (creation, status and close date), and the IDs of the messages that have been sent in both directions
### News
* the ORF integration stores which posts from ORF RSS were already sent.
* which ORF RSS feeds were subscribed
### Polls
* the **text** of polls, the creator of polls and who made which decision in polls
### Starboard (best-of)
* the message which was the origin for the starboard post
* the message which was the resulting starboard post
* the author of the message and the amount of stars
* who reacted to a starboard post
* this is necessary to provide the information about 'top star giver' and to disallow duplicate starboard reactions
### Suggestion
* **the message content** of the message used to create the suggestion
* this was used for the message used to update the status of a suggestion, but this is currently disabled
* the author of the suggestion and the message which has been posted in the suggestions channel
* every suggestion will be deleted completely from the database a few days after it has reached a final state (rejected, denied, accepted)
* whether you voted for a suggestion and which decision you made
### Leveling system
* the amount of messages which were considered for the leveling system
* it only considers a message once per minute, so it does not directly translate to your absolute message count
* the amount of experience, and the experience level you have
* whether experience gain has been disabled for you
* the role you received because of the experience system
* which roles are configured to be used as experience roles and at which level they are assigned
* which roles are used to disable experience gain
### Entertainment
* PressF: for **what** the pressF was initiated by whom and who participated
### Economy
* The amount of credits for each user
### Assignable roles
* the names of assignable role places and assignable role button text, together with the associated emote markdown (if given)
* the assigned assignable roles for each member in order to provide the 'unique' assignable role functionality
* custom configured conditions to enable a level restriction
### Weekly items (for Miepscord)
* The text of the weekly art posts and the creator of them
### Sticky roles
* The roles a user had when leaving the server to be re-applied when re-joining (opt out possible)
### Meetups
* The meta data of meetups: text, location, creator and the decision of each user interacting with the meetup. This information will be deleted a few days after a meetup has passed/is cancelled.
### Twitch
* The ID/**name** of streamers to follow accompanied with their discord ID
* The start/end dates of their streams
* The individual sections of streams identified by title and game for updating the message
### Custom commands
* the **names** given to custom commands and the configured **response text**
## Grafana dashboard
There is also a [Grafana](https://grafana.com/) dashboard in order to inspect how the bot is operating.
The information visible in this dashboard is:
* message events
* Discord gateway ping
* starboard reactions
* amount of command executions
* emotes currently being processed for tracking
* embedded messages
* invite filter activity
* amount of experience which is currently being processed
All of this information cannot be linked to any user (or any server for that matter, if the bot would be in multiple servers) and is deleted after 15 days.
## How can I decide which information is collected?
It is not possible to opt-out of singular sub-services of the bot. Should you decide that your information should not be collected, please cease usage of the bot immediately (leave any guild the bot operates in).
_Should you decide to no longer utilize the bot, you may request your data to be erased within 30 days as per GDPR if you are a citizen of the EU. You can do this by sending a message to the user "sheldan" on Discord: GDPR Data removal <Username> <UserId>. If your request is incomplete, we cannot acknowledge it and therefore your data will not be removed. In order to identify authentic requests, please contact modmail beforehand by sending a direct message to the bot and stating your intention._
## Open source content
This bot uses the following open source libraries and frameworks:
* [abstracto](https://github.com/Sheldan/abstracto) is used as a base for this bot, providing most of the functionalities
* [JDA](https://github.com/DV8FromTheWorld/JDA/) The Discord API Wrapper used
* [Spring boot](https://github.com/spring-projects/spring-boot) is used as a framework to create standalone application in Java with Java EE methods. (including Dependency injection and more)
* [Hibernate](https://github.com/hibernate/hibernate-orm) is used as a reference implementation of JPA.
* [Freemarker](https://github.com/apache/freemarker) is used as a templating engine. This is used to provide internationalization for user facing text and enable dynamic embed configuration.
* [Ehcache](https://github.com/ehcache/ehcache3) is used as a caching implementation.
* [Lombok](https://github.com/rzwitserloot/lombok) is used as a framework in order to speed up creation of container classes and builders.
* [Quartz](https://github.com/quartz-scheduler/quartz) is used as a scheduling framework in order to provide functionalities which either require a delayed or cronjob behaviour.
* [Docker](https://github.com/docker) is used to package the application into a container and [k3s](https://k3s.io/) to orchestrate the containers
* [Liquibase](https://github.com/liquibase/liquibase) is used to manage changes to the database
* [Prometheus](https://prometheus.io) to scrap and collect the metrics about how the bot is operating
* [Grafana](https://grafana.com) to visualize metrics of the bot and [Loki](https://grafana.com/oss/loki/) for logging

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>executable</artifactId>
@@ -55,12 +55,13 @@
<artifactId>metrics-impl</artifactId>
</dependency>
<!-- modules containing commands -->
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-impl</artifactId>
</dependency>
<!-- modules containing commands -->
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>link-embed-impl</artifactId>
@@ -165,6 +166,13 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>miepscord</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>rss-news</artifactId>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -4,7 +4,7 @@
<parent>
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
<artifactId>sissi-customizations</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<artifactId>image-generation-custom</artifactId>

View File

@@ -61,7 +61,7 @@ public class OrangeSunDogeCommandAlternative implements CommandAlternative {
List<String> parameters = Arrays.asList(contentStripped.split(" "));
String inputText = commandRegistry.getCommandName(parameters.get(0), message.getGuild().getIdLong());
File triggeredGifFile = imageGenerationService.getOrangeSunDogeImage(inputText);
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOGE_ORANGE_SUN_RESPONSE_TEMPLATE_KEY, new Object());
MessageToSend messageToSend = templateService.renderEmbedTemplate(DOGE_ORANGE_SUN_RESPONSE_TEMPLATE_KEY, new Object(), message.getGuildIdLong());
// template support does not support binary files
AttachedFile file = AttachedFile
.builder()

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
<artifactId>sissi-customizations</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.moderation.config.ModerationModuleDefinition;
import dev.sheldan.sissi.module.custom.moderation.config.ModerationCustomFeatureDefinition;
@@ -72,6 +73,7 @@ public class ModMode extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(ModerationCustomSlashCommandNames.MODERATION)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName(MOD_MODE_COMMAND)
.build();

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>application</artifactId>
<groupId>dev.sheldan.sissi.application</groupId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition;
import dev.sheldan.sissi.module.debra.config.DebraSlashCommandNames;
@@ -58,6 +59,7 @@ public class DebraInfoButton extends AbstractConditionableCommand {
.enabled(true)
.rootCommandName(DebraSlashCommandNames.DEBRA_INTERNAL)
.commandName("debrainfobutton")
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.build();
Parameter targetChannelParameter = Parameter

View File

@@ -124,7 +124,7 @@ public class Donations extends AbstractConditionableCommand {
} else {
donationModel.setDonations(new ArrayList<>());
}
return templateService.renderEmbedTemplate(DONATIONS_RESPONSE_TEMPLATE_KEY, donationModel);
return templateService.renderEmbedTemplate(DONATIONS_RESPONSE_TEMPLATE_KEY, donationModel, serverId);
}
@Override

View File

@@ -182,7 +182,7 @@ public class DonationService {
.donation(donation)
.totalDonationAmount(donationInfoModel.getTotalAmount())
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY, model);
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY, model, targetServerId);
List<CompletableFuture<Message>> firstMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION, targetServerId);
List<CompletableFuture<Message>> secondMessage = postTargetService.sendEmbedInPostTarget(messageToSend, DebraPostTarget.DEBRA_DONATION_NOTIFICATION2, targetServerId);
firstMessage.addAll(secondMessage);

View File

@@ -5,7 +5,7 @@ abstracto.postTargets.debraDonationNotification.name=debraDonationNotification
abstracto.postTargets.debraDonationNotification2.name=debraDonationNotification2
sissi.debra.websocketURL=ws://spenden.baba.fm:8765/
sissi.debra.donationAPIUrl=https://www.altruja.de/api/page/discord-gg-austria-fuer-debra-2023?details=1&num=%s&ort=0
sissi.debra.donationAPIUrl=https://www.altruja.de/api/page/discord-schmetterlingsaktion-2024?details=1&num=%s&ort=0
abstracto.systemConfigs.debraDonationNotificationDelayMillis.name=debraDonationNotificationDelayMillis
abstracto.systemConfigs.debraDonationNotificationDelayMillis.longValue=60000

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.utils.FutureUtils;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
@@ -88,6 +89,7 @@ public class CancelMeetup extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName("cancel")
.build();

View File

@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
@@ -131,6 +132,7 @@ public class ChangeMeetup extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName("changeMeetup")
.build();

View File

@@ -11,6 +11,7 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.ComponentService;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.service.ChannelService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
@@ -150,6 +151,7 @@ public class ChangeMeetupTime extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName("changeTime")
.build();

View File

@@ -12,6 +12,7 @@ import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.ComponentService;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
@@ -198,6 +199,7 @@ public class CreateMeetup extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName("create")
.build();

View File

@@ -10,6 +10,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
@@ -22,6 +23,7 @@ import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEve
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@@ -48,19 +50,6 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
private static final String NOTIFY_MEETUP_PARTICIPANTS_COMMAND = "notifyMeetupParticipants";
private static final String NOTIFY_MEETUP_PARTICIPANTS_RESPONSE = "notifyMeetupParticipants_response";
@Override
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
List<Object> parameters = commandContext.getParameters().getParameters();
Long meetupId = (Long) parameters.get(0);
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, commandContext.getGuild().getIdLong());
if(!meetup.getOrganizer().getUserReference().getId().equals(commandContext.getAuthor().getIdLong())) {
throw new NotMeetupOrganizerException();
}
String notificationMessage = (String) parameters.get(1);
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage, null)
.thenApply(unused -> CommandResult.fromSuccess());
}
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Long meetupId = slashCommandParameterService.getCommandOption(MEETUP_ID_PARAMETER, event, Integer.class).longValue();
@@ -68,12 +57,15 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
throw new NotMeetupOrganizerException();
}
MeetupDecision toNotify = null;
if(slashCommandParameterService.hasCommandOption(NOTIFICATION_MEETUP_DECISION, event)) {
toNotify = MeetupDecision.valueOf(slashCommandParameterService.getCommandOption(NOTIFICATION_MEETUP_DECISION, event, String.class));
List<MeetupDecision> decisionsToNotify = new ArrayList<>();
for (int i = 0; i < MeetupDecision.values().length; i++) {
if(slashCommandParameterService.hasCommandOption(NOTIFICATION_MEETUP_DECISION + "_" + i, event)) {
String choice = slashCommandParameterService.getCommandOption(NOTIFICATION_MEETUP_DECISION + "_" + i, event, String.class);
decisionsToNotify.add(MeetupDecision.valueOf(choice));
}
}
String notificationMessage = slashCommandParameterService.getCommandOption(NOTIFICATION_MESSAGE_PARAMETER, event, String.class);
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage, toNotify)
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage, decisionsToNotify)
.thenCompose(unused -> interactionService.replyEmbed(NOTIFY_MEETUP_PARTICIPANTS_RESPONSE, event))
.thenApply(unused -> CommandResult.fromSuccess());
}
@@ -105,6 +97,8 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
.templated(true)
.name(NOTIFICATION_MEETUP_DECISION)
.type(String.class)
.listSize(MeetupDecision.values().length)
.isListParam(true)
.optional(true)
.choices(meetupDecisions)
.slashCommandOnly(true)
@@ -120,6 +114,7 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(MeetupSlashCommandNames.MEETUP)
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
.commandName("notify")
.build();
@@ -129,6 +124,7 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
.templated(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.slashCommandOnly(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)

View File

@@ -115,7 +115,7 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
messageModel.setCancelled(false);
Long meetupId = payload.getMeetupId();
Long serverId = payload.getGuildId();
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(messageModel);
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(messageModel, model.getServerId());
List<CompletableFuture<Message>> messageFutures = channelService.sendMessageToSendToChannel(messageToSend, model.getEvent().getMessageChannel());
FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused -> {
messageService.deleteMessage(model.getEvent().getMessage());

View File

@@ -59,7 +59,7 @@ public class MeetupDecisionListener implements ButtonClickedListener {
}
MeetupMessageModel meetupMessageModel = meetupServiceBean.getMeetupMessageModel(meetup);
addParticipationToModel(meetupMessageModel, userInAServer, payload.getMeetupDecision());
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(meetupMessageModel);
MessageToSend messageToSend = meetupServiceBean.getMeetupMessage(meetupMessageModel, model.getServerId());
channelService.editEmbedMessageInAChannel(messageToSend.getEmbeds().get(0), model.getEvent().getChannel(), meetup.getMessageId())
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetup.getId().getId(), meetup.getMeetupChannel().getId(), meetup.getServer().getId()))
.exceptionally(throwable -> {

View File

@@ -206,8 +206,8 @@ public class MeetupServiceBean {
.collect(Collectors.toList());
}
public MessageToSend getMeetupMessage(MeetupMessageModel model) {
return templateService.renderEmbedTemplate(MEETUP_DISPLAY_TEMPLATE, model);
public MessageToSend getMeetupMessage(MeetupMessageModel model, Long serverId) {
return templateService.renderEmbedTemplate(MEETUP_DISPLAY_TEMPLATE, model, serverId);
}
public CompletableFuture<Void> cancelMeetup(Meetup meetup) {
@@ -221,7 +221,7 @@ public class MeetupServiceBean {
.map(meetupComponent -> meetupComponent.getId().getComponentId())
.collect(Collectors.toList());
model.setCancelled(true);
MessageToSend meetupMessage = getMeetupMessage(model);
MessageToSend meetupMessage = getMeetupMessage(model, serverId);
return messageService.editMessageInChannel(channel, meetupMessage, meetup.getMessageId())
.thenAccept(unused -> self.notifyParticipants(meetupId, serverId))
.thenAccept(unused -> self.cleanupMeetup(meetupId, serverId, componentPayloads));
@@ -231,7 +231,7 @@ public class MeetupServiceBean {
public void notifyParticipants(Long meetupId, Long serverId) {
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
MeetupMessageModel model = getMeetupMessageModel(meetup);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_CANCELLATION_TEMPLATE, model);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_CANCELLATION_TEMPLATE, model, serverId);
meetup
.getParticipants()
.stream()
@@ -293,8 +293,8 @@ public class MeetupServiceBean {
}
}
public CompletableFuture<Void> notifyMeetupParticipants(Meetup meetup, String message, MeetupDecision toNotify) {
List<MeetupDecision> decisionsToBeNotified = toNotify == null ? Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.YES) : Arrays.asList(toNotify);
public CompletableFuture<Void> notifyMeetupParticipants(Meetup meetup, String message, List<MeetupDecision> toNotify) {
List<MeetupDecision> decisionsToBeNotified = toNotify == null || toNotify.isEmpty() ? Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.YES) : toNotify;
List<MemberDisplay> participants = meetup
.getParticipants()
.stream()
@@ -319,7 +319,7 @@ public class MeetupServiceBean {
public void remindParticipants(Long meetupId, Long serverId) {
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, serverId);
MeetupMessageModel model = getMeetupMessageModel(meetup);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_REMINDER_TEMPLATE, model);
MessageToSend messageToSend = templateService.renderEmbedTemplate(MEETUP_REMINDER_TEMPLATE, model, serverId);
meetup
.getParticipants()
.stream()
@@ -423,7 +423,7 @@ public class MeetupServiceBean {
meetupMessageModel.setMaybeParticipants(new ArrayList<>());
meetupMessageModel.setNoTimeParticipants(new ArrayList<>());
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel);
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel, serverId);
GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId())
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId))
@@ -457,7 +457,7 @@ public class MeetupServiceBean {
Long meetupId = meetup.getId().getId();
Long serverId = meetup.getId().getServerId();
MeetupMessageModel meetupMessageModel = getMeetupMessageModel(meetup);
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel);
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel, serverId);
GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId())
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId))

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>sissi-modules</artifactId>
<groupId>dev.sheldan.sissi.application</groupId>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>miepscord</artifactId>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly/liquibase.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.scheduling</groupId>
<artifactId>scheduling-int</artifactId>
<version>${abstracto.version}</version>
</dependency>
</dependencies>
</project>

View File

@@ -0,0 +1,18 @@
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
<id>liquibase</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<outputDirectory>.</outputDirectory>
<directory>${project.basedir}/src/main/resources/migrations</directory>
<includes>
<include>**/*</include>
</includes>
</fileSet>
</fileSets>
</assembly>

View File

@@ -0,0 +1,15 @@
package dev.sheldan.sissi.module.miepscord;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import lombok.Getter;
@Getter
public enum MiepscordFeatureDefinition implements FeatureDefinition {
WEEKLY_TEXT("weeklyText");
private String key;
MiepscordFeatureDefinition(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,9 @@
package dev.sheldan.sissi.module.miepscord;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
@Configuration
@PropertySource("classpath:miepscord.properties")
public class MiepscordProperties {
}

View File

@@ -0,0 +1,6 @@
package dev.sheldan.sissi.module.miepscord;
public class MiepscordSlashCommandNames {
public static final String MIEPSCORD_ROOT_NAME = "miepscord";
public static final String MIEPSCORD_ROOT_NAME_CONFIG = "miepscordManage";
}

View File

@@ -0,0 +1,92 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.miepscord.MiepscordFeatureDefinition;
import dev.sheldan.sissi.module.miepscord.MiepscordSlashCommandNames;
import dev.sheldan.sissi.module.miepscord.weeklytext.service.TextItemServiceBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class AddTextItem extends AbstractConditionableCommand {
private static final String ADD_WEEKLY_TEXT_TEXT_PARAMETER = "text";
private static final String ADD_WEEKLY_TEXT_COMMAND_NAME = "addWeeklyText";
private static final String ADD_WEEKLY_TEXT_RESPONSE = "addWeeklyText_response";
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private TextItemServiceBean textItemServiceBean;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
String weeklyText = slashCommandParameterService.getCommandOption(ADD_WEEKLY_TEXT_TEXT_PARAMETER, event, String.class);
textItemServiceBean.createTextItem(weeklyText, event.getMember());
return interactionService.replyEmbed(ADD_WEEKLY_TEXT_RESPONSE, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter textitemTextParameter = Parameter
.builder()
.templated(true)
.name(ADD_WEEKLY_TEXT_TEXT_PARAMETER)
.type(String.class)
.build();
List<Parameter> parameters = Arrays.asList(textitemTextParameter);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MiepscordSlashCommandNames.MIEPSCORD_ROOT_NAME_CONFIG)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("weeklytexts")
.commandName("add")
.build();
return CommandConfiguration.builder()
.name(ADD_WEEKLY_TEXT_COMMAND_NAME)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.slashCommandOnly(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MiepscordFeatureDefinition.WEEKLY_TEXT;
}
}

View File

@@ -0,0 +1,93 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.miepscord.MiepscordFeatureDefinition;
import dev.sheldan.sissi.module.miepscord.MiepscordSlashCommandNames;
import dev.sheldan.sissi.module.miepscord.weeklytext.service.TextItemServiceBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class RemoveTextItem extends AbstractConditionableCommand {
private static final String REMOVE_WEEKLY_TEXT_ID_PARAMETER = "id";
private static final String REMOVE_WEEKLY_TEXT_COMMAND_NAME = "removeWeeklyText";
private static final String REMOVE_WEEKLY_TEXT_RESPONSE = "removeWeeklyText_response";
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Autowired
private TextItemServiceBean textItemServiceBean;
@Autowired
private InteractionService interactionService;
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
Long itemId = slashCommandParameterService.getCommandOption(REMOVE_WEEKLY_TEXT_ID_PARAMETER, event, Integer.class).longValue();
textItemServiceBean.removeTextItem(itemId);
return interactionService.replyEmbed(REMOVE_WEEKLY_TEXT_RESPONSE, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
@Override
public CommandConfiguration getConfiguration() {
Parameter textItemId = Parameter
.builder()
.templated(true)
.name(REMOVE_WEEKLY_TEXT_ID_PARAMETER)
.type(Long.class)
.build();
List<Parameter> parameters = Arrays.asList(textItemId);
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MiepscordSlashCommandNames.MIEPSCORD_ROOT_NAME_CONFIG)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("weeklytexts")
.commandName("remove")
.build();
return CommandConfiguration.builder()
.name(REMOVE_WEEKLY_TEXT_COMMAND_NAME)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.slashCommandOnly(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.supportsEmbedException(true)
.causesReaction(true)
.parameters(parameters)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MiepscordFeatureDefinition.WEEKLY_TEXT;
}
}

View File

@@ -0,0 +1,137 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.commands;
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
import dev.sheldan.abstracto.core.command.config.HelpInfo;
import dev.sheldan.abstracto.core.command.config.Parameter;
import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.service.PaginatorService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.sissi.module.miepscord.MiepscordFeatureDefinition;
import dev.sheldan.sissi.module.miepscord.MiepscordSlashCommandNames;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.database.TextItem;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.template.ShowTextItemModel;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.template.ShowTextItemsModel;
import dev.sheldan.sissi.module.miepscord.weeklytext.service.management.TextItemServiceManagementBean;
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CompletableFuture;
@Component
public class ShowTextItems extends AbstractConditionableCommand {
private static final String SHOW_WEEKLY_TEXTS_COMMAND_NAME = "showWeeklyTexts";
private static final String SHOW_WEEKLY_TEXTS_RESPONSE_TEMPLATE = "showWeeklyTexts";
public static final String NO_ITEMS_TEMPLATE_KEY = "showWeeklyTexts_no_items_found";
private static final String SHOW_WEEKLY_TEXT_SHOW_ALL_PARAMETER = "showAll";
@Autowired
private TextItemServiceManagementBean textItemServiceManagementBean;
@Autowired
private PaginatorService paginatorService;
@Autowired
private TemplateService templateService;
@Autowired
private InteractionService interactionService;
@Autowired
private SlashCommandParameterService slashCommandParameterService;
@Override
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
boolean showAll = false;
if(slashCommandParameterService.hasCommandOption(SHOW_WEEKLY_TEXT_SHOW_ALL_PARAMETER, event)) {
showAll = slashCommandParameterService.getCommandOption(SHOW_WEEKLY_TEXT_SHOW_ALL_PARAMETER, event, Boolean.class);
}
List<TextItem> textItems;
if(showAll) {
textItems = textItemServiceManagementBean.getAllTextItems();
} else {
textItems = textItemServiceManagementBean.getAllTextItemsWithDoneFlag(false);
}
textItems.sort(Comparator.comparing(TextItem::getCreated));
if(textItems.isEmpty()) {
MessageToSend messageToSend = templateService.renderEmbedTemplate(NO_ITEMS_TEMPLATE_KEY, new Object(), event.getGuild().getIdLong());
return interactionService.replyMessageToSend(messageToSend, event)
.thenApply(interactionHook -> CommandResult.fromSuccess());
}
List<ShowTextItemModel> convertedTextItems = textItems.stream().map(this::convertTextItem).toList();
ShowTextItemsModel items = ShowTextItemsModel
.builder()
.items(convertedTextItems)
.build();
return paginatorService.createPaginatorFromTemplate(SHOW_WEEKLY_TEXTS_RESPONSE_TEMPLATE, items, event)
.thenApply(unused -> CommandResult.fromIgnored());
}
private ShowTextItemModel convertTextItem(TextItem textItem) {
return ShowTextItemModel
.builder()
.text(textItem.getText())
.id(textItem.getId())
.done(textItem.getDone())
.created(textItem.getCreated())
.build();
}
@Override
public CommandConfiguration getConfiguration() {
HelpInfo helpInfo = HelpInfo
.builder()
.templated(true)
.build();
Parameter showAllItems = Parameter
.builder()
.name(SHOW_WEEKLY_TEXT_SHOW_ALL_PARAMETER)
.type(Boolean.class)
.optional(true)
.templated(true)
.build();
List<Parameter> parameters = Arrays.asList(showAllItems);
SlashCommandConfig slashCommandConfig = SlashCommandConfig
.builder()
.enabled(true)
.rootCommandName(MiepscordSlashCommandNames.MIEPSCORD_ROOT_NAME)
.groupName("weeklytexts")
.commandName("show")
.build();
return CommandConfiguration.builder()
.name(SHOW_WEEKLY_TEXTS_COMMAND_NAME)
.module(UtilityModuleDefinition.UTILITY)
.templated(true)
.slashCommandOnly(true)
.slashCommandConfig(slashCommandConfig)
.async(true)
.parameters(parameters)
.supportsEmbedException(true)
.causesReaction(true)
.help(helpInfo)
.build();
}
@Override
public FeatureDefinition getFeature() {
return MiepscordFeatureDefinition.WEEKLY_TEXT;
}
}

View File

@@ -0,0 +1,27 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.config;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.config.PostTargetEnum;
import dev.sheldan.sissi.module.miepscord.MiepscordFeatureDefinition;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
@Component
public class WeeklyTextFeatureConfig implements FeatureConfig {
public static final String WEEKLY_TEXT_SERVER_ID = "WEEKLY_TEXT_SERVER_ID";
@Override
public FeatureDefinition getFeature() {
return MiepscordFeatureDefinition.WEEKLY_TEXT;
}
@Override
public List<PostTargetEnum> getRequiredPostTargets() {
return Arrays.asList(WeeklyTextPostTarget.TEXT_ITEM_TARGET);
}
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.config;
import dev.sheldan.abstracto.core.config.PostTargetEnum;
import lombok.Getter;
@Getter
public enum WeeklyTextPostTarget implements PostTargetEnum {
TEXT_ITEM_TARGET("textItemTarget");
private String key;
WeeklyTextPostTarget(String key) {
this.key = key;
}
}

View File

@@ -0,0 +1,31 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.job;
import dev.sheldan.sissi.module.miepscord.weeklytext.service.TextItemServiceBean;
import lombok.extern.slf4j.Slf4j;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.PersistJobDataAfterExecution;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.QuartzJobBean;
import org.springframework.stereotype.Component;
@Slf4j
@DisallowConcurrentExecution
@Component
@PersistJobDataAfterExecution
public class WeeklyTextJob extends QuartzJobBean {
@Autowired
private TextItemServiceBean textItemServiceBean;
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
try {
log.info("Executing text item job.");
textItemServiceBean.sendTexItem();
} catch (Exception e) {
log.error("Text item job failed.", e);
}
}
}

View File

@@ -0,0 +1,38 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.model.database;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import jakarta.persistence.*;
import lombok.*;
import java.time.Instant;
@Builder
@Entity
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "text_item")
@Getter
@Setter
@EqualsAndHashCode
public class TextItem {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@Column(name = "text")
private String text;
@Column(name = "done")
private Boolean done;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "creator_id", nullable = false)
private AUserInAServer creator;
@Column(name = "created")
private Instant created;
@Column(name = "updated")
private Instant updated;
}

View File

@@ -0,0 +1,15 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.model.template;
import lombok.Builder;
import lombok.Getter;
import java.time.Instant;
@Builder
@Getter
public class ShowTextItemModel {
private String text;
private Boolean done;
private Instant created;
private Long id;
}

View File

@@ -0,0 +1,12 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.model.template;
import lombok.Builder;
import lombok.Getter;
import java.util.List;
@Builder
@Getter
public class ShowTextItemsModel {
private List<ShowTextItemModel> items;
}

View File

@@ -0,0 +1,14 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.model.template;
import lombok.Builder;
import lombok.Getter;
import java.time.Instant;
@Builder
@Getter
public class TextItemPostModel {
private String text;
private Long id;
private Instant created;
}

View File

@@ -0,0 +1,13 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.repository;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.database.TextItem;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
@Repository
public interface TextItemRepository extends JpaRepository<TextItem, Long> {
List<TextItem> findByDoneFalseOrderByCreated();
List<TextItem> findByDone(Boolean done);
}

View File

@@ -0,0 +1,89 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.service;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.PostTargetService;
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
import dev.sheldan.abstracto.core.templating.service.TemplateService;
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
import dev.sheldan.sissi.module.miepscord.weeklytext.config.WeeklyTextPostTarget;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.database.TextItem;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.template.TextItemPostModel;
import dev.sheldan.sissi.module.miepscord.weeklytext.service.management.TextItemServiceManagementBean;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import static dev.sheldan.sissi.module.miepscord.weeklytext.config.WeeklyTextFeatureConfig.WEEKLY_TEXT_SERVER_ID;
@Component
@Slf4j
public class TextItemServiceBean {
public static final String WEEKLY_TEXT_ITEM_POST_TEMPLATE = "weekly_text_item_post";
@Autowired
private TextItemServiceManagementBean textItemServiceManagementBean;
@Autowired
private UserInServerManagementService userInServerManagementService;
@Autowired
private PostTargetService postTargetService;
@Autowired
private TemplateService templateService;
@Autowired
private TextItemServiceBean self;
public TextItem createTextItem(String text, Member creator) {
log.info("Creating new text item in server {} from user {}.", creator.getGuild().getIdLong(), creator.getIdLong());
AUserInAServer creatorUser = userInServerManagementService.loadOrCreateUser(creator);
return textItemServiceManagementBean.createTextItem(text, creatorUser);
}
public CompletableFuture<Void> sendTexItem() {
Long serverId = Long.parseLong(System.getenv(WEEKLY_TEXT_SERVER_ID));
Optional<TextItem> nextTextItemOptional = textItemServiceManagementBean.getNextTextItem();
if(nextTextItemOptional.isEmpty()) {
log.info("No next text item found.");
return CompletableFuture.completedFuture(null);
}
TextItem textItem = nextTextItemOptional.get();
log.info("Sending text item {}.", textItem.getId());
Long textItemId = textItem.getId();
TextItemPostModel model = TextItemPostModel
.builder()
.id(textItemId)
.created(textItem.getCreated())
.text(textItem.getText())
.build();
MessageToSend messageToSend = templateService.renderEmbedTemplate(WEEKLY_TEXT_ITEM_POST_TEMPLATE, model, serverId);
List<CompletableFuture<Message>> futures = postTargetService.sendEmbedInPostTarget(messageToSend, WeeklyTextPostTarget.TEXT_ITEM_TARGET, serverId);
CompletableFutureList<Message> futureList = new CompletableFutureList<>(futures);
return futureList.getMainFuture().thenAccept(unused -> {
self.setTexItemToDone(textItemId);
});
}
@Transactional
public void setTexItemToDone(Long id) {
Optional<TextItem> textItemOptional = textItemServiceManagementBean.findTextItemById(id);
textItemOptional.ifPresentOrElse(textItem -> {
log.info("Setting textItem with ID {} to done.", id);
textItem.setDone(true);
}, () -> log.info("TextItem {} not found.", id));
}
public void removeTextItem(Long id) {
log.info("Deleting text item with ID {}.", id);
textItemServiceManagementBean.deleteById(id);
}
}

View File

@@ -0,0 +1,56 @@
package dev.sheldan.sissi.module.miepscord.weeklytext.service.management;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.sissi.module.miepscord.weeklytext.model.database.TextItem;
import dev.sheldan.sissi.module.miepscord.weeklytext.repository.TextItemRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.security.SecureRandom;
import java.util.List;
import java.util.Optional;
@Component
public class TextItemServiceManagementBean {
@Autowired
private TextItemRepository textItemRepository;
@Autowired
private SecureRandom secureRandom;
public TextItem createTextItem(String text, AUserInAServer aUserInAServer) {
TextItem textItem = TextItem
.builder()
.text(text)
.creator(aUserInAServer)
.done(false)
.build();
return textItemRepository.save(textItem);
}
public Optional<TextItem> getNextTextItem() {
List<TextItem> allItems = textItemRepository.findByDoneFalseOrderByCreated();
if(allItems.isEmpty()) {
return Optional.empty();
} else {
return Optional.of(allItems.get(secureRandom.nextInt(allItems.size())));
}
}
public Optional<TextItem> findTextItemById(Long id) {
return textItemRepository.findById(id);
}
public void deleteById(Long id) {
textItemRepository.deleteById(id);
}
public List<TextItem> getAllTextItems() {
return textItemRepository.findAll();
}
public List<TextItem> getAllTextItemsWithDoneFlag(boolean done) {
return textItemRepository.findByDone(done);
}
}

View File

@@ -0,0 +1,4 @@
abstracto.featureFlags.weeklyText.featureName=weeklyText
abstracto.featureFlags.weeklyText.enabled=false
abstracto.postTargets.textItemTarget.name=textItemTarget

View File

@@ -0,0 +1,7 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,24 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
<property name="weeklyTextFeature" value="(SELECT id FROM feature WHERE key = 'weeklyText')"/>
<changeSet author="Sheldan" id="weeklyText-commands" >
<insert tableName="command">
<column name="name" value="addWeeklyText"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${weeklyTextFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="removeWeeklyText"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${weeklyTextFeature}"/>
</insert>
<insert tableName="command">
<column name="name" value="showWeeklyTexts"/>
<column name="module_id" valueComputed="${utilityModule}"/>
<column name="feature_id" valueComputed="${weeklyTextFeature}"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,8 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
<include file="command.xml" relativeToChangelogFile="true"/>
<include file="weekly_text_job.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="weeklyText_feature-insertion">
<insert tableName="feature">
<column name="key" value="weeklyText"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="weekly_text_job-insert">
<insert tableName="scheduler_job">
<column name="name" value="weeklyTextJob"/>
<column name="group_name" value="miepscord"/>
<column name="clazz" value="dev.sheldan.sissi.module.miepscord.weeklytext.job.WeeklyTextJob"/>
<column name="active" value="true"/>
<column name="cron_expression" value="0 0 14 ? * FRI *"/>
<column name="recovery" value="false"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="text_item.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,38 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="text_item-table">
<createTable tableName="text_item">
<column name="id" autoIncrement="true" type="BIGINT">
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_text_item"/>
</column>
<column name="text" type="VARCHAR">
<constraints nullable="false"/>
</column>
<column name="done" type="BOOLEAN">
<constraints nullable="false"/>
</column>
<column name="creator_id" type="BIGINT">
<constraints nullable="false"/>
</column>
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
<constraints nullable="true"/>
</column>
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
</createTable>
<addForeignKeyConstraint baseColumnNames="creator_id" baseTableName="text_item" constraintName="fk_text_item_creator"
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
<sql>
DROP TRIGGER IF EXISTS text_item_update_trigger ON text_item;
CREATE TRIGGER repost_check_channel_group_update_trigger BEFORE UPDATE ON text_item FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS text_item_insert_trigger ON text_item;
CREATE TRIGGER repost_check_channel_group_insert_trigger BEFORE INSERT ON text_item FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="1.4.61/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>application</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -3,13 +3,21 @@
<parent>
<groupId>dev.sheldan.sissi.application</groupId>
<artifactId>sissi-modules</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>quotes</artifactId>
<dependencies>
<dependency>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>starboard-int</artifactId>
<version>${abstracto.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
@@ -79,6 +80,7 @@ public class QuoteDelete extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(QuoteSlashCommandNames.QUOTE_INTERNAL)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.commandName("delete")
.build();

View File

@@ -53,7 +53,7 @@ public class QuoteStats extends AbstractConditionableCommand {
targetMember = (Member) parameters.get(0);
}
QuoteStatsModel model = quoteServiceBean.getQuoteStats(targetMember);
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannelList(QUOTE_STATS_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
return FutureUtils.toSingleFutureGeneric(channelService.sendEmbedTemplateInMessageChannel(QUOTE_STATS_RESPONSE_TEMPLATE_KEY, model, commandContext.getChannel()))
.thenApply(unused -> CommandResult.fromSuccess());
}

View File

@@ -5,7 +5,7 @@ import lombok.Getter;
@Getter
public enum QuotesFeatureDefinition implements FeatureDefinition {
QUOTES("quotes");
QUOTES("quotes"), STARBOARD_QUOTE_SYNC("starboardQuoteSync");
private String key;

View File

@@ -0,0 +1,13 @@
package dev.sheldan.sissi.module.quotes.config;
import dev.sheldan.abstracto.core.config.FeatureConfig;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import org.springframework.stereotype.Component;
@Component
public class StarboardQuoteSyncFeatureConfig implements FeatureConfig {
@Override
public FeatureDefinition getFeature() {
return QuotesFeatureDefinition.STARBOARD_QUOTE_SYNC;
}
}

View File

@@ -0,0 +1,54 @@
package dev.sheldan.sissi.module.quotes.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.core.service.MessageService;
import dev.sheldan.abstracto.starboard.listener.StarboardPostCreatedListener;
import dev.sheldan.abstracto.starboard.model.StarboardPostCreatedModel;
import dev.sheldan.sissi.module.quotes.config.QuotesFeatureDefinition;
import dev.sheldan.sissi.module.quotes.service.QuoteServiceBean;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.Message;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@Slf4j
@Component
public class StarboardPostCreatedListenerBean implements StarboardPostCreatedListener {
@Autowired
private MessageService messageService;
@Autowired
private QuoteServiceBean quoteServiceBean;
@Autowired
private StarboardPostCreatedListenerBean self;
@Override
public DefaultListenerResult execute(StarboardPostCreatedModel model) {
Long serverId = model.getServerId();
Long starboardPostId = model.getStarboardPostId();
messageService.loadMessage(serverId, model.getStarredMessage().getChannelId(), model.getStarredMessage().getMessageId())
.thenAccept(message -> self.storeQuote(message, model))
.exceptionally(throwable -> {
log.error("Failed to persist quote for starboard post {} in server {}.", starboardPostId, serverId, throwable);
return null;
});
return DefaultListenerResult.PROCESSED;
}
@Transactional
public void storeQuote(Message message, StarboardPostCreatedModel model) {
log.info("Creating quote from starboard post {} in server {} from user {} because of user {}.", model.getStarboardPostId(), model.getServerId(),
model.getStarredUser().getUserId(), model.getLastStarrer().getUserId());
quoteServiceBean.createQuote(model.getStarredUser(), model.getLastStarrer(), message);
}
@Override
public FeatureDefinition getFeature() {
return QuotesFeatureDefinition.STARBOARD_QUOTE_SYNC;
}
}

View File

@@ -0,0 +1,32 @@
package dev.sheldan.sissi.module.quotes.listener;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
import dev.sheldan.abstracto.starboard.listener.StarboardPostDeletedListener;
import dev.sheldan.abstracto.starboard.model.StarboardPostDeletedModel;
import dev.sheldan.sissi.module.quotes.config.QuotesFeatureDefinition;
import dev.sheldan.sissi.module.quotes.service.QuoteServiceBean;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Slf4j
@Component
public class StarboardPostDeletedListenerBean implements StarboardPostDeletedListener {
@Autowired
private QuoteServiceBean quoteServiceBean;
@Override
public DefaultListenerResult execute(StarboardPostDeletedModel model) {
log.info("Handling delete of starboard post {}, causing the quote of message {} in server {} to be deleted.", model.getStarboardPostId(), model.getStarredMessage().getMessageId(), model.getServerId());
quoteServiceBean.deleteByMessageId(model.getStarredMessage().getMessageId());
return DefaultListenerResult.PROCESSED;
}
@Override
public FeatureDefinition getFeature() {
return QuotesFeatureDefinition.STARBOARD_QUOTE_SYNC;
}
}

View File

@@ -21,12 +21,12 @@ import java.util.List;
@EqualsAndHashCode
public class Quote {
@EmbeddedId
@Getter
private ServerSpecificId id;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@MapsId("serverId")
@JoinColumn(name = "server_id", nullable = false)
private AServer server;
@@ -58,9 +58,9 @@ public class Quote {
@Column(name = "text")
private String text;
@Column(name = "created")
@Column(name = "created", insertable = false, updatable = false)
private Instant created;
@Column(name = "updated")
@Column(name = "updated", insertable = false, updatable = false)
private Instant updated;
}

View File

@@ -1,5 +1,6 @@
package dev.sheldan.sissi.module.quotes.model.database;
import dev.sheldan.abstracto.core.models.database.AServer;
import lombok.*;
import jakarta.persistence.*;
@@ -16,7 +17,7 @@ public class QuoteAttachment {
@Id
@Getter
@Setter
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false)
private Long id;
@@ -25,8 +26,7 @@ public class QuoteAttachment {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumns(
{
@JoinColumn(updatable = false, insertable = false, name = "quote_id", referencedColumnName = "id"),
@JoinColumn(updatable = false, insertable = false, name = "server_id", referencedColumnName = "server_id")
@JoinColumn(updatable = false, name = "quote_id", referencedColumnName = "id")
})
private Quote quote;
@@ -35,6 +35,10 @@ public class QuoteAttachment {
@Column(name = "url", nullable = false)
private String url;
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
@JoinColumn(name = "server_id", nullable = false)
private AServer server;
@Getter
@Setter
@Column(name = "is_image", nullable = false)

View File

@@ -1,6 +1,5 @@
package dev.sheldan.sissi.module.quotes.repository;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.sissi.module.quotes.model.database.Quote;
@@ -8,13 +7,16 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
import java.util.List;
import java.util.Optional;
@Repository
public interface QuoteRepository extends JpaRepository<Quote, ServerSpecificId> {
public interface QuoteRepository extends JpaRepository<Quote, Long> {
List<Quote> findByTextContainingAndServer(String text, AServer server);
List<Quote> findByTextContainingAndServerAndAuthor(String text, AServer server, AUserInAServer author);
List<Quote> findByServer(AServer server);
List<Quote> findByAuthor(AUserInAServer author);
Long countByAuthor(AUserInAServer author);
Long countByAdder(AUserInAServer adder);
Optional<Quote> findByMessageId(Long messageId);
}

View File

@@ -1,7 +1,7 @@
package dev.sheldan.sissi.module.quotes.service;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.ServerSpecificId;
import dev.sheldan.abstracto.core.models.ServerUser;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.ChannelService;
@@ -16,11 +16,12 @@ import dev.sheldan.sissi.module.quotes.model.command.QuoteResponseModel;
import dev.sheldan.sissi.module.quotes.model.command.QuoteStatsModel;
import dev.sheldan.sissi.module.quotes.model.database.Quote;
import dev.sheldan.sissi.module.quotes.model.database.QuoteAttachment;
import dev.sheldan.sissi.module.quotes.repository.QuoteRepository;
import dev.sheldan.sissi.module.quotes.service.management.QuoteManagementService;
import lombok.extern.slf4j.Slf4j;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.entities.channel.Channel;
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -35,9 +36,6 @@ import java.util.stream.Collectors;
@Slf4j
public class QuoteServiceBean {
@Autowired
private QuoteRepository quoteRepository;
@Autowired
private MemberService memberService;
@@ -56,11 +54,14 @@ public class QuoteServiceBean {
@Autowired
private ChannelService channelService;
@Autowired
private QuoteManagementService quoteManagementService;
private static final String QUOTE_RESPONSE_TEMPLATE_KEY = "quote_response";
public Optional<Quote> getRandomQuoteForMember(AUserInAServer aUserInAServer) {
// not nice, but good enough for now
List<Quote> allQuotes = quoteRepository.findByAuthor(aUserInAServer);
List<Quote> allQuotes = quoteManagementService.getFromAuthor(aUserInAServer);
if(allQuotes.isEmpty()) {
return Optional.empty();
}
@@ -69,7 +70,7 @@ public class QuoteServiceBean {
public Optional<Quote> getRandomQuote(AServer server) {
// not nice, but good enough for now
List<Quote> allQuotes = quoteRepository.findByServer(server);
List<Quote> allQuotes = quoteManagementService.getFromServer(server);
if(allQuotes.isEmpty()) {
return Optional.empty();
}
@@ -79,7 +80,7 @@ public class QuoteServiceBean {
public void deleteQuote(Long quoteId, AServer server) {
Optional<Quote> existingQuote = getQuote(quoteId, server);
if(existingQuote.isPresent()) {
quoteRepository.delete(existingQuote.get());
quoteManagementService.deleteQuote(existingQuote.get());
log.info("Deleting quote with id {} in server {}.", quoteId, server.getId());
} else {
throw new QuoteNotFoundException();
@@ -87,9 +88,8 @@ public class QuoteServiceBean {
}
public Optional<Quote> getQuote(Long quoteId, AServer server) {
ServerSpecificId id = new ServerSpecificId(server.getId(), quoteId);
log.info("Loading quote with id {} in server {}.", quoteId, server.getId());
return quoteRepository.findById(id);
return quoteManagementService.getQuote(quoteId);
}
public CompletableFuture<MessageToSend> renderQuoteToMessageToSend(Quote quote) {
@@ -118,7 +118,7 @@ public class QuoteServiceBean {
.builder()
.quoteContent(quote.getText())
.imageAttachmentURLs(imageAttachments)
.quoteId(quote.getId().getId())
.quoteId(quote.getId())
.fileAttachmentURLs(fileAttachments)
.creationDate(quote.getCreated())
.quotedMessage(quotedMessage);
@@ -209,7 +209,7 @@ public class QuoteServiceBean {
}
public Optional<Quote> searchQuote(String query, AServer server) {
List<Quote> foundQuotes = quoteRepository.findByTextContainingAndServer(query, server);
List<Quote> foundQuotes = quoteManagementService.getQuotesWithTextInServer(query, server);
if(foundQuotes.isEmpty()) {
return Optional.empty();
}
@@ -224,7 +224,7 @@ public class QuoteServiceBean {
public Optional<Quote> searchQuote(String query, AServer server, Member targetMember) {
AUserInAServer author = userInServerManagementService.loadOrCreateUser(targetMember);
List<Quote> foundQuotes = quoteRepository.findByTextContainingAndServerAndAuthor(query, server, author);
List<Quote> foundQuotes = quoteManagementService.getQuotesWithTextInServerFromAuthor(query, server, author);
if(foundQuotes.isEmpty()) {
return Optional.empty();
}
@@ -242,8 +242,8 @@ public class QuoteServiceBean {
return getQuoteStats(user, member);
}
public QuoteStatsModel getQuoteStats(AUserInAServer user, Member member) {
Long authored = quoteRepository.countByAuthor(user);
Long added = quoteRepository.countByAdder(user);
Long authored = quoteManagementService.getAmountOfQuotesOfAuthor(user);
Long added = quoteManagementService.getAmountOfQuotesOfAdder(user);
return QuoteStatsModel
.builder()
.quoteCount(added)
@@ -253,4 +253,21 @@ public class QuoteServiceBean {
.serverId(user.getServerReference().getId())
.build();
}
public Quote createQuote(ServerUser authorUser, ServerUser adderUser, Message quoteMessage) {
AUserInAServer author = userInServerManagementService.loadOrCreateUser(authorUser);
AUserInAServer adder = userInServerManagementService.loadOrCreateUser(adderUser);
List<Pair<String, Boolean>> attachments = quoteMessage
.getAttachments()
.stream()
.map(attachment -> Pair.of(attachment.getProxyUrl(), attachment.isImage()))
.toList();
return quoteManagementService.createQuote(author, adder, quoteMessage.getContentDisplay(), ServerChannelMessage.fromMessage(quoteMessage), attachments);
}
public void deleteByMessageId(Long messageId) {
Quote quote = quoteManagementService.findByMessage(messageId).orElseThrow(QuoteNotFoundException::new);
log.info("Deleting quote {} in server {}.", quote.getId(), quote.getServer().getId());
quoteManagementService.deleteQuote(quote);
}
}

View File

@@ -0,0 +1,94 @@
package dev.sheldan.sissi.module.quotes.service.management;
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
import dev.sheldan.abstracto.core.models.database.AChannel;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
import dev.sheldan.sissi.module.quotes.model.database.Quote;
import dev.sheldan.sissi.module.quotes.model.database.QuoteAttachment;
import dev.sheldan.sissi.module.quotes.repository.QuoteRepository;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Optional;
@Component
@Slf4j
public class QuoteManagementService {
@Autowired
private QuoteRepository quoteRepository;
@Autowired
private ChannelManagementService channelManagementService;
public Quote createQuote(AUserInAServer author, AUserInAServer adder, String messageText, ServerChannelMessage quotedMessage, List<Pair<String, Boolean>> attachments) {
AChannel channel = channelManagementService.loadChannel(quotedMessage.getChannelId());
Quote quote = Quote
.builder()
.adder(adder)
.author(author)
.text(messageText)
.messageId(quotedMessage.getMessageId())
.server(adder.getServerReference())
.sourceChannel(channel)
.build();
List<QuoteAttachment> quoteAttachments = attachments
.stream()
.map(stringBooleanPair -> QuoteAttachment
.builder()
.url(stringBooleanPair.getLeft())
.quote(quote)
.server(adder.getServerReference())
.isImage(stringBooleanPair.getRight())
.build())
.toList();
log.info("Creating quote from {} added by {} in server {}.", author.getUserReference().getId(), adder.getUserReference().getId(), author.getServerReference().getId());
quote.setAttachments(quoteAttachments);
return quoteRepository.save(quote);
}
public List<Quote> getFromAuthor(AUserInAServer author) {
return quoteRepository.findByAuthor(author);
}
public List<Quote> getFromServer(AServer aServer) {
return quoteRepository.findByServer(aServer);
}
public void deleteQuote(Quote quote) {
quoteRepository.delete(quote);
}
public Optional<Quote> getQuote(Long quoteId) {
return quoteRepository.findById(quoteId);
}
public List<Quote> getQuotesWithTextInServer(String text, AServer server) {
return quoteRepository.findByTextContainingAndServer(text, server);
}
public List<Quote> getQuotesWithTextInServerFromAuthor(String text, AServer server, AUserInAServer aUserInAServer) {
return quoteRepository.findByTextContainingAndServerAndAuthor(text, server, aUserInAServer);
}
public Long getAmountOfQuotesOfAuthor(AUserInAServer aUserInAServer) {
return quoteRepository.countByAuthor(aUserInAServer);
}
public Long getAmountOfQuotesOfAdder(AUserInAServer aUserInAServer) {
return quoteRepository.countByAdder(aUserInAServer);
}
public Optional<Quote> findByMessage(Long messageId) {
return quoteRepository.findByMessageId(messageId);
}
}

View File

@@ -0,0 +1,7 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="feature.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,10 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="starboard_quote_sync_feature-insertion">
<insert tableName="feature">
<column name="key" value="starboardQuoteSync"/>
</insert>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,16 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="quote-add_tracking_columns">
<sql>
DROP TRIGGER IF EXISTS quote_update_trigger ON quote;
CREATE TRIGGER quote_update_trigger BEFORE UPDATE ON quote FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
</sql>
<sql>
DROP TRIGGER IF EXISTS quote_insert_trigger ON quote;
CREATE TRIGGER quote_insert_trigger BEFORE INSERT ON quote FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
</sql>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="quote.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -0,0 +1,11 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<changeSet author="Sheldan" id="quote_attachment-longer_attachment_url">
<modifyDataType columnName="url"
newDataType="VARCHAR(4096)"
tableName="quote_attachment"/>
</changeSet>
</databaseChangeLog>

View File

@@ -0,0 +1,6 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="quote_attachment.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -3,4 +3,6 @@
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog https://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.26.xsd" >
<include file="1.0.2/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.56/collection.xml" relativeToChangelogFile="true"/>
<include file="1.4.57/collection.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>

View File

@@ -1,2 +1,5 @@
abstracto.featureFlags.quotes.featureName=quotes
abstracto.featureFlags.quotes.enabled=false
abstracto.featureFlags.starboardQuoteSync.featureName=starboardQuoteSync
abstracto.featureFlags.starboardQuoteSync.enabled=false

View File

@@ -3,7 +3,7 @@
<parent>
<artifactId>sissi-modules</artifactId>
<groupId>dev.sheldan.sissi.application</groupId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
@@ -70,6 +71,7 @@ public class CreateNewsCategory extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("category")
.commandName("create")
.build();

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
@@ -97,6 +98,7 @@ public class CreateNewsCategoryChannelMapping extends AbstractConditionableComma
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("categorychannelmapping")
.commandName("create")
.build();

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
@@ -127,6 +128,7 @@ public class CreateNewsCategorySubscription extends AbstractConditionableCommand
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("categorysubscription")
.commandName("create")
.build();

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.abstracto.core.models.database.AServer;
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
@@ -70,6 +71,7 @@ public class DeleteNewsCategory extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("category")
.commandName("delete")
.build();

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
@@ -96,6 +97,7 @@ public class DeleteNewsCategoryChannelMapping extends AbstractConditionableComma
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("categorychannelmapping")
.commandName("delete")
.build();

View File

@@ -9,6 +9,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
@@ -127,6 +128,7 @@ public class DeleteNewsCategorySubscription extends AbstractConditionableCommand
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("categorysubscription")
.commandName("delete")
.build();

View File

@@ -8,6 +8,7 @@ import dev.sheldan.abstracto.core.command.execution.CommandResult;
import dev.sheldan.abstracto.core.config.FeatureDefinition;
import dev.sheldan.abstracto.core.interaction.InteractionService;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandPrivilegeLevels;
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
import dev.sheldan.sissi.module.rssnews.model.template.NewsCategoryInfo;
@@ -54,6 +55,7 @@ public class ShowNewsCategories extends AbstractConditionableCommand {
.builder()
.enabled(true)
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
.defaultPrivilege(SlashCommandPrivilegeLevels.INVITER)
.groupName("category")
.commandName("show")
.build();

View File

@@ -2,4 +2,4 @@ apiVersion: v2
name: sissi
description: A Helm chart for Kubernetes
type: application
version: 1.4.46
version: 1.5.3

View File

@@ -7,4 +7,5 @@ data:
youtubeApiKey: {{ $.Values.apiKeys.youtube.apiKey | b64enc }}
twitchClientId: {{ $.Values.apiKeys.twitch.clientId | b64enc }}
twitchSecret: {{ $.Values.apiKeys.twitch.secret | b64enc }}
openWeatherMapApiKey: {{ $.Values.apiKeys.openWeatherMap.apiKey | b64enc }}
openWeatherMapApiKey: {{ $.Values.apiKeys.openWeatherMap.apiKey | b64enc }}
freeCurrencyApiApiKey: {{ $.Values.apiKeys.freeCurrencyApi.apiKey | b64enc }}

View File

@@ -61,6 +61,8 @@ spec:
value: {{ .Values.dbCredentials.schema }}
- name: DEBRA_DONATION_NOTIFICATION_SERVER_ID
value: "297910194841583616"
- name: WEEKLY_TEXT_SERVER_ID
value: "{{ .Values.bot.config.weeklyTextServerId }}"
- name: TOKEN
valueFrom:
secretKeyRef:
@@ -76,6 +78,11 @@ spec:
secretKeyRef:
name: api-keys
key: openWeatherMapApiKey
- name: FREE_CURRENCY_API_API_KEY
valueFrom:
secretKeyRef:
name: api-keys
key: freeCurrencyApiApiKey
- name: TWITCH_CLIENT_ID
valueFrom:
secretKeyRef:
@@ -90,6 +97,8 @@ spec:
value: "{{ .Values.privateRestApi.service.name }}.{{ .Release.Namespace }}.svc.cluster.local"
- name: PRIVATE_REST_API_PORT
value: "{{ .Values.privateRestApi.service.targetPort }}"
- name: FRONTEND_BASE
value: "https://{{ .Values.bot.host }}"
{{- range $key, $value := .Values.bot.propertyConfig }}
- name: {{ $key | quote }}
value: {{ $value | quote}}

View File

@@ -3,7 +3,7 @@ bot:
repository: harbor.sheldan.dev/sissi
pullPolicy: Always
image: sissi-bot
tag: 1.4.46
tag: 1.5.3
livenessProbe:
initialDelaySeconds: 60
periodSeconds: 5
@@ -14,12 +14,15 @@ bot:
failureThreshold: 3
propertyConfig:
hikariPoolSize: 10
host: null
config:
weeklyTextServerId: null
restApi:
enabled: true
repository: harbor.sheldan.dev/sissi
pullPolicy: Always
image: sissi-rest-api
tag: 1.4.46
tag: 1.5.3
podAnnotations: {}
podSecurityContext: {}
securityContext: {}
@@ -59,7 +62,7 @@ privateRestApi:
repository: harbor.sheldan.dev/sissi
pullPolicy: Always
image: sissi-private-rest-api
tag: 1.4.46
tag: 1.5.3
podAnnotations: {}
podSecurityContext: {}
securityContext: {}
@@ -90,23 +93,23 @@ templateDeployment:
repository: harbor.sheldan.dev/abstracto
pullPolicy: Always
image: abstracto-template-deployment
tag: 1.5.28
tag: 1.6.7
templateDeploymentData:
repository: harbor.sheldan.dev/sissi
pullPolicy: Always
image: sissi-template-data
tag: 1.4.46
tag: 1.5.3
dbConfigDeployment:
enabled: true
repository: harbor.sheldan.dev/abstracto
pullPolicy: Always
image: abstracto-db-deployment
tag: 1.5.28
tag: 1.6.7
dbConfigDeploymentData:
repository: harbor.sheldan.dev/sissi
pullPolicy: Always
image: sissi-db-data
tag: 1.4.46
tag: 1.5.3
dbCredentials:
host: null
port: null
@@ -135,6 +138,8 @@ apiKeys:
twitch:
secret: null
clientId: null
freeCurrencyApi:
apiKey: null
imagePullSecrets: null
nameOverride: ''
fullnameOverride: ''

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>deployment</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -263,6 +263,17 @@
<destFileName>meetup.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>miepscord-templates</artifactId>
<version>${project.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/template-data/template-artifacts/</outputDirectory>
<destFileName>miepscord.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.templates</groupId>
<artifactId>debra-templates</artifactId>
@@ -519,6 +530,16 @@
<destFileName>meetup.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>miepscord-translations</artifactId>
<version>${project.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/template-data/translation-artifacts/</outputDirectory>
<destFileName>miepscord.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.templates.translations</groupId>
<artifactId>debra-translations</artifactId>
@@ -631,17 +652,6 @@
<destFileName>assignable-roles.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>utility-impl</artifactId>
<version>${abstracto.version}</version>
<classifier>liquibase</classifier>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/db-data/liquibase-artifacts/</outputDirectory>
<destFileName>utility.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.abstracto.modules</groupId>
<artifactId>modmail-impl</artifactId>
@@ -765,6 +775,17 @@
<destFileName>meetup.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>miepscord</artifactId>
<version>${project.version}</version>
<classifier>liquibase</classifier>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/db-data/liquibase-artifacts/</outputDirectory>
<destFileName>miepscord.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.application.module</groupId>
<artifactId>rss-news</artifactId>
@@ -896,6 +917,16 @@
<destFileName>logging-translation-overrides.zip</destFileName>
</artifactItem>
<artifactItem>
<groupId>dev.sheldan.sissi.templates.translations.overrides</groupId>
<artifactId>giveaway-translation-overrides</artifactId>
<version>${project.version}</version>
<type>zip</type>
<overWrite>true</overWrite>
<outputDirectory>${file.basedir}/template-data/translation-artifacts/</outputDirectory>
<destFileName>giveaway-translation-overrides.zip</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>

View File

@@ -13,6 +13,7 @@
{ "zip": "meetup", "file": "meetup-changeLog.xml"},
{ "zip": "rss-news", "file": "rssNews-changeLog.xml"},
{ "zip": "debra", "file": "debra-changeLog.xml"},
{ "zip": "miepscord", "file": "miepscord-changeLog.xml"},
{ "zip": "moderation", "file": "moderation-changeLog.xml"},
{ "zip": "entertainment", "file": "entertainment-changeLog.xml"},
{ "zip": "custom-command", "file": "custom-command-changeLog.xml"},

View File

@@ -1,8 +1,32 @@
FROM amazoncorretto:17.0.8-alpine3.18
MAINTAINER Sheldan
VOLUME /tmp
ADD config/* /config/
ADD wrapper/*.sh /
# https://careers.wolt.com/en/blog/tech/how-to-reduce-jvm-docker-image-size
FROM amazoncorretto:17.0.14-alpine3.20 AS corretto-jdk
RUN apk add --no-cache binutils
RUN $JAVA_HOME/bin/jlink \
--verbose \
--add-modules ALL-MODULE-PATH \
--strip-debug \
--no-man-pages \
--no-header-files \
--compress=2 \
--output /customjre
FROM alpine:3.21
ENV JAVA_HOME=/jre
ENV PATH="${JAVA_HOME}/bin:${PATH}"
COPY --from=corretto-jdk /customjre $JAVA_HOME
ARG APPLICATION_USER=appuser
RUN adduser --no-create-home -u 1000 -D $APPLICATION_USER
RUN mkdir /app && chown -R $APPLICATION_USER /app
COPY --chown=1000:1000 config/* /config/
COPY --chown=1000:1000 wrapper/*.sh /
RUN chmod +x /start.sh
ADD bot/app.jar /app.jar
COPY --chown=1000:1000 bot/app.jar /app.jar
CMD ["/start.sh"]

View File

@@ -3,7 +3,7 @@
"core","starboard", "link-embed", "moderation", "entertainment", "custom-command", "utility", "webservices", "remind",
"suggestion", "modmail", "assignable-roles", "experience-tracking", "logging", "statistic", "twitch", "giveaway", "sticky-roles",
"image-generation",
"quotes", "meetup", "debra", "rss-news",
"quotes", "meetup", "debra", "rss-news", "miepscord",
"moderation-custom", "image-generation-custom",
"moderation-template-overrides", "experience-template-overrides", "logging-template-overrides"
],
@@ -12,9 +12,9 @@
"starboard", "link-embed", "moderation", "entertainment", "custom-command", "utility", "webservices",
"suggestion", "remind", "modmail", "assignable-roles", "experience-tracking", "logging", "statistic", "twitch", "giveaway", "sticky-roles",
"image-generation",
"quotes", "meetup", "debra", "rss-news",
"quotes", "meetup", "debra", "rss-news", "miepscord",
"moderation-custom",
"moderation-translation-overrides", "experience-translation-overrides", "logging-translation-overrides"
"moderation-translation-overrides", "experience-translation-overrides", "logging-translation-overrides", "giveaway-translation-overrides"
]
}

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@@ -44,4 +44,4 @@ services:
template-data:
build:
context: deployment/image-packaging/src/main/docker/template-data
image: ${REGISTRY_PREFIX}sissi-template-data:${VERSION:-latest}
image: ${REGISTRY_PREFIX}sissi-template-data:${VERSION:-latest}

View File

@@ -13,13 +13,13 @@
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<name>Sissi</name>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
<properties>
<maven.compiler.target>17</maven.compiler.target>
<maven.compiler.source>17</maven.compiler.source>
<abstracto.version>1.5.28</abstracto.version>
<abstracto.templates.version>1.4.35</abstracto.templates.version>
<abstracto.version>1.6.7</abstracto.version>
<abstracto.templates.version>1.4.55</abstracto.templates.version>
<apache-jena.version>4.9.0</apache-jena.version>
<rssreader.version>3.5.0</rssreader.version>
</properties>
@@ -28,6 +28,7 @@
<module>application</module>
<module>templates</module>
<module>deployment</module>
<module>application/sissi-modules/miepscord</module>
</modules>
<repositories>
@@ -72,7 +73,7 @@
<connection>scm:git:${project.scm.url}</connection>
<developerConnection>scm:git:${project.scm.url}</developerConnection>
<url>https://github.com/Sheldan/Sissi.git</url>
<tag>HEAD</tag>
<tag>sissi-1.5.4</tag>
</scm>
</project>

View File

@@ -0,0 +1,30 @@
import sqlalchemy as db
import os
from starboard_loader import load_all_starboard_posts
from post_loader import enrich_posts
from quote_importer import import_quotes, fix_quote_created
db_host = os.getenv('DB_HOST')
db_port = os.getenv('DB_PORT')
db_database = os.getenv('DB_NAME')
db_user = os.getenv('DB_USER')
db_password = os.getenv('DB_PASS')
engine = db.create_engine('postgresql://%s:%s@%s:%s/%s' % (db_user, db_password, db_host, db_port, db_database))
with engine.connect() as con:
posts = load_all_starboard_posts(con)
sub_posts = chunks = [posts[x:x+100] for x in range(0, len(posts), 100)]
print(f'Loaded {len(posts)} into {len(sub_posts)} partitions')
counter = 0
for sub_post in sub_posts:
print(f'Partition size {len(sub_post)}')
enriched_posts = enrich_posts(sub_post)
print(f'Enriched posts')
import_quotes(enriched_posts, con)
print(f'Done storing quotes')
con.commit()
fix_quote_created(enriched_posts, con)
con.commit()
counter += 1
print(f'Done. {counter}')

View File

@@ -0,0 +1,32 @@
import requests
import os
import json
import time
token = os.getenv('TOKEN')
image_extension = ["jpg", "jpeg", "png", "gif", "webp", "tiff", "svg", "apng"]
def enrich_posts(posts):
for post in posts:
print(f"Loading post {post['message_id']}")
url = f"https://discord.com/api/v10/channels/{post['channel_id']}/messages/{post['message_id']}"
message = requests.get(url, headers={'Authorization': token})
time.sleep(1)
if message.status_code == 200:
message_obj = json.loads(message.content)
post['content'] = message_obj['content']
attachments = []
attachment_objs = message_obj['attachments']
if len(attachment_objs) > 0:
for attachment in attachment_objs:
extension = attachment['filename'][attachment['filename'].rfind('.') + 1]
attachment = {
'url': attachment['proxy_url'],
'is_image': extension.lower() in image_extension
}
attachments.append(attachment)
post['attachments'] = attachments
else:
print(f"{post['message_id']}: Didnt find post {url}: {message.status_code}")
return posts

View File

@@ -0,0 +1,26 @@
from sqlalchemy.sql import text
def import_quotes(posts, con):
for post in posts:
if 'content' not in post:
print(f"Skipping {post['message_id']} because no content, did it fail?")
continue
print(f"Inserting {post['message_id']}")
statement = text("""INSERT INTO quote(author_user_in_server_id, adder_user_in_server_id, source_channel_id,
server_id, message_id, text, created)
VALUES(:author_id, :adder_id, :channel_id, :server_id, :message_id, :content, :created) returning id""")
quote_id = con.execute(statement, {'author_id': post['author_id'], 'adder_id': post['adder_id'], 'channel_id': post['channel_id'], 'server_id': post['server_id'],
'message_id': post['message_id'], 'content': post['content'], 'created': post['created']}).fetchone()[0]
print(f'Created quote {quote_id}')
for attachment in post['attachments']:
statement = text("""INSERT INTO quote_attachment(quote_id, server_id, url, is_image)
VALUES(:quote_id, :server_id, :url, :is_image)""")
con.execute(statement, {'quote_id': quote_id, 'server_id': post['server_id'], 'url': attachment['url'], 'is_image': attachment['is_image']})
post['quote_id'] = quote_id
# the insert trigger always updated created, we have to re-do it (will be changed, but not for now)
def fix_quote_created(posts, con):
for post in posts:
if 'quote_id' in post:
statement = text("""update quote set created = :created where id = :quote_id""")
con.execute(statement, {'created': post['created'], 'quote_id': post['quote_id']})

View File

@@ -0,0 +1,30 @@
from sqlalchemy.sql import text
def load_all_starboard_posts(conn):
squery = text("""select distinct sp.id, sp.author_user_in_server_id, sp.source_channel_id, sp.server_id, sp.post_message_id, spr.reactor_user_in_server_id, sp.created
from starboard_post sp
inner join starboard_post_reaction spr
on sp.id = spr.post_id
and spr.reactor_user_in_server_id = (
select reactor_user_in_server_id
from starboard_post_reaction spr2
where spr2.post_id = sp.id
order by created limit 1
)
where sp.ignored = false
and sp.post_message_id not in (select message_id from quote)
""")
rs = conn.execute(squery)
found_posts = []
for post in rs:
found_posts.append({
'post_id': post[0],
'channel_id': post[2],
'message_id': post[4],
'adder_id': post[5],
'author_id': post[1],
'server_id': post[3],
'created': post[6]
})
return found_posts

View File

@@ -3,7 +3,7 @@
<parent>
<groupId>dev.sheldan.sissi</groupId>
<artifactId>sissi</artifactId>
<version>1.4.47-SNAPSHOT</version>
<version>1.5.4</version>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -13,6 +13,7 @@
<modules>
<module>sissi-templates</module>
<module>sissi-translations</module>
<module>sissi-templates/module-templates/miepscord-templates</module>
</modules>

Some files were not shown because too many files have changed in this diff Show More