mirror of
https://github.com/Sheldan/Sissi.git
synced 2026-01-10 11:19:25 +00:00
Compare commits
115 Commits
sissi-1.3.
...
sissi-1.4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
11
.github/workflows/build.yml
vendored
11
.github/workflows/build.yml
vendored
@@ -17,11 +17,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
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:
|
||||
|
||||
36
.github/workflows/release.yml
vendored
36
.github/workflows/release.yml
vendored
@@ -6,13 +6,14 @@ jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Set up Java for publishing to GitHub Packages
|
||||
uses: actions/setup-java@v1
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: 1.8
|
||||
distribution: 'corretto'
|
||||
java-version: 17
|
||||
- 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
|
||||
@@ -22,17 +23,26 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
user: Sheldan
|
||||
token: ${{ secrets.ABSTRACTO_PAT }}
|
||||
- name: Login to GitHub Packages Docker Registry
|
||||
uses: docker/login-action@v1
|
||||
- name: Login to Harbor
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: docker.pkg.github.com
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push deployment container
|
||||
registry: harbor.sheldan.dev
|
||||
username: ${{ secrets.HARBOR_USERNAME }}
|
||||
password: ${{ secrets.HARBOR_TOKEN }}
|
||||
- name: Load env files
|
||||
id: dotenv
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: ./deployment/image-packaging/src/main/docker/.env
|
||||
- name: Push 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.4.15
|
||||
ABSTRACTO_REGISTRY_PREFIX: docker.pkg.github.com/sheldan/abstracto/
|
||||
REGISTRY_PREFIX: ${{ steps.dotenv.outputs.registry_prefix }}
|
||||
VERSION: ${{ steps.dotenv.outputs.version }}
|
||||
- name: Helm 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
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Sheldan
|
||||
Copyright (c) 2023 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
|
||||
|
||||
40
Tiltfile
Normal file
40
Tiltfile
Normal file
@@ -0,0 +1,40 @@
|
||||
allow_k8s_contexts('k8s-cluster')
|
||||
|
||||
load('ext://restart_process', 'docker_build_with_restart')
|
||||
registry = 'harbor.sheldan.dev/sissi/'
|
||||
|
||||
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', '-noverify', '-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-template-data', 'deployment/image-packaging/src/main/docker/template-data/')
|
||||
|
||||
|
||||
k8s_yaml(helm('deployment/helm/sissi', 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.3.17</version>
|
||||
<version>1.4.19</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>
|
||||
@@ -75,6 +71,11 @@
|
||||
<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>
|
||||
@@ -130,6 +131,11 @@
|
||||
<artifactId>logging-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>statistic-impl</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sissi modules -->
|
||||
|
||||
<dependency>
|
||||
@@ -144,6 +150,12 @@
|
||||
<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>
|
||||
|
||||
@@ -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,13 @@
|
||||
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.jpa.hibernate.default_schema=abstracto
|
||||
spring.jpa.properties.hibernate.default_schema=abstracto
|
||||
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.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -22,6 +22,18 @@
|
||||
<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>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application.module.custom</groupId>
|
||||
<artifactId>sissi-customizations</artifactId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>application</artifactId>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>sissi-modules</artifactId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>sissi-modules</artifactId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
package dev.sheldan.sissi.module.meetup.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.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.meetup.exception.NotMeetupOrganizerException;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
|
||||
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
|
||||
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;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class ChangeMeetup extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CHANGE_MEETUP_COMMAND = "changeMeetup";
|
||||
private static final String MEETUP_ID_PARAMETER = "meetupId";
|
||||
private static final String MEETUP_NEW_VALUE_PARAMETER = "newValue";
|
||||
private static final String MEETUP_PROPERTY_PARAMETER = "property";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private MeetupManagementServiceBean meetupManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private MeetupServiceBean meetupServiceBean;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
List<Object> parameters = commandContext.getParameters().getParameters();
|
||||
Long meetupId = (Long) parameters.get(0);
|
||||
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, commandContext.getGuild().getIdLong());
|
||||
if(!meetup.getOrganizer().getUserReference().getId().equals(commandContext.getAuthor().getIdLong())) {
|
||||
throw new NotMeetupOrganizerException();
|
||||
}
|
||||
String property = (String) parameters.get(1);
|
||||
MeetupProperty propertyEnum = MeetupProperty.valueOf(property);
|
||||
String newValue = (String) parameters.get(2);
|
||||
return updateMeetup(meetup, propertyEnum, newValue).thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> updateMeetup(Meetup meetup, MeetupProperty propertyEnum, String newValue) {
|
||||
CompletableFuture<Void> future;
|
||||
switch (propertyEnum) {
|
||||
case TOPIC:
|
||||
future = meetupServiceBean.changeMeetupTopic(meetup, newValue);
|
||||
break;
|
||||
case LOCATION:
|
||||
future = meetupServiceBean.changeMeetupLocation(meetup, newValue);
|
||||
break;
|
||||
default:
|
||||
case DESCRIPTION:
|
||||
future = meetupServiceBean.changeMeetupDescription(meetup, newValue);
|
||||
break;
|
||||
}
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
Long meetupId = slashCommandParameterService.getCommandOption(MEETUP_ID_PARAMETER, event, Integer.class).longValue();
|
||||
Meetup meetup = meetupManagementServiceBean.getMeetup(meetupId, event.getGuild().getIdLong());
|
||||
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
|
||||
throw new NotMeetupOrganizerException();
|
||||
}
|
||||
String newValue = slashCommandParameterService.getCommandOption(MEETUP_NEW_VALUE_PARAMETER, event, String.class);
|
||||
String property = slashCommandParameterService.getCommandOption(MEETUP_PROPERTY_PARAMETER, event, String.class);
|
||||
MeetupProperty propertyEnum = MeetupProperty.valueOf(property);
|
||||
return updateMeetup(meetup, propertyEnum, newValue)
|
||||
.thenCompose(commandResult -> interactionService.replyEmbed("changeMeetup_response", event))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter meetupIdParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(MEETUP_ID_PARAMETER)
|
||||
.type(Long.class)
|
||||
.build();
|
||||
|
||||
List<String> meetupProperties = Arrays
|
||||
.stream(MeetupProperty.values())
|
||||
.map(Enum::name)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Parameter meetupPropertyParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(MEETUP_PROPERTY_PARAMETER)
|
||||
.type(String.class)
|
||||
.choices(meetupProperties)
|
||||
.build();
|
||||
|
||||
Parameter newValueParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(MEETUP_NEW_VALUE_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(meetupIdParameter, meetupPropertyParameter, newValueParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(MeetupSlashCommandNames.MEETUP)
|
||||
.commandName("changeMeetup")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CHANGE_MEETUP_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return MeetupFeatureDefinition.MEETUP;
|
||||
}
|
||||
|
||||
public enum MeetupProperty {
|
||||
DESCRIPTION, TOPIC, LOCATION
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ 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.config.validator.MaxStringLengthValidator;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandContext;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
@@ -71,7 +72,9 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
private static final String MEETUP_TIME_PARAMETER = "meetupTime";
|
||||
private static final String TOPIC_PARAMETER = "topic";
|
||||
private static final String DESCRIPTION_PARAMETER = "description";
|
||||
private static final String LOCATION_PARAMETER = "location";
|
||||
private static final String CONFIRMATION_TEMPLATE = "createMeetup_confirmation";
|
||||
private static final String DEFAULT_LOCATION_STRING = "\"\"";
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
@@ -86,7 +89,7 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
}
|
||||
AUserInAServer organizer = userInServerManagementService.loadOrCreateUser(commandContext.getAuthor());
|
||||
AChannel meetupChannel = channelManagementService.loadChannel(commandContext.getChannel().getIdLong());
|
||||
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, meetupTopic, description, organizer, meetupChannel);
|
||||
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, meetupTopic, description, organizer, meetupChannel, DEFAULT_LOCATION_STRING);
|
||||
String confirmationId = componentService.generateComponentId();
|
||||
String cancelId = componentService.generateComponentId();
|
||||
MeetupConfirmationModel model = MeetupConfirmationModel
|
||||
@@ -95,6 +98,7 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
.guildId(commandContext.getGuild().getIdLong())
|
||||
.description(description)
|
||||
.topic(meetupTopic)
|
||||
.location(meetup.getLocation())
|
||||
.confirmationId(confirmationId)
|
||||
.cancelId(cancelId)
|
||||
.meetupId(meetup.getId().getId())
|
||||
@@ -117,10 +121,17 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
} else {
|
||||
description = "";
|
||||
}
|
||||
|
||||
String location;
|
||||
if(slashCommandParameterService.hasCommandOption(LOCATION_PARAMETER, event)) {
|
||||
location = slashCommandParameterService.getCommandOption(LOCATION_PARAMETER, event, String.class);
|
||||
} else {
|
||||
location = DEFAULT_LOCATION_STRING;
|
||||
}
|
||||
Instant meetupTime = Instant.ofEpochSecond(time);
|
||||
AUserInAServer organizer = userInServerManagementService.loadOrCreateUser(event.getMember());
|
||||
AChannel meetupChannel = channelManagementService.loadChannel(event.getChannel().getIdLong());
|
||||
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, topic, description, organizer, meetupChannel);
|
||||
Meetup meetup = meetupManagementServiceBean.createMeetup(meetupTime, topic, description, organizer, meetupChannel, location);
|
||||
String confirmationId = componentService.generateComponentId();
|
||||
String cancelId = componentService.generateComponentId();
|
||||
MeetupConfirmationModel model = MeetupConfirmationModel
|
||||
@@ -129,6 +140,7 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
.guildId(event.getGuild().getIdLong())
|
||||
.description(description)
|
||||
.topic(topic)
|
||||
.location(meetup.getLocation())
|
||||
.confirmationId(confirmationId)
|
||||
.cancelId(cancelId)
|
||||
.meetupId(meetup.getId().getId())
|
||||
@@ -166,7 +178,17 @@ public class CreateMeetup extends AbstractConditionableCommand {
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(timeParameter, topicParameter, descriptionParameter);
|
||||
Parameter locationParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(LOCATION_PARAMETER)
|
||||
.remainder(true)
|
||||
.optional(true)
|
||||
.slashCommandOnly(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(timeParameter, topicParameter, descriptionParameter, locationParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
|
||||
@@ -49,19 +49,19 @@ public class ListMeetups extends AbstractConditionableCommand {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeAsync(CommandContext commandContext) {
|
||||
MessageToSend messageToSend = getMessageToSend(commandContext.getGuild().getIdLong());
|
||||
MessageToSend messageToSend = getMessageToSend(commandContext.getGuild().getIdLong(), commandContext.getChannel().getIdLong());
|
||||
return FutureUtils.toSingleFutureGeneric(channelService.sendMessageToSendToChannel(messageToSend, commandContext.getChannel()))
|
||||
.thenApply(unused -> CommandResult.fromIgnored());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
return interactionService.replyMessageToSend(getMessageToSend(event.getGuild().getIdLong()), event)
|
||||
return interactionService.replyMessageToSend(getMessageToSend(event.getGuild().getIdLong(), event.getChannel().getIdLong()), event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private MessageToSend getMessageToSend(Long serverId) {
|
||||
List<Meetup> meetups = meetupManagementServiceBean.getIncomingMeetups();
|
||||
private MessageToSend getMessageToSend(Long serverId, Long channelId) {
|
||||
List<Meetup> meetups = meetupManagementServiceBean.getIncomingMeetups(serverId, channelId);
|
||||
List<MeetupListItemModel> listItems = meetups
|
||||
.stream()
|
||||
.map(MeetupListItemModel::fromMeetup)
|
||||
|
||||
@@ -15,6 +15,7 @@ import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.meetup.exception.NotMeetupOrganizerException;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.MeetupDecision;
|
||||
import dev.sheldan.sissi.module.meetup.service.MeetupServiceBean;
|
||||
import dev.sheldan.sissi.module.meetup.service.management.MeetupManagementServiceBean;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
@@ -24,6 +25,7 @@ import org.springframework.stereotype.Component;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class NotifyMeetupParticipants extends AbstractConditionableCommand {
|
||||
@@ -42,6 +44,7 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
|
||||
|
||||
private static final String MEETUP_ID_PARAMETER = "meetupId";
|
||||
private static final String NOTIFICATION_MESSAGE_PARAMETER = "notificationMessage";
|
||||
private static final String NOTIFICATION_MEETUP_DECISION = "decision";
|
||||
private static final String NOTIFY_MEETUP_PARTICIPANTS_COMMAND = "notifyMeetupParticipants";
|
||||
private static final String NOTIFY_MEETUP_PARTICIPANTS_RESPONSE = "notifyMeetupParticipants_response";
|
||||
|
||||
@@ -54,7 +57,7 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
|
||||
throw new NotMeetupOrganizerException();
|
||||
}
|
||||
String notificationMessage = (String) parameters.get(1);
|
||||
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage)
|
||||
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage, null)
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@@ -65,8 +68,12 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
|
||||
if(!meetup.getOrganizer().getUserReference().getId().equals(event.getMember().getIdLong())) {
|
||||
throw new NotMeetupOrganizerException();
|
||||
}
|
||||
MeetupDecision toNotify = null;
|
||||
if(slashCommandParameterService.hasCommandOption(NOTIFICATION_MEETUP_DECISION, event)) {
|
||||
toNotify = MeetupDecision.valueOf(slashCommandParameterService.getCommandOption(NOTIFICATION_MEETUP_DECISION, event, String.class));
|
||||
}
|
||||
String notificationMessage = slashCommandParameterService.getCommandOption(NOTIFICATION_MESSAGE_PARAMETER, event, String.class);
|
||||
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage)
|
||||
return meetupServiceBean.notifyMeetupParticipants(meetup, notificationMessage, toNotify)
|
||||
.thenCompose(unused -> interactionService.replyEmbed(NOTIFY_MEETUP_PARTICIPANTS_RESPONSE, event))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
@@ -88,7 +95,22 @@ public class NotifyMeetupParticipants extends AbstractConditionableCommand {
|
||||
.remainder(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(meetupIdParameter, notificationMessage);
|
||||
List<String> meetupDecisions = Arrays
|
||||
.stream(MeetupDecision.values())
|
||||
.map(Enum::name)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Parameter meetupDecisionChoice = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(NOTIFICATION_MEETUP_DECISION)
|
||||
.type(String.class)
|
||||
.optional(true)
|
||||
.choices(meetupDecisions)
|
||||
.slashCommandOnly(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(meetupIdParameter, notificationMessage, meetupDecisionChoice);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
|
||||
@@ -2,8 +2,14 @@ package dev.sheldan.sissi.module.meetup.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static dev.sheldan.sissi.module.meetup.config.MeetupFeatureMode.ATTACH_ICS_FILE;
|
||||
|
||||
@Component
|
||||
public class MeetupFeatureConfig implements FeatureConfig {
|
||||
@Override
|
||||
@@ -11,4 +17,8 @@ public class MeetupFeatureConfig implements FeatureConfig {
|
||||
return MeetupFeatureDefinition.MEETUP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(ATTACH_ICS_FILE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.meetup.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum MeetupFeatureMode implements FeatureMode {
|
||||
ATTACH_ICS_FILE("attachIcsFile");
|
||||
|
||||
private final String key;
|
||||
|
||||
MeetupFeatureMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,6 @@ import org.springframework.stereotype.Component;
|
||||
@PersistJobDataAfterExecution
|
||||
public class MeetupCleanupJob extends QuartzJobBean {
|
||||
|
||||
|
||||
@Autowired
|
||||
private MeetupServiceBean meetupServiceBean;
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import dev.sheldan.abstracto.core.service.MessageService;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.utils.FileService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||
@@ -76,6 +77,9 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
|
||||
@Autowired
|
||||
private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Override
|
||||
public ButtonClickedListenerResult execute(ButtonClickedListenerModel model) {
|
||||
MeetupConfirmationPayload payload = (MeetupConfirmationPayload) model.getDeserializedPayload();
|
||||
@@ -104,6 +108,10 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
|
||||
messageModel.setNoId(noButtonId);
|
||||
messageModel.setMaybeId(maybeButtonId);
|
||||
messageModel.setNoTimeId(noTimeButtonId);
|
||||
meetup.setYesButtonId(yesButtonId);
|
||||
meetup.setMaybeButtonId(maybeButtonId);
|
||||
meetup.setNoTimeButtonId(noTimeButtonId);
|
||||
meetup.setNotInterestedButtonId(noButtonId);
|
||||
messageModel.setCancelled(false);
|
||||
Long meetupId = payload.getMeetupId();
|
||||
Long serverId = payload.getGuildId();
|
||||
@@ -111,6 +119,9 @@ public class MeetupConfirmationListener implements ButtonClickedListener {
|
||||
List<CompletableFuture<Message>> messageFutures = channelService.sendMessageToSendToChannel(messageToSend, model.getEvent().getMessageChannel());
|
||||
FutureUtils.toSingleFutureGeneric(messageFutures).thenAccept(unused -> {
|
||||
messageService.deleteMessage(model.getEvent().getMessage());
|
||||
messageToSend.getAttachedFiles().forEach(attachedFile -> {
|
||||
fileService.safeDeleteIgnoreException(attachedFile.getFile());
|
||||
});
|
||||
Message meetupMessage = messageFutures.get(0).join();
|
||||
messageService.pinMessage(meetupMessage);
|
||||
self.persistPayloads(meetupId, serverId, yesButtonId, noButtonId, maybeButtonId, noTimeButtonId, meetupMessage);
|
||||
|
||||
@@ -14,6 +14,7 @@ public class MeetupConfirmationModel {
|
||||
private MemberDisplay organizer;
|
||||
private Instant meetupTime;
|
||||
private Long meetupId;
|
||||
private String location;
|
||||
private String topic;
|
||||
private String description;
|
||||
private Long guildId;
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -43,6 +43,26 @@ public class Meetup {
|
||||
@Column(name = "message_id")
|
||||
private Long messageId;
|
||||
|
||||
@Getter
|
||||
@Column(name = "location")
|
||||
private String location;
|
||||
|
||||
@Getter
|
||||
@Column(name = "yes_button_id")
|
||||
private String yesButtonId;
|
||||
|
||||
@Getter
|
||||
@Column(name = "maybe_button_id")
|
||||
private String maybeButtonId;
|
||||
|
||||
@Getter
|
||||
@Column(name = "no_time_button_id")
|
||||
private String noTimeButtonId;
|
||||
|
||||
@Getter
|
||||
@Column(name = "not_interested_button_id")
|
||||
private String notInterestedButtonId;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
orphanRemoval = true,
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupComponentId;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.embed.MeetupParticipationId;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.sissi.module.meetup.model.database.embed;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Embeddable
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.sissi.module.meetup.model.database.embed;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Embeddable
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.sissi.module.meetup.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
public class MeetupIcsModel {
|
||||
private Boolean attachIcsFile;
|
||||
private String iceFileName;
|
||||
private String icsFormattedCreationTime;
|
||||
private String icsFormattedStartTime;
|
||||
private String icsFormattedEndTime;
|
||||
}
|
||||
@@ -15,6 +15,8 @@ public class MeetupMessageModel {
|
||||
private String topic;
|
||||
private String description;
|
||||
private Instant meetupTime;
|
||||
private String location;
|
||||
private String decodedLocation;
|
||||
private MemberDisplay organizer;
|
||||
private Long meetupId;
|
||||
private String yesId;
|
||||
@@ -26,4 +28,5 @@ public class MeetupMessageModel {
|
||||
private List<MemberDisplay> maybeParticipants;
|
||||
private List<MemberDisplay> noTimeParticipants;
|
||||
private List<MemberDisplay> declinedParticipants;
|
||||
private MeetupIcsModel meetupIcsModel;
|
||||
}
|
||||
|
||||
@@ -11,4 +11,7 @@ import java.util.List;
|
||||
public class MeetupNotificationModel {
|
||||
private List<MemberDisplay> participants;
|
||||
private String notificationMessage;
|
||||
private Long meetupMessageId;
|
||||
private String meetupTopic;
|
||||
private Long meetupId;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import java.util.List;
|
||||
@Repository
|
||||
public interface MeetupRepository extends JpaRepository<Meetup, ServerSpecificId> {
|
||||
List<Meetup> findByMeetupTimeLessThan(Instant date);
|
||||
List<Meetup> findByMeetupTimeGreaterThan(Instant date);
|
||||
List<Meetup> findByMeetupTimeGreaterThanAndState(Instant date, MeetupState state);
|
||||
List<Meetup> findByMeetupTimeGreaterThanAndStateAndServer_IdAndMeetupChannel_Id(Instant date, MeetupState state, Long serverId, Long channelId);
|
||||
List<Meetup> findByState(MeetupState state);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.sissi.module.meetup.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadManagementService;
|
||||
import dev.sheldan.abstracto.core.interaction.ComponentPayloadService;
|
||||
import dev.sheldan.abstracto.core.models.ServerChannelMessage;
|
||||
@@ -9,9 +10,12 @@ import dev.sheldan.abstracto.core.service.*;
|
||||
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.FileService;
|
||||
import dev.sheldan.abstracto.core.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.scheduling.model.JobParameters;
|
||||
import dev.sheldan.abstracto.scheduling.service.SchedulerService;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.meetup.config.MeetupFeatureMode;
|
||||
import dev.sheldan.sissi.module.meetup.model.command.MeetupChangeTimeConfirmationModel;
|
||||
import dev.sheldan.sissi.module.meetup.model.command.MeetupConfirmationModel;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.Meetup;
|
||||
@@ -20,6 +24,7 @@ import dev.sheldan.sissi.module.meetup.model.database.MeetupParticipant;
|
||||
import dev.sheldan.sissi.module.meetup.model.database.MeetupState;
|
||||
import dev.sheldan.sissi.module.meetup.model.payload.MeetupChangeTimeConfirmationPayload;
|
||||
import dev.sheldan.sissi.module.meetup.model.payload.MeetupConfirmationPayload;
|
||||
import dev.sheldan.sissi.module.meetup.model.template.MeetupIcsModel;
|
||||
import dev.sheldan.sissi.module.meetup.model.template.MeetupMessageModel;
|
||||
import dev.sheldan.sissi.module.meetup.model.template.MeetupNotificationModel;
|
||||
import dev.sheldan.sissi.module.meetup.model.template.MeetupTimeChangedNotificationModel;
|
||||
@@ -33,7 +38,13 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -75,6 +86,9 @@ public class MeetupServiceBean {
|
||||
@Autowired
|
||||
private MeetupServiceBean self;
|
||||
|
||||
@Autowired
|
||||
private FileService fileService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@@ -87,11 +101,16 @@ public class MeetupServiceBean {
|
||||
@Autowired
|
||||
private SchedulerService schedulerService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private MeetupParticipatorManagementServiceBean meetupParticipatorManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private MeetupComponentManagementServiceBean meetupComponentManagementServiceBean;
|
||||
private static final String ICS_TIME_STAMP_FORMAT = "yMMdd'T'kkmmss'Z'";
|
||||
private static final DateTimeFormatter ICS_DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(ICS_TIME_STAMP_FORMAT);
|
||||
|
||||
public void storeMeetupConfirmation(MeetupConfirmationModel model) {
|
||||
AServer server = serverManagementService.loadServer(model.getGuildId());
|
||||
@@ -122,6 +141,22 @@ public class MeetupServiceBean {
|
||||
componentPayloadService.createButtonPayload(model.getCancelId(), confirmationPayload, MEETUP_CHANGE_TIME_CONFIRMATION_BUTTON, server);
|
||||
}
|
||||
|
||||
private MeetupIcsModel getMeetupICSModel(Meetup meetup) {
|
||||
ZonedDateTime startTime = meetup.getMeetupTime().atZone(ZoneId.of("UTC"));
|
||||
ZonedDateTime endTime = meetup.getMeetupTime().plus(1, ChronoUnit.HOURS).atZone(ZoneId.of("UTC"));
|
||||
String icsFormattedStartTime = startTime.format(ICS_DATE_TIME_FORMATTER);
|
||||
String icsFormattedEndTime = endTime.format(ICS_DATE_TIME_FORMATTER);
|
||||
String icsFormattedMeetupCreationTime = Instant.now().atZone(ZoneId.of("UTC"))
|
||||
.format(ICS_DATE_TIME_FORMATTER);
|
||||
boolean attachIcsFile = featureModeService.featureModeActive(MeetupFeatureDefinition.MEETUP, meetup.getServer().getId(), MeetupFeatureMode.ATTACH_ICS_FILE);
|
||||
return MeetupIcsModel
|
||||
.builder()
|
||||
.attachIcsFile(attachIcsFile)
|
||||
.icsFormattedCreationTime(icsFormattedMeetupCreationTime)
|
||||
.icsFormattedStartTime(icsFormattedStartTime)
|
||||
.icsFormattedEndTime(icsFormattedEndTime)
|
||||
.build();
|
||||
}
|
||||
|
||||
public MeetupMessageModel getMeetupMessageModel(Meetup meetup) {
|
||||
List<MeetupParticipant> allParticipants = meetup.getParticipants();
|
||||
@@ -141,10 +176,17 @@ public class MeetupServiceBean {
|
||||
.stream()
|
||||
.filter(meetupParticipator -> meetupParticipator.getDecision().equals(MeetupDecision.NO_TIME))
|
||||
.collect(Collectors.toList());
|
||||
String rawLocation = java.net.URLDecoder.decode(meetup.getLocation(), StandardCharsets.UTF_8);
|
||||
return MeetupMessageModel
|
||||
.builder()
|
||||
.description(meetup.getDescription())
|
||||
.topic(meetup.getTopic())
|
||||
.location(meetup.getLocation())
|
||||
.decodedLocation(rawLocation)
|
||||
.noTimeId(meetup.getNoTimeButtonId())
|
||||
.yesId(meetup.getYesButtonId())
|
||||
.maybeId(meetup.getMaybeButtonId())
|
||||
.noId(meetup.getNotInterestedButtonId())
|
||||
.meetupTime(meetup.getMeetupTime())
|
||||
.meetupId(meetup.getId().getId())
|
||||
.participants(getMemberDisplays(participating))
|
||||
@@ -153,6 +195,7 @@ public class MeetupServiceBean {
|
||||
.maybeParticipants(getMemberDisplays(maybe))
|
||||
.cancelled(meetup.getState().equals(MeetupState.CANCELLED))
|
||||
.organizer(MemberDisplay.fromAUserInAServer(meetup.getOrganizer()))
|
||||
.meetupIcsModel(getMeetupICSModel(meetup))
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -250,8 +293,8 @@ public class MeetupServiceBean {
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> notifyMeetupParticipants(Meetup meetup, String message) {
|
||||
List<MeetupDecision> decisionsToBeNotified = Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.YES);
|
||||
public CompletableFuture<Void> notifyMeetupParticipants(Meetup meetup, String message, MeetupDecision toNotify) {
|
||||
List<MeetupDecision> decisionsToBeNotified = toNotify == null ? Arrays.asList(MeetupDecision.MAYBE, MeetupDecision.YES) : Arrays.asList(toNotify);
|
||||
List<MemberDisplay> participants = meetup
|
||||
.getParticipants()
|
||||
.stream()
|
||||
@@ -262,6 +305,9 @@ public class MeetupServiceBean {
|
||||
MeetupNotificationModel model = MeetupNotificationModel
|
||||
.builder()
|
||||
.notificationMessage(message)
|
||||
.meetupId(meetup.getId().getId())
|
||||
.meetupMessageId(meetup.getMessageId())
|
||||
.meetupTopic(meetup.getTopic())
|
||||
.participants(participants)
|
||||
.build();
|
||||
MessageChannel channel = channelService.getMessageChannelFromServer(meetup.getServer().getId(), meetup.getMeetupChannel().getId());
|
||||
@@ -379,8 +425,43 @@ public class MeetupServiceBean {
|
||||
|
||||
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel);
|
||||
GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
|
||||
return channelService.editEmbedMessageInAChannel(updatedMeetupMessage.getEmbeds().get(0), meetupChannel, meetup.getMessageId())
|
||||
return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId())
|
||||
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId))
|
||||
.thenAccept(unused -> fileService.safeDeleteIgnoreException(updatedMeetupMessage.getAttachedFiles().get(0).getFile()))
|
||||
.exceptionally(throwable -> {
|
||||
log.info("Failed to update message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId, throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> changeMeetupDescription(Meetup meetup, String newDescription) {
|
||||
meetup.setDescription(newDescription);
|
||||
return updateMeetupMessage(meetup);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> changeMeetupLocation(Meetup meetup, String newLocation) {
|
||||
try {
|
||||
meetup.setLocation(URLEncoder.encode(newLocation, StandardCharsets.UTF_8.toString()));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AbstractoRunTimeException(e);
|
||||
}
|
||||
return updateMeetupMessage(meetup);
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> changeMeetupTopic(Meetup meetup, String newTopic) {
|
||||
meetup.setTopic(newTopic);
|
||||
return updateMeetupMessage(meetup);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> updateMeetupMessage(Meetup meetup) {
|
||||
Long meetupId = meetup.getId().getId();
|
||||
Long serverId = meetup.getId().getServerId();
|
||||
MeetupMessageModel meetupMessageModel = getMeetupMessageModel(meetup);
|
||||
MessageToSend updatedMeetupMessage = getMeetupMessage(meetupMessageModel);
|
||||
GuildMessageChannel meetupChannel = channelService.getMessageChannelFromServer(serverId, meetup.getMeetupChannel().getId());
|
||||
return channelService.editMessageInAChannelFuture(updatedMeetupMessage, meetupChannel, meetup.getMessageId())
|
||||
.thenAccept(message -> log.info("Updated message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId))
|
||||
.thenAccept(unused -> fileService.safeDeleteIgnoreException(updatedMeetupMessage.getAttachedFiles().get(0).getFile()))
|
||||
.exceptionally(throwable -> {
|
||||
log.info("Failed to update message of meetup {} in channel {} in server {}.", meetupId, meetup.getMeetupChannel().getId(), serverId, throwable);
|
||||
return null;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package dev.sheldan.sissi.module.meetup.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.ServerSpecificId;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
@@ -12,6 +13,9 @@ import dev.sheldan.sissi.module.meetup.repository.MeetupRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@@ -26,22 +30,28 @@ public class MeetupManagementServiceBean {
|
||||
|
||||
public static final String MEETUP_COUNTER_KEY = "meetup";
|
||||
|
||||
public Meetup createMeetup(Instant timeStamp, String topic, String description, AUserInAServer organizer, AChannel meetupChannel) {
|
||||
public Meetup createMeetup(Instant timeStamp, String topic, String description, AUserInAServer organizer, AChannel meetupChannel, String location) {
|
||||
if(timeStamp.isBefore(Instant.now())) {
|
||||
throw new MeetupPastTimeException();
|
||||
}
|
||||
Long meetupId = counterService.getNextCounterValue(organizer.getServerReference(), MEETUP_COUNTER_KEY);
|
||||
Meetup meetup = Meetup
|
||||
.builder()
|
||||
.meetupTime(timeStamp)
|
||||
.description(description)
|
||||
.topic(topic)
|
||||
.organizer(organizer)
|
||||
.server(organizer.getServerReference())
|
||||
.meetupChannel(meetupChannel)
|
||||
.state(MeetupState.NEW)
|
||||
.id(new ServerSpecificId(organizer.getServerReference().getId(), meetupId))
|
||||
.build();
|
||||
Meetup meetup = null;
|
||||
try {
|
||||
meetup = Meetup
|
||||
.builder()
|
||||
.meetupTime(timeStamp)
|
||||
.description(description)
|
||||
.topic(topic)
|
||||
.location(URLEncoder.encode(location, StandardCharsets.UTF_8.toString()))
|
||||
.organizer(organizer)
|
||||
.server(organizer.getServerReference())
|
||||
.meetupChannel(meetupChannel)
|
||||
.state(MeetupState.NEW)
|
||||
.id(new ServerSpecificId(organizer.getServerReference().getId(), meetupId))
|
||||
.build();
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AbstractoRunTimeException(e);
|
||||
}
|
||||
return meetupRepository.save(meetup);
|
||||
}
|
||||
|
||||
@@ -62,12 +72,8 @@ public class MeetupManagementServiceBean {
|
||||
return meetupRepository.findByState(MeetupState.CANCELLED);
|
||||
}
|
||||
|
||||
public List<Meetup> getFutureMeetups() {
|
||||
return meetupRepository.findByMeetupTimeGreaterThan(Instant.now());
|
||||
}
|
||||
|
||||
public List<Meetup> getIncomingMeetups() {
|
||||
return meetupRepository.findByMeetupTimeGreaterThanAndState(Instant.now(), MeetupState.CONFIRMED);
|
||||
public List<Meetup> getIncomingMeetups(Long serverId, Long channelId) {
|
||||
return meetupRepository.findByMeetupTimeGreaterThanAndStateAndServer_IdAndMeetupChannel_Id(Instant.now(), MeetupState.CONFIRMED, serverId, channelId);
|
||||
}
|
||||
|
||||
public void deleteMeetups(List<Meetup> meetups) {
|
||||
|
||||
@@ -5,4 +5,8 @@ abstracto.systemConfigs.meetupEarlyReminderSeconds.name=meetupEarlyReminderSecon
|
||||
abstracto.systemConfigs.meetupEarlyReminderSeconds.longValue=604800
|
||||
|
||||
abstracto.systemConfigs.meetupLateReminderSeconds.name=meetupLateReminderSeconds
|
||||
abstracto.systemConfigs.meetupLateReminderSeconds.longValue=86400
|
||||
abstracto.systemConfigs.meetupLateReminderSeconds.longValue=86400
|
||||
|
||||
abstracto.featureModes.attachIcsFile.featureName=meetup
|
||||
abstracto.featureModes.attachIcsFile.mode=attachIcsFile
|
||||
abstracto.featureModes.attachIcsFile.enabled=false
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<property name="utilityModule" value="(SELECT id FROM module WHERE name = 'utility')"/>
|
||||
<property name="meetupFeature" value="(SELECT id FROM feature WHERE key = 'meetup')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="meetup-change_command">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="changeMeetup"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${meetupFeature}"/>
|
||||
</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:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="command.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:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<changeSet author="Sheldan" id="meetup-add_info_columns">
|
||||
<addColumn tableName="meetup">
|
||||
<column name="location" type="VARCHAR(100)" />
|
||||
</addColumn>
|
||||
<addColumn tableName="meetup">
|
||||
<column name="yes_button_id" type="VARCHAR(100)" />
|
||||
</addColumn>
|
||||
<addColumn tableName="meetup">
|
||||
<column name="maybe_button_id" type="VARCHAR(100)" />
|
||||
</addColumn>
|
||||
<addColumn tableName="meetup">
|
||||
<column name="no_time_button_id" type="VARCHAR(100)" />
|
||||
</addColumn>
|
||||
<addColumn tableName="meetup">
|
||||
<column name="not_interested_button_id" type="VARCHAR(100)" />
|
||||
</addColumn>
|
||||
</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:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
|
||||
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/dbchangelog-ext dbchangelog.xsd
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="meetup.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -8,4 +8,5 @@
|
||||
http://www.liquibase.org/xml/ns/pro dbchangelog.xsd" >
|
||||
<include file="1.1.0/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.2.0/collection.xml" relativeToChangelogFile="true"/>
|
||||
<include file="1.3.18/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>application</artifactId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<module>quotes</module>
|
||||
<module>meetup</module>
|
||||
<module>debra</module>
|
||||
<module>rss-news</module>
|
||||
</modules>
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<artifactId>sissi-modules</artifactId>
|
||||
<version>1.3.17</version>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import dev.sheldan.sissi.module.quotes.config.QuotesModuleDefinition;
|
||||
import dev.sheldan.sissi.module.quotes.exception.QuoteNotFoundException;
|
||||
import dev.sheldan.sissi.module.quotes.model.database.Quote;
|
||||
import dev.sheldan.sissi.module.quotes.service.QuoteServiceBean;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.MessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
@@ -28,7 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -38,6 +39,7 @@ public class QuoteSearch extends AbstractConditionableCommand {
|
||||
|
||||
private static final String QUOTE_SEARCH_COMMAND = "quoteSearch";
|
||||
private static final String QUERY_PARAMETER = "query";
|
||||
private static final String MEMBER_PARAMETER = "member";
|
||||
|
||||
@Autowired
|
||||
private QuoteServiceBean quoteServiceBean;
|
||||
@@ -80,7 +82,14 @@ public class QuoteSearch extends AbstractConditionableCommand {
|
||||
String query = slashCommandParameterService.getCommandOption(QUERY_PARAMETER, event, String.class);
|
||||
AServer server = serverManagementService.loadServer(event.getGuild().getIdLong());
|
||||
|
||||
Optional<Quote> possibleQuote = quoteServiceBean.searchQuote(query, server);
|
||||
Optional<Quote> possibleQuote;
|
||||
if(slashCommandParameterService.hasCommandOption(MEMBER_PARAMETER, event)) {
|
||||
Member targetMember = slashCommandParameterService.getCommandOption(MEMBER_PARAMETER, event, Member.class);
|
||||
possibleQuote = quoteServiceBean.searchQuote(query, server, targetMember);
|
||||
} else {
|
||||
possibleQuote = quoteServiceBean.searchQuote(query, server);
|
||||
}
|
||||
|
||||
Quote quoteToDisplay = possibleQuote.orElseThrow(QuoteNotFoundException::new);
|
||||
return quoteServiceBean.renderQuoteToMessageToSend(quoteToDisplay)
|
||||
.thenCompose(messageToSend -> self.replyMessage(event, messageToSend))
|
||||
@@ -100,7 +109,17 @@ public class QuoteSearch extends AbstractConditionableCommand {
|
||||
.name(QUERY_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
List<Parameter> parameters = Collections.singletonList(searchParameter);
|
||||
|
||||
Parameter memberParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(MEMBER_PARAMETER)
|
||||
.slashCommandOnly(true)
|
||||
.optional(true)
|
||||
.type(Member.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(searchParameter, memberParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.sheldan.sissi.module.quotes.model.database;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.List;
|
||||
@Repository
|
||||
public interface QuoteRepository extends JpaRepository<Quote, ServerSpecificId> {
|
||||
List<Quote> findByTextContainingAndServer(String text, AServer server);
|
||||
List<Quote> findByTextContainingAndServerAndAuthor(String text, AServer server, AUserInAServer author);
|
||||
List<Quote> findByServer(AServer server);
|
||||
List<Quote> findByAuthor(AUserInAServer author);
|
||||
Long countByAuthor(AUserInAServer author);
|
||||
|
||||
@@ -214,9 +214,27 @@ public class QuoteServiceBean {
|
||||
return Optional.empty();
|
||||
}
|
||||
if(foundQuotes.size() > 1) {
|
||||
log.info("Found multiple quotes in server {}, returning first one.", server.getId());
|
||||
log.info("Found multiple quotes in server {}, returning random one.", server.getId());
|
||||
int randomIndex = secureRandom.nextInt(foundQuotes.size());
|
||||
return Optional.of(foundQuotes.get(randomIndex));
|
||||
} else {
|
||||
return Optional.of(foundQuotes.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Quote> searchQuote(String query, AServer server, Member targetMember) {
|
||||
AUserInAServer author = userInServerManagementService.loadOrCreateUser(targetMember);
|
||||
List<Quote> foundQuotes = quoteRepository.findByTextContainingAndServerAndAuthor(query, server, author);
|
||||
if(foundQuotes.isEmpty()) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if(foundQuotes.size() > 1) {
|
||||
log.info("Found multiple quotes in server {}, returning random one.", server.getId());
|
||||
int randomIndex = secureRandom.nextInt(foundQuotes.size());
|
||||
return Optional.of(foundQuotes.get(randomIndex));
|
||||
} else {
|
||||
return Optional.of(foundQuotes.get(0));
|
||||
}
|
||||
return Optional.of(foundQuotes.get(0));
|
||||
}
|
||||
|
||||
public QuoteStatsModel getQuoteStats(Member member) {
|
||||
|
||||
59
application/sissi-modules/rss-news/pom.xml
Normal file
59
application/sissi-modules/rss-news/pom.xml
Normal file
@@ -0,0 +1,59 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<artifactId>sissi-modules</artifactId>
|
||||
<groupId>dev.sheldan.sissi.application</groupId>
|
||||
<version>1.4.19</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>dev.sheldan.sissi.application.module</groupId>
|
||||
<artifactId>rss-news</artifactId>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/liquibase.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-int</artifactId>
|
||||
<version>${abstracto.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jena</groupId>
|
||||
<artifactId>jena-arq</artifactId>
|
||||
<version>${apache-jena.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.jena</groupId>
|
||||
<artifactId>jena-core</artifactId>
|
||||
<version>${apache-jena.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.apptasticsoftware</groupId>
|
||||
<artifactId>rssreader</artifactId>
|
||||
</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,95 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
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 CreateNewsCategory extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String CREATE_SERVER_NEWS_CATEGORY_RESPONSE_TEMPLATE_KEY = "createNewsCategory_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
|
||||
newsCategoryServiceBean.createCategory(categoryName, server);
|
||||
return interactionService.replyEmbed(CREATE_SERVER_NEWS_CATEGORY_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter nameParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(nameParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("category")
|
||||
.commandName("create")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("createNewsCategory")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryChannelMappingServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
@Component
|
||||
public class CreateNewsCategoryChannelMapping extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String CHANNEL_PARAMETER = "channel";
|
||||
private static final String CREATE_NEWS_CATEGORY_CHANNEL_MAPPING_RESPONSE_TEMPLATE_KEY = "createNewsCategoryChannelMapping_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingServiceBean newsCategoryMappingServiceBean;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
GuildChannel channel = slashCommandParameterService.getCommandOption(CHANNEL_PARAMETER, event, TextChannel.class, GuildChannel.class);
|
||||
newsCategoryMappingServiceBean.createNewsCategoryChannelMapping(categoryName, channel);
|
||||
return interactionService.replyEmbed(CREATE_NEWS_CATEGORY_CHANNEL_MAPPING_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
|
||||
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), CATEGORY_KEY_NAME_PARAMETER)) {
|
||||
return newsCategoryServiceBean.getNamesOfNewsCategoriesStartingWith(event.getFocusedOption().getValue(), event.getGuild());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter categoryParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.supportsAutoComplete(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter channelParameter = Parameter
|
||||
.builder()
|
||||
.name(CHANNEL_PARAMETER)
|
||||
.type(TextChannel.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(categoryParameter, channelParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("categorychannelmapping")
|
||||
.commandName("create")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("createNewsCategoryChannelMapping")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsFeedSourceCategoryServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsFeedSourceCategorySubscriptionServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceManagementServiceBean;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
@Component
|
||||
public class CreateNewsCategorySubscription extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String SOURCE_CATEGORY_PARAMETER = "sourceCategory";
|
||||
private static final String NEWS_FEED_SOURCE_KEY_PARAMETER = "newsFeed";
|
||||
private static final String CREATE_NEWS_CATEGORY_SUBSCRIPTION_RESPONSE_TEMPLATE_KEY = "createNewsCategorySubscription_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategorySubscriptionServiceBean newsFeedSourceCategorySubscriptionServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategoryServiceBean newsFeedSourceCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceManagementServiceBean newsFeedSourceManagementServiceBean;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
String sourceCategoryName = slashCommandParameterService.getCommandOption(SOURCE_CATEGORY_PARAMETER, event, String.class);
|
||||
String newsFeedSourceName = slashCommandParameterService.getCommandOption(NEWS_FEED_SOURCE_KEY_PARAMETER, event, String.class);
|
||||
Guild guild = event.getGuild();
|
||||
newsFeedSourceCategorySubscriptionServiceBean.createNewsFeedSourceCategorySubscription(categoryName, sourceCategoryName, newsFeedSourceName, guild);
|
||||
return interactionService.replyEmbed(CREATE_NEWS_CATEGORY_SUBSCRIPTION_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
|
||||
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), CATEGORY_KEY_NAME_PARAMETER)) {
|
||||
return newsCategoryServiceBean.getNamesOfNewsCategoriesStartingWith(event.getFocusedOption().getValue(), event.getGuild());
|
||||
} if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), SOURCE_CATEGORY_PARAMETER)) {
|
||||
String newsFeedSourceName = slashCommandParameterService.getCommandOption(NEWS_FEED_SOURCE_KEY_PARAMETER, event, String.class);
|
||||
Optional<NewsFeedSource> newsFeedSourceOptional = newsFeedSourceManagementServiceBean.getNewsFeedSourceWithNameOptional(newsFeedSourceName);
|
||||
if(newsFeedSourceOptional.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return newsFeedSourceCategoryServiceBean.getNamesOfNewsSourceCategoriesInNewsFeedStartingWith(event.getFocusedOption().getValue(), newsFeedSourceOptional.get());
|
||||
} if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), NEWS_FEED_SOURCE_KEY_PARAMETER)) {
|
||||
return newsFeedSourceManagementServiceBean.getNewsFeedSourceNamesStartingWithName(event.getFocusedOption().getValue());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter categoryParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.supportsAutoComplete(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter sourceCategoryParameter = Parameter
|
||||
.builder()
|
||||
.name(SOURCE_CATEGORY_PARAMETER)
|
||||
.type(String.class)
|
||||
.supportsAutoComplete(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter newsFeedKeyParameter = Parameter
|
||||
.builder()
|
||||
.name(NEWS_FEED_SOURCE_KEY_PARAMETER)
|
||||
.type(String.class)
|
||||
.supportsAutoComplete(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(categoryParameter, newsFeedKeyParameter, sourceCategoryParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("categorysubscription")
|
||||
.commandName("create")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("createNewsCategorySubscription")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
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 DeleteNewsCategory extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String DELETE_NEWS_CATEGORY_RESPONSE_TEMPLATE_KEY = "deleteNewsCategory_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
AServer server = serverManagementService.loadOrCreate(event.getGuild().getIdLong());
|
||||
newsCategoryServiceBean.deleteNewsCategoryByName(categoryName, server);
|
||||
return interactionService.replyEmbed(DELETE_NEWS_CATEGORY_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter nameParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(nameParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("category")
|
||||
.commandName("delete")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("deleteNewsCategory")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryChannelMappingServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class DeleteNewsCategoryChannelMapping extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String CHANNEL_PARAMETER = "channel";
|
||||
private static final String DELETE_NEWS_CATEGORY_CHANNEL_MAPPING_RESPONSE_TEMPLATE_KEY = "deleteNewsCategoryChannelMapping_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingServiceBean newsCategoryMappingServiceBean;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
GuildChannel channel = slashCommandParameterService.getCommandOption(CHANNEL_PARAMETER, event, TextChannel.class, GuildChannel.class);
|
||||
newsCategoryMappingServiceBean.deleteNewsCategoryChannelMapping(categoryName, channel);
|
||||
return interactionService.replyEmbed(DELETE_NEWS_CATEGORY_CHANNEL_MAPPING_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
|
||||
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), CATEGORY_KEY_NAME_PARAMETER)) {
|
||||
return newsCategoryServiceBean.getNamesOfNewsCategoriesStartingWith(event.getFocusedOption().getValue(), event.getGuild());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter categoryParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.supportsAutoComplete(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter channelParameter = Parameter
|
||||
.builder()
|
||||
.name(CHANNEL_PARAMETER)
|
||||
.type(TextChannel.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(categoryParameter, channelParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("categorychannelmapping")
|
||||
.commandName("delete")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("deleteNewsCategoryChannelMapping")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.parameters(parameters)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
package dev.sheldan.sissi.module.rssnews.commands;
|
||||
|
||||
import dev.sheldan.abstracto.core.command.UtilityModuleDefinition;
|
||||
import dev.sheldan.abstracto.core.command.condition.AbstractConditionableCommand;
|
||||
import dev.sheldan.abstracto.core.command.config.CommandConfiguration;
|
||||
import dev.sheldan.abstracto.core.command.config.HelpInfo;
|
||||
import dev.sheldan.abstracto.core.command.config.Parameter;
|
||||
import dev.sheldan.abstracto.core.command.execution.CommandResult;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.interaction.InteractionService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.SlashCommandConfig;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandAutoCompleteService;
|
||||
import dev.sheldan.abstracto.core.interaction.slash.parameter.SlashCommandParameterService;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsFeedSourceCategoryServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsFeedSourceCategorySubscriptionServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceManagementServiceBean;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.events.interaction.command.CommandAutoCompleteInteractionEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
|
||||
@Component
|
||||
public class DeleteNewsCategorySubscription extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CATEGORY_KEY_NAME_PARAMETER = "categoryName";
|
||||
private static final String SOURCE_CATEGORY_PARAMETER = "sourceCategory";
|
||||
private static final String NEWS_FEED_SOURCE_KEY_PARAMETER = "newsFeed";
|
||||
private static final String CREATE_NEWS_CATEGORY_SUBSCRIPTION_RESPONSE_TEMPLATE_KEY = "deleteNewsCategorySubscription_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private SlashCommandAutoCompleteService slashCommandAutoCompleteService;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategorySubscriptionServiceBean newsFeedSourceCategorySubscriptionServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategoryServiceBean newsFeedSourceCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceManagementServiceBean newsFeedSourceManagementServiceBean;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String categoryName = slashCommandParameterService.getCommandOption(CATEGORY_KEY_NAME_PARAMETER, event, String.class);
|
||||
String sourceCategoryName = slashCommandParameterService.getCommandOption(SOURCE_CATEGORY_PARAMETER, event, String.class);
|
||||
String newsFeedSourceName = slashCommandParameterService.getCommandOption(NEWS_FEED_SOURCE_KEY_PARAMETER, event, String.class);
|
||||
Guild guild = event.getGuild();
|
||||
newsFeedSourceCategorySubscriptionServiceBean.deleteNewsFeedSourceCategorySubscription(categoryName, sourceCategoryName, newsFeedSourceName, guild);
|
||||
return interactionService.replyEmbed(CREATE_NEWS_CATEGORY_SUBSCRIPTION_RESPONSE_TEMPLATE_KEY, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> performAutoComplete(CommandAutoCompleteInteractionEvent event) {
|
||||
if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), CATEGORY_KEY_NAME_PARAMETER)) {
|
||||
return newsCategoryServiceBean.getNamesOfNewsCategoriesStartingWith(event.getFocusedOption().getValue(), event.getGuild());
|
||||
} if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), SOURCE_CATEGORY_PARAMETER)) {
|
||||
String newsFeedSourceName = slashCommandParameterService.getCommandOption(NEWS_FEED_SOURCE_KEY_PARAMETER, event, String.class);
|
||||
Optional<NewsFeedSource> newsFeedSourceOptional = newsFeedSourceManagementServiceBean.getNewsFeedSourceWithNameOptional(newsFeedSourceName);
|
||||
if(newsFeedSourceOptional.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return newsFeedSourceCategoryServiceBean.getNamesOfNewsSourceCategoriesInNewsFeedStartingWith(event.getFocusedOption().getValue(), newsFeedSourceOptional.get());
|
||||
} if(slashCommandAutoCompleteService.matchesParameter(event.getFocusedOption(), NEWS_FEED_SOURCE_KEY_PARAMETER)) {
|
||||
return newsFeedSourceManagementServiceBean.getNewsFeedSourceNamesStartingWithName(event.getFocusedOption().getValue());
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
Parameter categoryParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(CATEGORY_KEY_NAME_PARAMETER)
|
||||
.supportsAutoComplete(true)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
Parameter sourceCategoryParameter = Parameter
|
||||
.builder()
|
||||
.name(SOURCE_CATEGORY_PARAMETER)
|
||||
.type(String.class)
|
||||
.supportsAutoComplete(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter newsFeedKeyParameter = Parameter
|
||||
.builder()
|
||||
.name(NEWS_FEED_SOURCE_KEY_PARAMETER)
|
||||
.type(String.class)
|
||||
.supportsAutoComplete(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(categoryParameter, newsFeedKeyParameter, sourceCategoryParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("categorysubscription")
|
||||
.commandName("delete")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("deleteNewsCategorySubscription")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.parameters(parameters)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
package dev.sheldan.sissi.module.rssnews.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.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.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsSlashCommandNames;
|
||||
import dev.sheldan.sissi.module.rssnews.model.template.NewsCategoryInfo;
|
||||
import dev.sheldan.sissi.module.rssnews.model.template.ShowNewsCategoriesResponse;
|
||||
import dev.sheldan.sissi.module.rssnews.service.NewsCategoryServiceBean;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ShowNewsCategories extends AbstractConditionableCommand {
|
||||
|
||||
private static final String SHOW_NEWS_CATEGORIES_TEMPLATE_KEY = "showNewsCategories_response";
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryServiceBean newsCategoryServiceBean;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
List<NewsCategoryInfo> categoryInfos = newsCategoryServiceBean.getCategoryInfos(event.getGuild());
|
||||
ShowNewsCategoriesResponse responseModel = ShowNewsCategoriesResponse
|
||||
.builder()
|
||||
.newsCategories(categoryInfos)
|
||||
.build();
|
||||
return interactionService.replyEmbed(SHOW_NEWS_CATEGORIES_TEMPLATE_KEY, responseModel, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(RssNewsSlashCommandNames.RSS_NEWS)
|
||||
.groupName("category")
|
||||
.commandName("show")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name("showNewsCategories")
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.async(true)
|
||||
.slashCommandOnly(true)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(false)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.sissi.module.rssnews.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.orf.config.OrfNewsFeatureConfig;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@Component
|
||||
public class RSSNewsFeatureConfig implements FeatureConfig {
|
||||
|
||||
@Autowired
|
||||
private OrfNewsFeatureConfig orfNewsFeatureConfig;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.RSS_NEWS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureConfig> getDependantFeatures() {
|
||||
return Arrays.asList(orfNewsFeatureConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.sissi.module.rssnews.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum RssNewsFeatureDefinition implements FeatureDefinition {
|
||||
RSS_NEWS("rssNews"), ORF_NEWS("orfNews");
|
||||
|
||||
private String key;
|
||||
|
||||
RssNewsFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.sissi.module.rssnews.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:rss-news.properties")
|
||||
public class RssNewsProperties {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.sissi.module.rssnews.config;
|
||||
|
||||
public class RssNewsSlashCommandNames {
|
||||
public static final String RSS_NEWS = "rssnews";
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsCategoryAlreadyExistsException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsCategoryAlreadyExistsException() {
|
||||
super("News Category already exists.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_category_already_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsCategoryChannelMappingAlreadyExistsException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsCategoryChannelMappingAlreadyExistsException() {
|
||||
super("News Category channel mapping already exists.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_category_channel_mapping_already_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class NewsCategoryChannelMappingNotFoundException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsCategoryChannelMappingNotFoundException() {
|
||||
super("News Category channel mapping not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_category_channel_mapping_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
public class NewsCategoryNotFoundException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsCategoryNotFoundException() {
|
||||
super("News Category not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_category_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsFeedSourceCategoryNotFoundException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsFeedSourceCategoryNotFoundException() {
|
||||
super("News feed source category not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_feed_source_category_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsFeedSourceCategorySubscriptionAlreadyExistsException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsFeedSourceCategorySubscriptionAlreadyExistsException() {
|
||||
super("News feed source category subscription already exists.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_feed_source_category_subscription_already_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsFeedSourceCategorySubscriptionNotFoundException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsFeedSourceCategorySubscriptionNotFoundException() {
|
||||
super("News feed source category subscription not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_feed_source_category_subscription_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.sissi.module.rssnews.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoTemplatableException;
|
||||
|
||||
|
||||
public class NewsFeedSourceNotFoundException extends AbstractoTemplatableException {
|
||||
|
||||
public NewsFeedSourceNotFoundException() {
|
||||
super("News feed source not found.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "news_feed_source_not_found_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_category")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsCategory {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "news_category_in_news_feed_source_category",
|
||||
joinColumns = @JoinColumn(name = "server_category_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "source_category_id"))
|
||||
private List<NewsFeedSourceCategory> sourceCategories;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "newsCategory")
|
||||
@Builder.Default
|
||||
private List<NewsCategoryChannelMapping> mappings = new ArrayList<>();
|
||||
|
||||
@Column(name = "key", nullable = false)
|
||||
private String key;
|
||||
|
||||
@Column(name = "enabled", nullable = false)
|
||||
private Boolean enabled;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_category_channel_mapping")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsCategoryChannelMapping {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id", referencedColumnName = "id", nullable = false)
|
||||
private AChannel channel;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "category_id", referencedColumnName = "id", nullable = false)
|
||||
private NewsCategory newsCategory;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "mapping")
|
||||
@Builder.Default
|
||||
private List<NewsPost> posts = new ArrayList<>();
|
||||
|
||||
@Column(name = "enabled", nullable = false)
|
||||
private Boolean enabled;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_feed_record")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsFeedRecord {
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "source_id", referencedColumnName = "id")
|
||||
private NewsFeedSource source;
|
||||
|
||||
@Column(name = "url")
|
||||
private String url;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_feed_source")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsFeedSource {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "url", nullable = false)
|
||||
private String url;
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "feed_type", nullable = false)
|
||||
private NewsFeedSourceCategoryType type;
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "source")
|
||||
@Builder.Default
|
||||
private List<NewsFeedSourceCategory> categories = new ArrayList<>();
|
||||
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "source")
|
||||
@Builder.Default
|
||||
private List<NewsFeedRecord> records = new ArrayList<>();
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_feed_source_category")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsFeedSourceCategory {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "source_id", referencedColumnName = "id")
|
||||
private NewsFeedSource source;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
|
||||
@Getter
|
||||
@ManyToMany(mappedBy = "sourceCategories")
|
||||
private List<NewsCategory> categories;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
public enum NewsFeedSourceCategoryType {
|
||||
RFD, RSS
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "news_post")
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class NewsPost {
|
||||
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "url")
|
||||
private String url;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id", referencedColumnName = "id", nullable = false)
|
||||
private AChannel postChannel;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", referencedColumnName = "id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "news_category_channel_mapping_id", referencedColumnName = "id", nullable = false)
|
||||
private NewsCategoryChannelMapping mapping;
|
||||
|
||||
@Column(name = "created")
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated")
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.feed;
|
||||
|
||||
import com.apptasticsoftware.rssreader.Item;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSourceCategoryType;
|
||||
import dev.sheldan.sissi.module.rssnews.model.feed.rfd.RFDItem;
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class NewsResponseItem {
|
||||
private String title;
|
||||
private String link;
|
||||
private String mainCategory;
|
||||
private String date;
|
||||
private String secondCategory;
|
||||
private String description;
|
||||
private String imageURL;
|
||||
private NewsFeedSourceCategoryType type;
|
||||
private NewsFeedSource newsFeedSource;
|
||||
|
||||
public static NewsResponseItem fromRFDItem(RFDItem item) {
|
||||
return NewsResponseItem
|
||||
.builder()
|
||||
.title(item.getTitle())
|
||||
.date(item.getDate())
|
||||
.description(item.getDescription())
|
||||
.mainCategory(item.getSubject())
|
||||
.secondCategory(item.getOewaCategory())
|
||||
.type(NewsFeedSourceCategoryType.RFD)
|
||||
.link(item.getLink())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static NewsResponseItem fromRSSItem(Item item) {
|
||||
String imageUrl = null;
|
||||
if(item.getEnclosure().isPresent()) {
|
||||
imageUrl = item.getEnclosure().get().getUrl();
|
||||
}
|
||||
return NewsResponseItem
|
||||
.builder()
|
||||
.title(item.getTitle().orElse(null))
|
||||
.date(item.getPubDate().orElse(null))
|
||||
.description(item.getDescription().orElse(null))
|
||||
.mainCategory(item.getCategory().orElse(null))
|
||||
.type(NewsFeedSourceCategoryType.RSS)
|
||||
.link(item.getLink().orElse(null))
|
||||
.imageURL(imageUrl)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.feed.rfd;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class RFDItem {
|
||||
private String title;
|
||||
private String link;
|
||||
private String subject;
|
||||
private String date;
|
||||
private String oewaCategory;
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.template;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.template.display.ChannelDisplay;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class NewsCategoryChannelMappingInfo {
|
||||
private ChannelDisplay channel;
|
||||
private Boolean enabled;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class NewsCategoryInfo {
|
||||
private String name;
|
||||
private List<NewsCategorySubscriptionInfo> subscriptions;
|
||||
private List<NewsCategoryChannelMappingInfo> mappings;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class NewsCategorySubscriptionInfo {
|
||||
private String newsFeedName;
|
||||
private List<String> newsFeedCategories;
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package dev.sheldan.sissi.module.rssnews.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class ShowNewsCategoriesResponse {
|
||||
private List<NewsCategoryInfo> newsCategories;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.sissi.module.rssnews.orf.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RSSNewsFeatureConfig;
|
||||
import dev.sheldan.sissi.module.rssnews.config.RssNewsFeatureDefinition;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class OrfNewsFeatureConfig implements FeatureConfig {
|
||||
|
||||
@Autowired
|
||||
private RSSNewsFeatureConfig rssNewsFeatureConfig;
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return RssNewsFeatureDefinition.ORF_NEWS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureConfig> getRequiredFeatures() {
|
||||
return Arrays.asList(rssNewsFeatureConfig);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.sissi.module.rssnews.orf.job;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.orf.service.OrfNewsService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.quartz.DisallowConcurrentExecution;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.quartz.PersistJobDataAfterExecution;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.quartz.QuartzJobBean;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@DisallowConcurrentExecution
|
||||
@Component
|
||||
@PersistJobDataAfterExecution
|
||||
public class NewsPostGatherJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private OrfNewsService orfNewsRFDService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
|
||||
try {
|
||||
log.info("Executing news retrieval job.");
|
||||
orfNewsRFDService.checkNewsPosts();
|
||||
} catch (Exception e) {
|
||||
log.error("News retrieval job failed.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package dev.sheldan.sissi.module.rssnews.orf.model;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.feed.NewsResponseItem;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@Builder
|
||||
public class OrfNewsMessagePost {
|
||||
private String title;
|
||||
private String url;
|
||||
private String category;
|
||||
private String description;
|
||||
private String imageURL;
|
||||
|
||||
public static OrfNewsMessagePost fromNewsResponseItem(NewsResponseItem newsResponseItem) {
|
||||
return OrfNewsMessagePost
|
||||
.builder()
|
||||
.category(newsResponseItem.getMainCategory())
|
||||
.description(newsResponseItem.getDescription())
|
||||
.imageURL(newsResponseItem.getImageURL())
|
||||
.title(newsResponseItem.getTitle())
|
||||
.url(newsResponseItem.getLink())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
package dev.sheldan.sissi.module.rssnews.orf.service;
|
||||
|
||||
import com.apptasticsoftware.rssreader.Item;
|
||||
import com.apptasticsoftware.rssreader.RssReader;
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.ChannelService;
|
||||
import dev.sheldan.abstracto.core.service.FeatureFlagService;
|
||||
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.CompletableFutureList;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.*;
|
||||
import dev.sheldan.sissi.module.rssnews.orf.config.OrfNewsFeatureConfig;
|
||||
import dev.sheldan.sissi.module.rssnews.model.feed.NewsResponseItem;
|
||||
import dev.sheldan.sissi.module.rssnews.model.feed.rfd.RFDItem;
|
||||
import dev.sheldan.sissi.module.rssnews.orf.model.OrfNewsMessagePost;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.*;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import org.apache.jena.rdf.model.*;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class OrfNewsService {
|
||||
|
||||
@Autowired
|
||||
private OkHttpClient okHttpClient;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceManagementServiceBean newsFeedSourceManagementBean;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private OrfNewsFeatureConfig orfNewsFeatureConfig;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedRecordManagementServiceBean newsFeedRecordManagementBean;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryManagementServiceBean newsCategoryManagementBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategoryManagementServiceBean newsFeedSourceCategoryManagementBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedRecordManagementServiceBean newsFeedRecordManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingManagementServiceBean newsCategoryChannelMappingManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsPostManagementServiceBean newsPostManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private OrfNewsService self;
|
||||
|
||||
private static final String ORF_NEWS_POST_TEMPLATE_KEY = "orf_news_post";
|
||||
|
||||
@Transactional
|
||||
public void checkNewsPosts() {
|
||||
List<AServer> servers = serverManagementService.getAllServers();
|
||||
List<AServer> serversWithEnabledFeature = servers
|
||||
.stream()
|
||||
.filter(server -> featureFlagService.isFeatureEnabled(orfNewsFeatureConfig, server))
|
||||
.toList();
|
||||
if(serversWithEnabledFeature.isEmpty()) {
|
||||
log.info("No servers have orf news enabled - skipping execution.");
|
||||
return;
|
||||
}
|
||||
List<NewsFeedSource> sources = newsFeedSourceManagementBean.getAllSources();
|
||||
List<NewsResponseItem> newsItems = new ArrayList<>();
|
||||
sources.forEach(source -> newsItems.addAll(loadItemsFromNewsSource(source)));
|
||||
Set<String> existingRecordUrls = newsFeedRecordManagementBean.getAllRecords()
|
||||
.stream()
|
||||
.map(NewsFeedRecord::getUrl)
|
||||
.collect(Collectors.toSet());
|
||||
List<NewsResponseItem> newItems = newsItems
|
||||
.stream()
|
||||
.filter(newsResponseItem -> !existingRecordUrls.contains(newsResponseItem.getLink()))
|
||||
.toList();
|
||||
|
||||
List<NewsCategory> categoriesToCover = newsCategoryManagementBean.getNewsCategoriesOfServers(serversWithEnabledFeature);
|
||||
categoriesToCover.forEach(category -> sendNewsItemsToNewsCategory(newItems, category));
|
||||
createNewCategories(newsItems);
|
||||
saveNewsRecords(newItems);
|
||||
}
|
||||
|
||||
private void saveNewsRecords(List<NewsResponseItem> newItems) {
|
||||
newItems.forEach(newsResponseItem -> newsFeedRecordManagementServiceBean.createRecord(newsResponseItem));
|
||||
}
|
||||
|
||||
private void createNewCategories(List<NewsResponseItem> newsItems) {
|
||||
Set<String> allExistingCategories = newsFeedSourceCategoryManagementBean.getAllCategories()
|
||||
.stream()
|
||||
.map(NewsFeedSourceCategory::getName)
|
||||
.collect(Collectors.toSet());
|
||||
Set<String> incomingCategories = newsItems
|
||||
.stream()
|
||||
.map(NewsResponseItem::getMainCategory)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
HashSet<Object> seenCategories = new HashSet<>();
|
||||
newsItems.removeIf(e -> !seenCategories.add(e.getMainCategory()));
|
||||
|
||||
Map<String, NewsResponseItem> categoryToNewsItem = newsItems
|
||||
.stream()
|
||||
.collect(Collectors.toMap(NewsResponseItem::getMainCategory, Function.identity()));
|
||||
incomingCategories.removeAll(allExistingCategories);
|
||||
incomingCategories.removeIf(Objects::isNull);
|
||||
if(!incomingCategories.isEmpty()) {
|
||||
incomingCategories.forEach(categoryName ->
|
||||
newsFeedSourceCategoryManagementBean.createCategory(categoryName, categoryToNewsItem.get(categoryName).getNewsFeedSource()));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNewsItemsToNewsCategory(List<NewsResponseItem> newsItems, NewsCategory category) {
|
||||
if(!category.getEnabled()) {
|
||||
return;
|
||||
}
|
||||
Set<String> categoriesToSend = category
|
||||
.getSourceCategories()
|
||||
.stream()
|
||||
.map(NewsFeedSourceCategory::getName)
|
||||
.collect(Collectors.toSet());
|
||||
List<NewsResponseItem> itemsToSend = newsItems
|
||||
.stream()
|
||||
.filter(newsResponseItem -> categoriesToSend.contains(newsResponseItem.getMainCategory()))
|
||||
.toList();
|
||||
category.getMappings().forEach(newsCategoryChannelMapping -> sendNewsItemToChannel(itemsToSend, newsCategoryChannelMapping));
|
||||
}
|
||||
|
||||
private void sendNewsItemToChannel(List<NewsResponseItem> items, NewsCategoryChannelMapping mapping) {
|
||||
items.forEach(item -> {
|
||||
Long channelId = mapping.getChannel().getId();
|
||||
Long serverId = mapping.getServer().getId();
|
||||
Long mappingId = mapping.getId();
|
||||
OrfNewsMessagePost orfNewsMessagePostModel = OrfNewsMessagePost.fromNewsResponseItem(item);
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(ORF_NEWS_POST_TEMPLATE_KEY, orfNewsMessagePostModel, serverId);
|
||||
CompletableFutureList<Message> futureList = new CompletableFutureList<>(channelService.sendMessageEmbedToSendToAChannel(messageToSend, mapping.getChannel()));
|
||||
futureList.getMainFuture().thenAccept(unused -> {
|
||||
log.info("Sent news post {} to channel {}.", item.getTitle(), channelId);
|
||||
Long messageId = futureList.getObjects().get(0).getIdLong();
|
||||
self.persistNewsPost(messageId, mappingId, item);
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to send news post {} to channel {}.", item.getTitle(), channelId);
|
||||
return null;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void persistNewsPost(Long messageId, Long mappingId, NewsResponseItem item) {
|
||||
NewsCategoryChannelMapping channelMapping = newsCategoryChannelMappingManagementServiceBean.getChannelMappingById(mappingId);
|
||||
newsPostManagementServiceBean.createNewsPost(messageId, item, channelMapping);
|
||||
}
|
||||
|
||||
public List<NewsResponseItem> loadItemsFromNewsSource(NewsFeedSource source) {
|
||||
Request request = new Request.Builder()
|
||||
.url(source.getUrl())
|
||||
.get()
|
||||
.build();
|
||||
try {
|
||||
Response response = okHttpClient.newCall(request).execute();
|
||||
return switch (source.getType()) {
|
||||
case RFD -> loadNewsSourceRFD(response, source);
|
||||
case RSS -> loadNewsSourceRSS(response, source);
|
||||
};
|
||||
} catch (IOException ex) {
|
||||
throw new AbstractoRunTimeException(String.format("Failed to gather news from %s", source.getName()), ex);
|
||||
}
|
||||
}
|
||||
|
||||
private List<NewsResponseItem> loadNewsSourceRSS(Response response, NewsFeedSource source) {
|
||||
RssReader reader = new RssReader();
|
||||
try (response) {
|
||||
InputStream is = response.body().byteStream();
|
||||
Stream<Item> rssFeed = reader.read(is);
|
||||
return rssFeed.map(NewsResponseItem::fromRSSItem)
|
||||
.peek(newsResponseItem -> newsResponseItem.setNewsFeedSource(source))
|
||||
.toList();
|
||||
}
|
||||
}
|
||||
|
||||
private List<NewsResponseItem> loadNewsSourceRFD(Response response, NewsFeedSource source) throws IOException {
|
||||
Map<String, RFDItem> items = new HashMap<>();
|
||||
final Model model = ModelFactory.createDefaultModel();
|
||||
model.read(new ByteArrayInputStream(response.body().bytes()), null);
|
||||
StmtIterator statements = model.listStatements();
|
||||
while(statements.hasNext()) {
|
||||
Statement x = statements.nextStatement();
|
||||
String article = x.getSubject().toString();
|
||||
RFDItem item;
|
||||
if(!items.containsKey(article)) {
|
||||
item = new RFDItem();
|
||||
} else {
|
||||
item = items.get(article);
|
||||
}
|
||||
String predicate = x.getPredicate().toString();
|
||||
String objectValue = x.getObject().toString();
|
||||
switch (predicate) {
|
||||
case "http://rss.orf.at/1.0/oewaCategory":
|
||||
item.setOewaCategory(objectValue);
|
||||
break;
|
||||
case "http://purl.org/rss/1.0/link":
|
||||
item.setLink(objectValue);
|
||||
break;
|
||||
case "http://purl.org/dc/elements/1.1/subject":
|
||||
item.setSubject(objectValue);
|
||||
break;
|
||||
case "http://purl.org/dc/elements/1.1/date":
|
||||
item.setDate(objectValue);
|
||||
break;
|
||||
case "http://purl.org/rss/1.0/description":
|
||||
item.setDescription(objectValue);
|
||||
break;
|
||||
case "http://purl.org/rss/1.0/title":
|
||||
item.setTitle(objectValue);
|
||||
break;
|
||||
}
|
||||
items.putIfAbsent(article, item);
|
||||
}
|
||||
Set<String> uselessEntries = new HashSet<>();
|
||||
items.forEach((s, rfdItem) -> {
|
||||
if(rfdItem.getLink() == null) {
|
||||
uselessEntries.add(s);
|
||||
}
|
||||
});
|
||||
uselessEntries.forEach(items::remove);
|
||||
return items
|
||||
.values()
|
||||
.stream()
|
||||
.map(NewsResponseItem::fromRFDItem)
|
||||
.peek(newsResponseItem -> newsResponseItem.setNewsFeedSource(source))
|
||||
.toList();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategoryChannelMapping;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface NewsCategoryChannelMappingRepository extends JpaRepository<NewsCategoryChannelMapping, Long> {
|
||||
boolean existsByChannelAndNewsCategory(AChannel channel, NewsCategory newsCategory);
|
||||
void deleteByNewsCategory(NewsCategory newsCategory);
|
||||
void deleteByNewsCategoryAndChannel(NewsCategory newsCategory, AChannel channel);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface NewsCategoryRepository extends JpaRepository<NewsCategory, Long> {
|
||||
List<NewsCategory> getByServerIn(List<AServer> servers);
|
||||
List<NewsCategory> getByServer(AServer server);
|
||||
Optional<NewsCategory> findByKeyAndServer(String name, AServer server);
|
||||
boolean existsByKeyAndServer(String name, AServer server);
|
||||
List<NewsCategory> findByKeyStartsWithAndServer(String name, AServer server);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedRecord;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface NewsFeedRecordRepository extends JpaRepository<NewsFeedRecord, Long> {
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSourceCategory;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface NewsFeedSourceCategoryRepository extends JpaRepository<NewsFeedSourceCategory, Long> {
|
||||
List<NewsFeedSourceCategory> findByNameStartsWith(String name);
|
||||
List<NewsFeedSourceCategory> findByNameStartsWithAndSource(String name, NewsFeedSource newsFeedSource);
|
||||
Optional<NewsFeedSourceCategory> findByNameAndSource(String name, NewsFeedSource newsFeedSource);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface NewsFeedSourceRepository extends JpaRepository<NewsFeedSource, Long> {
|
||||
Optional<NewsFeedSource> findByName(String name);
|
||||
List<NewsFeedSource> findByNameStartsWith(String name);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.sissi.module.rssnews.repository;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsPost;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface NewsPostRepository extends JpaRepository<NewsPost, Long> {
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsCategoryChannelMappingAlreadyExistsException;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsCategoryChannelMappingNotFoundException;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategoryChannelMapping;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsCategoryChannelMappingManagementServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsCategoryManagementServiceBean;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class NewsCategoryChannelMappingServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryManagementServiceBean newsCategoryManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingManagementServiceBean newsCategoryChannelMappingManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
public NewsCategoryChannelMapping createNewsCategoryChannelMapping(String categoryName, GuildChannel channel) {
|
||||
AChannel aChannel = channelManagementService.loadChannel(channel.getIdLong());
|
||||
NewsCategory newsCategory = newsCategoryManagementServiceBean.findNewsCategoryByNameInServer(categoryName, aChannel.getServer());
|
||||
if(newsCategoryChannelMappingManagementServiceBean.newsCategoryChannelMappingExists(newsCategory, aChannel)) {
|
||||
throw new NewsCategoryChannelMappingAlreadyExistsException();
|
||||
}
|
||||
return newsCategoryChannelMappingManagementServiceBean.createNewsCategoryChannelMapping(newsCategory, aChannel);
|
||||
}
|
||||
|
||||
public void deleteNewsCategoryChannelMapping(String categoryName, GuildChannel channel) {
|
||||
AChannel aChannel = channelManagementService.loadChannel(channel.getIdLong());
|
||||
NewsCategory newsCategory = newsCategoryManagementServiceBean.findNewsCategoryByNameInServer(categoryName, aChannel.getServer());
|
||||
if(!newsCategoryChannelMappingManagementServiceBean.newsCategoryChannelMappingExists(newsCategory, aChannel)) {
|
||||
throw new NewsCategoryChannelMappingNotFoundException();
|
||||
}
|
||||
newsCategoryChannelMappingManagementServiceBean.deleteNewsCategoryChannelMapping(newsCategory, aChannel);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.ChannelDisplay;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.utils.ChannelUtils;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsCategoryAlreadyExistsException;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.model.template.NewsCategoryChannelMappingInfo;
|
||||
import dev.sheldan.sissi.module.rssnews.model.template.NewsCategoryInfo;
|
||||
import dev.sheldan.sissi.module.rssnews.model.template.NewsCategorySubscriptionInfo;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsCategoryChannelMappingManagementServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsCategoryManagementServiceBean;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Component
|
||||
public class NewsCategoryServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryManagementServiceBean newsCategoryManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingManagementServiceBean newsCategoryChannelMappingManagementServiceBean;
|
||||
|
||||
public void createCategory(String name, AServer server) {
|
||||
if(newsCategoryManagementServiceBean.newsCategoryExistsByNameInServer(name, server)) {
|
||||
throw new NewsCategoryAlreadyExistsException();
|
||||
}
|
||||
newsCategoryManagementServiceBean.createCategory(name, server);
|
||||
}
|
||||
|
||||
public void deleteNewsCategoryByName(String name, AServer server) {
|
||||
NewsCategory newsCategory = newsCategoryManagementServiceBean.findNewsCategoryByNameInServer(name, server);
|
||||
newsCategoryChannelMappingManagementServiceBean.deleteChannelMappingsOfNewsCategory(newsCategory);
|
||||
newsCategoryManagementServiceBean.deleteNewsCategory(newsCategory);
|
||||
}
|
||||
|
||||
public List<NewsCategory> findNewsCategoriesStartingWith(String name, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
return newsCategoryManagementServiceBean.findNewsCategoriesStartingWith(name, server);
|
||||
}
|
||||
|
||||
public List<String> getNamesOfNewsCategoriesStartingWith(String name, Guild guild) {
|
||||
return findNewsCategoriesStartingWith(name, guild)
|
||||
.stream()
|
||||
.map(NewsCategory::getKey)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<NewsCategoryInfo> getCategoryInfos(Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild);
|
||||
List<NewsCategory> newsCategories = newsCategoryManagementServiceBean.getNewsCategoriesOfServers(server);
|
||||
return newsCategories.stream().map(newsCategory -> {
|
||||
List<NewsCategorySubscriptionInfo> subscriptionInfos = new ArrayList<>();
|
||||
|
||||
Map<String, List<String>> sourceCategories = new HashMap<>();
|
||||
newsCategory
|
||||
.getSourceCategories()
|
||||
.forEach(sourceCategory -> {
|
||||
if(!sourceCategories.containsKey(sourceCategory.getSource().getName())) {
|
||||
sourceCategories.put(sourceCategory.getSource().getName(), new ArrayList<>());
|
||||
}
|
||||
sourceCategories.get(sourceCategory.getSource().getName()).add(sourceCategory.getName());
|
||||
});
|
||||
sourceCategories.forEach((sourceName, categoryList) ->
|
||||
subscriptionInfos.add(NewsCategorySubscriptionInfo
|
||||
.builder()
|
||||
.newsFeedName(sourceName)
|
||||
.newsFeedCategories(categoryList)
|
||||
.build()));
|
||||
List<NewsCategoryChannelMappingInfo> mappings = new ArrayList<>();
|
||||
newsCategory.getMappings().forEach(newsCategoryChannelMapping -> {
|
||||
ChannelDisplay channelDisplay = ChannelDisplay
|
||||
.builder()
|
||||
.channelMention(ChannelUtils.getAsMention(newsCategoryChannelMapping.getChannel().getId()))
|
||||
.build();
|
||||
mappings.add(NewsCategoryChannelMappingInfo
|
||||
.builder()
|
||||
.enabled(newsCategoryChannelMapping.getEnabled())
|
||||
.channel(channelDisplay)
|
||||
.build());
|
||||
});
|
||||
return NewsCategoryInfo
|
||||
.builder()
|
||||
.name(newsCategory.getKey())
|
||||
.subscriptions(subscriptionInfos)
|
||||
.mappings(mappings)
|
||||
.build();
|
||||
}).toList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSourceCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceCategoryManagementServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class NewsFeedSourceCategoryServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategoryManagementServiceBean newsFeedSourceCategoryManagementServiceBean;
|
||||
|
||||
public List<NewsFeedSourceCategory> findNewsFeedSourceCategoriesStartingWith(String name) {
|
||||
return newsFeedSourceCategoryManagementServiceBean.findNewsFeedSourceCategoriesNameStartingWith(name);
|
||||
}
|
||||
|
||||
public List<NewsFeedSourceCategory> getNewsSourceCategoriesInNewsFeedStartingWith(String name, NewsFeedSource newsFeedSource) {
|
||||
return newsFeedSourceCategoryManagementServiceBean.findNewsFeedSourceCategoriesNameStartingWith(name, newsFeedSource);
|
||||
}
|
||||
|
||||
public List<String> getNamesOfNewsCategoriesStartingWith(String name) {
|
||||
return findNewsFeedSourceCategoriesStartingWith(name)
|
||||
.stream()
|
||||
.map(NewsFeedSourceCategory::getName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
public List<String> getNamesOfNewsSourceCategoriesInNewsFeedStartingWith(String name, NewsFeedSource newsFeedSource) {
|
||||
return getNewsSourceCategoriesInNewsFeedStartingWith(name, newsFeedSource)
|
||||
.stream()
|
||||
.map(NewsFeedSourceCategory::getName)
|
||||
.toList();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsFeedSourceCategorySubscriptionAlreadyExistsException;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsFeedSourceCategorySubscriptionNotFoundException;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSource;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedSourceCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsCategoryManagementServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceCategoryManagementServiceBean;
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceManagementServiceBean;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class NewsFeedSourceCategorySubscriptionServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryManagementServiceBean newsCategoryManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceCategoryManagementServiceBean newsFeedSourceCategoryManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceManagementServiceBean newsFeedSourceManagementServiceBean;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
public void createNewsFeedSourceCategorySubscription(String categoryName, String sourceCategoryName, String newsFeedSourceName, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
NewsCategory newsCategory = newsCategoryManagementServiceBean.findNewsCategoryByNameInServer(categoryName, server);
|
||||
NewsFeedSource newsFeedSource = newsFeedSourceManagementServiceBean.getNewsFeedSourceWithName(newsFeedSourceName);
|
||||
NewsFeedSourceCategory sourceCategory = newsFeedSourceCategoryManagementServiceBean.findNewsFeedSourceCategoryByNameAndNewsFeedSource(sourceCategoryName, newsFeedSource);
|
||||
if(newsCategory.getSourceCategories().contains(sourceCategory)) {
|
||||
throw new NewsFeedSourceCategorySubscriptionAlreadyExistsException();
|
||||
}
|
||||
newsCategory.getSourceCategories().add(sourceCategory);
|
||||
sourceCategory.getCategories().add(newsCategory);
|
||||
}
|
||||
|
||||
public void deleteNewsFeedSourceCategorySubscription(String categoryName, String sourceCategoryName, String newsFeedSourceName, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
NewsCategory newsCategory = newsCategoryManagementServiceBean.findNewsCategoryByNameInServer(categoryName, server);
|
||||
NewsFeedSource newsFeedSource = newsFeedSourceManagementServiceBean.getNewsFeedSourceWithName(newsFeedSourceName);
|
||||
NewsFeedSourceCategory sourceCategory = newsFeedSourceCategoryManagementServiceBean.findNewsFeedSourceCategoryByNameAndNewsFeedSource(sourceCategoryName, newsFeedSource);
|
||||
if(!newsCategory.getSourceCategories().contains(sourceCategory)) {
|
||||
throw new NewsFeedSourceCategorySubscriptionNotFoundException();
|
||||
}
|
||||
newsCategory.getSourceCategories().remove(sourceCategory);
|
||||
sourceCategory.getCategories().remove(newsCategory);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.service.management.NewsFeedSourceManagementServiceBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class NewsFeedSourceServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsFeedSourceManagementServiceBean newsFeedSourceManagementServiceBean;
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsCategoryChannelMappingNotFoundException;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategoryChannelMapping;
|
||||
import dev.sheldan.sissi.module.rssnews.repository.NewsCategoryChannelMappingRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class NewsCategoryChannelMappingManagementServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryChannelMappingRepository repository;
|
||||
|
||||
public NewsCategoryChannelMapping createNewsCategoryChannelMapping(NewsCategory newsCategory, AChannel channel) {
|
||||
NewsCategoryChannelMapping category = NewsCategoryChannelMapping
|
||||
.builder()
|
||||
.channel(channel)
|
||||
.server(channel.getServer())
|
||||
.newsCategory(newsCategory)
|
||||
.enabled(true)
|
||||
.build();
|
||||
return repository.save(category);
|
||||
}
|
||||
|
||||
public NewsCategoryChannelMapping getChannelMappingById(Long id) {
|
||||
return repository.findById(id).orElseThrow(NewsCategoryChannelMappingNotFoundException::new);
|
||||
}
|
||||
|
||||
public boolean newsCategoryChannelMappingExists(NewsCategory newsCategory, AChannel channel) {
|
||||
return repository.existsByChannelAndNewsCategory(channel, newsCategory);
|
||||
}
|
||||
|
||||
public void deleteChannelMappingsOfNewsCategory(NewsCategory newsCategory) {
|
||||
repository.deleteByNewsCategory(newsCategory);
|
||||
}
|
||||
|
||||
public void deleteNewsCategoryChannelMapping(NewsCategory newsCategory, AChannel channel) {
|
||||
repository.deleteByNewsCategoryAndChannel(newsCategory, channel);
|
||||
}
|
||||
|
||||
public void deleteNewsCategoryChannelMapping(NewsCategoryChannelMapping mapping) {
|
||||
repository.delete(mapping);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.sissi.module.rssnews.exception.NewsCategoryNotFoundException;
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsCategory;
|
||||
import dev.sheldan.sissi.module.rssnews.repository.NewsCategoryRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class NewsCategoryManagementServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsCategoryRepository repository;
|
||||
|
||||
public List<NewsCategory> getNewsCategoriesOfServers(List<AServer> servers) {
|
||||
return repository.getByServerIn(servers);
|
||||
}
|
||||
|
||||
public List<NewsCategory> getNewsCategoriesOfServers(AServer server) {
|
||||
return repository.getByServer(server);
|
||||
}
|
||||
|
||||
public NewsCategory createCategory(String name, AServer server) {
|
||||
NewsCategory category = NewsCategory
|
||||
.builder()
|
||||
.key(name)
|
||||
.server(server)
|
||||
.enabled(true)
|
||||
.build();
|
||||
return repository.save(category);
|
||||
}
|
||||
|
||||
public Optional<NewsCategory> findNewsCategoryByNameInServerOptional(String name, AServer server) {
|
||||
return repository.findByKeyAndServer(name, server);
|
||||
}
|
||||
|
||||
public NewsCategory findNewsCategoryByNameInServer(String name, AServer server) {
|
||||
return findNewsCategoryByNameInServerOptional(name, server).orElseThrow(NewsCategoryNotFoundException::new);
|
||||
}
|
||||
|
||||
public boolean newsCategoryExistsByNameInServer(String name, AServer server) {
|
||||
return repository.existsByKeyAndServer(name, server);
|
||||
}
|
||||
|
||||
public void deleteNewsCategory(NewsCategory newsCategory) {
|
||||
repository.delete(newsCategory);
|
||||
}
|
||||
|
||||
public List<NewsCategory> findNewsCategoriesStartingWith(String name, AServer server) {
|
||||
return repository.findByKeyStartsWithAndServer(name, server);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package dev.sheldan.sissi.module.rssnews.service.management;
|
||||
|
||||
import dev.sheldan.sissi.module.rssnews.model.database.NewsFeedRecord;
|
||||
import dev.sheldan.sissi.module.rssnews.model.feed.NewsResponseItem;
|
||||
import dev.sheldan.sissi.module.rssnews.repository.NewsFeedRecordRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class NewsFeedRecordManagementServiceBean {
|
||||
|
||||
@Autowired
|
||||
private NewsFeedRecordRepository repository;
|
||||
|
||||
public List<NewsFeedRecord> getAllRecords() {
|
||||
return repository.findAll();
|
||||
}
|
||||
|
||||
public NewsFeedRecord createRecord(NewsResponseItem newsResponseItem) {
|
||||
NewsFeedRecord newsFeedRecord = NewsFeedRecord
|
||||
.builder()
|
||||
.source(newsResponseItem.getNewsFeedSource())
|
||||
.url(newsResponseItem.getLink())
|
||||
.build();
|
||||
return repository.save(newsFeedRecord);
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user