mirror of
https://github.com/Sheldan/abstracto.git
synced 2026-01-08 18:34:05 +00:00
[AB-98] adding twitch support
upgrading to java 17 upgrade of dependencies
This commit is contained in:
19
.github/workflows/build.yml
vendored
19
.github/workflows/build.yml
vendored
@@ -1,7 +1,7 @@
|
||||
# This workflow will build a Java project with Maven
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
|
||||
|
||||
name: Execute build and Sonar
|
||||
name: Execute Build
|
||||
|
||||
on:
|
||||
push:
|
||||
@@ -20,26 +20,13 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 1.8
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'corretto'
|
||||
java-version: 8
|
||||
java-version: 17
|
||||
- name: Build with Maven
|
||||
run: mvn -B install --file abstracto-application/pom.xml
|
||||
- name: Setup sonarqube
|
||||
uses: warchant/setup-sonar-scanner@v3
|
||||
- name: Run sonarqube
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: sonar-scanner
|
||||
-Dsonar.login=${{ secrets.SONAR_TOKEN }}
|
||||
-Dsonar.organization=sheldan
|
||||
-Dsonar.host.url=https://sonarcloud.io/
|
||||
-Dsonar.projectKey=abstracto-core
|
||||
-Dsonar.java.binaries=**/target/classes
|
||||
-Dsonar.coverage.jacoco.xmlReportPaths=abstracto-application/coverage/target/site/jacoco-aggregate/jacoco.xml
|
||||
-Dsonar.coverage.exclusions=**/*Test.java
|
||||
- uses: actions/setup-ruby@v1
|
||||
- name: Send Webhook Notification
|
||||
if: always()
|
||||
|
||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'corretto'
|
||||
java-version: 8
|
||||
java-version: 17
|
||||
- name: Load current version
|
||||
id: version
|
||||
run: echo "version=$(mvn --file abstracto-application/pom.xml -q -Dexec.executable="echo" -Dexec.args='${project.version}' --non-recursive exec:exec)" >> $GITHUB_ENV
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# Abstracto
|
||||
|
||||

|
||||
[](https://sonarcloud.io/dashboard?id=abstracto-core)
|
||||
[](https://sonarcloud.io/dashboard?id=abstracto-core)
|
||||

|
||||
[](https://github.com/Sheldan/abstracto/blob/master/LICENSE)
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.ComponentPayload;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.assignableroles.model.database;
|
||||
import dev.sheldan.abstracto.assignableroles.model.condition.AssignableRoleConditionType;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "assignable_role_condition")
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.assignableroles.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.customcommand.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.*;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.activity.models;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -4,7 +4,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.experience.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package dev.sheldan.abstracto.experience.model.database;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -4,7 +4,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.invitefilter.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.invitefilter.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.invitefilter.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,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;
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.moderation.model.database;
|
||||
import dev.sheldan.abstracto.moderation.model.database.embedded.InfractionParameterId;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -4,7 +4,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;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,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;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.abstracto.moderation.model.database.embedded;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
|
||||
@Embeddable
|
||||
|
||||
@@ -4,7 +4,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.ARole;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -4,7 +4,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
<module>dynamic-activity</module>
|
||||
<module>anti-raid</module>
|
||||
<module>custom-command</module>
|
||||
<module>twitch</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
@@ -5,7 +5,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.ProfanityGroup;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -4,7 +4,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.List;
|
||||
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.remind.model.database.embed.ReminderUserId;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package dev.sheldan.abstracto.remind.model.database.embed;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Embeddable;
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.PostIdentifier;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.repostdetection.model.database.embed.RepostIdentifier;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.repostdetection.model.database;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannelGroup;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Builder
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.abstracto.repostdetection.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.abstracto.repostdetection.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
|
||||
|
||||
@@ -5,7 +5,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@@ -4,7 +4,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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.statistic.emote.config.EmoteTrackingFeatureConfig;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serializable;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ package dev.sheldan.abstracto.statistic.emote.model.database;
|
||||
import dev.sheldan.abstracto.statistic.emote.model.database.embed.UsedEmoteDay;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.abstracto.statistic.emote.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;
|
||||
import java.time.Instant;
|
||||
|
||||
|
||||
@@ -5,7 +5,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;
|
||||
|
||||
@@ -4,7 +4,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;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -4,7 +4,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.abstracto.suggestion.model.database;
|
||||
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -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.io.Serializable;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -4,7 +4,7 @@ import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.suggestion.model.database.embed.SuggestionVoterId;
|
||||
import lombok.*;
|
||||
|
||||
import javax.persistence.*;
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
|
||||
@@ -2,8 +2,8 @@ package dev.sheldan.abstracto.suggestion.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
|
||||
|
||||
35
abstracto-application/abstracto-modules/twitch/pom.xml
Normal file
35
abstracto-application/abstracto-modules/twitch/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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>abstracto-modules</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.27-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>twitch</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<modules>
|
||||
<module>twitch-int</module>
|
||||
<module>twitch-impl</module>
|
||||
</modules>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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>twitch</artifactId>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<version>1.4.27-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>twitch-impl</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.modules</groupId>
|
||||
<artifactId>twitch-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.core</groupId>
|
||||
<artifactId>core-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>test-jar</type>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>dev.sheldan.abstracto.scheduling</groupId>
|
||||
<artifactId>scheduling-int</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,18 @@
|
||||
<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">
|
||||
<id>liquibase</id>
|
||||
<formats>
|
||||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<outputDirectory>.</outputDirectory>
|
||||
<directory>${project.basedir}/src/main/resources/migrations</directory>
|
||||
<includes>
|
||||
<include>**/*</include>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
</assembly>
|
||||
@@ -0,0 +1,131 @@
|
||||
package dev.sheldan.abstracto.twitch.command;
|
||||
|
||||
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.utils.FutureUtils;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchFeatureDefinition;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchSlashCommandNames;
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.interactions.InteractionHook;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class AddTwitchStreamer extends AbstractConditionableCommand {
|
||||
|
||||
private static final String ADD_TWITCH_STREAMER_COMMAND = "addTwitchStreamer";
|
||||
private static final String STREAMER_NAME_PARAMETER = "streamerName";
|
||||
private static final String TARGET_CHANNEL_PARAMETER = "targetChannel";
|
||||
private static final String SERVER_MEMBER_PARAMETER = "streamerMember";
|
||||
private static final String ADD_TWITCH_STREAMER_RESPONSE = "addTwitchStreamer_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private StreamerService streamerService;
|
||||
|
||||
@Autowired
|
||||
private AddTwitchStreamer self;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
// its likely that this command times out
|
||||
return event.deferReply().submit().thenCompose(interactionHook -> self.executeAddStreamerCommandLogic(event, interactionHook));
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public CompletableFuture<CommandResult> executeAddStreamerCommandLogic(SlashCommandInteractionEvent event, InteractionHook interactionHook) {
|
||||
String streamerName = slashCommandParameterService.getCommandOption(STREAMER_NAME_PARAMETER, event, String.class);
|
||||
GuildMessageChannel guildMessageChannel = null;
|
||||
if(slashCommandParameterService.hasCommandOption(TARGET_CHANNEL_PARAMETER, event)) {
|
||||
guildMessageChannel = slashCommandParameterService.getCommandOption(TARGET_CHANNEL_PARAMETER, event, TextChannel.class, GuildMessageChannel.class);
|
||||
}
|
||||
Member streamerMember = null;
|
||||
if(slashCommandParameterService.hasCommandOption(SERVER_MEMBER_PARAMETER, event)) {
|
||||
streamerMember = slashCommandParameterService.getCommandOption(SERVER_MEMBER_PARAMETER, event, Member.class);
|
||||
}
|
||||
streamerService.createStreamer(streamerName, guildMessageChannel, event.getMember(), streamerMember);
|
||||
return FutureUtils.toSingleFutureGeneric(interactionService.sendMessageToInteraction(ADD_TWITCH_STREAMER_RESPONSE, new Object(), interactionHook))
|
||||
.thenApply(unused -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter streamerNameParameter = Parameter
|
||||
.builder()
|
||||
.name(STREAMER_NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter targetChannelParameter = Parameter
|
||||
.builder()
|
||||
.name(TARGET_CHANNEL_PARAMETER)
|
||||
.type(TextChannel.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
Parameter streamerMemberParameter = Parameter
|
||||
.builder()
|
||||
.name(SERVER_MEMBER_PARAMETER)
|
||||
.type(Member.class)
|
||||
.optional(true)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(streamerNameParameter, targetChannelParameter, streamerMemberParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(TwitchSlashCommandNames.TWITCH)
|
||||
.groupName("streamer")
|
||||
.commandName("add")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(ADD_TWITCH_STREAMER_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return TwitchFeatureDefinition.TWITCH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package dev.sheldan.abstracto.twitch.command;
|
||||
|
||||
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.abstracto.twitch.config.TwitchFeatureDefinition;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchSlashCommandNames;
|
||||
import dev.sheldan.abstracto.twitch.exception.StreamerNotFoundInServerException;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
import dev.sheldan.abstracto.twitch.service.management.StreamerManagementService;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
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.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class ChangeTwitchStreamer extends AbstractConditionableCommand {
|
||||
|
||||
private static final String CHANGE_STREAMER_COMMAND = "changeTwitchStreamer";
|
||||
private static final String STREAMER_NAME_PARAMETER = "streamerName";
|
||||
private static final String STREAMER_NEW_VALUE_PARAMETER = "newValue";
|
||||
private static final String STREAMER_PROPERTY_PARAMETER = "property";
|
||||
private static final String CHANGE_TWITCH_STREAMER_RESPONSE = "changeTwitchStreamer_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private StreamerManagementService streamerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private StreamerService streamerService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String streamerName = slashCommandParameterService.getCommandOption(STREAMER_NAME_PARAMETER, event, String.class);
|
||||
String property = slashCommandParameterService.getCommandOption(STREAMER_PROPERTY_PARAMETER, event, String.class);
|
||||
AServer server = serverManagementService.loadServer(event.getGuild());
|
||||
Streamer streamerInServerByName = streamerManagementService.getStreamerInServerByName(streamerName, server).orElseThrow(StreamerNotFoundInServerException::new);
|
||||
StreamerProperty propertyEnum = StreamerProperty.valueOf(property);
|
||||
String newValue = slashCommandParameterService.getCommandOption(STREAMER_NEW_VALUE_PARAMETER, event, String.class);
|
||||
updateStreamer(streamerInServerByName, propertyEnum, newValue);
|
||||
return interactionService.replyEmbed(CHANGE_TWITCH_STREAMER_RESPONSE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
private void updateStreamer(Streamer streamer, StreamerProperty propertyEnum, String newValue) {
|
||||
switch (propertyEnum) {
|
||||
case TARGET_CHANNEL -> {
|
||||
Matcher channelMatcher = Message.MentionType.CHANNEL.getPattern().matcher(newValue);
|
||||
if (channelMatcher.matches()) {
|
||||
Long channelId = Long.parseLong(channelMatcher.group(1));
|
||||
streamerService.changeStreamerNotificationToChannel(streamer, channelId);
|
||||
} else {
|
||||
streamerService.changeStreamerNotificationToChannel(streamer, null);
|
||||
}
|
||||
}
|
||||
case STREAMER_MEMBER -> {
|
||||
Matcher memberMatcher = Message.MentionType.USER.getPattern().matcher(newValue);
|
||||
if (memberMatcher.matches()) {
|
||||
Long channelId = Long.parseLong(memberMatcher.group(1));
|
||||
streamerService.changeStreamerMemberToUserId(streamer, channelId);
|
||||
} else {
|
||||
streamerService.changeStreamerMemberToUserId(streamer, null);
|
||||
}
|
||||
}
|
||||
case TEMPLATE_KEY -> {
|
||||
String newTemplateKey = newValue;
|
||||
if ("default".equals(newTemplateKey)) {
|
||||
newTemplateKey = null;
|
||||
}
|
||||
streamerService.changeTemplateKeyTo(streamer, newTemplateKey);
|
||||
}
|
||||
case DISABLE_NOTIFICATIONS -> {
|
||||
Boolean newState = BooleanUtils.toBoolean(newValue);
|
||||
streamerService.disableNotificationsForStreamer(streamer, newState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter streamerNameParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(STREAMER_NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<String> streamerProperties = Arrays
|
||||
.stream(StreamerProperty.values())
|
||||
.map(Enum::name)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
Parameter streamerPropertyParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(STREAMER_PROPERTY_PARAMETER)
|
||||
.type(String.class)
|
||||
.choices(streamerProperties)
|
||||
.build();
|
||||
|
||||
Parameter newValueParameter = Parameter
|
||||
.builder()
|
||||
.templated(true)
|
||||
.name(STREAMER_NEW_VALUE_PARAMETER)
|
||||
.type(String.class)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(streamerNameParameter, streamerPropertyParameter, newValueParameter);
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(TwitchSlashCommandNames.TWITCH)
|
||||
.groupName("streamer")
|
||||
.commandName("edit")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(CHANGE_STREAMER_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return TwitchFeatureDefinition.TWITCH;
|
||||
}
|
||||
|
||||
public enum StreamerProperty {
|
||||
TARGET_CHANNEL, STREAMER_MEMBER, DISABLE_NOTIFICATIONS, TEMPLATE_KEY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package dev.sheldan.abstracto.twitch.command;
|
||||
|
||||
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.abstracto.twitch.config.TwitchFeatureDefinition;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchSlashCommandNames;
|
||||
import dev.sheldan.abstracto.twitch.model.template.ListTwitchStreamerResponseModel;
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@Component
|
||||
public class ListTwitchStreamer extends AbstractConditionableCommand {
|
||||
|
||||
private static final String LIST_TWITCH_STREAMER_COMMAND = "listTwitchStreamer";
|
||||
private static final String LIST_TWITCH_STREAMER_RESPONSE = "listTwitchStreamer_response";
|
||||
|
||||
@Autowired
|
||||
private StreamerService streamerService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
ListTwitchStreamerResponseModel model = streamerService.getStreamersFromServer(event.getGuild());
|
||||
return interactionService.replyEmbed(LIST_TWITCH_STREAMER_RESPONSE, model, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(TwitchSlashCommandNames.TWITCH)
|
||||
.groupName("streamer")
|
||||
.commandName("list")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(LIST_TWITCH_STREAMER_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return TwitchFeatureDefinition.TWITCH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package dev.sheldan.abstracto.twitch.command;
|
||||
|
||||
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.twitch.config.TwitchFeatureDefinition;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchSlashCommandNames;
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
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 RemoveTwitchStreamer extends AbstractConditionableCommand {
|
||||
|
||||
private static final String REMOVE_TWITCH_STREAMER_COMMAND = "removeTwitchStreamer";
|
||||
private static final String STREAMER_NAME_PARAMETER = "streamerName";
|
||||
private static final String REMOVE_TWITCH_STREAMER_RESPONSE = "removeTwitchStreamer_response";
|
||||
|
||||
@Autowired
|
||||
private SlashCommandParameterService slashCommandParameterService;
|
||||
|
||||
@Autowired
|
||||
private InteractionService interactionService;
|
||||
|
||||
@Autowired
|
||||
private StreamerService streamerService;
|
||||
|
||||
@Override
|
||||
public CompletableFuture<CommandResult> executeSlash(SlashCommandInteractionEvent event) {
|
||||
String streamerName = slashCommandParameterService.getCommandOption(STREAMER_NAME_PARAMETER, event, String.class);
|
||||
streamerService.removeStreamer(streamerName, event.getGuild());
|
||||
return interactionService.replyEmbed(REMOVE_TWITCH_STREAMER_RESPONSE, event)
|
||||
.thenApply(interactionHook -> CommandResult.fromSuccess());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandConfiguration getConfiguration() {
|
||||
Parameter streamerNameParameter = Parameter
|
||||
.builder()
|
||||
.name(STREAMER_NAME_PARAMETER)
|
||||
.type(String.class)
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
List<Parameter> parameters = Arrays.asList(streamerNameParameter);
|
||||
|
||||
HelpInfo helpInfo = HelpInfo
|
||||
.builder()
|
||||
.templated(true)
|
||||
.build();
|
||||
|
||||
SlashCommandConfig slashCommandConfig = SlashCommandConfig
|
||||
.builder()
|
||||
.enabled(true)
|
||||
.rootCommandName(TwitchSlashCommandNames.TWITCH)
|
||||
.groupName("streamer")
|
||||
.commandName("remove")
|
||||
.build();
|
||||
|
||||
return CommandConfiguration.builder()
|
||||
.name(REMOVE_TWITCH_STREAMER_COMMAND)
|
||||
.module(UtilityModuleDefinition.UTILITY)
|
||||
.templated(true)
|
||||
.async(true)
|
||||
.slashCommandConfig(slashCommandConfig)
|
||||
.supportsEmbedException(true)
|
||||
.causesReaction(true)
|
||||
.parameters(parameters)
|
||||
.help(helpInfo)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return TwitchFeatureDefinition.TWITCH;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:twitch-config.properties")
|
||||
public class TwitchConfig {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.abstracto.twitch.job;
|
||||
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
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 StreamerOnlineCheckJob extends QuartzJobBean {
|
||||
|
||||
@Autowired
|
||||
private StreamerService streamerService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info("Executing streamer online check");
|
||||
try {
|
||||
streamerService.checkAndNotifyAboutOnlineStreamers();
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to check online status for streamers.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package dev.sheldan.abstracto.twitch.job;
|
||||
|
||||
import dev.sheldan.abstracto.twitch.service.StreamerService;
|
||||
import dev.sheldan.abstracto.twitch.service.TwitchService;
|
||||
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 TwitchRefreshTokenJob extends QuartzJobBean {
|
||||
@Autowired
|
||||
private TwitchService twitchService;
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||
log.info("Refreshing twitch token..");
|
||||
try {
|
||||
twitchService.refreshToken();
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to refresh twitch token.", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.twitch.repository;
|
||||
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface StreamSessionRepository extends JpaRepository<StreamSession, Long> {
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package dev.sheldan.abstracto.twitch.repository;
|
||||
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSessionSection;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface StreamSessionSectionRepository extends JpaRepository<StreamSessionSection, Long> {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.twitch.repository;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Repository
|
||||
public interface StreamerRepository extends JpaRepository<Streamer, Long> {
|
||||
boolean existsByServerAndUserId(AServer server, String userId);
|
||||
boolean existsByServerAndName(AServer server, String name);
|
||||
Optional<Streamer> findByServerAndName(AServer server, String name);
|
||||
Optional<Streamer> findByServer_IdAndUserId(Long serverId, String userId);
|
||||
List<Streamer> getByUserId(String userId);
|
||||
List<Streamer> getStreamerByServer(AServer server);
|
||||
void deleteByUserId(String id);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package dev.sheldan.abstracto.twitch.service;
|
||||
|
||||
import com.github.twitch4j.helix.domain.Stream;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSessionSection;
|
||||
import dev.sheldan.abstracto.twitch.service.management.StreamSessionSectionManagementService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StreamSessionSectionServiceBean implements StreamSessionSectionService {
|
||||
|
||||
@Autowired
|
||||
private StreamSessionSectionManagementService sessionSectionManagementService;
|
||||
|
||||
@Override
|
||||
public StreamSessionSection createSectionFromStream(StreamSession session, Stream stream) {
|
||||
return sessionSectionManagementService.addSection(session, stream.getGameId(), stream.getGameName(),
|
||||
stream.getStartedAtInstant(), stream.getTitle(), stream.getViewerCount());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,437 @@
|
||||
package dev.sheldan.abstracto.twitch.service;
|
||||
|
||||
import com.github.twitch4j.helix.domain.Stream;
|
||||
import com.github.twitch4j.helix.domain.User;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.core.models.template.display.ChannelDisplay;
|
||||
import dev.sheldan.abstracto.core.service.*;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.ServerManagementService;
|
||||
import dev.sheldan.abstracto.core.service.management.UserInServerManagementService;
|
||||
import dev.sheldan.abstracto.core.templating.model.MessageToSend;
|
||||
import dev.sheldan.abstracto.core.templating.service.TemplateService;
|
||||
import dev.sheldan.abstracto.core.utils.CompletableFutureList;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchFeatureConfig;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchFeatureDefinition;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchFeatureMode;
|
||||
import dev.sheldan.abstracto.twitch.config.TwitchPostTarget;
|
||||
import dev.sheldan.abstracto.twitch.exception.StreamerExistsException;
|
||||
import dev.sheldan.abstracto.twitch.exception.StreamerNotFoundInServerException;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSessionSection;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
|
||||
import dev.sheldan.abstracto.twitch.model.template.*;
|
||||
import dev.sheldan.abstracto.twitch.service.management.StreamSessionManagementService;
|
||||
import dev.sheldan.abstracto.twitch.service.management.StreamSessionSectionManagementService;
|
||||
import dev.sheldan.abstracto.twitch.service.management.StreamerManagementService;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import net.dv8tion.jda.api.entities.Guild;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.Message;
|
||||
import net.dv8tion.jda.api.entities.channel.middleman.GuildMessageChannel;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StreamerServiceBean implements StreamerService {
|
||||
|
||||
@Autowired
|
||||
private TwitchService twitchService;
|
||||
|
||||
@Autowired
|
||||
private StreamerManagementService streamerManagementService;
|
||||
|
||||
@Autowired
|
||||
private UserInServerManagementService userInServerManagementService;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Autowired
|
||||
private ServerManagementService serverManagementService;
|
||||
|
||||
@Autowired
|
||||
private PostTargetService postTargetService;
|
||||
|
||||
@Autowired
|
||||
private ChannelService channelService;
|
||||
|
||||
@Autowired
|
||||
private TemplateService templateService;
|
||||
|
||||
@Autowired
|
||||
private FeatureFlagService featureFlagService;
|
||||
|
||||
@Autowired
|
||||
private FeatureModeService featureModeService;
|
||||
|
||||
@Autowired
|
||||
private TwitchFeatureConfig twitchFeatureConfig;
|
||||
|
||||
@Autowired
|
||||
private StreamSessionSectionService streamSessionSectionService;
|
||||
|
||||
@Autowired
|
||||
private StreamSessionManagementService streamSessionManagementService;
|
||||
|
||||
@Autowired
|
||||
private StreamSessionSectionManagementService streamSessionSectionManagementService;
|
||||
|
||||
@Autowired
|
||||
private MessageService messageService;
|
||||
|
||||
@Autowired
|
||||
private StreamerServiceBean self;
|
||||
|
||||
private static final String DEFAULT_NOTIFICATION_TEMPLATE = "twitch_streamer_go_live_notification";
|
||||
private static final String WENT_OFF_LINE_MESSAGE_TEMPLATE = "twitch_streamer_went_offline_message";
|
||||
|
||||
@Override
|
||||
public void createStreamer(String name, GuildMessageChannel targetChannel, Member creator, Member streamerMember) {
|
||||
User streamerByName = twitchService.getStreamerByName(name);
|
||||
Optional<Stream> optionalStream = twitchService.getStreamOfUser(streamerByName.getId());
|
||||
AServer server = serverManagementService.loadServer(creator.getGuild().getIdLong());
|
||||
if(streamerManagementService.streamerExistsInServerByID(streamerByName.getId(), server)) {
|
||||
throw new StreamerExistsException();
|
||||
}
|
||||
AChannel aTargetChannel = null;
|
||||
if(targetChannel != null) {
|
||||
aTargetChannel = channelManagementService.loadChannel(targetChannel);
|
||||
}
|
||||
AUserInAServer creatorUser = userInServerManagementService.loadOrCreateUser(creator);
|
||||
AUserInAServer streamerUser = null;
|
||||
if(streamerMember != null) {
|
||||
streamerUser = userInServerManagementService.loadOrCreateUser(streamerMember);
|
||||
}
|
||||
Streamer createdStreamer = streamerManagementService.createStreamer(streamerByName.getId(), name, aTargetChannel, creatorUser, streamerUser, optionalStream.isPresent());
|
||||
log.info("User {} created streamer {} in server {}.", creatorUser.getUserReference().getId(),
|
||||
createdStreamer.getId(), creatorUser.getServerReference().getId());
|
||||
optionalStream.ifPresent(stream -> createdStreamer.setCurrentGameId(stream.getGameId()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStreamer(String name, Guild guild) {
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
Streamer streamerInServerByName = streamerManagementService.getStreamerInServerByName(name, server).orElseThrow(StreamerNotFoundInServerException::new);
|
||||
log.info("Removing streamer {} for server {}.", streamerInServerByName.getId(), guild.getIdLong());
|
||||
streamSessionSectionManagementService.deleteSectionsOfStreamer(streamerInServerByName);
|
||||
streamSessionManagementService.deleteSessionsOfStreamer(streamerInServerByName);
|
||||
streamerManagementService.removeStreamer(streamerInServerByName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFutureList<Message> notifyAboutOnlineStream(Stream stream, Streamer streamer, User streamerUser) {
|
||||
GoLiveNotificationModel model = GoLiveNotificationModel
|
||||
.builder()
|
||||
.channelName(stream.getUserName())
|
||||
.mature(stream.isMature())
|
||||
.currentSection(StreamSectionDisplay.fromStream(stream))
|
||||
.streamerAvatarURL(streamerUser.getProfileImageUrl())
|
||||
.streamURL(formatStreamUrl(stream.getUserName()))
|
||||
.build();
|
||||
MessageToSend messagetoSend;
|
||||
if(streamer.getTemplateKey() == null) {
|
||||
messagetoSend = templateService.renderEmbedTemplate(DEFAULT_NOTIFICATION_TEMPLATE, model, streamer.getServer().getId());
|
||||
} else {
|
||||
messagetoSend = templateService.renderEmbedTemplate(streamer.getTemplateKey(), model, streamer.getServer().getId());
|
||||
}
|
||||
if(Boolean.FALSE.equals(streamer.getShowNotifications())) {
|
||||
log.info("Not announcing streamer {} in server {}.", streamer.getId(), streamer.getServer().getId());
|
||||
return new CompletableFutureList<>(Arrays.asList(CompletableFuture.completedFuture(null)));
|
||||
}
|
||||
if(streamer.getNotificationChannel() != null) {
|
||||
log.info("Announcing streamer {} in server {} to channel {}.", streamer.getId(), streamer.getServer().getId(), streamer.getNotificationChannel().getId());
|
||||
List<CompletableFuture<Message>> futures = channelService.sendMessageEmbedToSendToAChannel(messagetoSend, streamer.getNotificationChannel());
|
||||
return new CompletableFutureList<>(futures);
|
||||
} else {
|
||||
log.info("Announcing streamer {} in server {}.", streamer.getId(), streamer.getServer().getId());
|
||||
List<CompletableFuture<Message>> futures = postTargetService.sendEmbedInPostTarget(messagetoSend, TwitchPostTarget.TWITCH_LIVE_NOTIFICATION, streamer.getServer().getId());
|
||||
return new CompletableFutureList<>(futures);
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> updateExistingNotification(Stream stream, Streamer streamer, User streamerUser) {
|
||||
List<StreamSectionDisplay> pastSections = streamer
|
||||
.getCurrentSession()
|
||||
.getSections()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(StreamSessionSection::getId).reversed())
|
||||
.map(StreamSectionDisplay::fromSection)
|
||||
.toList();
|
||||
GoLiveNotificationModel model = GoLiveNotificationModel
|
||||
.builder()
|
||||
.channelName(stream.getUserName())
|
||||
.mature(stream.isMature())
|
||||
.currentSection(StreamSectionDisplay.fromStream(stream))
|
||||
.streamerAvatarURL(streamerUser.getProfileImageUrl())
|
||||
.pastSections(pastSections)
|
||||
.streamURL(formatStreamUrl(stream.getUserName()))
|
||||
.build();
|
||||
MessageToSend messagetoSend;
|
||||
if(streamer.getTemplateKey() == null) {
|
||||
messagetoSend = templateService.renderEmbedTemplate(DEFAULT_NOTIFICATION_TEMPLATE, model, streamer.getServer().getId());
|
||||
} else {
|
||||
messagetoSend = templateService.renderEmbedTemplate(streamer.getTemplateKey(), model, streamer.getServer().getId());
|
||||
}
|
||||
if(Boolean.FALSE.equals(streamer.getShowNotifications())) {
|
||||
log.info("Not editing notification, because notifications are disabled for streamer {} in server {}.", streamer.getId(), streamer.getServer().getId());
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
StreamSession currentSession = streamer.getCurrentSession();
|
||||
log.info("Updating notification {} for streamer {} in server {} in channel {}.", currentSession.getId(), streamer.getId(), streamer.getServer().getId(), currentSession.getChannel().getId());
|
||||
return channelService.editMessageInAChannelFuture(messagetoSend, streamer.getServer().getId(), currentSession.getChannel().getId(), currentSession.getId())
|
||||
.thenAccept(message -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeStreamerNotificationToChannel(Streamer streamer, Long channelId) {
|
||||
log.info("Changing notification channel of streamer {} to channel {} in server {}.", streamer.getId(), channelId, streamer.getServer().getId());
|
||||
if(channelId != null) {
|
||||
AChannel channel = channelManagementService.loadChannel(channelId);
|
||||
streamer.setNotificationChannel(channel);
|
||||
} else {
|
||||
streamer.setNotificationChannel(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disableNotificationsForStreamer(Streamer streamer, Boolean newState) {
|
||||
log.info("Setting notifications of streamer {} to {} in server {}.", streamer.getId(), newState, streamer.getServer().getId());
|
||||
streamer.setShowNotifications(newState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeStreamerMemberToUserId(Streamer streamer, Long userId) {
|
||||
log.info("Changing user id of streamer {} to channel {} in server {}.", streamer.getId(), userId, streamer.getServer().getId());
|
||||
if(userId != null) {
|
||||
AUserInAServer user = userInServerManagementService.loadOrCreateUser(streamer.getServer(), userId);
|
||||
streamer.setStreamerUser(user);
|
||||
} else {
|
||||
streamer.setStreamerUser(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeTemplateKeyTo(Streamer streamer, String templateKey) {
|
||||
log.info("Changing template key of streamer {} in server {}.", streamer.getId(), streamer.getServer().getId());
|
||||
streamer.setTemplateKey(templateKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListTwitchStreamerResponseModel getStreamersFromServer(Guild guild) {
|
||||
log.info("Loading streamers into a model for server {}.", guild.getIdLong());
|
||||
AServer server = serverManagementService.loadServer(guild.getIdLong());
|
||||
List<Streamer> streamers = streamerManagementService.getStreamersForServer(server);
|
||||
GuildMessageChannel postTargetChannel = postTargetService.getPostTargetChannel(TwitchPostTarget.TWITCH_LIVE_NOTIFICATION, server.getId()).orElse(null);
|
||||
List<TwitchStreamerDisplayModel> models = streamers
|
||||
.stream()
|
||||
.map(streamer -> {
|
||||
GuildMessageChannel notificationChannel;
|
||||
if(streamer.getNotificationChannel() != null) {
|
||||
notificationChannel = channelService.getMessageChannelFromServer(server.getId(), streamer.getNotificationChannel().getId());
|
||||
} else {
|
||||
notificationChannel = postTargetChannel;
|
||||
}
|
||||
return TwitchStreamerDisplayModel
|
||||
.builder()
|
||||
.name(streamer.getName())
|
||||
.targetChannel(ChannelDisplay.fromChannel(notificationChannel))
|
||||
.streamerURL(formatStreamUrl(streamer.getName()))
|
||||
.showNotifications(streamer.getShowNotifications())
|
||||
.build();
|
||||
|
||||
}).collect(Collectors.toList());
|
||||
return ListTwitchStreamerResponseModel
|
||||
.builder()
|
||||
.streamers(models)
|
||||
.build();
|
||||
}
|
||||
|
||||
private String formatStreamUrl(String name) {
|
||||
return String.format("https://twitch.tv/%s", name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
public void checkAndNotifyAboutOnlineStreamers() {
|
||||
log.info("Checking if stream notifications need to be sent.");
|
||||
List<AServer> servers = serverManagementService.getAllServers();
|
||||
List<AServer> serversWithEnabledFeature = servers
|
||||
.stream()
|
||||
.filter(server -> featureFlagService.isFeatureEnabled(twitchFeatureConfig, server))
|
||||
.toList();
|
||||
log.debug("Searching through {} servers for twitch notifications and {} have twitch feature enabled.", servers.size(), serversWithEnabledFeature.size());
|
||||
serversWithEnabledFeature.forEach(server -> {
|
||||
List<Streamer> streamersInServer = streamerManagementService.getStreamersForServer(server);
|
||||
Map<Long, Streamer> streamerIdMap = streamersInServer
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Streamer::getId, Function.identity()));
|
||||
Map<String, Streamer> streamerMap = streamersInServer
|
||||
.stream()
|
||||
.collect(Collectors.toMap(Streamer::getUserId, Function.identity()));
|
||||
log.debug("Found {} streamers for server {}.", streamersInServer.size(), server.getId());
|
||||
if(streamersInServer.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
List<String> userIds = streamersInServer
|
||||
.stream()
|
||||
.map(Streamer::getUserId)
|
||||
.distinct()
|
||||
.toList();
|
||||
List<Stream> streamsOfUsers = twitchService.getStreamsByUserIds(userIds);
|
||||
Set<Long> onlineStreamers = new HashSet<>();
|
||||
Map<Long, Boolean> updateNotificationFlagValues = new HashMap<>();
|
||||
streamsOfUsers.forEach(stream -> self.processOnlineStreamer(server, streamerMap, onlineStreamers, updateNotificationFlagValues, stream));
|
||||
Set<Long> allStreamersInServer = streamerIdMap.keySet();
|
||||
allStreamersInServer.removeAll(onlineStreamers); // then we have those that went offline
|
||||
Map<Long, Boolean> deleteFlagValues = new HashMap<>();
|
||||
allStreamersInServer.forEach(streamerId -> {
|
||||
Streamer streamer = streamerIdMap.get(streamerId);
|
||||
self.processOfflineStreamer(server, streamer, deleteFlagValues);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void processOfflineStreamer(AServer server, Streamer streamer, Map<Long, Boolean> deleteFlagValues) {
|
||||
Long streamerId = streamer.getId();
|
||||
if(!streamer.getOnline()) {
|
||||
return;
|
||||
}
|
||||
log.info("Streamer {} went offline.", streamerId);
|
||||
if (deleteFlagValues.computeIfAbsent(streamer.getServer().getId(),
|
||||
aLong -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, aLong, TwitchFeatureMode.DELETE_NOTIFICATION))) {
|
||||
Long channelId = streamer.getCurrentSession().getChannel().getId();
|
||||
Long messageId = streamer.getCurrentSession().getId();
|
||||
messageService.deleteMessageInChannelInServer(streamer.getServer().getId(), channelId, messageId).thenAccept(unused -> {
|
||||
log.info("Deleted notification message for streamer {}", streamerId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.warn("Failed to delete notification message for streamer {}", streamerId, throwable);
|
||||
return null;
|
||||
});
|
||||
} else {
|
||||
User streamerUser = twitchService.getStreamerById(streamer.getUserId());
|
||||
if(streamer.getCurrentSession() == null) {
|
||||
log.warn("No session found for streamer {} - nothing to update or delete.", streamer.getId());
|
||||
streamer.setCurrentSession(null);
|
||||
streamer.setOnline(false);
|
||||
streamer.setCurrentGameId(null);
|
||||
streamerManagementService.saveStreamer(streamer);
|
||||
return;
|
||||
}
|
||||
List<StreamSectionDisplay> pastSections = streamer
|
||||
.getCurrentSession()
|
||||
.getSections()
|
||||
.stream()
|
||||
.sorted(Comparator.comparing(StreamSessionSection::getId).reversed())
|
||||
.map(StreamSectionDisplay::fromSection)
|
||||
.toList();
|
||||
String offlineImageURL = StringUtils.isBlank(streamerUser.getOfflineImageUrl()) ? null : streamerUser.getOfflineImageUrl();
|
||||
GoOfflineNotificationModel model = GoOfflineNotificationModel
|
||||
.builder()
|
||||
.channelName(streamer.getName())
|
||||
.avatarURL(streamerUser.getProfileImageUrl())
|
||||
.offlineImageURL(offlineImageURL)
|
||||
.pastSections(pastSections)
|
||||
.build();
|
||||
log.info("Updating existing notification for streamer {} in server {}.", streamer.getId(), server.getId());
|
||||
MessageToSend messageToSend = templateService.renderEmbedTemplate(WENT_OFF_LINE_MESSAGE_TEMPLATE, model, server.getId());
|
||||
Long channelId = streamer.getCurrentSession().getChannel().getId();
|
||||
Long messageId = streamer.getCurrentSession().getId();
|
||||
channelService.editMessageInAChannelFuture(messageToSend, server.getId(), channelId, messageId).thenAccept(message -> {
|
||||
log.debug("Successfully updated notification {}.", messageId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.debug("Failed to update notification {}", messageId, throwable);
|
||||
return null;
|
||||
});
|
||||
if(!streamer.getName().equals(streamerUser.getLogin())) {
|
||||
streamer.setName(streamerUser.getLogin());
|
||||
}
|
||||
}
|
||||
streamer.setCurrentSession(null);
|
||||
streamer.setOnline(false);
|
||||
streamer.setCurrentGameId(null);
|
||||
streamerManagementService.saveStreamer(streamer);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void processOnlineStreamer(AServer server, Map<String, Streamer> streamerMap, Set<Long> onlineStreamers, Map<Long, Boolean> updateNotificationFlagValues, Stream stream) {
|
||||
Streamer streamer = streamerMap.get(stream.getUserId());
|
||||
Long streamerId = streamer.getId();
|
||||
onlineStreamers.add(streamerId);
|
||||
// it could be that the streamer is already online, but we have no sessions yet
|
||||
// that is the case if you add an online streamer
|
||||
User streamerUser = twitchService.getStreamerById(stream.getUserId());
|
||||
StreamSession currentSession = streamer.getCurrentSession();
|
||||
if (Boolean.TRUE.equals(streamer.getOnline()) && currentSession != null) {
|
||||
// we already know that this streamer is online
|
||||
log.debug("Not notifying for streamer {} in server {} - streamer is already online.", streamerId, server.getId());
|
||||
if(!stream.getGameId().equals(streamer.getCurrentGameId())) {
|
||||
log.info("Streamer {} changed game from {} to {} - storing new section.", streamerId, streamer.getCurrentGameId(), stream.getGameId());
|
||||
streamSessionSectionService.createSectionFromStream(currentSession, stream);
|
||||
if (updateNotificationFlagValues.computeIfAbsent(streamer.getServer().getId(),
|
||||
aLong -> featureModeService.featureModeActive(TwitchFeatureDefinition.TWITCH, aLong, TwitchFeatureMode.UPDATE_NOTIFICATION))) {
|
||||
log.info("Updating notification is enabled - updating notification for streamer {}.", streamer.getId());
|
||||
Long notificationMessageId = currentSession.getId();
|
||||
Long notificationChannelId = currentSession.getChannel().getId();
|
||||
Long serverId = streamer.getServer().getId();
|
||||
updateExistingNotification(stream, streamer, streamerUser).thenAccept(unused -> {
|
||||
log.info("Updating existing notification {} for server {} in channel {} about streamer {}.",
|
||||
notificationMessageId, serverId, notificationChannelId, streamerId);
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to update existing notification {} for server {} in channel {} about streamer {}.",
|
||||
notificationMessageId, serverId, notificationChannelId, streamerId, throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
streamer.setCurrentGameId(stream.getGameId());
|
||||
}
|
||||
return;
|
||||
}
|
||||
CompletableFutureList<Message> messages = notifyAboutOnlineStream(stream, streamer, streamerUser);
|
||||
messages.getMainFuture()
|
||||
.thenAccept(unused -> {
|
||||
Message message = messages.getFutures().get(0).join();
|
||||
if(message != null) {
|
||||
try {
|
||||
self.storeStreamNotificationMessage(message, streamerId, stream);
|
||||
} catch (Exception exception) {
|
||||
log.error("Failed to store stream notification message of streamer {}.", streamerId, exception);
|
||||
}
|
||||
}
|
||||
}).exceptionally(throwable -> {
|
||||
log.error("Failed to notify about online stream of streamer {}.", streamerId, throwable);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void storeStreamNotificationMessage(Message message, Long streamerId, Stream stream) {
|
||||
log.info("Storing notification for streamer {} in in server {} in channel {} using message {}.",
|
||||
streamerId, message.getGuild().getIdLong(), message.getChannel().getIdLong(), message.getIdLong());
|
||||
Optional<Streamer> streamerOptional = streamerManagementService.getStreamerById(streamerId);
|
||||
streamerOptional.
|
||||
ifPresent(streamer -> {
|
||||
streamer.setCurrentGameId(stream.getGameId());
|
||||
StreamSession session = streamSessionManagementService.startSession(streamer, message.getIdLong(), message.getChannel().getIdLong(), stream);
|
||||
streamer.setCurrentSession(session);
|
||||
streamer.setOnline(true);
|
||||
if(!streamer.getName().equals(stream.getUserLogin())) {
|
||||
streamer.setName(stream.getUserLogin());
|
||||
}
|
||||
streamSessionSectionService.createSectionFromStream(session, stream);
|
||||
streamerManagementService.saveStreamer(streamer);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package dev.sheldan.abstracto.twitch.service;
|
||||
|
||||
import com.github.philippheuer.credentialmanager.domain.OAuth2Credential;
|
||||
import com.github.twitch4j.ITwitchClient;
|
||||
import com.github.twitch4j.auth.providers.TwitchIdentityProvider;
|
||||
import com.github.twitch4j.helix.domain.Stream;
|
||||
import com.github.twitch4j.helix.domain.User;
|
||||
import dev.sheldan.abstracto.twitch.exception.StreamerNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class TwitchServiceBean implements TwitchService {
|
||||
|
||||
@Autowired
|
||||
private ITwitchClient twitchClient;
|
||||
|
||||
@Autowired
|
||||
private TwitchIdentityProvider identityProvider;
|
||||
|
||||
@Autowired
|
||||
private OAuth2Credential oAuth2Credential;
|
||||
|
||||
@Override
|
||||
public User getStreamerByName(String name) {
|
||||
return getStreamerByNameOptional(name).orElseThrow(StreamerNotFoundException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<User> getStreamerByNameOptional(String name) {
|
||||
List<User> allUsersWithName = twitchClient.getClientHelper().getTwitchHelix().getUsers(null, null, Collections.singletonList(name)).execute().getUsers();
|
||||
if(allUsersWithName.size() != 1) {
|
||||
return Optional.empty();
|
||||
} else {
|
||||
return Optional.of(allUsersWithName.get(0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public User getStreamerById(String userId) {
|
||||
return twitchClient.getClientHelper().getTwitchHelix().getUsers(null, Collections.singletonList(userId), null).execute().getUsers().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Stream> getStreamsByUserIds(List<String> userIds) {
|
||||
return twitchClient.getClientHelper().getTwitchHelix().getStreams(null, null, null, null, null, null, userIds, null).execute().getStreams();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Stream> getStreamOfUser(String userId) {
|
||||
List<Stream> allStreams = getStreamsByUserIds(Arrays.asList(userId));
|
||||
return allStreams.stream().findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Stream> getStreamsByUserIdsMapped(List<String> userIds) {
|
||||
return getStreamsByUserIds(userIds).stream().collect(Collectors.toMap(Stream::getUserId, Function.identity()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshToken() {
|
||||
oAuth2Credential.updateCredential(identityProvider.getAppAccessToken());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package dev.sheldan.abstracto.twitch.service;
|
||||
|
||||
import com.github.philippheuer.credentialmanager.domain.OAuth2Credential;
|
||||
import com.github.twitch4j.ITwitchClient;
|
||||
import com.github.twitch4j.TwitchClientBuilder;
|
||||
import com.github.twitch4j.auth.providers.TwitchIdentityProvider;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TwitchServiceConfig {
|
||||
|
||||
@Value("${abstracto.feature.twitch.clientId}")
|
||||
private String twitchClientId;
|
||||
|
||||
@Value("${abstracto.feature.twitch.clientSecret}")
|
||||
private String twitchSecret;
|
||||
|
||||
@Bean
|
||||
public TwitchIdentityProvider twitchIdentityProvider() {
|
||||
return new TwitchIdentityProvider(twitchClientId, twitchSecret, null);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public OAuth2Credential credential(TwitchIdentityProvider tip) {
|
||||
return tip.getAppAccessToken();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ITwitchClient twitchClient(OAuth2Credential oAuth2Credential) {;
|
||||
return TwitchClientBuilder.builder()
|
||||
.withClientId(twitchClientId)
|
||||
.withClientSecret(twitchSecret)
|
||||
.withDefaultAuthToken(oAuth2Credential)
|
||||
.withEnableHelix(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sheldan.abstracto.twitch.service.management;
|
||||
|
||||
import com.github.twitch4j.helix.domain.Stream;
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.service.management.ChannelManagementService;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
|
||||
import dev.sheldan.abstracto.twitch.repository.StreamSessionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class StreamSessionManagementServiceBean implements StreamSessionManagementService {
|
||||
|
||||
@Autowired
|
||||
private StreamSessionRepository repository;
|
||||
|
||||
@Autowired
|
||||
private ChannelManagementService channelManagementService;
|
||||
|
||||
@Override
|
||||
public StreamSession startSession(Streamer streamer, Long messageId, Long channelId, Stream stream) {
|
||||
AChannel channel = channelManagementService.loadChannel(channelId);
|
||||
StreamSession notification = StreamSession
|
||||
.builder()
|
||||
.id(messageId)
|
||||
.startTime(stream.getStartedAtInstant())
|
||||
.channel(channel)
|
||||
.streamer(streamer)
|
||||
.streamId(stream.getId())
|
||||
.build();
|
||||
return repository.save(notification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSessionsOfStreamer(Streamer streamer) {
|
||||
repository.deleteAll(streamer.getSessions());
|
||||
streamer.getSessions().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSession(StreamSession notification) {
|
||||
notification.getStreamer().getSessions().remove(notification);
|
||||
repository.delete(notification);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSession(Streamer streamer, Long messageId) {
|
||||
streamer.getSessions().removeIf(notification -> notification.getId().equals(messageId));
|
||||
repository.deleteById(messageId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.twitch.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSession;
|
||||
import dev.sheldan.abstracto.twitch.model.database.StreamSessionSection;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import dev.sheldan.abstracto.twitch.repository.StreamSessionSectionRepository;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class StreamSessionSectionManagementServiceBean implements StreamSessionSectionManagementService {
|
||||
|
||||
@Autowired
|
||||
private StreamSessionSectionRepository repository;
|
||||
|
||||
@Override
|
||||
public StreamSessionSection addSection(StreamSession session, String gameId, String gameName, Instant startTime, String title, Integer viewerCount) {
|
||||
StreamSessionSection section = StreamSessionSection
|
||||
.builder()
|
||||
.streamer(session.getStreamer())
|
||||
.gameId(gameId)
|
||||
.gameName(gameName)
|
||||
.title(title)
|
||||
.viewerCount(viewerCount)
|
||||
.session(session)
|
||||
.build();
|
||||
return repository.save(section);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSectionsOfSession(StreamSession session) {
|
||||
repository.deleteAll(session.getSections());
|
||||
session.getSections().clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteSectionsOfStreamer(Streamer streamer) {
|
||||
List<StreamSessionSection> sections = streamer
|
||||
.getSessions()
|
||||
.stream()
|
||||
.flatMap(session -> session.getSections().stream())
|
||||
.toList();
|
||||
repository.deleteAll(sections);
|
||||
streamer.getSessions().forEach(session -> {
|
||||
session.getSections().clear();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package dev.sheldan.abstracto.twitch.service.management;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import dev.sheldan.abstracto.twitch.exception.StreamerExistsException;
|
||||
import dev.sheldan.abstracto.twitch.model.database.Streamer;
|
||||
import dev.sheldan.abstracto.twitch.repository.StreamerRepository;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class StreamerManagementServiceBean implements StreamerManagementService {
|
||||
|
||||
@Autowired
|
||||
private StreamerRepository streamerRepository;
|
||||
|
||||
@Override
|
||||
public Streamer createStreamer(String id, String name, AChannel targetChannel, AUserInAServer creator, AUserInAServer member, Boolean isOnline) {
|
||||
Streamer streamer = Streamer
|
||||
.builder()
|
||||
.name(name)
|
||||
.showNotifications(true)
|
||||
.userId(id)
|
||||
.online(isOnline)
|
||||
.creator(creator)
|
||||
.server(creator.getServerReference())
|
||||
.streamerUser(member)
|
||||
.notificationChannel(targetChannel)
|
||||
.build();
|
||||
log.info("Creating streamer {} because of user {} in server {}.", id, creator.getServerReference().getId(), creator.getUserReference().getId());
|
||||
return streamerRepository.save(streamer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStreamer(String id) {
|
||||
streamerRepository.deleteByUserId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Streamer> getStreamerById(Long id) {
|
||||
return streamerRepository.findById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeStreamer(Streamer streamer) {
|
||||
streamerRepository.delete(streamer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveStreamer(Streamer streamer) {
|
||||
streamerRepository.save(streamer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Streamer getStreamerInServerById(String id, Long serverId) {
|
||||
return streamerRepository.findByServer_IdAndUserId(serverId, id)
|
||||
.orElseThrow(StreamerExistsException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Streamer> getStreamerInServers(String id) {
|
||||
return streamerRepository.getByUserId(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean streamerExistsInServerByID(String id, AServer server) {
|
||||
return streamerRepository.existsByServerAndUserId(server, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean streamerExistsInServerByName(String name, AServer server) {
|
||||
return streamerRepository.existsByServerAndName(server, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Streamer> getStreamerInServerByName(String name, AServer server) {
|
||||
return streamerRepository.findByServerAndName(server, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Streamer> getStreamersForServer(AServer server) {
|
||||
return streamerRepository.getStreamerByServer(server);
|
||||
}
|
||||
}
|
||||
@@ -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="seedData/data.xml" relativeToChangelogFile="true"/>
|
||||
<include file="tables/tables.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?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="twitchFeature" value="(SELECT id FROM feature WHERE key = 'twitch')"/>
|
||||
|
||||
<changeSet author="Sheldan" id="twitch-commands">
|
||||
<insert tableName="command">
|
||||
<column name="name" value="addTwitchStreamer"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${twitchFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="listTwitchStreamer"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${twitchFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="changeTwitchStreamer"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${twitchFeature}"/>
|
||||
</insert>
|
||||
<insert tableName="command">
|
||||
<column name="name" value="removeTwitchStreamer"/>
|
||||
<column name="module_id" valueComputed="${utilityModule}"/>
|
||||
<column name="feature_id" valueComputed="${twitchFeature}"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,13 @@
|
||||
<?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="feature.xml" relativeToChangelogFile="true"/>
|
||||
<include file="command.xml" relativeToChangelogFile="true"/>
|
||||
<include file="streamer_online_check_job.xml" relativeToChangelogFile="true"/>
|
||||
<include file="twitch_refresh_token_job.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns: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="twitch_feature-insertion">
|
||||
<insert tableName="feature">
|
||||
<column name="key" value="twitch"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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="streamer_online_check_job-insert">
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="streamerOnlineCheckJob"/>
|
||||
<column name="group_name" value="twitch"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.twitch.job.StreamerOnlineCheckJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="cron_expression" value="0 * * * * ?"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,21 @@
|
||||
<?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="twitch_refresh_token_job-insert">
|
||||
<insert tableName="scheduler_job">
|
||||
<column name="name" value="twitchRefreshTokenJob"/>
|
||||
<column name="group_name" value="twitch"/>
|
||||
<column name="clazz" value="dev.sheldan.abstracto.twitch.job.TwitchRefreshTokenJob"/>
|
||||
<column name="active" value="true"/>
|
||||
<column name="cron_expression" value="55 0 0 * * ?"/>
|
||||
<column name="recovery" value="false"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,58 @@
|
||||
<?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="stream_session-table">
|
||||
<createTable tableName="stream_session">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="streamer_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="stream_id" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="channel_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="start_time" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint baseColumnNames="streamer_id" baseTableName="stream_session" constraintName="fk_stream_session_streamer"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="streamer" validate="true"/>
|
||||
|
||||
<addForeignKeyConstraint baseColumnNames="channel_id" baseTableName="stream_session" constraintName="fk_stream_session_channel"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="channel" validate="true"/>
|
||||
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS stream_session_update_trigger ON stream_session;
|
||||
CREATE TRIGGER stream_session_update_trigger BEFORE UPDATE ON stream_session FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS stream_session_insert_trigger ON stream_session;
|
||||
CREATE TRIGGER stream_session_insert_trigger BEFORE INSERT ON stream_session FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
<addColumn tableName="streamer">
|
||||
<column name="current_session_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseColumnNames="current_session_id" baseTableName="streamer" constraintName="fk_streamer_current_session"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="stream_session" validate="true"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,56 @@
|
||||
<?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="stream_session_section-table">
|
||||
<createTable tableName="stream_session_section">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="stream_session_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="streamer_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="game_id" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="game_name" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="viewer_count" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="title" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
|
||||
</createTable>
|
||||
|
||||
<addForeignKeyConstraint baseColumnNames="streamer_id" baseTableName="stream_session_section" constraintName="fk_stream_session_section_streamer"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="streamer" validate="true"/>
|
||||
|
||||
<addForeignKeyConstraint baseColumnNames="stream_session_id" baseTableName="stream_session_section" constraintName="fk_stream_session_section_session"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="stream_session" validate="true"/>
|
||||
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS stream_session_section_update_trigger ON stream_session_section;
|
||||
CREATE TRIGGER stream_session_section_update_trigger BEFORE UPDATE ON stream_session_section FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS stream_session_section_insert_trigger ON stream_session_section;
|
||||
CREATE TRIGGER stream_session_section_insert_trigger BEFORE INSERT ON stream_session_section FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,75 @@
|
||||
<?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="streamer-table">
|
||||
<createTable tableName="streamer">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="user_id" type="VARCHAR(128)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="template_key" type="VARCHAR(128)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="name" type="VARCHAR(255)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="notification_channel_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="creator_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="streamer_user_in_server_id" type="BIGINT">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="server_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="current_game_id" type="VARCHAR(255)">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
<column name="online" type="BOOLEAN">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="created" type="TIMESTAMP WITHOUT TIME ZONE">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="updated" type="TIMESTAMP WITHOUT TIME ZONE"/>
|
||||
<column name="show_notifications" type="BOOLEAN">
|
||||
<constraints nullable="true"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<addUniqueConstraint
|
||||
columnNames="user_id, server_id"
|
||||
constraintName="uq_streamer_id"
|
||||
tableName="streamer"
|
||||
/>
|
||||
<addForeignKeyConstraint baseColumnNames="notification_channel_id" baseTableName="streamer" constraintName="fk_streamer_notification_channel"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="channel" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="creator_user_in_server_id" baseTableName="streamer" constraintName="fk_streamer_creator"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="streamer_user_in_server_id" baseTableName="streamer" constraintName="fk_streamer_user"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="user_in_server_id" referencedTableName="user_in_server" validate="true"/>
|
||||
<addForeignKeyConstraint baseColumnNames="server_id" baseTableName="streamer" constraintName="fk_streamer_server"
|
||||
deferrable="false" initiallyDeferred="false" onDelete="NO ACTION" onUpdate="NO ACTION"
|
||||
referencedColumnNames="id" referencedTableName="server" validate="true"/>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS streamer_update_trigger ON streamer;
|
||||
CREATE TRIGGER streamer_update_trigger BEFORE UPDATE ON streamer FOR EACH ROW EXECUTE PROCEDURE update_trigger_procedure();
|
||||
</sql>
|
||||
<sql>
|
||||
DROP TRIGGER IF EXISTS streamer_insert_trigger ON streamer;
|
||||
CREATE TRIGGER streamer_insert_trigger BEFORE INSERT ON streamer FOR EACH ROW EXECUTE PROCEDURE insert_trigger_procedure();
|
||||
</sql>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?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="streamer.xml" relativeToChangelogFile="true"/>
|
||||
<include file="stream_session.xml" relativeToChangelogFile="true"/>
|
||||
<include file="stream_session_section.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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="1.4.27/collection.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,15 @@
|
||||
abstracto.featureFlags.twitch.featureName=twitch
|
||||
abstracto.featureFlags.twitch.enabled=false
|
||||
|
||||
abstracto.postTargets.twitchLiveNotification.name=twitchLiveNotification
|
||||
|
||||
abstracto.feature.twitch.clientId=${TWITCH_CLIENT_ID}
|
||||
abstracto.feature.twitch.clientSecret=${TWITCH_SECRET}
|
||||
|
||||
abstracto.featureModes.deleteNotification.featureName=twitch
|
||||
abstracto.featureModes.deleteNotification.mode=deleteNotification
|
||||
abstracto.featureModes.deleteNotification.enabled=true
|
||||
|
||||
abstracto.featureModes.updateNotification.featureName=twitch
|
||||
abstracto.featureModes.updateNotification.mode=updateNotification
|
||||
abstracto.featureModes.updateNotification.enabled=true
|
||||
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>dev.sheldan.abstracto.modules</groupId>
|
||||
<artifactId>twitch</artifactId>
|
||||
<version>1.4.27-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>twitch-int</artifactId>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.twitch4j</groupId>
|
||||
<artifactId>twitch4j</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>8</maven.compiler.source>
|
||||
<maven.compiler.target>8</maven.compiler.target>
|
||||
</properties>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,28 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureConfig;
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class TwitchFeatureConfig implements FeatureConfig {
|
||||
@Override
|
||||
public FeatureDefinition getFeature() {
|
||||
return TwitchFeatureDefinition.TWITCH;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PostTargetEnum> getRequiredPostTargets() {
|
||||
return Arrays.asList(TwitchPostTarget.TWITCH_LIVE_NOTIFICATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<FeatureMode> getAvailableModes() {
|
||||
return Arrays.asList(TwitchFeatureMode.DELETE_NOTIFICATION, TwitchFeatureMode.UPDATE_NOTIFICATION);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureDefinition;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum TwitchFeatureDefinition implements FeatureDefinition {
|
||||
TWITCH("twitch");
|
||||
|
||||
private String key;
|
||||
|
||||
TwitchFeatureDefinition(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.FeatureMode;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum TwitchFeatureMode implements FeatureMode {
|
||||
DELETE_NOTIFICATION("deleteNotification"), UPDATE_NOTIFICATION("updateNotification");
|
||||
|
||||
private final String key;
|
||||
|
||||
TwitchFeatureMode(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
import dev.sheldan.abstracto.core.config.PostTargetEnum;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public enum TwitchPostTarget implements PostTargetEnum {
|
||||
TWITCH_LIVE_NOTIFICATION("twitchLiveNotification");
|
||||
|
||||
private String key;
|
||||
|
||||
TwitchPostTarget(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package dev.sheldan.abstracto.twitch.config;
|
||||
|
||||
public class TwitchSlashCommandNames {
|
||||
private TwitchSlashCommandNames() {
|
||||
|
||||
}
|
||||
public static final String TWITCH = "twitch";
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.twitch.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class StreamerExistsException extends AbstractoRunTimeException implements Templatable {
|
||||
public StreamerExistsException() {
|
||||
super("Streamer is already setup in server.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "streamer_already_exists_in_server_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.twitch.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class StreamerNotFoundException extends AbstractoRunTimeException implements Templatable {
|
||||
public StreamerNotFoundException() {
|
||||
super("Streamer was not found on Twitch..");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "streamer_not_exists_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package dev.sheldan.abstracto.twitch.exception;
|
||||
|
||||
import dev.sheldan.abstracto.core.exception.AbstractoRunTimeException;
|
||||
import dev.sheldan.abstracto.core.templating.Templatable;
|
||||
|
||||
public class StreamerNotFoundInServerException extends AbstractoRunTimeException implements Templatable {
|
||||
public StreamerNotFoundInServerException() {
|
||||
super("Streamer was not set up in server.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTemplateName() {
|
||||
return "streamer_not_exists_in_server_exception";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getTemplateModel() {
|
||||
return new Object();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package dev.sheldan.abstracto.twitch.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import lombok.*;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="stream_session")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StreamSession {
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "streamer_id", nullable = false)
|
||||
private Streamer streamer;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "channel_id", nullable = false)
|
||||
private AChannel channel;
|
||||
|
||||
@Column(name = "stream_id", nullable = false)
|
||||
private String streamId;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
|
||||
@Column(name = "startTime", nullable = false)
|
||||
private Instant startTime;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "session")
|
||||
@Builder.Default
|
||||
private List<StreamSessionSection> sections = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package dev.sheldan.abstracto.twitch.model.database;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import lombok.*;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
@Entity
|
||||
@Table(name="stream_session_section")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class StreamSessionSection {
|
||||
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
@Column(name = "id", nullable = false)
|
||||
private Long id;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "streamer_id", nullable = false)
|
||||
private Streamer streamer;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "stream_session_id", nullable = false)
|
||||
private StreamSession session;
|
||||
|
||||
@Column(name = "game_id", nullable = false)
|
||||
private String gameId;
|
||||
|
||||
@Column(name = "game_name", nullable = false)
|
||||
private String gameName;
|
||||
|
||||
@Column(name = "viewer_count", nullable = false)
|
||||
private Integer viewerCount;
|
||||
|
||||
@Column(name = "title", nullable = false)
|
||||
private String title;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package dev.sheldan.abstracto.twitch.model.database;
|
||||
|
||||
import dev.sheldan.abstracto.core.models.database.AChannel;
|
||||
import dev.sheldan.abstracto.core.models.database.AServer;
|
||||
import dev.sheldan.abstracto.core.models.database.AUserInAServer;
|
||||
import lombok.*;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Entity
|
||||
@Table(name="streamer")
|
||||
@Builder
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@EqualsAndHashCode
|
||||
public class Streamer {
|
||||
@Id
|
||||
@Column(name = "id", nullable = false)
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "user_id", nullable = false)
|
||||
private String userId;
|
||||
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
@Column(name = "template_key")
|
||||
private String templateKey;
|
||||
|
||||
@Column(name = "current_game_id")
|
||||
private String currentGameId;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "notification_channel_id")
|
||||
private AChannel notificationChannel;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "creator_user_in_server_id", nullable = false)
|
||||
private AUserInAServer creator;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "server_id", nullable = false)
|
||||
private AServer server;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "streamer_user_in_server_id")
|
||||
private AUserInAServer streamerUser;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@OneToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_session_id")
|
||||
private StreamSession currentSession;
|
||||
|
||||
@Column(name = "show_notifications", nullable = false)
|
||||
private Boolean showNotifications;
|
||||
|
||||
@Column(name = "online", nullable = false)
|
||||
private Boolean online;
|
||||
|
||||
@Column(name = "created", nullable = false, insertable = false, updatable = false)
|
||||
private Instant created;
|
||||
|
||||
@Column(name = "updated", insertable = false, updatable = false)
|
||||
private Instant updated;
|
||||
|
||||
@EqualsAndHashCode.Exclude
|
||||
@OneToMany(
|
||||
fetch = FetchType.LAZY,
|
||||
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
|
||||
mappedBy = "streamer")
|
||||
@Builder.Default
|
||||
private List<StreamSession> sessions = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package dev.sheldan.abstracto.twitch.model.template;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Builder
|
||||
@Getter
|
||||
public class GoLiveNotificationModel {
|
||||
private String channelName;
|
||||
private StreamSectionDisplay currentSection;
|
||||
private List<StreamSectionDisplay> pastSections;
|
||||
private Boolean mature;
|
||||
private String streamURL;
|
||||
private String streamerAvatarURL;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user