mirror of
https://github.com/Sheldan/Sissi.git
synced 2026-01-26 19:21:43 +00:00
Compare commits
502 Commits
hotfix/1.0
...
release-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7faafc9ad1 | ||
|
|
1de0cae589 | ||
|
|
dfbf15ad61 | ||
|
|
db271cd448 | ||
|
|
8f289baadd | ||
|
|
2ee5578f4e | ||
|
|
b458d8d3a8 | ||
|
|
f8353ca19b | ||
|
|
023b22b2c2 | ||
|
|
9ada2c39a2 | ||
|
|
d61d378a6a | ||
|
|
09af4b516f | ||
|
|
0e50a7b826 | ||
|
|
d4dc118f66 | ||
|
|
be35a84dcf | ||
|
|
5f6df14c24 | ||
|
|
a60cf5d745 | ||
|
|
6e7ae8b36f | ||
|
|
3f22955df2 | ||
|
|
938f9e5cd4 | ||
|
|
45516f2458 | ||
|
|
9d9c8beb88 | ||
|
|
427250e0bc | ||
|
|
35d20be13b | ||
|
|
693bc2cd2c | ||
|
|
c62757590a | ||
|
|
1b2d326655 | ||
|
|
180c2681e0 | ||
|
|
80d0552d65 | ||
|
|
f76f8afef5 | ||
|
|
8bf9fe6c45 | ||
|
|
de8301750a | ||
|
|
555c60caad | ||
|
|
0481deae4a | ||
|
|
edb887f51a | ||
|
|
4dc424b87a | ||
|
|
290e59f8da | ||
|
|
aca7e3449c | ||
|
|
aa1a7344de | ||
|
|
faa85173cc | ||
|
|
2ee2907c72 | ||
|
|
51d9ec2931 | ||
|
|
dc801dc220 | ||
|
|
71aaa31fa1 | ||
|
|
80a56f4426 | ||
|
|
9f3d1a0080 | ||
|
|
ecf30513b1 | ||
|
|
4f9369ce22 | ||
|
|
c0369d6cf3 | ||
|
|
0bd4082f72 | ||
|
|
cda1b2d61c | ||
|
|
e9d2ceb2af | ||
|
|
3c9e8606fa | ||
|
|
f726a4ca95 | ||
|
|
311eb7d3fa | ||
|
|
7c47159508 | ||
|
|
5edba2c037 | ||
|
|
e6b35af78a | ||
|
|
f11f74507d | ||
|
|
9bdc023e99 | ||
|
|
f343a5a280 | ||
|
|
2312892f0a | ||
|
|
d69c4b5b79 | ||
|
|
2ffa0feb3f | ||
|
|
5a3b7216fc | ||
|
|
5676d7291c | ||
|
|
f6452077f0 | ||
|
|
2602d073d3 | ||
|
|
d85ebedfcc | ||
|
|
841bfc19ac | ||
|
|
d02f2d3088 | ||
|
|
c164969afb | ||
|
|
af37454918 | ||
|
|
5e915713e2 | ||
|
|
1f7ffc16e2 | ||
|
|
3734d271f0 | ||
|
|
f219c4ab54 | ||
|
|
2c984cd183 | ||
|
|
d06a1db108 | ||
|
|
6125f39670 | ||
|
|
c020a3a0f2 | ||
|
|
91a0265e6e | ||
|
|
a822c5486f | ||
|
|
fd50050870 | ||
|
|
9a5e6e1df2 | ||
|
|
423bf33402 | ||
|
|
f9b193a95b | ||
|
|
b46c8a1348 | ||
|
|
109a770524 | ||
|
|
3001b14782 | ||
|
|
49932641b3 | ||
|
|
829d6cc136 | ||
|
|
c28a864a47 | ||
|
|
fae50c2914 | ||
|
|
8f80df1484 | ||
|
|
1b5ed0d70d | ||
|
|
098d748b96 | ||
|
|
075f3b3201 | ||
|
|
d5e996e1d0 | ||
|
|
198054ecfe | ||
|
|
efcf93492b | ||
|
|
564e22d948 | ||
|
|
29a1473073 | ||
|
|
208dd8c893 | ||
|
|
752be470e8 | ||
|
|
b9cee83afd | ||
|
|
ed9bf49e19 | ||
|
|
8fe46f6172 | ||
|
|
1bc47d962e | ||
|
|
b9ce6f22a7 | ||
|
|
45b8c3c588 | ||
|
|
ba5f34d667 | ||
|
|
1f5ed1b623 | ||
|
|
170588d638 | ||
|
|
4d69a90d5d | ||
|
|
19ed221329 | ||
|
|
5ba3036e1d | ||
|
|
25a4d47dc0 | ||
|
|
3347fdd8f1 | ||
|
|
47eef33850 | ||
|
|
583a49df5b | ||
|
|
ca938a0164 | ||
|
|
e22f94ff1e | ||
|
|
307c9eac67 | ||
|
|
6002c979d9 | ||
|
|
df49c313a4 | ||
|
|
68bf6b5062 | ||
|
|
29eb743c35 | ||
|
|
03f9b64db2 | ||
|
|
212bc09d90 | ||
|
|
e1f327a687 | ||
|
|
7af0d2db1c | ||
|
|
b4f740fcf6 | ||
|
|
dda7ed7db8 | ||
|
|
af006ee880 | ||
|
|
125febc02a | ||
|
|
13f92247cf | ||
|
|
79ed55d988 | ||
|
|
7bc04a7906 | ||
|
|
89d743987d | ||
|
|
32ddd4e6f0 | ||
|
|
68afc31b2e | ||
|
|
d0ba46c440 | ||
|
|
554d197ca4 | ||
|
|
8826796fcb | ||
|
|
c8ed0e2195 | ||
|
|
25d19bfa26 | ||
|
|
f7e19b580e | ||
|
|
5f6bd0d88e | ||
|
|
a110c54411 | ||
|
|
a4a729dfc2 | ||
|
|
85eee4835f | ||
|
|
cab11140fa | ||
|
|
5854ca2ba7 | ||
|
|
3f613eeddf | ||
|
|
5fda777a62 | ||
|
|
e447eca9dd | ||
|
|
17e2e09541 | ||
|
|
1ea2cc02c8 | ||
|
|
3a1071b65e | ||
|
|
32274561e9 | ||
|
|
b3550549de | ||
|
|
eef245ede0 | ||
|
|
6ac950358f | ||
|
|
01c59f5059 | ||
|
|
be0325deb9 | ||
|
|
f8d84ff943 | ||
|
|
5ec3b3a1f4 | ||
|
|
fef1a5f0ae | ||
|
|
db89b59600 | ||
|
|
3ca37c448d | ||
|
|
b6a416135a | ||
|
|
ed181a2bc3 | ||
|
|
2ee2cb18f5 | ||
|
|
d0908e7315 | ||
|
|
7c6809500a | ||
|
|
a6e3f2df17 | ||
|
|
6b35a75539 | ||
|
|
32ed3bff5d | ||
|
|
30765ee80a | ||
|
|
91a1807abe | ||
|
|
2567c139ae | ||
|
|
1f141d53de | ||
|
|
0bd1e7d120 | ||
|
|
927f0f8ab2 | ||
|
|
c2df483301 | ||
|
|
90c36cc506 | ||
|
|
376a34fc2e | ||
|
|
5ed0c89014 | ||
|
|
2351787221 | ||
|
|
ca6e64832a | ||
|
|
8334562e2b | ||
|
|
07b4de5df8 | ||
|
|
17933f9a22 | ||
|
|
12d564e5cd | ||
|
|
e097fbe0ef | ||
|
|
8639038be2 | ||
|
|
295abaf4cf | ||
|
|
de478506fc | ||
|
|
b0b3db0a44 | ||
|
|
ed5e4ea5a7 | ||
|
|
627229ebd9 | ||
|
|
f4300070b9 | ||
|
|
725a0c4f2c | ||
|
|
1fbeb880b7 | ||
|
|
7a327deab9 | ||
|
|
a1f0cf58b9 | ||
|
|
2e7caa80bb | ||
|
|
32e80a5b84 | ||
|
|
96a230f347 | ||
|
|
88a4d45d22 | ||
|
|
858317a7f4 | ||
|
|
b69c873efe | ||
|
|
c93be84aef | ||
|
|
a61a128236 | ||
|
|
a1b2700092 | ||
|
|
da7cc2f6a7 | ||
|
|
4cb118339f | ||
|
|
11460f1e19 | ||
|
|
c9b856b300 | ||
|
|
c513087d30 | ||
|
|
8a110215f1 | ||
|
|
90b9c3674c | ||
|
|
68771a7b26 | ||
|
|
72e7bb57e3 | ||
|
|
3e147a37d9 | ||
|
|
99dca4906a | ||
|
|
32bfefc5b2 | ||
|
|
aa135b4663 | ||
|
|
4ffb5e5640 | ||
|
|
9376ac416f | ||
|
|
7cf44c99b7 | ||
|
|
5dce059d2b | ||
|
|
da30a120d7 | ||
|
|
49875b2467 | ||
|
|
2236710086 | ||
|
|
99b266e94a | ||
|
|
974ab230ac | ||
|
|
e5239f971c | ||
|
|
23db0b7c9e | ||
|
|
8167accd34 | ||
|
|
375045f508 | ||
|
|
3f4d5510d8 | ||
|
|
ba67f65bea | ||
|
|
1b7c2263ae | ||
|
|
f065bf5244 | ||
|
|
e036fd0867 | ||
|
|
96960d77ac | ||
|
|
3894d4567e | ||
|
|
503fd2520d | ||
|
|
58d6b12a67 | ||
|
|
4128274a7d | ||
|
|
3b498c5d3f | ||
|
|
c6bdcaa84c | ||
|
|
90f3dd0ae9 | ||
|
|
cd482d640f | ||
|
|
ae2f88daa3 | ||
|
|
c13f40fd3b | ||
|
|
37147a866f | ||
|
|
9a7d0613b1 | ||
|
|
7e60447ae6 | ||
|
|
e4a899a125 | ||
|
|
ce8341e69a | ||
|
|
fa6333fa49 | ||
|
|
3393dea591 | ||
|
|
3c3bdfaed9 | ||
|
|
172e3c4190 | ||
|
|
52b86804b9 | ||
|
|
de8d9982f3 | ||
|
|
29e1b22783 | ||
|
|
5852d4837e | ||
|
|
b345fa5502 | ||
|
|
d6470e3714 | ||
|
|
b4cebe2b41 | ||
|
|
f3dd85d7d5 | ||
|
|
db318afb2b | ||
|
|
ddd710d1c2 | ||
|
|
81824db1f1 | ||
|
|
0390d7c8ca | ||
|
|
61412f434c | ||
|
|
12e69a18fb | ||
|
|
170ddd9c33 | ||
|
|
de8bbdcbee | ||
|
|
b5bf53fb6a | ||
|
|
159326dde3 | ||
|
|
7124d4e1d8 | ||
|
|
c6f20d617d | ||
|
|
7449c05462 | ||
|
|
6bd0f0eaa2 | ||
|
|
9b8a3bcc1e | ||
|
|
7b11a88256 | ||
|
|
30289e1166 | ||
|
|
0bab3bbe69 | ||
|
|
6f75c76fc4 | ||
|
|
0d9aa4ae64 | ||
|
|
c6b0bf582b | ||
|
|
dcd94ba5c0 | ||
|
|
98ae8ada8b | ||
|
|
96d3918a4d | ||
|
|
0d6f71baac | ||
|
|
d3421a6f95 | ||
|
|
0722bd6320 | ||
|
|
a910870259 | ||
|
|
18cc97600f | ||
|
|
a1ea57a0f3 | ||
|
|
23b554c93f | ||
|
|
5671c5019a | ||
|
|
fbb0876c7f | ||
|
|
bbaee9a47a | ||
|
|
b9f2a06173 | ||
|
|
55ba69bb0f | ||
|
|
9ed71b8660 | ||
|
|
28cf141a02 | ||
|
|
03ca4d128d | ||
|
|
ff2029819d | ||
|
|
a26503650e | ||
|
|
7a37f7e040 | ||
|
|
0073d5b069 | ||
|
|
c210e34437 | ||
|
|
7a43b23d68 | ||
|
|
7c15648e75 | ||
|
|
d629bf633f | ||
|
|
4115037141 | ||
|
|
5d02bb99d4 | ||
|
|
96bdc3d089 | ||
|
|
71546fcc89 | ||
|
|
22c330c7e4 | ||
|
|
fd402a966a | ||
|
|
b3029deea4 | ||
|
|
24b23c445f | ||
|
|
a9c44e24f1 | ||
|
|
7deee4008d | ||
|
|
2ab922cc84 | ||
|
|
c6a7b60e41 | ||
|
|
49974648b6 | ||
|
|
cd7580f45d | ||
|
|
076afb35b4 | ||
|
|
f901aeaefc | ||
|
|
6b37de3db5 | ||
|
|
0b80e351a5 | ||
|
|
3fe47ab682 | ||
|
|
9b69fe5f2d | ||
|
|
953eb1b4ff | ||
|
|
876dd82d87 | ||
|
|
454d66c71e | ||
|
|
87f72a077d | ||
|
|
62c27d1461 | ||
|
|
3b2bbb1dce | ||
|
|
8f40a95cbe | ||
|
|
5e9518de71 | ||
|
|
0ecab3b21b | ||
|
|
5e0e546eb4 | ||
|
|
ade0d4e57d | ||
|
|
26b08c593c | ||
|
|
888f2bd402 | ||
|
|
eb369d9116 | ||
|
|
f2acdbdd81 | ||
|
|
d65f6d380f | ||
|
|
30d45952be | ||
|
|
068cbdb33c | ||
|
|
effca93b7a | ||
|
|
ac815b5972 | ||
|
|
e6cccef48d | ||
|
|
4f35aa56f4 | ||
|
|
66204ca061 | ||
|
|
2960173517 | ||
|
|
b810c25613 | ||
|
|
583c2cc4be | ||
|
|
0c36564331 | ||
|
|
d7bd458bed | ||
|
|
bbcd77e3c8 | ||
|
|
ec166167f4 | ||
|
|
d5b4835d1f | ||
|
|
41304551e4 | ||
|
|
279959f256 | ||
|
|
7cc0e8e21c | ||
|
|
87e9122c41 | ||
|
|
f22cc03e14 | ||
|
|
84b103cfba | ||
|
|
a015e01c40 | ||
|
|
981db7b43f | ||
|
|
65560991bc | ||
|
|
b914ba035f | ||
|
|
d3e77f17ec | ||
|
|
9498458165 | ||
|
|
03a112fb43 | ||
|
|
782773fef5 | ||
|
|
5076e79c1d | ||
|
|
ac1baa4734 | ||
|
|
2c508665be | ||
|
|
1023951a76 | ||
|
|
a1923427a0 | ||
|
|
4c8ca91712 | ||
|
|
f78ab3372e | ||
|
|
c70815f25d | ||
|
|
7ee3653ab9 | ||
|
|
bb60d767a7 | ||
|
|
5a34447abe | ||
|
|
bbcfcfcc6f | ||
|
|
75187cae00 | ||
|
|
710a039707 | ||
|
|
b7dcb72e7a | ||
|
|
ead142cf5d | ||
|
|
11bf8cc9bc | ||
|
|
1083f93d2c | ||
|
|
6de38d3bea | ||
|
|
9de6eb4b8b | ||
|
|
df1392bf84 | ||
|
|
6e065de915 | ||
|
|
a1820aea67 | ||
|
|
09c113c6bc | ||
|
|
d080292e85 | ||
|
|
0e9ea8cf1a | ||
|
|
5d1037f66d | ||
|
|
eb6251aae0 | ||
|
|
caccf8b405 | ||
|
|
5390c0e53e | ||
|
|
8732064764 | ||
|
|
46833e024f | ||
|
|
e459ef77f3 | ||
|
|
a827d7e946 | ||
|
|
85da8684a4 | ||
|
|
52c3c5bcc8 | ||
|
|
a3c1b0537e | ||
|
|
127ff821d1 | ||
|
|
7e3b23aec0 | ||
|
|
c0ced48ff2 | ||
|
|
b5dfb59458 | ||
|
|
c89e8591f0 | ||
|
|
507ac7b043 | ||
|
|
d64abb4cce | ||
|
|
e56999da19 | ||
|
|
06dc90a51e | ||
|
|
1842094036 | ||
|
|
b2d55c3236 | ||
|
|
b88ed34ed2 | ||
|
|
939ea35f39 | ||
|
|
5c718bfa5e | ||
|
|
0efee9e7aa | ||
|
|
f1f56b03d4 | ||
|
|
725afbd115 | ||
|
|
015ff303b7 | ||
|
|
55d25697ce | ||
|
|
cdcfd5c8f8 | ||
|
|
42c307d962 | ||
|
|
3fbb635b4a | ||
|
|
53761fba98 | ||
|
|
d0280ea116 | ||
|
|
bb605133bd | ||
|
|
194f18ee22 | ||
|
|
4e1196a405 | ||
|
|
672ad9b9e4 | ||
|
|
fd548b7bfe | ||
|
|
888246cbbc | ||
|
|
a26114331f | ||
|
|
2ae472ae94 | ||
|
|
4cf1e0c1f1 | ||
|
|
6d1d70e664 | ||
|
|
2c9f38952c | ||
|
|
b801fc82c6 | ||
|
|
10255daa29 | ||
|
|
f0d7e98f70 | ||
|
|
dfcfdd53c3 | ||
|
|
4a75447b7e | ||
|
|
bce5c89ad1 | ||
|
|
686afb88f6 | ||
|
|
1abce06e2f | ||
|
|
69011ddac7 | ||
|
|
177934d1c9 | ||
|
|
44e38ca1de | ||
|
|
cc23eaf2d6 | ||
|
|
d7f9a62a62 | ||
|
|
af8f2c10ff | ||
|
|
a2818241f6 | ||
|
|
af8bf920c0 | ||
|
|
b4d3aaac15 | ||
|
|
01c86558cd | ||
|
|
08bab02451 | ||
|
|
84359fcdac | ||
|
|
c006665a0c | ||
|
|
4e29134fa5 | ||
|
|
249a3e3d19 | ||
|
|
7f8c429a04 | ||
|
|
d74c10c618 | ||
|
|
0ec7d83191 | ||
|
|
4bfa706e7c | ||
|
|
2485bf4113 | ||
|
|
48e2e705c2 | ||
|
|
f688a066b4 | ||
|
|
1e8a01dccc | ||
|
|
e7fb1857b0 | ||
|
|
b5498ab79a | ||
|
|
1f5aebef1c | ||
|
|
b0bb0e02d1 | ||
|
|
9bc4ec0253 | ||
|
|
533c9e3a63 | ||
|
|
6ae631c78d | ||
|
|
622bbefc54 | ||
|
|
f6956958bb | ||
|
|
853e1e4946 | ||
|
|
5fbc012afa | ||
|
|
ce2c35f4bd |
4
.env
Normal file
4
.env
Normal file
@@ -0,0 +1,4 @@
|
||||
REGISTRY_PREFIX=harbor.sheldan.dev/sissi/
|
||||
ABSTRACTO_PREFIX=harbor.sheldan.dev/abstracto/
|
||||
VERSION=1.5.8
|
||||
ABSTRACTO_VERSION=1.6.11
|
||||
42
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
42
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: Bug Report
|
||||
description: Found a bug that needs fixing?
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: General Troubleshooting
|
||||
description: You confirm to have made the following checks first.
|
||||
options:
|
||||
- label: I have checked for similar issues on the Issue-tracker.
|
||||
required: true
|
||||
- label: I have updated to the latest version
|
||||
required: true
|
||||
- label: I have checked the branches or the maintainers' PRs for upcoming bug fixes.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Description"
|
||||
description: "General information about the bug"
|
||||
placeholder: "..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Steps to reproduce"
|
||||
description: "What happened when the bug occurred?"
|
||||
placeholder: "1. ..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Expected behaviour"
|
||||
description: "What should happen?"
|
||||
placeholder: "It should..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Actual behaviour"
|
||||
description: "What did happen instead?"
|
||||
placeholder: "It actually ..."
|
||||
validations:
|
||||
required: true
|
||||
36
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
36
.github/ISSUE_TEMPLATE/feature.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name: Feature request
|
||||
description: Want some functionality added?
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: General Information
|
||||
description: You confirm to have made the following checks first.
|
||||
options:
|
||||
- label: I have checked for similar issues on the Issue-tracker.
|
||||
required: true
|
||||
- label: I have updated to the latest version
|
||||
required: true
|
||||
- label: I have checked the branches or the maintainers' PRs for upcoming features fixes.
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Description"
|
||||
description: "General description of the feature"
|
||||
placeholder: "..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Feature worth and general use"
|
||||
description: "Why should this exist?"
|
||||
placeholder: "..."
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: "Suggestions for implementation"
|
||||
description: "Any ideas about what the feature should behave/look like? Commands?"
|
||||
placeholder: "It should..."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
13
.github/workflows/build.yml
vendored
13
.github/workflows/build.yml
vendored
@@ -14,14 +14,17 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 1.8
|
||||
uses: actions/setup-java@v1
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
persist-credentials: false
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'corretto'
|
||||
java-version: 17
|
||||
- name: Build with Maven
|
||||
run: mvn -s settings.xml -B install --file pom.xml
|
||||
env:
|
||||
|
||||
38
.github/workflows/release.yml
vendored
38
.github/workflows/release.yml
vendored
@@ -1,38 +0,0 @@
|
||||
name: Publish package to GitHub Packages
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Java for publishing to GitHub Packages
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 1.8
|
||||
- name: Load current version
|
||||
id: version
|
||||
run: echo "version=$(mvn -s settings.xml --file pom.xml -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec)" >> $GITHUB_ENV
|
||||
- name: Publish to GitHub Packages
|
||||
run: mvn -s settings.xml --file pom.xml -B deploy -Dmaven.wagon.http.pool=false -DskipTests=true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
user: Sheldan
|
||||
token: ${{ secrets.ABSTRACTO_PAT }}
|
||||
- name: Login to GitHub Packages Docker Registry
|
||||
uses: docker/login-action@v1
|
||||
with:
|
||||
registry: docker.pkg.github.com
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push deployment container
|
||||
working-directory: ./deployment/image-packaging/src/main/docker
|
||||
run: docker-compose build && docker-compose push
|
||||
env:
|
||||
REGISTRY_PREFIX: docker.pkg.github.com/sheldan/sissi/
|
||||
VERSION: ${{ env.version }}
|
||||
ABSTRACTO_VERSION: 1.3.13
|
||||
ABSTRACTO_REGISTRY_PREFIX: docker.pkg.github.com/sheldan/abstracto/
|
||||
92
.github/workflows/release_manual.yaml
vendored
Normal file
92
.github/workflows/release_manual.yaml
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
name: Publishes a new version of Sissi
|
||||
on: workflow_dispatch
|
||||
permissions:
|
||||
packages: write
|
||||
contents: write
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-24.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: master
|
||||
- name: Set up JDK
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'corretto'
|
||||
java-version: 17
|
||||
- name: Load current version
|
||||
id: version
|
||||
run: echo "version=$(mvn -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec | cut -d- -f1)" >> $GITHUB_ENV
|
||||
- name: Create a Release
|
||||
uses: elgohr/Github-Release-Action@v5
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
title: Release of version ${{ env.version }}
|
||||
- name: Release maven packages
|
||||
uses: qcastel/github-actions-maven-release@v1.12.41
|
||||
env:
|
||||
JAVA_HOME: /usr/lib/jvm/java-17-openjdk/
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
abstractoUser: Sheldan
|
||||
abstractoToken: ${{ secrets.ABSTRACTO_PAT }}
|
||||
with:
|
||||
git-release-bot-name: "release-bot"
|
||||
git-release-bot-email: "release-bot@sheldan.dev"
|
||||
release-branch-name: master
|
||||
maven-args: "-Dmaven.javadoc.skip=true -s settings.xml -DskipTests"
|
||||
access-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Login to Harbor
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: harbor.sheldan.dev
|
||||
username: ${{ secrets.HARBOR_USERNAME }}
|
||||
password: ${{ secrets.HARBOR_TOKEN }}
|
||||
- name: Update Chart version file
|
||||
uses: fjogeleit/yaml-update-action@v0.13.2
|
||||
with:
|
||||
valueFile: 'deployment/helm/sissi/Chart.yaml'
|
||||
propertyPath: 'version'
|
||||
value: ${{ env.version }}
|
||||
commitChange: false
|
||||
- name: Update value files version
|
||||
uses: fjogeleit/yaml-update-action@v0.13.2
|
||||
with:
|
||||
valueFile: 'deployment/helm/sissi/values.yaml'
|
||||
commitChange: false
|
||||
changes: |
|
||||
{
|
||||
"bot.tag": "${{ env.version }}",
|
||||
"restApi.tag": "${{ env.version }}",
|
||||
"privateRestApi.tag": "${{ env.version }}",
|
||||
"templateDeploymentData.tag": "${{ env.version }}",
|
||||
"dbConfigDeploymentData.tag": "${{ env.version }}"
|
||||
}
|
||||
- name: Update .env version
|
||||
run:
|
||||
sed -i '3s/.*/VERSION=${{ env.version }}/' .env
|
||||
- name: Load env file
|
||||
id: dotenv
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: .env
|
||||
- name: Build and push Docker containers
|
||||
run: docker compose build && docker compose push
|
||||
env:
|
||||
REGISTRY_PREFIX: ${{ steps.dotenv.outputs.registry_prefix }}
|
||||
VERSION: ${{ steps.dotenv.outputs.version }}
|
||||
- name: Helm package and push
|
||||
working-directory: ./deployment/helm/
|
||||
run: |-
|
||||
helm registry login -u '${{ secrets.HARBOR_USERNAME }}' -p '${{ secrets.HARBOR_TOKEN }}' harbor.sheldan.dev
|
||||
helm package sissi
|
||||
helm push sissi*.tgz oci://harbor.sheldan.dev/sissi
|
||||
- name: Fix file permissions
|
||||
run:
|
||||
sudo chmod -R ugo+rwX . # https://github.com/actions/checkout/issues/164
|
||||
- name: Commit updated versions
|
||||
uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
author_name: "release-bot"
|
||||
author_email: "release-bot@sheldan.dev"
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -21,5 +21,9 @@ target/
|
||||
*.tar.gz
|
||||
*.rar
|
||||
|
||||
Chart.lock
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
*.tgz
|
||||
3
.tiltignore
Normal file
3
.tiltignore
Normal file
@@ -0,0 +1,3 @@
|
||||
*.tgz
|
||||
tilt/sissi-dev/tmpcharts/
|
||||
tilt/sissi-dev/charts/*.tgz
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 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
164
PRIVACY_POLICY.md
Normal 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
|
||||
4
README
Normal file
4
README
Normal file
@@ -0,0 +1,4 @@
|
||||
|
||||
|
||||
Attributions:
|
||||
Code for debra module has been inspired with approval of zinnsoldat91 by: https://github.com/zinnsoldat91/spendenbot. The code has been adapted to fit into the structure.
|
||||
48
Tiltfile
Normal file
48
Tiltfile
Normal file
@@ -0,0 +1,48 @@
|
||||
allow_k8s_contexts('k8s-cluster')
|
||||
|
||||
load('ext://restart_process', 'docker_build_with_restart')
|
||||
registry = 'harbor.sheldan.dev/sissi/'
|
||||
abstracto_registry = 'harbor.sheldan.dev/abstracto/'
|
||||
|
||||
local_resource(
|
||||
'sissi-java-compile',
|
||||
' mvn install && ' +
|
||||
' rm -rf application/executable/target/jar-staging && ' +
|
||||
' unzip -o application/executable/target/sissi-exec.jar -d application/executable/target/jar-staging && ' +
|
||||
' rsync --delete --delete-excluded --inplace --checksum --exclude="*-SNAPSHOT.jar" -r application/executable/target/jar-staging/ application/executable/target/jar && ' +
|
||||
' rm -rf application/executable/target/jar/snapshots && ' +
|
||||
' mkdir application/executable/target/jar/snapshots && ' +
|
||||
' rsync --delete --delete-excluded --inplace --checksum --include="*/" --include="*-SNAPSHOT.jar" --exclude="*" -r application/executable/target/jar-staging/BOOT-INF/lib/ application/executable/target/jar/snapshots',
|
||||
deps=['pom.xml'], auto_init=False, trigger_mode = TRIGGER_MODE_MANUAL)
|
||||
|
||||
docker_build_with_restart(
|
||||
registry + 'sissi-bot',
|
||||
'./application/executable/target/jar',
|
||||
entrypoint=['java', '-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005', '-cp', '.:./lib/*', 'dev.sheldan.sissi.executable.Application'],
|
||||
dockerfile='./application/executable/Dockerfile',
|
||||
live_update=[
|
||||
sync('./application/executable/target/jar/BOOT-INF/lib', '/app/lib'),
|
||||
sync('./application/executable/target/jar/META-INF', '/app/META-INF'),
|
||||
sync('./application/executable/target/jar/BOOT-INF/classes', '/app'),
|
||||
sync('./application/executable/target/jar/snapshots', '/app/lib')
|
||||
],
|
||||
)
|
||||
|
||||
docker_build(registry + 'sissi-db-data', 'deployment/image-packaging/src/main/docker/db-data/')
|
||||
docker_build(registry + 'sissi-debra-rest-api', 'python/modules/debra-rest-api/', dockerfile='python/modules/debra-rest-api/docker/Dockerfile')
|
||||
update_settings(suppress_unused_image_warnings=[registry + "sissi-debra-rest-api"]) # only used in docker image building
|
||||
docker_build(registry + 'sissi-image-gen-api', 'python/modules/image-gen-api/', dockerfile='python/modules/image-gen-api/docker/Dockerfile')
|
||||
update_settings(suppress_unused_image_warnings=[registry + "sissi-image-gen-api"]) # only used in docker image building
|
||||
docker_build(registry + 'sissi-rest-api', 'deployment/image-packaging/src/main/docker/rest-api/', build_args={'REGISTRY_PREFIX': abstracto_registry, 'SISSI_REGISTRY_PREFIX': registry})
|
||||
docker_build(registry + 'sissi-private-rest-api', 'deployment/image-packaging/src/main/docker/private-rest-api/', build_args={'REGISTRY_PREFIX': abstracto_registry, 'SISSI_REGISTRY_PREFIX': registry})
|
||||
docker_build(registry + 'sissi-template-data', 'deployment/image-packaging/src/main/docker/template-data/')
|
||||
|
||||
|
||||
local('cd tilt/sissi-dev && helm dep up')
|
||||
k8s_yaml(helm('tilt/sissi-dev', values=
|
||||
['./../Sissi-environments/argocd/apps/sissi/values/local/values.yaml',
|
||||
'secrets://./../Sissi-environments/argocd/apps/sissi/values/local/values.secrets.yaml']
|
||||
))
|
||||
|
||||
local_resource('fetch-packages', 'mvn install -f deployment/image-packaging/pom.xml', auto_init=False, trigger_mode = TRIGGER_MODE_MANUAL)
|
||||
k8s_resource('chart-sissi', port_forwards='5005:5005')
|
||||
10
application/executable/Dockerfile
Normal file
10
application/executable/Dockerfile
Normal file
@@ -0,0 +1,10 @@
|
||||
FROM amazoncorretto:17.0.8-alpine3.18
|
||||
RUN apk add entr
|
||||
|
||||
WORKDIR /app
|
||||
ADD BOOT-INF/lib/ /app/lib
|
||||
ADD snapshots/ /app/lib
|
||||
ADD META-INF /app/META-INF
|
||||
ADD BOOT-INF/classes /app
|
||||
|
||||
ENTRYPOINT java -cp .:./lib/* dev.sheldan.sissi.executable.Application
|
||||
@@ -3,17 +3,13 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>application</artifactId>
|
||||
<version>1.0.3-SNAPSHOT</version>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>executable</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
<build>
|
||||
<finalName>sissi</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -59,28 +55,150 @@
|
||||
<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>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>webservices-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>twitch-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>utility-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>remind-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>suggestion-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>starboard-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>entertainment-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>assignable-roles-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>custom-command-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>modmail-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>experience-tracking-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>logging-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>sticky-roles-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>giveaway-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>image-generation-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sissi modules -->
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||
<artifactId>quotes</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||
<artifactId>meetup</artifactId>
|
||||
<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>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||
<artifactId>debra</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- sissi customizations -->
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>moderation-custom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>image-generation-custom</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.sissi.executable;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
|
||||
@Configuration
|
||||
public class SecurityConfig {
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http.authorizeHttpRequests((authorize) -> authorize
|
||||
.anyRequest().permitAll());
|
||||
return http.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
spring.datasource.url=jdbc:postgresql://localhost:5432/abstracto
|
||||
spring.datasource.username=abstracto
|
||||
spring.datasource.password=abstracto
|
||||
spring.jpa.properties.hibernate.default_schema=abstracto
|
||||
spring.quartz.jdbc.initialize-schema=never
|
||||
|
||||
spring.jpa.hibernate.ddl-auto = none
|
||||
|
||||
spring.jpa.show-sql = false
|
||||
|
||||
spring.jpa.properties.hibernate.format_sql = true
|
||||
log4j.logger.org.hibernate.SQL=trace
|
||||
log4j.logger.org.hibernate.type.descriptor.sql=trace
|
||||
log4j.logger.org.hibernate.type=trace
|
||||
|
||||
management.metrics.tags.application=sissi
|
||||
spring.security.user.name=abstracto
|
||||
spring.security.user.password=password
|
||||
spring.security.user.roles=USER
|
||||
|
||||
spring.application.name=Sissi
|
||||
@@ -1,11 +1,14 @@
|
||||
spring.datasource.url=jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME}
|
||||
spring.datasource.username= ${DB_USER}
|
||||
spring.datasource.password= ${DB_PASS}
|
||||
spring.jpa.hibernate.default_schema=${DB_NAME}
|
||||
spring.datasource.hikari.maximum-pool-size=${hikariPoolSize}
|
||||
spring.jpa.hibernate.default_schema=${DB_SCHEMA}
|
||||
spring.jpa.properties.hibernate.default_schema=${DB_SCHEMA}
|
||||
spring.quartz.jdbc.initialize-schema=never
|
||||
management.metrics.tags.application=Sissi
|
||||
spring.security.user.name= ${REST_USER_NAME}
|
||||
spring.security.user.password= ${REST_PASSWORD}
|
||||
spring.security.user.roles=USER
|
||||
management.endpoint.health.probes.enabled=true
|
||||
management.health.livenessState.enabled=true
|
||||
management.health.readinessState.enabled=true
|
||||
spring.application.name=Sissi
|
||||
|
||||
spring.application.name=Sissi
|
||||
spring.main.allow-circular-references=true
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi</groupId>
|
||||
<artifactId>sissi</artifactId>
|
||||
<version>1.0.3-SNAPSHOT</version>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -22,12 +22,25 @@
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jena</groupId>
|
||||
<artifactId>apache-jena-libs</artifactId>
|
||||
<version>${apache-jena.version}</version>
|
||||
<scope>import</scope>
|
||||
<type>pom</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.apptasticsoftware</groupId>
|
||||
<artifactId>rssreader</artifactId>
|
||||
<version>${rssreader.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<modules>
|
||||
<module>executable</module>
|
||||
<module>sissi-modules</module>
|
||||
<module>sissi-customizations</module>
|
||||
<module>executable</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
<?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">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>sissi-customizations</artifactId>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>image-generation-custom</artifactId>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>image-generation-int</artifactId>
|
||||
<version>${abstracto.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${abstracto.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -1,19 +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>docker-compose</id>
|
||||
<id>liquibase</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<outputDirectory>./docker-compose</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/</directory>
|
||||
<outputDirectory>.</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,77 @@
|
||||
package dev.sheldan.sissi.module.custom.imagegeneration.command;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.CommandAlternative;
|
||||
import dev.sheldan.abstracto.core.command.execution.UnParsedCommandParameter;
|
||||
import dev.sheldan.abstracto.core.command.service.CommandRegistry;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
import dev.sheldan.abstracto.core.templating.model.AttachedFile;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.imagegeneration.config.ImageGenerationFeatureConfig;
|
||||
import dev.sheldan.sissi.module.custom.imagegeneration.service.ImageGenerationService;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class OrangeSunDogeCommandAlternative implements CommandAlternative {
|
||||
|
||||
@Autowired
|
||||
private ImageGenerationService imageGenerationService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private CommandRegistry commandRegistry;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private ImageGenerationFeatureConfig imageGenerationFeatureConfig;
|
||||
|
||||
private static final String DOGE_ORANGE_SUN_RESPONSE_TEMPLATE_KEY = "doge_orangeSun_response";
|
||||
|
||||
@Override
|
||||
public boolean shouldExecute(UnParsedCommandParameter parameter, Guild guild, Message message) {
|
||||
return featureFlagService.isFeatureEnabled(imageGenerationFeatureConfig, guild.getIdLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(UnParsedCommandParameter parameter, Message message) {
|
||||
String contentStripped = message.getContentRaw();
|
||||
String inputText = commandRegistry.getCommandName(contentStripped, message.getGuild().getIdLong());
|
||||
File triggeredGifFile = imageGenerationService.getOrangeSunDogeImage(inputText);
|
||||
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()
|
||||
.file(triggeredGifFile)
|
||||
.fileName("doge.png")
|
||||
.build();
|
||||
messageToSend.getAttachedFiles().add(file);
|
||||
FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, message.getGuildChannel()))
|
||||
.thenAccept(unused -> fileService.safeDeleteIgnoreException(messageToSend.getAttachedFiles().get(0).getFile()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.LOW;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.sissi.module.custom.imagegeneration.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:custom-image-generation-config.properties")
|
||||
public class CustomImageGenerationConfig {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.sissi.module.custom.imagegeneration.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.service.HttpService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
@Component
|
||||
public class ImageGenerationService {
|
||||
|
||||
@Value("${abstracto.feature.imagegeneration.doge.orangeSun.url}")
|
||||
private String dogeOrangeSunUrl;
|
||||
|
||||
@Autowired
|
||||
private HttpService httpService;
|
||||
|
||||
public File getOrangeSunDogeImage(String inputText) {
|
||||
try {
|
||||
return httpService.downloadFileToTempFile(dogeOrangeSunUrl.replace("{1}", URLEncoder.encode(inputText, StandardCharsets.UTF_8)));
|
||||
} catch (IOException e) {
|
||||
throw new AbstractoRunTimeException(String.format("Failed to download orange doge image for url %s with error %s", inputText, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
abstracto.feature.imagegeneration.doge.orangeSun.url=http://${PRIVATE_REST_API_HOST}:${PRIVATE_REST_API_PORT}/memes/doge/orangeSun/?text={1}
|
||||
42
application/sissi-customizations/moderation-custom/pom.xml
Normal file
42
application/sissi-customizations/moderation-custom/pom.xml
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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>
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>sissi-customizations</artifactId>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>moderation-custom</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>moderation-int</artifactId>
|
||||
<version>${abstracto.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<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>
|
||||
|
||||
</project>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,97 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.commands;
|
||||
|
||||
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.CommandContext;
|
||||
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;
|
||||
import dev.sheldan.sissi.module.custom.moderation.config.ModerationCustomSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.custom.moderation.service.ModModeServiceBean;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ModMode extends AbstractConditionableCommand {
|
||||
|
||||
public static final String NEW_STATE_PARAMETER = "newState";
|
||||
public static final String MOD_MODE_COMMAND = "modMode";
|
||||
public static final String MOD_MODE_RESPONSE = "modMode_response";
|
||||
|
||||
@Autowired
|
||||
private ModModeServiceBean modModeServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
Boolean newState = (Boolean) commandContext.getParameters().getParameters().get(0);
|
||||
return modModeServiceBean.setModModeTo(commandContext.getGuild(), newState)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Boolean newState = slashCommandParameterService.getCommandOption(NEW_STATE_PARAMETER, event, Boolean.class);
|
||||
return modModeServiceBean.setModModeTo(event.getGuild(), newState)
|
||||
.thenApply(unused -> interactionService.replyEmbed(MOD_MODE_RESPONSE, event))
|
||||
.thenApply(interactionHookCompletableFuture -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter memberParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(NEW_STATE_PARAMETER)
|
||||
.type(Boolean.class)
|
||||
.build();
|
||||
List<Parameter> parameters = Collections.singletonList(memberParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(ModerationCustomSlashCommandNames.MODERATION)
|
||||
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
|
||||
.commandName(MOD_MODE_COMMAND)
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(MOD_MODE_COMMAND)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.module(ModerationModuleDefinition.MODERATION)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationCustomFeatureDefinition.MODERATION_CUSTOM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.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.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.sissi.module.custom.moderation.config.ModerationCustomFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.custom.moderation.service.SelfMuteServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class SelfMute extends AbstractConditionableCommand {
|
||||
|
||||
public static final String DURATION_PARAMETER = "duration";
|
||||
|
||||
@Autowired
|
||||
private SelfMuteServiceBean selfMuteServiceBean;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Duration muteDuration = (Duration) parameters.get(0);
|
||||
return selfMuteServiceBean.selfMuteMember(commandContext.getAuthor(), muteDuration)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter durationParameter = Parameter
|
||||
.builder()
|
||||
.name(DURATION_PARAMETER)
|
||||
.type(Duration.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
List<Parameter> parameters = Arrays.asList(durationParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("selfMute")
|
||||
.async(true)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationCustomFeatureDefinition.MODERATION_CUSTOM;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.moderation.config.feature.ReportReactionFeatureConfig;
|
||||
import dev.sheldan.sissi.module.custom.moderation.service.ModModeServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.sheldan.sissi.module.custom.moderation.listener.ReactionReportReactionListener.REACTION_REPORT_REACTION_AMOUNT_CONFIG_KEY;
|
||||
|
||||
@Component
|
||||
public class ModerationCustomFeature implements FeatureConfig {
|
||||
|
||||
@Autowired
|
||||
private ReportReactionFeatureConfig reportReactionFeatureConfig;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationCustomFeatureDefinition.MODERATION_CUSTOM;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureConfig> getRequiredFeatures() {
|
||||
return Arrays.asList(reportReactionFeatureConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(REACTION_REPORT_REACTION_AMOUNT_CONFIG_KEY, ModModeServiceBean.MODMODE_ROLE_CONFIG_KEY,
|
||||
ModModeServiceBean.MODMODE_CHANGED_ROLE_COLOR_CONFIG_KEY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum ModerationCustomFeatureDefinition implements FeatureDefinition {
|
||||
MODERATION_CUSTOM("moderationCustom");
|
||||
|
||||
private String key;
|
||||
|
||||
ModerationCustomFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:moderation-custom.properties")
|
||||
public class ModerationCustomProperties {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.config;
|
||||
|
||||
public class ModerationCustomSlashCommandNames {
|
||||
public static final String MODERATION = "moderation";
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class ModRoleNotFoundException extends AbstractoTemplatableException {
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "mod_role_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.listener.DefaultListenerResult;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.ReactionService;
|
||||
import dev.sheldan.abstracto.moderation.listener.ReportMessageCreatedListener;
|
||||
import dev.sheldan.abstracto.moderation.model.listener.ReportMessageCreatedModel;
|
||||
import dev.sheldan.sissi.module.custom.moderation.config.ModerationCustomFeatureDefinition;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ReactionReportReactionListener implements ReportMessageCreatedListener {
|
||||
|
||||
public static final String REACTION_REPORT_REACTION_AMOUNT_CONFIG_KEY = "reportReactionAmount";
|
||||
public static final String REACTION_REPORT_EMOTE_PREFIX = "reactionReport";
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ReactionService reactionService;
|
||||
|
||||
@Override
|
||||
public DefaultListenerResult execute(ReportMessageCreatedModel model) {
|
||||
if(model.getReportMessage() == null) {
|
||||
return DefaultListenerResult.IGNORED;
|
||||
}
|
||||
Long reactionAmount = configService.getLongValueOrConfigDefault(REACTION_REPORT_REACTION_AMOUNT_CONFIG_KEY, model.getServerId());
|
||||
for (int i = 0; i < reactionAmount; i++) {
|
||||
String emoteKey = buildReactionEmoteName(i + 1);
|
||||
reactionService.addReactionToMessageAsync(emoteKey,
|
||||
model.getServerId(), model.getReportMessage().getChannelId(), model.getReportMessage().getMessageId())
|
||||
.thenAccept(unused -> log.info("Added reaction emote {} on report message {} in channel {} in server {}",
|
||||
emoteKey, model.getReportMessage().getMessageId(), model.getReportMessage().getChannelId(), model.getServerId()))
|
||||
.exceptionally(throwable -> {
|
||||
log.info("Failed to add reaction emote {} on report message {} in channel {} in server {}",
|
||||
emoteKey, model.getReportMessage().getMessageId(), model.getReportMessage().getChannelId(), model.getServerId());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
return DefaultListenerResult.PROCESSED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return ModerationCustomFeatureDefinition.MODERATION_CUSTOM;
|
||||
}
|
||||
|
||||
private String buildReactionEmoteName(Integer position) {
|
||||
return REACTION_REPORT_EMOTE_PREFIX + position;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.sissi.module.custom.moderation.exception.ModRoleNotFoundException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class ModModeServiceBean {
|
||||
public static final String MODMODE_ROLE_CONFIG_KEY = "modModeRoleId";
|
||||
public static final String MODMODE_CHANGED_ROLE_COLOR_CONFIG_KEY = "modModeNewRoleColor";
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
public CompletableFuture<Void> setModModeTo(Guild guild, Boolean newState) {
|
||||
if(Boolean.TRUE.equals(newState)) {
|
||||
return enableModMode(guild);
|
||||
} else {
|
||||
return disableModMoe(guild);
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> enableModMode(Guild guild) {
|
||||
Color colorToSet = getColorFromConfig(MODMODE_CHANGED_ROLE_COLOR_CONFIG_KEY, guild);
|
||||
return setModRoleTo(guild, colorToSet);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> disableModMoe(Guild guild) {
|
||||
return setModRoleTo(guild, null);
|
||||
}
|
||||
|
||||
private Color getColorFromConfig(String key, Guild guild) {
|
||||
String colorString = configService.getStringValueOrConfigDefault(key, guild.getIdLong());
|
||||
String[] parts = colorString.split(",");
|
||||
return new Color(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> setModRoleTo(Guild guild, Color color) {
|
||||
Long roleId = configService.getLongValue(MODMODE_ROLE_CONFIG_KEY, guild.getIdLong());
|
||||
Role modRole = guild.getRoleById(roleId);
|
||||
if(modRole != null) {
|
||||
return modRole.getManager().setColor(color).submit();
|
||||
} else {
|
||||
throw new ModRoleNotFoundException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package dev.sheldan.sissi.module.custom.moderation.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.MemberService;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class SelfMuteServiceBean {
|
||||
|
||||
@Autowired
|
||||
private MemberService memberService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
private static final String SELF_MUTE_REASON_TEMPLATE = "self_mute_reason";
|
||||
|
||||
public CompletableFuture<Void> selfMuteMember(Member member, Duration duration) {
|
||||
String reason = templateService.renderSimpleTemplate(SELF_MUTE_REASON_TEMPLATE, member.getGuild().getIdLong());
|
||||
log.info("Self muting user {} in server {}.", member.getIdLong(), member.getGuild().getIdLong());
|
||||
return memberService.timeoutUser(member, duration, reason);
|
||||
}
|
||||
}
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="default_emote.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,27 @@
|
||||
<?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="moderation_custom_reaction_message_default_emote-insert">
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport1"/>
|
||||
<column name="name" value="♂️"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport2"/>
|
||||
<column name="name" value="📣"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport3"/>
|
||||
<column name="name" value="🤫"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport4"/>
|
||||
<column name="name" value="🔨"/>
|
||||
</insert>
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport5"/>
|
||||
<column name="name" value="⚠️"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="moderation_custom_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="moderationCustom"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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="moderationCustomFeature" value="(SELECT id FROM feature WHERE key = 'moderationCustom')"/>
|
||||
<property name="moderationModule" value="(SELECT id FROM module WHERE name = 'moderation')"/>
|
||||
<changeSet author="Sheldan" id="moderationCustom_modmode-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="modMode"/>
|
||||
<column name="module_id" valueComputed="${moderationModule}"/>
|
||||
<column name="feature_id" valueComputed="${moderationCustomFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="default_emote.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="moderation_custom_reaction_message_question_mark_emote-insert">
|
||||
<insert tableName="default_emote">
|
||||
<column name="emote_key" value="reactionReport6"/>
|
||||
<column name="name" value="❓"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?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="moderationCustomFeature" value="(SELECT id FROM feature WHERE key = 'moderationCustom')"/>
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<changeSet author="Sheldan" id="moderationCustom_selfmute-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="selfMute"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${moderationCustomFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?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.1.0/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.1/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.45/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.5.9/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,11 @@
|
||||
abstracto.featureFlags.moderationCustom.featureName=moderationCustom
|
||||
abstracto.featureFlags.moderationCustom.enabled=false
|
||||
|
||||
abstracto.systemConfigs.reportReactionAmount.name=reportReactionAmount
|
||||
abstracto.systemConfigs.reportReactionAmount.longValue=7
|
||||
|
||||
abstracto.systemConfigs.modModeRoleId.name=modModeRoleId
|
||||
abstracto.systemConfigs.modModeRoleId.longValue=0
|
||||
|
||||
abstracto.systemConfigs.modModeNewRoleColor.name=modModeNewRoleColor
|
||||
abstracto.systemConfigs.modModeNewRoleColor.stringValue=0,0,0
|
||||
20
application/sissi-customizations/pom.xml
Normal file
20
application/sissi-customizations/pom.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?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>application</artifactId>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>sissi-customizations</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>moderation-custom</module>
|
||||
<module>image-generation-custom</module>
|
||||
</modules>
|
||||
|
||||
|
||||
</project>
|
||||
55
application/sissi-modules/debra/pom.xml
Normal file
55
application/sissi-modules/debra/pom.xml
Normal file
@@ -0,0 +1,55 @@
|
||||
<?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>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>sissi-modules</artifactId>
|
||||
<version>1.5.9-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||
<artifactId>debra</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ehcache</groupId>
|
||||
<artifactId>ehcache</artifactId>
|
||||
<classifier>jakarta</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<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>
|
||||
|
||||
</project>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,69 @@
|
||||
package dev.sheldan.sissi.module.debra.api;
|
||||
|
||||
import dev.sheldan.sissi.module.debra.model.api.*;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/debra")
|
||||
public class DebraDonationStatusController {
|
||||
|
||||
@Autowired
|
||||
private DonationService donationService;
|
||||
|
||||
@GetMapping(value = "/latestDonations", produces = "application/json")
|
||||
public DonationStats getLatestDonations() {
|
||||
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
|
||||
List<DonationInfo> donations = donationService.getLatestDonations(donationResponse, Integer.MAX_VALUE)
|
||||
.stream()
|
||||
.map(DonationInfo::fromDonationItemModel)
|
||||
.toList();
|
||||
return DonationStats
|
||||
.builder()
|
||||
.totalAmount(donationResponse.getPage().getCollected())
|
||||
.donations(donations)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/highestDonations", produces = "application/json")
|
||||
public DonationStats getHighestDonations() {
|
||||
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
|
||||
List<DonationInfo> donations = donationService.getHighestDonations(donationResponse, Integer.MAX_VALUE)
|
||||
.stream()
|
||||
.map(DonationInfo::fromDonationItemModel)
|
||||
.toList();
|
||||
return DonationStats
|
||||
.builder()
|
||||
.totalAmount(donationResponse.getPage().getCollected())
|
||||
.donations(donations)
|
||||
.build();
|
||||
}
|
||||
|
||||
@GetMapping(value = "/campaignInfo", produces = "application/json")
|
||||
public CampaignInfo getCampaignInfo() {
|
||||
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
DonationsResponse donationResponse = donationService.getSynchronizedCachedDonationAmount(serverId);
|
||||
|
||||
Description pageObject = donationResponse.getPage();
|
||||
return CampaignInfo
|
||||
.builder()
|
||||
.collected(pageObject.getCollected())
|
||||
.collectedNet(pageObject.getCollectedNet())
|
||||
.donationCount(donationResponse.getDonationCount())
|
||||
.currency(pageObject.getCurrency())
|
||||
.percent(pageObject.getPercent())
|
||||
.displayName(pageObject.getDisplayName())
|
||||
.slug(pageObject.getSlug())
|
||||
.target(pageObject.getTarget())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.sissi.module.debra.api;
|
||||
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraFeatureConfig;
|
||||
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||
import dev.sheldan.sissi.module.debra.model.api.EndlessStreamInfo;
|
||||
import dev.sheldan.sissi.module.debra.model.database.EndlessStream;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import dev.sheldan.sissi.module.debra.service.management.EndlessStreamManagementServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.Instant;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
||||
|
||||
@RestController
|
||||
@RequestMapping(value = "/stream")
|
||||
public class EndlessStreamController {
|
||||
|
||||
@Autowired
|
||||
private EndlessStreamManagementServiceBean endlessStreamManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private DonationService donationService;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@GetMapping(value = "/endlessStream/{id}", produces = "application/json")
|
||||
public EndlessStreamInfo getLatestDonations(@PathVariable("id") Long id) {
|
||||
Long serverId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
EndlessStream endlessStream = endlessStreamManagementServiceBean.getEndlessStream(id);
|
||||
DonationsResponse donationInfo = donationService.getSynchronizedCachedDonationAmount(serverId);
|
||||
BigDecimal collectedAmount = donationInfo.getPage().getCollected();
|
||||
Long minuteRate = configService.getLongValueOrConfigDefault(DebraFeatureConfig.ENDLESS_STREAM_MINUTE_RATE, serverId);
|
||||
Instant endDate = endlessStream.getStartTime().plus(collectedAmount.multiply(new BigDecimal(minuteRate)).toBigInteger().longValue(), ChronoUnit.MINUTES);
|
||||
return EndlessStreamInfo
|
||||
.builder()
|
||||
.startDate(endlessStream.getStartTime())
|
||||
.endDate(endDate)
|
||||
.donationAmount(collectedAmount.longValue())
|
||||
.minuteRate(minuteRate)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
package dev.sheldan.sissi.module.debra.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.debra.config.DebraFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
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 DebraInfoButton extends AbstractConditionableCommand {
|
||||
|
||||
private static final String DEBRA_INFO_BUTTON = "debraInfoButton";
|
||||
private static final String DEBRA_INFO_BUTTON_RESPONSE_TEMPLATE_KEY = "debraInfoButton_response";
|
||||
private static final String TARGET_CHANNEL_PARAMETER_KEY = "targetChannel";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private DonationService donationService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
GuildMessageChannel targetChannel = slashCommandParameterService.getCommandOption(TARGET_CHANNEL_PARAMETER_KEY, event, GuildMessageChannel.class);
|
||||
return donationService.sendDebraInfoButtonMessage(targetChannel)
|
||||
.thenCompose(unused -> interactionService.replyEmbed(DEBRA_INFO_BUTTON_RESPONSE_TEMPLATE_KEY, event))
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(DebraSlashCommandNames.DEBRA_INTERNAL)
|
||||
.commandName("debrainfobutton")
|
||||
.defaultPrivilege(SlashCommandPrivilegeLevels.ADMIN)
|
||||
.build();
|
||||
|
||||
Parameter targetChannelParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(TARGET_CHANNEL_PARAMETER_KEY)
|
||||
.type(GuildMessageChannel.class)
|
||||
.build();
|
||||
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(targetChannelParameter);
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(DEBRA_INFO_BUTTON)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.parameters(parameters)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return DebraFeatureDefinition.DEBRA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
package dev.sheldan.sissi.module.debra.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.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
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.ChannelService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.debra.converter.DonationConverter;
|
||||
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
@Component
|
||||
public class Donations extends AbstractConditionableCommand {
|
||||
|
||||
private static final String DONATIONS_COMMAND_NAME = "donations";
|
||||
private static final String DONATIONS_RESPONSE_TEMPLATE_KEY = "donations_response";
|
||||
private static final String SELECTION_PARAMETER = "type";
|
||||
private static final String SELECTION_VALUE_PARAMETER = "parametervalue";
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private DonationService donationService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private DonationConverter donationConverter;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
MessageToSend messageToSend;
|
||||
if(parameters.isEmpty()) {
|
||||
messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), null, null);
|
||||
} else {
|
||||
String type = (String) parameters.get(0);
|
||||
Integer selectionValue = (Integer) parameters.get(1);
|
||||
Integer top = null;
|
||||
Integer latest = null;
|
||||
switch (type) {
|
||||
case "top": top = selectionValue; break;
|
||||
default:
|
||||
case "latest" :
|
||||
latest = selectionValue; break;
|
||||
}
|
||||
messageToSend = getDonationMessageToSend(commandContext.getGuild().getIdLong(), top, latest);
|
||||
}
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String selectionType = null;
|
||||
if(slashCommandParameterService.hasCommandOption(SELECTION_PARAMETER, event)) {
|
||||
selectionType = slashCommandParameterService.getCommandOption(SELECTION_PARAMETER, event, String.class);
|
||||
}
|
||||
Integer selectionValue = 5;
|
||||
if(slashCommandParameterService.hasCommandOption(SELECTION_VALUE_PARAMETER, event)) {
|
||||
selectionValue = slashCommandParameterService.getCommandOption(SELECTION_VALUE_PARAMETER, event, Integer.class);
|
||||
}
|
||||
if(selectionValue > 20) {
|
||||
selectionValue = 5;
|
||||
}
|
||||
Integer top = null;
|
||||
Integer latest = null;
|
||||
if(selectionType != null) {
|
||||
switch (selectionType) {
|
||||
case "top": top = selectionValue; break;
|
||||
default:
|
||||
case "latest" :
|
||||
latest = selectionValue; break;
|
||||
}
|
||||
}
|
||||
|
||||
MessageToSend messageToSend = getDonationMessageToSend(event.getGuild().getIdLong(), top, latest);
|
||||
return interactionService.replyMessageToSend(messageToSend, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private MessageToSend getDonationMessageToSend(Long serverId, Integer top, Integer latest) {
|
||||
DonationsModel donationModel;
|
||||
DonationsResponse donationResponse = donationService.fetchCurrentDonationAmount(serverId);
|
||||
donationModel = donationConverter.convertDonationResponse(donationResponse);
|
||||
if(top != null) {
|
||||
donationModel.setDonations(donationService.getHighestDonations(donationResponse, top));
|
||||
donationModel.setType(DonationsModel.DonationType.TOP);
|
||||
} else if(latest != null) {
|
||||
donationModel.setType(DonationsModel.DonationType.LATEST);
|
||||
donationModel.setDonations(donationService.getLatestDonations(donationResponse, latest));
|
||||
} else {
|
||||
donationModel.setDonations(new ArrayList<>());
|
||||
}
|
||||
return templateService.renderEmbedTemplate(DONATIONS_RESPONSE_TEMPLATE_KEY, donationModel, serverId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(DebraSlashCommandNames.DEBRA)
|
||||
.commandName(DONATIONS_COMMAND_NAME)
|
||||
.build();
|
||||
|
||||
Parameter selectionParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(SELECTION_PARAMETER)
|
||||
.optional(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
|
||||
Parameter selectionValueParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(SELECTION_VALUE_PARAMETER)
|
||||
.optional(true)
|
||||
.type(Integer.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(selectionParameter, selectionValueParameter);
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(DONATIONS_COMMAND_NAME)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.parameters(parameters)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return DebraFeatureDefinition.DEBRA;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.ehcache.config.builders.CacheManagerBuilder;
|
||||
import org.ehcache.jsr107.Eh107Configuration;
|
||||
import org.ehcache.xml.XmlConfiguration;
|
||||
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
@Configuration
|
||||
@Slf4j
|
||||
@EnableCaching
|
||||
public class CacheConfig {
|
||||
|
||||
@Bean
|
||||
public JCacheManagerCustomizer cacheManagerCustomizer() {
|
||||
URL myUrl = getClass().getResource("/donation-cache-config.xml");
|
||||
XmlConfiguration xmlConfig = new XmlConfiguration(myUrl);
|
||||
org.ehcache.CacheManager myCacheManager = CacheManagerBuilder.newCacheManager(xmlConfig);
|
||||
return cm -> {
|
||||
myCacheManager.getRuntimeConfiguration().getCacheConfigurations().entrySet().forEach(cacheConfiguration -> {
|
||||
javax.cache.configuration.Configuration<?, ?> jConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration(cacheConfiguration.getValue());
|
||||
log.info("Creating custom cache: " + cacheConfiguration.getKey());
|
||||
cm.createCache(cacheConfiguration.getKey(), jConfiguration);
|
||||
});
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class DebraFeatureConfig implements FeatureConfig {
|
||||
|
||||
public static final String DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY = "debraDonationNotificationDelayMillis";
|
||||
public static final String ENDLESS_STREAM_MINUTE_RATE = "endlessStreamMinuteRate";
|
||||
public static final String DEBRA_DONATION_API_FETCH_SIZE_KEY = "debraDonationApiFetchSize";
|
||||
public static final String DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME = "DEBRA_DONATION_NOTIFICATION_SERVER_ID";
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return DebraFeatureDefinition.DEBRA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||
return Arrays.asList(DebraPostTarget.DEBRA_DONATION_NOTIFICATION, DebraPostTarget.DEBRA_DONATION_NOTIFICATION2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRequiredSystemConfigKeys() {
|
||||
return Arrays.asList(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY, DEBRA_DONATION_API_FETCH_SIZE_KEY, ENDLESS_STREAM_MINUTE_RATE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum DebraFeatureDefinition implements FeatureDefinition {
|
||||
DEBRA("debra");
|
||||
|
||||
private String key;
|
||||
|
||||
DebraFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum DebraPostTarget implements PostTargetEnum {
|
||||
DEBRA_DONATION_NOTIFICATION("debraDonationNotification"), DEBRA_DONATION_NOTIFICATION2("debraDonationNotification2");
|
||||
|
||||
private String key;
|
||||
|
||||
DebraPostTarget(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:debra.properties")
|
||||
public class DebraPropertieSource {
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
@Getter
|
||||
@Setter
|
||||
@ConfigurationProperties(prefix = "sissi.debra")
|
||||
public class DebraProperties {
|
||||
private String websocketURL;
|
||||
private String donationAPIUrl;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package dev.sheldan.sissi.module.debra.config;
|
||||
|
||||
public class DebraSlashCommandNames {
|
||||
public static final String DEBRA = "debra";
|
||||
public static final String DEBRA_INTERNAL = "debrainternal";
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.sissi.module.debra.converter;
|
||||
|
||||
import dev.sheldan.sissi.module.debra.model.api.Donation;
|
||||
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class DonationConverter {
|
||||
public DonationItemModel convertDonation(Donation donation) {
|
||||
return DonationItemModel
|
||||
.builder()
|
||||
.donationAmount(donation.getAmount())
|
||||
.firstName(donation.getFirstname())
|
||||
.lastName(donation.getLastname())
|
||||
.anonymous(BooleanUtils.toBoolean(donation.getAnonym()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public DonationsModel convertDonationResponse(DonationsResponse response) {
|
||||
return DonationsModel
|
||||
.builder()
|
||||
.totalAmount(response.getPage().getCollected())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.debra.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class DonationAmountNotFoundException extends AbstractoTemplatableException {
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "donation_amount_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package dev.sheldan.sissi.module.debra.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.ListenerPriority;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListener;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerModel;
|
||||
import dev.sheldan.abstracto.core.interaction.button.listener.ButtonClickedListenerResult;
|
||||
import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DebraInfoButtonClickedListener implements ButtonClickedListener {
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
private static final String DEBRA_INFO_MESSAGE_TEMPLATE_KEY = "debraInfoMessage";
|
||||
private static final String DEBRA_INFO_MESSAGE_RESPONSE_TEMPLATE_KEY = "debraInfoMessage_response";
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_INFO_MESSAGE_TEMPLATE_KEY, new Object(), model.getServerId());
|
||||
messageService.sendMessageToSendToUser(model.getEvent().getUser(), messageToSend).thenAccept(interactionHook -> {
|
||||
log.info("Send debra info message to user {}", model.getEvent().getUser().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to send debra info message to user {}", model.getEvent().getUser().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
MessageToSend responseMessageToSend = templateService.renderEmbedTemplate(DEBRA_INFO_MESSAGE_RESPONSE_TEMPLATE_KEY, new Object(), model.getServerId());
|
||||
FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(responseMessageToSend, model.getEvent().getInteraction().getHook()))
|
||||
.thenAccept(interactionHook -> {
|
||||
log.info("Send debra info message response to user {}", model.getEvent().getUser().getIdLong());
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to send debra info message response to user {}", model.getEvent().getUser().getIdLong(), throwable);
|
||||
return null;
|
||||
});
|
||||
return ButtonClickedListenerResult.ACKNOWLEDGED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean handlesEvent(ButtonClickedListenerModel model) {
|
||||
return model.getOrigin().equals(DonationService.DEBRA_INFO_BUTTON_ORIGIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return DebraFeatureDefinition.DEBRA;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPriority() {
|
||||
return ListenerPriority.MEDIUM;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package dev.sheldan.sissi.module.debra.listener;
|
||||
|
||||
import dev.sheldan.abstracto.core.listener.AsyncStartupListener;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
||||
import dev.sheldan.sissi.module.debra.model.listener.DonationResponseModel;
|
||||
import dev.sheldan.sissi.module.debra.service.DonationService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import okhttp3.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY;
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class WebsocketListener extends WebSocketListener implements AsyncStartupListener {
|
||||
|
||||
@Autowired
|
||||
private DonationService donationService;
|
||||
|
||||
@Autowired
|
||||
private DebraProperties debraProperties;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
private WebSocket webSocketObj;
|
||||
private OkHttpClient clientObj;
|
||||
|
||||
@Override
|
||||
public void onOpen(WebSocket webSocket, Response response) {
|
||||
log.info("Connected to donation websocket.");
|
||||
super.onOpen(webSocket, response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket webSocket, String text) {
|
||||
CompletableFuture.runAsync(() -> {
|
||||
log.info("Handling received message on websocket.");
|
||||
try {
|
||||
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
Long delayMillis = configService.getLongValueOrConfigDefault(DEBRA_DONATION_NOTIFICATION_DELAY_CONFIG_KEY, targetServerId);
|
||||
log.info("Waiting {} milli seconds to send notification.", delayMillis);
|
||||
Thread.sleep(delayMillis);
|
||||
log.info("Loading new donation amount and sending notification.");
|
||||
DonationResponseModel donation = donationService.parseDonationFromMessage(text);
|
||||
donationService.sendDonationNotification(donation).thenAccept(unused -> {
|
||||
log.info("Successfully notified about donation.");
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to notify about donation.", throwable);
|
||||
return null;
|
||||
});
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to handle websocket message.", exception);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(WebSocket webSocket, Throwable t, @Nullable Response response) {
|
||||
log.warn("Websocket connection failed...", t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosing(WebSocket webSocket, int code, String reason) {
|
||||
log.info("Closing websocket connection. It was closed with code {} and reason {}.", code, reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
if(clientObj != null) {
|
||||
clientObj.connectionPool().evictAll();
|
||||
clientObj.dispatcher().executorService().shutdownNow();
|
||||
}
|
||||
clientObj = new OkHttpClient.Builder()
|
||||
.readTimeout(0, TimeUnit.MILLISECONDS)
|
||||
.retryOnConnectionFailure(true)
|
||||
.build();
|
||||
startConnection(clientObj);
|
||||
clientObj.dispatcher().executorService().shutdown();
|
||||
}
|
||||
|
||||
private void startConnection(OkHttpClient client) {
|
||||
log.info("Starting websocket connection.");
|
||||
Request request = new Request.Builder()
|
||||
.url(debraProperties.getWebsocketURL())
|
||||
.build();
|
||||
this.webSocketObj = client.newWebSocket(request, this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class CampaignInfo {
|
||||
private BigInteger donationCount;
|
||||
private BigDecimal collected;
|
||||
private BigDecimal target;
|
||||
private String currency;
|
||||
private String slug;
|
||||
private String displayName;
|
||||
private BigDecimal collectedNet;
|
||||
private BigDecimal percent;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class Description {
|
||||
@SerializedName("collected")
|
||||
private BigDecimal collected;
|
||||
@SerializedName("target")
|
||||
private BigDecimal target;
|
||||
@SerializedName("currency")
|
||||
private String currency;
|
||||
@SerializedName("slug")
|
||||
private String slug;
|
||||
@SerializedName("displayname")
|
||||
private String displayName;
|
||||
@SerializedName("collectednet")
|
||||
private BigDecimal collectedNet;
|
||||
@SerializedName("percent")
|
||||
private BigDecimal percent;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class Donation {
|
||||
@SerializedName("amount")
|
||||
private BigDecimal amount;
|
||||
@SerializedName("currency")
|
||||
private String currency;
|
||||
@SerializedName("text")
|
||||
private String text;
|
||||
@SerializedName("anonym")
|
||||
private Integer anonym;
|
||||
@SerializedName("firstname")
|
||||
private String firstname;
|
||||
@SerializedName("lastname")
|
||||
private String lastname;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class DonationInfo {
|
||||
private String firstName;
|
||||
private BigDecimal donationAmount;
|
||||
private Boolean anonymous;
|
||||
|
||||
public static DonationInfo fromDonationItemModel(DonationItemModel donationItemModel) {
|
||||
return DonationInfo
|
||||
.builder()
|
||||
.donationAmount(donationItemModel.getDonationAmount())
|
||||
.anonymous(donationItemModel.getAnonymous())
|
||||
.firstName(donationItemModel.getFirstName())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class DonationStats {
|
||||
private List<DonationInfo> donations;
|
||||
private BigDecimal totalAmount;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class DonationsResponse {
|
||||
@SerializedName("page")
|
||||
private Description page;
|
||||
@SerializedName("donation_count")
|
||||
private BigInteger donationCount;
|
||||
@SerializedName("donations")
|
||||
private List<Donation> donations;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.debra.model.api;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class EndlessStreamInfo {
|
||||
private Instant endDate;
|
||||
private Instant startDate;
|
||||
private Long donationAmount;
|
||||
private Long minuteRate;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.sissi.module.debra.model.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.interaction.button.ButtonPayload;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
@Setter
|
||||
public class DebraInfoButtonPayload implements ButtonPayload {
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.sissi.module.debra.model.commands;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class DebraInfoModel {
|
||||
private String buttonId;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.sissi.module.debra.model.commands;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
public class DonationItemModel {
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
private BigDecimal donationAmount;
|
||||
private Boolean anonymous;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.sissi.module.debra.model.commands;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
public class DonationsModel {
|
||||
private BigDecimal totalAmount;
|
||||
private DonationType type;
|
||||
private List<DonationItemModel> donations;
|
||||
|
||||
public enum DonationType {
|
||||
LATEST, TOP
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.sissi.module.debra.model.database;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "endless_stream")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class EndlessStream {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "start_time")
|
||||
private Instant startTime;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.sissi.module.debra.model.listener;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class DonationNotificationModel {
|
||||
private DonationResponseModel donation;
|
||||
private BigDecimal totalDonationAmount;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.sissi.module.debra.model.listener;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@ToString
|
||||
public class DonationResponseModel {
|
||||
private String donatorName;
|
||||
private BigDecimal amount;
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.sissi.module.debra.repository;
|
||||
|
||||
import dev.sheldan.sissi.module.debra.model.database.EndlessStream;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface EndlessStreamRepository extends JpaRepository<EndlessStream, Long> {
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package dev.sheldan.sissi.module.debra.service;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class BigDecimalGsonAdapter implements JsonDeserializer<BigDecimal> {
|
||||
@Override
|
||||
public BigDecimal deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
try {
|
||||
return new BigDecimal(json.getAsString()
|
||||
.replace(".", "")
|
||||
.replace(',', '.'));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new JsonParseException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
package dev.sheldan.sissi.module.debra.service;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentService;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.ConfigService;
|
||||
import dev.sheldan.abstracto.core.service.PostTargetService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.sissi.module.debra.exception.DonationAmountNotFoundException;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraPostTarget;
|
||||
import dev.sheldan.sissi.module.debra.config.DebraProperties;
|
||||
import dev.sheldan.sissi.module.debra.converter.DonationConverter;
|
||||
import dev.sheldan.sissi.module.debra.model.api.Donation;
|
||||
import dev.sheldan.sissi.module.debra.model.api.DonationsResponse;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DebraInfoButtonPayload;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DebraInfoModel;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationItemModel;
|
||||
import dev.sheldan.sissi.module.debra.model.commands.DonationsModel;
|
||||
import dev.sheldan.sissi.module.debra.model.listener.DonationResponseModel;
|
||||
import dev.sheldan.sissi.module.debra.model.listener.DonationNotificationModel;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.annotation.Cacheable;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_API_FETCH_SIZE_KEY;
|
||||
import static dev.sheldan.sissi.module.debra.config.DebraFeatureConfig.DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class DonationService {
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private DebraProperties debraProperties;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
@Autowired
|
||||
private DonationConverter donationConverter;
|
||||
|
||||
@Autowired
|
||||
private ConfigService configService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private ComponentService componentService;
|
||||
|
||||
@Autowired
|
||||
private ComponentPayloadService componentPayloadService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private DonationService self;
|
||||
|
||||
private static final String DEBRA_DONATION_NOTIFICATION_TEMPLATE_KEY = "debra_donation_notification";
|
||||
|
||||
private static final Pattern MESSAGE_PATTERN = Pattern.compile("(.*) hat (\\d{1,9},\\d{2}) Euro gespendet!<br \\/>Vielen Dank!<br \\/>Nachricht:<br \\/>(.*)");
|
||||
|
||||
private static final String DEBRA_INFO_BUTTON_MESSAGE_TEMPLATE_KEY = "debraInfoButton";
|
||||
public static final String DEBRA_INFO_BUTTON_ORIGIN = "DEBRA_INFO_BUTTON";
|
||||
|
||||
public DonationResponseModel parseDonationFromMessage(String message) {
|
||||
Matcher matcher = MESSAGE_PATTERN.matcher(message);
|
||||
if (matcher.find()) {
|
||||
String donatorName = matcher.group(1);
|
||||
String amountString = matcher.group(2);
|
||||
BigDecimal amount = new BigDecimal(amountString.replace(',', '.'));
|
||||
String donationMessage = Optional.ofNullable(matcher.group(3)).map(msg -> msg.replaceAll("(<br>)+", " ")).map(String::trim).orElse("");
|
||||
return DonationResponseModel
|
||||
.builder()
|
||||
.message(donationMessage)
|
||||
.donatorName(donatorName)
|
||||
.amount(amount)
|
||||
.build();
|
||||
} else {
|
||||
throw new IllegalArgumentException("String in wrong format");
|
||||
}
|
||||
}
|
||||
|
||||
public List<DonationItemModel> getHighestDonations(DonationsResponse response, Integer maxCount) {
|
||||
List<Donation> topDonations = response
|
||||
.getDonations()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(Donation::getAmount)
|
||||
.reversed())
|
||||
.collect(Collectors.toList());
|
||||
return topDonations
|
||||
.stream()
|
||||
.limit(maxCount)
|
||||
.map(donation -> donationConverter.convertDonation(donation))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public List<DonationItemModel> getLatestDonations(DonationsResponse response, Integer maxCount) {
|
||||
return response
|
||||
.getDonations()
|
||||
.stream()
|
||||
.limit(maxCount)
|
||||
.map(donation -> donationConverter.convertDonation(donation))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public synchronized DonationsResponse getSynchronizedCachedDonationAmount(Long serverId) {
|
||||
return self.getCachedDonationAmount(serverId);
|
||||
}
|
||||
|
||||
@Cacheable(value = "donation-cache")
|
||||
public synchronized DonationsResponse getCachedDonationAmount(Long serverId) {
|
||||
return self.fetchCurrentDonationAmount(serverId);
|
||||
}
|
||||
|
||||
public DonationsResponse fetchCurrentDonationAmount(Long serverId) {
|
||||
try {
|
||||
Long fetchSize = configService.getLongValueOrConfigDefault(DEBRA_DONATION_API_FETCH_SIZE_KEY, serverId);
|
||||
Request request = new Request.Builder()
|
||||
.url(String.format(debraProperties.getDonationAPIUrl(), fetchSize))
|
||||
.get()
|
||||
.build();
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
if(!response.isSuccessful()) {
|
||||
log.error("Failed to retrieve donation response. Response had code {} with body {} and headers {}.",
|
||||
response.code(), response.body().string(), response.headers());
|
||||
throw new DonationAmountNotFoundException();
|
||||
}
|
||||
Gson gson = getGson();
|
||||
return gson.fromJson(response.body().string(), DonationsResponse.class);
|
||||
} catch (Exception exception) {
|
||||
throw new AbstractoRunTimeException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Gson getGson() {
|
||||
return new GsonBuilder()
|
||||
.registerTypeAdapter(BigDecimal.class, new BigDecimalGsonAdapter())
|
||||
.create();
|
||||
}
|
||||
|
||||
private DonationsModel getDonationInfoModel(Long serverId) {
|
||||
return donationConverter.convertDonationResponse(fetchCurrentDonationAmount(serverId));
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendDonationNotification(DonationResponseModel donation) throws IOException {
|
||||
Long targetServerId = Long.parseLong(System.getenv(DEBRA_DONATION_NOTIFICATION_SERVER_ID_ENV_NAME));
|
||||
DonationsModel donationInfoModel = getDonationInfoModel(targetServerId);
|
||||
DonationNotificationModel model = DonationNotificationModel
|
||||
.builder()
|
||||
.donation(donation)
|
||||
.totalDonationAmount(donationInfoModel.getTotalAmount())
|
||||
.build();
|
||||
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);
|
||||
return FutureUtils.toSingleFutureGeneric(firstMessage);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> sendDebraInfoButtonMessage(GuildMessageChannel guildMessageChannel) {
|
||||
String buttonId = componentService.generateComponentId();
|
||||
DebraInfoModel model = DebraInfoModel
|
||||
.builder()
|
||||
.buttonId(buttonId)
|
||||
.build();
|
||||
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(DEBRA_INFO_BUTTON_MESSAGE_TEMPLATE_KEY, model, guildMessageChannel.getGuild().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, guildMessageChannel)).thenAccept(unused -> {
|
||||
self.persistButtonPayload(guildMessageChannel, buttonId);
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistButtonPayload(GuildMessageChannel guildMessageChannel, String buttonId) {
|
||||
DebraInfoButtonPayload payload = DebraInfoButtonPayload
|
||||
.builder()
|
||||
.build();
|
||||
AServer server = serverManagementService.loadServer(guildMessageChannel.getGuild().getIdLong());
|
||||
componentPayloadService.createButtonPayload(buttonId, payload, DEBRA_INFO_BUTTON_ORIGIN, server);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.sissi.module.debra.service.management;
|
||||
|
||||
import dev.sheldan.sissi.module.debra.model.database.EndlessStream;
|
||||
import dev.sheldan.sissi.module.debra.repository.EndlessStreamRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class EndlessStreamManagementServiceBean {
|
||||
|
||||
@Autowired
|
||||
private EndlessStreamRepository endlessStreamRepository;
|
||||
|
||||
public EndlessStream getEndlessStream(Long id) {
|
||||
return endlessStreamRepository.getReferenceById(id);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
abstracto.featureFlags.debra.featureName=debra
|
||||
abstracto.featureFlags.debra.enabled=false
|
||||
|
||||
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-schmetterlingsaktion-2024?details=1&num=%s&ort=0
|
||||
|
||||
abstracto.systemConfigs.debraDonationNotificationDelayMillis.name=debraDonationNotificationDelayMillis
|
||||
abstracto.systemConfigs.debraDonationNotificationDelayMillis.longValue=60000
|
||||
|
||||
abstracto.systemConfigs.endlessStreamMinuteRate.name=endlessStreamMinuteRate
|
||||
abstracto.systemConfigs.endlessStreamMinuteRate.longValue=1
|
||||
|
||||
abstracto.systemConfigs.debraDonationApiFetchSize.name=debraDonationApiFetchSize
|
||||
abstracto.systemConfigs.debraDonationApiFetchSize.longValue=1000
|
||||
@@ -0,0 +1,24 @@
|
||||
<config
|
||||
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
|
||||
xmlns='http://www.ehcache.org/v3'
|
||||
xsi:schemaLocation="
|
||||
http://www.ehcache.org/v3
|
||||
http://www.ehcache.org/schema/ehcache-core-3.8-1.xsd">
|
||||
<cache uses-template="default" alias="donation-cache">
|
||||
<expiry>
|
||||
<ttl unit="seconds">120</ttl>
|
||||
</expiry>
|
||||
|
||||
<resources>
|
||||
<heap unit="entries">5</heap>
|
||||
</resources>
|
||||
</cache>
|
||||
<cache-template name="default">
|
||||
<expiry>
|
||||
<ttl unit="seconds">600</ttl>
|
||||
</expiry>
|
||||
<resources>
|
||||
<heap>50</heap>
|
||||
</resources>
|
||||
</cache-template>
|
||||
</config>
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="debraFeature" value="(SELECT id FROM feature WHERE key = 'debra')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="debra-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="donations"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${debraFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="debra_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="debra"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="debraFeature" value="(SELECT id FROM feature WHERE key = 'debra')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="debraInfoButton-command">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="debraInfoButton"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${debraFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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="command.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?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="endless_stream-table">
|
||||
<createTable tableName="endless_stream">
|
||||
<column name="id" autoIncrement="true" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="start_time" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
</createTable>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS endless_stream_update_trigger ON endless_stream;
|
||||
CREATE TRIGGER endless_stream_update_trigger BEFORE UPDATE ON endless_stream FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS endless_stream_insert_trigger ON endless_stream;
|
||||
CREATE TRIGGER endless_stream_insert_trigger BEFORE INSERT ON endless_stream FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -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="endless_stream.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -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="1.3.6/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.21/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.4.29/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user