Compare commits

..

No commits in common. "e5db36d558e589d58788999a114a3fee7f039359" and "c0146fa0c3af26b9b6e21e8ab504a4df5582591a" have entirely different histories.

111 changed files with 2786 additions and 554 deletions

View File

@ -4,7 +4,6 @@ plugins {
id 'java' id 'java'
id 'groovy' id 'groovy'
id 'org.liquibase.gradle' version '2.0.4' id 'org.liquibase.gradle' version '2.0.4'
id "nebula.lint" version "16.9.0"
} }
@ -36,33 +35,41 @@ dependencies {
implementation("org.springframework.boot:spring-boot-starter-web") implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-security") implementation("org.springframework.boot:spring-boot-starter-security")
implementation("org.springframework.boot:spring-boot-starter-data-jpa") implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-log4j2") implementation("org.springframework.boot:spring-boot-starter-log4j2")
implementation("org.springframework.boot:spring-boot-starter-oauth2-client") implementation("org.springframework.boot:spring-boot-starter-oauth2-client")
implementation('org.springdoc:springdoc-openapi-ui:1.6.9') implementation("org.springdoc:springdoc-openapi-ui:1.6.8")
implementation('org.springdoc:springdoc-openapi-security:1.6.9') implementation("org.springdoc:springdoc-openapi-security:1.6.8")
implementation('org.liquibase:liquibase-core') implementation('org.liquibase:liquibase-core')
implementation('io.jsonwebtoken:jjwt-api:0.11.5') implementation('io.jsonwebtoken:jjwt-api:0.11.5')
implementation('io.jsonwebtoken:jjwt-impl:0.11.5') implementation('io.jsonwebtoken:jjwt-impl:0.11.5')
implementation('io.jsonwebtoken:jjwt-jackson:0.11.5') implementation('io.jsonwebtoken:jjwt-gson:0.11.5')
implementation 'org.codehaus.groovy:groovy-all:3.0.8'
implementation 'com.sedmelluq:lavaplayer:1.3.77' implementation 'com.sedmelluq:lavaplayer:1.3.77'
implementation 'net.dv8tion:JDA:4.4.0_350' implementation 'net.dv8tion:JDA:4.4.0_350'
implementation group: 'org.json', name: 'json', version: '20210307'
// JPA Data (We are going to use Repositories, Entities, Hibernate, etc...)
implementation(platform("org.apache.logging.log4j:log4j-bom:2.17.1")) implementation(platform("org.apache.logging.log4j:log4j-bom:2.17.1"))
implementation group: 'org.hibernate', name: 'hibernate-validator', version: '7.0.4.Final' implementation group: 'org.hibernate', name: 'hibernate-validator', version: '7.0.4.Final'
// Use MySQL Connector-J // Use MySQL Connector-J
implementation 'mysql:mysql-connector-java:8.0.29' implementation 'mysql:mysql-connector-java'
implementation 'org.reflections:reflections:0.10.2' implementation 'org.reflections:reflections:0.9.12'
implementation 'org.apache.commons:commons-lang3:3.12.0' implementation 'org.apache.commons:commons-lang3:3.12.0'
implementation 'com.google.api-client:google-api-client:1.31.5'
implementation 'com.google.apis:google-api-services-youtube:v3-rev20210410-1.31.0'
implementation group: 'org.jsoup', name: 'jsoup', version: '1.13.1'
liquibaseRuntime 'org.liquibase:liquibase-core:4.8.0' liquibaseRuntime 'org.liquibase:liquibase-core:4.2.2'
liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:3.0.2' liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.1.1'
liquibaseRuntime 'mysql:mysql-connector-java:8.0.29' liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'
liquibaseRuntime group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1' liquibaseRuntime group: 'javax.xml.bind', name: 'jaxb-api', version: '2.3.1'
liquibaseRuntime group: 'org.liquibase.ext', name: 'liquibase-hibernate5', version: '4.10.0' liquibaseRuntime group: 'org.liquibase.ext', name: 'liquibase-hibernate5', version: '4.10.0'
liquibaseRuntime 'org.springframework.boot:spring-boot-starter-data-jpa' liquibaseRuntime 'org.springframework.boot:spring-boot-starter-data-jpa'

View File

@ -1,6 +1,5 @@
package net.Broken.Api.Controllers; package net.Broken.Api.Controllers;
import net.Broken.Api.Data.Music.Add;
import net.Broken.Api.Data.Music.Connect; import net.Broken.Api.Data.Music.Connect;
import net.Broken.Api.Data.Music.Status; import net.Broken.Api.Data.Music.Status;
import net.Broken.Api.Security.Data.JwtPrincipal; import net.Broken.Api.Security.Data.JwtPrincipal;
@ -10,8 +9,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import java.util.concurrent.ExecutionException;
@RestController @RestController
@RequestMapping("/api/v2/audio") @RequestMapping("/api/v2/audio")
@CrossOrigin(origins = "*", maxAge = 3600) @CrossOrigin(origins = "*", maxAge = 3600)
@ -26,7 +23,7 @@ public class AudioController {
@GetMapping("/{guildId}/status") @GetMapping("/{guildId}/status")
@PreAuthorize("isInGuild(#guildId)") @PreAuthorize("isInGuild(#guildId)")
public Status getMusicStatus(@PathVariable String guildId, Authentication authentication) { public Status getMusicStatus(@PathVariable String guildId, Authentication authentication){
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.getGuildAudioStatus(guildId, principal.user().getDiscordId()); return audioService.getGuildAudioStatus(guildId, principal.user().getDiscordId());
} }
@ -34,50 +31,7 @@ public class AudioController {
@PostMapping("/{guildId}/connect") @PostMapping("/{guildId}/connect")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId, #body)") @PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId, #body)")
public ResponseEntity<Status> connect(@PathVariable String guildId, @RequestBody Connect body, Authentication authentication) { public ResponseEntity<String> connect(@PathVariable String guildId, @RequestBody Connect body){
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); return audioService.connect(guildId, body);
return audioService.connect(guildId, body, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/disconnect")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> disconnect(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.disconnect(guildId, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/resume")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> resume(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.resume(guildId, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/pause")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> pause(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.pause(guildId, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/skip")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> skip(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.skip(guildId, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/stop")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> stop(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.stop(guildId, principal.user().getDiscordId());
}
@PostMapping("/{guildId}/add")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> add(@PathVariable String guildId, @RequestBody Add body, Authentication authentication) throws ExecutionException, InterruptedException {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.add(guildId, principal.user().getDiscordId(), body);
} }
} }

View File

@ -11,6 +11,8 @@ import org.springframework.security.core.Authentication;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
@RestController @RestController
@RequestMapping("/api/v2/auth") @RequestMapping("/api/v2/auth")
@CrossOrigin(origins = "*", maxAge = 3600) @CrossOrigin(origins = "*", maxAge = 3600)
@ -25,6 +27,7 @@ public class AuthController {
} }
@PostMapping("/discord") @PostMapping("/discord")
@SecurityRequirements(value = {})
public JwtResponse loginDiscord(@Validated @RequestBody Login login) { public JwtResponse loginDiscord(@Validated @RequestBody Login login) {
Authentication authentication = authenticationManager.authenticate( Authentication authentication = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(login.redirectUri(), login.code()) new UsernamePasswordAuthenticationToken(login.redirectUri(), login.code())

View File

@ -1,6 +1,5 @@
package net.Broken.Api.Controllers; package net.Broken.Api.Controllers;
import io.swagger.v3.oas.annotations.Hidden;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
@ -8,6 +7,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import io.swagger.v3.oas.annotations.Hidden;
@RestController @RestController
@RequestMapping("/api/v2") @RequestMapping("/api/v2")
@ -22,7 +23,7 @@ public class CrossOptionController {
value = "/**", value = "/**",
method = RequestMethod.OPTIONS method = RequestMethod.OPTIONS
) )
public ResponseEntity<String> handle() { public ResponseEntity handle() {
return new ResponseEntity<>("",HttpStatus.OK); return new ResponseEntity(HttpStatus.OK);
} }
} }

View File

@ -1,9 +1,9 @@
package net.Broken.Api.Controllers; package net.Broken.Api.Controllers;
import net.Broken.Api.Data.Guild.Channel;
import net.Broken.Api.Data.Guild.Guild; import net.Broken.Api.Data.Guild.Guild;
import net.Broken.Api.Data.Guild.Role; import net.Broken.Api.Data.Guild.Role;
import net.Broken.Api.Data.InviteLink; import net.Broken.Api.Data.InviteLink;
import net.Broken.Api.Data.Guild.Channel;
import net.Broken.Api.Security.Data.JwtPrincipal; import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.Api.Services.GuildService; import net.Broken.Api.Services.GuildService;
import net.Broken.MainBot; import net.Broken.MainBot;

View File

@ -1,6 +1,11 @@
package net.Broken.Api.Controllers; package net.Broken.Api.Controllers;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.security.SecurityRequirements;
import net.Broken.Api.Security.Data.JwtPrincipal; import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.DB.Entity.UserEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;

View File

@ -1,4 +0,0 @@
package net.Broken.Api.Data.Music;
public record Add(String url) {
}

View File

@ -2,12 +2,10 @@ package net.Broken.Api.Data.Music;
import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonInclude;
import net.Broken.Api.Data.Guild.Channel; import net.Broken.Api.Data.Guild.Channel;
import net.dv8tion.jda.api.audio.hooks.ConnectionStatus;
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public record Status( public record Status(
Boolean connected, Boolean connected,
ConnectionStatus connectionStatus,
Channel channel, Channel channel,
Boolean canView, Boolean canView,
Boolean canInteract, Boolean canInteract,

View File

@ -2,9 +2,13 @@ package net.Broken.Api.Data.Music;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.Api.Data.UserInfo; import net.Broken.Api.Data.UserInfo;
import net.Broken.Audio.UserAudioTrack; import net.Broken.audio.UserAudioTrack;
public record TrackInfo(UserInfo submitter, AudioTrackInfo detail) { public record TrackInfo(UserInfo submitter, AudioTrackInfo detail) {
public TrackInfo(UserInfo submitter, AudioTrackInfo detail) {
this.submitter = submitter;
this.detail = detail;
}
public TrackInfo(UserAudioTrack userAudioTrack) { public TrackInfo(UserAudioTrack userAudioTrack) {
this(new UserInfo(userAudioTrack.getSubmittedUser().getId(), userAudioTrack.getSubmittedUser().getName(), userAudioTrack.getSubmittedUser().getAvatarUrl()), this(new UserInfo(userAudioTrack.getSubmittedUser().getId(), userAudioTrack.getSubmittedUser().getName(), userAudioTrack.getSubmittedUser().getAvatarUrl()),

View File

@ -5,6 +5,7 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.security.SecurityRequirement; import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme; import io.swagger.v3.oas.models.security.SecurityScheme;
import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.oas.models.servers.Server;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;

View File

@ -8,6 +8,7 @@ import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint; import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
@ -19,7 +20,7 @@ public class UnauthorizedHandler implements AuthenticationEntryPoint {
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
@Override @Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException { public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
logger.error("[API] Unauthorized error: {}", authException.getMessage()); logger.error("[API] Unauthorized error: {}", authException.getMessage());
response.setContentType(MediaType.APPLICATION_JSON_VALUE); response.setContentType(MediaType.APPLICATION_JSON_VALUE);

View File

@ -1,5 +1,7 @@
package net.Broken.Api.Security.Data; package net.Broken.Api.Security.Data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
public record AccessTokenResponse( public record AccessTokenResponse(
String access_token, String access_token,
String token_type, String token_type,

View File

@ -1,5 +1,7 @@
package net.Broken.Api.Security.Data; package net.Broken.Api.Security.Data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
public record JwtResponse(String token) { public record JwtResponse(String token) {
} }

View File

@ -1,5 +1,6 @@
package net.Broken.Api.Security.Expression; package net.Broken.Api.Security.Expression;
import net.Broken.Api.Security.Expression.CustomMethodSecurityExpressionRoot;
import org.aopalliance.intercept.MethodInvocation; import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
@ -9,7 +10,7 @@ import org.springframework.security.core.Authentication;
public class CustomMethodSecurityExpressionHandler public class CustomMethodSecurityExpressionHandler
extends DefaultMethodSecurityExpressionHandler { extends DefaultMethodSecurityExpressionHandler {
private final AuthenticationTrustResolver trustResolver = private AuthenticationTrustResolver trustResolver =
new AuthenticationTrustResolverImpl(); new AuthenticationTrustResolverImpl();
@Override @Override

View File

@ -2,13 +2,13 @@ package net.Broken.Api.Security.Expression;
import net.Broken.Api.Data.Music.Connect; import net.Broken.Api.Data.Music.Connect;
import net.Broken.Api.Security.Data.JwtPrincipal; import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.Audio.GuildAudioBotService;
import net.Broken.MainBot; import net.Broken.MainBot;
import net.Broken.Tools.CacheTools; import net.Broken.Tools.CacheTools;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
import okhttp3.Cache;
import org.springframework.security.access.expression.SecurityExpressionRoot; import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
@ -58,23 +58,6 @@ public class CustomMethodSecurityExpressionRoot
&& member.hasPermission(channel, Permission.VOICE_SPEAK); && member.hasPermission(channel, Permission.VOICE_SPEAK);
} }
public boolean canInteractWithVoiceChannel(String guildId) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) authentication.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService guildAudioBotService = GuildAudioBotService.getInstance(guild);
VoiceChannel channel = guild.getAudioManager().getConnectedChannel();
if (channel == null) {
return false;
}
Member member = guild.getMemberById(jwtPrincipal.user().getDiscordId());
return (member.hasPermission(channel, Permission.VOICE_CONNECT)
|| member.getVoiceState() != null
&& member.getVoiceState().getChannel() == channel)
&& member.hasPermission(channel, Permission.VOICE_SPEAK);
}
@Override @Override
public void setFilterObject(Object filterObject) { public void setFilterObject(Object filterObject) {
this.filterObject = filterObject; this.filterObject = filterObject;

View File

@ -33,6 +33,9 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
http.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);
// http.exceptionHandling().authenticationEntryPoint((request, response, authException) -> {
// response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
// });
} }
@Bean @Bean

View File

@ -12,6 +12,7 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI; import java.net.URI;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.net.http.HttpClient; import java.net.http.HttpClient;
@ -142,7 +143,7 @@ public class DiscordOauthService {
} }
private String getFormString(HashMap<String, String> params) { private String getFormString(HashMap<String, String> params) throws UnsupportedEncodingException {
StringBuilder result = new StringBuilder(); StringBuilder result = new StringBuilder();
boolean first = true; boolean first = true;
for (Map.Entry<String, String> entry : params.entrySet()) { for (Map.Entry<String, String> entry : params.entrySet()) {

View File

@ -1,10 +1,7 @@
package net.Broken.Api.Security.Services; package net.Broken.Api.Security.Services;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.*;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.Keys;
import net.Broken.DB.Entity.UserEntity; import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.UserRepository; import net.Broken.DB.Repository.UserRepository;

View File

@ -1,35 +1,31 @@
package net.Broken.Api.Services; package net.Broken.Api.Services;
import net.Broken.Api.Data.Guild.Channel; import net.Broken.Api.Data.Guild.Channel;
import net.Broken.Api.Data.Music.*; import net.Broken.Api.Data.Music.Connect;
import net.Broken.Audio.GuildAudioBotService; import net.Broken.Api.Data.Music.PlayBackInfo;
import net.Broken.Audio.UserAudioTrack; import net.Broken.Api.Data.Music.Status;
import net.Broken.Api.Data.Music.TrackInfo;
import net.Broken.MainBot; import net.Broken.MainBot;
import net.Broken.audio.AudioM;
import net.Broken.audio.UserAudioTrack;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.audio.hooks.ConnectionStatus;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildVoiceState;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.concurrent.ExecutionException;
@Service @Service
public class AudioService { public class AudioService {
final Logger logger = LogManager.getLogger();
public Status getGuildAudioStatus(String guildId, String userId) { public Status getGuildAudioStatus(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId); Guild guild = MainBot.jda.getGuildById(guildId);
Member member = guild.getMemberById(userId); Member member = guild.getMemberById(userId);
GuildVoiceState voiceState = guild.getSelfMember().getVoiceState();
if (voiceState != null) {
VoiceChannel channel = guild.getAudioManager().getConnectedChannel(); VoiceChannel channel = voiceState.getChannel();
ConnectionStatus status = guild.getAudioManager().getConnectionStatus();
if (channel != null) { if (channel != null) {
// The user can view the audio status if: // The user can view the audio status if:
// -> He can view the voice channel // -> He can view the voice channel
@ -37,8 +33,6 @@ public class AudioService {
boolean canView = member.hasPermission(channel, Permission.VIEW_CHANNEL) boolean canView = member.hasPermission(channel, Permission.VIEW_CHANNEL)
|| (member.getVoiceState() != null || (member.getVoiceState() != null
&& member.getVoiceState().getChannel() == channel); && member.getVoiceState().getChannel() == channel);
GuildAudioBotService guildAudioBotService = GuildAudioBotService.getInstance(guild);
if (canView) { if (canView) {
// The user can interact with the audio if: // The user can interact with the audio if:
// -> He can connect to this voice channel // -> He can connect to this voice channel
@ -49,13 +43,13 @@ public class AudioService {
&& member.getVoiceState().getChannel() == channel) && member.getVoiceState().getChannel() == channel)
&& member.hasPermission(channel, Permission.VOICE_SPEAK); && member.hasPermission(channel, Permission.VOICE_SPEAK);
AudioM audioM = AudioM.getInstance(guild);
boolean stopped = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack() == null; boolean stopped = audioM.getGuildAudioPlayer().player.getPlayingTrack() == null;
PlayBackInfo playBackInfo; PlayBackInfo playBackInfo;
if (!stopped) { if (!stopped) {
boolean paused = guildAudioBotService.getGuidAudioManager().player.isPaused(); boolean paused = audioM.getGuildAudioPlayer().player.isPaused();
long position = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack().getPosition(); long position = audioM.getGuildAudioPlayer().player.getPlayingTrack().getPosition();
UserAudioTrack userAudioTrack = guildAudioBotService.getGuidAudioManager().scheduler.getCurrentPlayingTrack(); UserAudioTrack userAudioTrack = audioM.getGuildAudioPlayer().scheduler.getCurrentPlayingTrack();
playBackInfo = new PlayBackInfo(paused, false, position, new TrackInfo(userAudioTrack)); playBackInfo = new PlayBackInfo(paused, false, position, new TrackInfo(userAudioTrack));
@ -63,69 +57,25 @@ public class AudioService {
playBackInfo = new PlayBackInfo(false, true, null, null); playBackInfo = new PlayBackInfo(false, true, null, null);
} }
Channel channelApi = new Channel(channel.getId(), channel.getName()); Channel channelApi = new Channel(channel.getId(), channel.getName());
return new Status(true, status, channelApi, true, canInteract, playBackInfo); return new Status(true, channelApi, true, canInteract, playBackInfo);
} else { } else {
return new Status(true, status, null, false, false, null); return new Status(true, null, false, false, null);
}
}
return new Status(false, status, null, null, null, null);
} }
public ResponseEntity<Status> connect(String guildId, Connect body, String userId) {
}
}
return new Status(false, null, null, null, null);
}
public ResponseEntity<String> connect(String guildId, Connect body){
Guild guild = MainBot.jda.getGuildById(guildId); Guild guild = MainBot.jda.getGuildById(guildId);
AudioM audioM = AudioM.getInstance(guild);
VoiceChannel voiceChannel = guild.getVoiceChannelById(body.channelId()); VoiceChannel voiceChannel = guild.getVoiceChannelById(body.channelId());
GuildAudioBotService.getInstance(guild).connect(voiceChannel); audioM.getGuildAudioPlayer();
Status status = getGuildAudioStatus(guildId, userId); guild.getAudioManager().openAudioConnection(voiceChannel);
return new ResponseEntity<>(status, HttpStatus.OK); audioM.setPlayedChanel(voiceChannel);
} return new ResponseEntity<>("OK", HttpStatus.OK);
public ResponseEntity<Status> disconnect(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService guildAudioBotService = GuildAudioBotService.getInstance(guild);
guildAudioBotService.disconnect();
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
public ResponseEntity<Status> pause(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService.getInstance(guild).pause();
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
public ResponseEntity<Status> resume(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService.getInstance(guild).resume();
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
public ResponseEntity<Status> skip(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService.getInstance(guild).skipTrack();
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
public ResponseEntity<Status> stop(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService.getInstance(guild).stop();
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
}
public ResponseEntity<Status> add(String guildId, String userId, Add body) throws ExecutionException, InterruptedException {
Guild guild = MainBot.jda.getGuildById(guildId);
boolean success = GuildAudioBotService.getInstance(guild).loadAndPlaySync(body.url(), userId);
if (success) {
Status status = getGuildAudioStatus(guildId, userId);
return new ResponseEntity<>(status, HttpStatus.OK);
} else {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
} }
} }

View File

@ -1,10 +1,11 @@
package net.Broken.Api.Services; package net.Broken.Api.Services;
import net.Broken.Api.Data.Guild.Channel;
import net.Broken.Api.Data.Guild.Guild; import net.Broken.Api.Data.Guild.Guild;
import net.Broken.Api.Data.Guild.Channel;
import net.Broken.Api.Data.Guild.Role; import net.Broken.Api.Data.Guild.Role;
import net.Broken.DB.Entity.UserEntity; import net.Broken.DB.Entity.UserEntity;
import net.Broken.MainBot; import net.Broken.MainBot;
import net.Broken.Tools.CacheTools;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;

View File

@ -1,5 +1,7 @@
package net.Broken.Api.Services; package net.Broken.Api.Services;
import liquibase.pro.packaged.V;
import net.Broken.Api.Data.Settings.SettingDescriber;
import net.Broken.Api.Data.Settings.SettingGroup; import net.Broken.Api.Data.Settings.SettingGroup;
import net.Broken.Api.Data.Settings.Value; import net.Broken.Api.Data.Settings.Value;
import net.Broken.DB.Entity.GuildPreferenceEntity; import net.Broken.DB.Entity.GuildPreferenceEntity;
@ -11,6 +13,7 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@Service @Service

View File

@ -2,7 +2,7 @@ package net.Broken;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding; import org.springframework.boot.context.properties.ConstructorBinding;
import org.springframework.context.annotation.Configuration;
@ConfigurationProperties(prefix = "discord.bot") @ConfigurationProperties(prefix = "discord.bot")
@ConstructorBinding @ConstructorBinding
public record BotConfigLoader ( public record BotConfigLoader (

View File

@ -1,11 +1,11 @@
package net.Broken; package net.Broken;
import net.Broken.Audio.GuildAudioBotService;
import net.Broken.DB.Entity.GuildPreferenceEntity; import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository; import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.Tools.AutoVoiceChannel; import net.Broken.Tools.AutoVoiceChannel;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.Broken.Tools.UserManager.Stats.UserStatsUtils; import net.Broken.Tools.UserManager.Stats.UserStatsUtils;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.*; import net.dv8tion.jda.api.entities.*;
@ -119,10 +119,10 @@ public class BotListener extends ListenerAdapter {
if (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() == 1) { if (event.getGuild().getAudioManager().getConnectedChannel().getMembers().size() == 1) {
logger.debug("I'm alone, close audio connection."); logger.debug("I'm alone, close audio connection.");
GuildAudioBotService.getInstance(event.getGuild()).stop(); AudioM.getInstance(event.getGuild()).stop();
} }
} else if (event.getMember().getUser() == MainBot.jda.getSelfUser()) { } else if (event.getMember().getUser() == MainBot.jda.getSelfUser()) {
GuildAudioBotService.getInstance(event.getGuild()).clearLastButton(); AudioM.getInstance(event.getGuild()).clearLastButton();
} }
AutoVoiceChannel autoVoiceChannel = AutoVoiceChannel.getInstance(event.getGuild()); AutoVoiceChannel autoVoiceChannel = AutoVoiceChannel.getInstance(event.getGuild());
autoVoiceChannel.leave(event.getChannelLeft()); autoVoiceChannel.leave(event.getChannelLeft());
@ -147,13 +147,13 @@ public class BotListener extends ListenerAdapter {
public void onButtonClick(@NotNull ButtonClickEvent event) { public void onButtonClick(@NotNull ButtonClickEvent event) {
super.onButtonClick(event); super.onButtonClick(event);
event.deferReply().queue(); event.deferReply().queue();
GuildAudioBotService guildAudioBotService = GuildAudioBotService.getInstance(event.getGuild()); AudioM audioM = AudioM.getInstance(event.getGuild());
switch (event.getComponentId()) { switch (event.getComponentId()) {
case "pause" -> guildAudioBotService.pause(event); case "pause" -> audioM.pause(event);
case "play" -> guildAudioBotService.resume(event); case "play" -> audioM.resume(event);
case "next" -> guildAudioBotService.skipTrack(event); case "next" -> audioM.skipTrack(event);
case "stop" -> guildAudioBotService.stop(event); case "stop" -> audioM.stop(event);
case "disconnect" -> guildAudioBotService.disconnect(event); case "disconnect" -> audioM.disconect(event);
} }
} }
@ -193,7 +193,9 @@ public class BotListener extends ListenerAdapter {
logger.info("Join new guild! (" + event.getGuild().getName() + " " + event.getGuild().getMembers().size() + " Members)"); logger.info("Join new guild! (" + event.getGuild().getName() + " " + event.getGuild().getMembers().size() + " Members)");
super.onGuildJoin(event); super.onGuildJoin(event);
getPreference(event.getGuild()); getPreference(event.getGuild());
event.getGuild().loadMembers().onSuccess((members -> logger.debug("[" + event.getGuild().getName() + "] Members loaded"))); event.getGuild().loadMembers().onSuccess((members -> {
logger.debug("[" + event.getGuild().getName() + "] Members loaded");
}));
EmbedBuilder eb = new EmbedBuilder().setColor(Color.GREEN) EmbedBuilder eb = new EmbedBuilder().setColor(Color.GREEN)
.setTitle("Hello there !") .setTitle("Hello there !")
.setDescription("Allow me to introduce myself -- I am a CL4P-TP the discord bot, but my friends call me Claptrap ! Or they would, if any of them were real...\n" + .setDescription("Allow me to introduce myself -- I am a CL4P-TP the discord bot, but my friends call me Claptrap ! Or they would, if any of them were real...\n" +

View File

@ -17,7 +17,7 @@ import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
public class ChannelsReview implements Commande { public class ChannelsReview implements Commande {
final Logger logger = LogManager.getLogger(); Logger logger = LogManager.getLogger();
@Override @Override
public void action(String[] args, MessageReceivedEvent event) { public void action(String[] args, MessageReceivedEvent event) {
@ -45,7 +45,7 @@ public class ChannelsReview implements Commande {
try { try {
Message lastMessage = textChannel.retrieveMessageById(lastMessageId).complete(); Message lastMessage = textChannel.retrieveMessageById(lastMessageId).complete();
if (beforeDate.compareTo(format.parse(lastMessage.getTimeCreated().format(formatter))) > 0) { if (beforeDate.compareTo(format.parse(lastMessage.getTimeCreated().format(formatter))) > 0) {
logger.debug("Last message in channel " + textChannel + " is " + lastMessageId); logger.debug("Last message in channel " + textChannel.toString() + " is " + lastMessageId);
String date = lastMessage.getTimeCreated().format(formatter); String date = lastMessage.getTimeCreated().format(formatter);
charCtl += textChannel.getName().length() + date.length(); charCtl += textChannel.getName().length() + date.length();
result.put(textChannel.getName(), date); result.put(textChannel.getName(), date);
@ -77,7 +77,7 @@ public class ChannelsReview implements Commande {
for (TextChannel textChannel : event.getGuild().getTextChannels()) { for (TextChannel textChannel : event.getGuild().getTextChannels()) {
if (textChannel.hasLatestMessage()) { if (textChannel.hasLatestMessage()) {
String lastMessageId = textChannel.getLatestMessageId(); String lastMessageId = textChannel.getLatestMessageId();
logger.debug("Last message in channel " + textChannel + " is " + lastMessageId); logger.debug("Last message in channel " + textChannel.toString() + " is " + lastMessageId);
try { try {
Message lastMessage = textChannel.retrieveMessageById(lastMessageId).complete(); Message lastMessage = textChannel.retrieveMessageById(lastMessageId).complete();

View File

@ -6,8 +6,6 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.requests.RestAction; import net.dv8tion.jda.api.requests.RestAction;
import java.util.Objects;
public class ReportUsers implements Commande { public class ReportUsers implements Commande {
@ -20,8 +18,11 @@ public class ReportUsers implements Commande {
for (Member member : members) { for (Member member : members) {
if (member.getRoles().size() == 1) { //check if the member has a role if (member.getRoles().size() == 1) { //check if the member has a role
if (member.getRoles().contains(event.getMessage().getMentionedRoles().get(0))) { //check if the mentioned role is the same as the member's role if (member.getRoles().contains(event.getMessage().getMentionedRoles().get(0))) { //check if the mentioned role is the same as the member's role
restAction = Objects.requireNonNullElseGet(restAction, () -> event.getTextChannel().sendMessage("List des membres : ")) if (restAction == null) {
.and(event.getTextChannel().sendMessage(member.getEffectiveName())); restAction = event.getTextChannel().sendMessage("List des membres : ").and(event.getTextChannel().sendMessage(member.getEffectiveName()));
} else {
restAction = restAction.and(event.getTextChannel().sendMessage(member.getEffectiveName()));
}
} }
} }
} }

View File

@ -1,6 +1,11 @@
package net.Broken.DB.Entity; package net.Broken.DB.Entity;
import net.Broken.Api.Data.Settings.Value;
import net.dv8tion.jda.api.entities.Guild;
import javax.persistence.*; import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity @Entity
public class GuildPreferenceEntity { public class GuildPreferenceEntity {

View File

@ -0,0 +1,79 @@
package net.Broken.DB.Entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Entity
public class PlaylistEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String name;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "userEntity_id", nullable = false)
private UserEntity user;
@OneToMany(mappedBy = "playlist")
private List<TrackEntity> tracks;
public PlaylistEntity() {
}
public PlaylistEntity(String name, UserEntity user) {
this.name = name;
this.user = user;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public List<TrackEntity> getTracks() {
return tracks;
}
public void setTracks(List<TrackEntity> tracks) {
this.tracks = tracks;
}
public void addTracks(TrackEntity... tracks) {
if (this.tracks == null)
this.tracks = new ArrayList<>();
this.tracks.addAll(Arrays.asList(tracks));
}
}

View File

@ -0,0 +1,94 @@
package net.Broken.DB.Entity;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import javax.persistence.*;
@Entity
public class TrackEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private String url;
private String identifier;
private Integer pos;
@JsonIgnore
@ManyToOne
@JoinColumn(name = "playlistEntity_id", nullable = false)
private PlaylistEntity playlist;
public TrackEntity() {
}
public TrackEntity(AudioTrackInfo trackInfo, int pos, PlaylistEntity playlist) {
this.title = trackInfo.title;
this.url = trackInfo.uri;
this.identifier = trackInfo.identifier;
this.playlist = playlist;
this.pos = pos;
}
public TrackEntity(TrackEntity trackEntity) {
this.title = trackEntity.title;
this.url = trackEntity.url;
this.identifier = trackEntity.identifier;
this.pos = trackEntity.pos;
this.playlist = trackEntity.playlist;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public PlaylistEntity getPlaylist() {
return playlist;
}
public void setPlaylist(PlaylistEntity playlist) {
this.playlist = playlist;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
public Integer getPos() {
return pos;
}
public void setPos(Integer pos) {
this.pos = pos;
}
}

View File

@ -5,6 +5,8 @@ import net.Broken.Api.Security.Data.DiscordOauthUserInfo;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import javax.persistence.*; import javax.persistence.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
/** /**
@ -20,7 +22,7 @@ public class UserEntity {
private String discriminator; private String discriminator;
@Column(unique = true) @Column(unique=true)
private String discordId; private String discordId;
private String avatar; private String avatar;
@ -31,6 +33,10 @@ public class UserEntity {
@OneToMany(fetch = FetchType.EAGER, mappedBy = "user") @OneToMany(fetch = FetchType.EAGER, mappedBy = "user")
private List<UserStats> userStats; private List<UserStats> userStats;
@OneToMany(mappedBy = "user")
private List<PlaylistEntity> playlists;
public UserEntity() { public UserEntity() {
} }
@ -44,7 +50,7 @@ public class UserEntity {
this.discordId = id; this.discordId = id;
} }
public UserEntity(DiscordOauthUserInfo discordOauthUserInfo) { public UserEntity(DiscordOauthUserInfo discordOauthUserInfo){
this.username = discordOauthUserInfo.username(); this.username = discordOauthUserInfo.username();
this.discriminator = discordOauthUserInfo.discriminator(); this.discriminator = discordOauthUserInfo.discriminator();
this.discordId = discordOauthUserInfo.id(); this.discordId = discordOauthUserInfo.id();
@ -76,6 +82,21 @@ public class UserEntity {
this.discordId = discordId; this.discordId = discordId;
} }
public List<PlaylistEntity> getPlaylists() {
return playlists;
}
public void setPlaylists(List<PlaylistEntity> playlists) {
this.playlists = playlists;
}
public void addPlaylist(PlaylistEntity... playlists) {
if (this.playlists == null)
this.playlists = new ArrayList<>();
this.playlists.addAll(Arrays.asList(playlists));
}
public List<UserStats> getUserStats() { public List<UserStats> getUserStats() {
return userStats; return userStats;
} }

View File

@ -0,0 +1,8 @@
package net.Broken.DB.Repository;
import net.Broken.DB.Entity.PlaylistEntity;
import org.springframework.data.repository.CrudRepository;
public interface PlaylistRepository extends CrudRepository<PlaylistEntity, Integer> {
PlaylistEntity findById(int id);
}

View File

@ -0,0 +1,13 @@
package net.Broken.DB.Repository;
import net.Broken.DB.Entity.PlaylistEntity;
import net.Broken.DB.Entity.TrackEntity;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface TrackRepository extends CrudRepository<TrackEntity, Integer> {
List<TrackEntity> findDistinctByPlaylistOrderByPos(PlaylistEntity playlistEntity);
TrackEntity findById(int id);
}

View File

@ -4,6 +4,7 @@ import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Entity.UserEntity; import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository; import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.DB.Repository.UserRepository; import net.Broken.DB.Repository.UserRepository;
import net.Broken.RestApi.ApiCommandLoader;
import net.Broken.Tools.Command.SlashCommandLoader; import net.Broken.Tools.Command.SlashCommandLoader;
import net.Broken.Tools.DayListener.DayListener; import net.Broken.Tools.DayListener.DayListener;
import net.Broken.Tools.DayListener.Listeners.DailyMadame; import net.Broken.Tools.DayListener.Listeners.DailyMadame;
@ -18,6 +19,7 @@ import net.dv8tion.jda.api.utils.MemberCachePolicy;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.thymeleaf.spring5.processor.SpringOptionFieldTagProcessor;
import javax.security.auth.login.LoginException; import javax.security.auth.login.LoginException;
import java.util.List; import java.util.List;
@ -66,6 +68,7 @@ public class Init {
logger.info("Loading commands"); logger.info("Loading commands");
SlashCommandLoader.load(config); SlashCommandLoader.load(config);
SlashCommandLoader.registerSlashCommands(jda.updateCommands()); SlashCommandLoader.registerSlashCommands(jda.updateCommands());
ApiCommandLoader.load();
DayListener dayListener = DayListener.getInstance(); DayListener dayListener = DayListener.getInstance();
dayListener.addListener(new DailyMadame()); dayListener.addListener(new DailyMadame());
dayListener.start(); dayListener.start();

View File

@ -3,6 +3,7 @@ package net.Broken;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan; import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@ -17,8 +18,10 @@ import java.util.HashMap;
@ConfigurationPropertiesScan @ConfigurationPropertiesScan
public class MainBot { public class MainBot {
public static final HashMap<String, SlashCommand> slashCommands = new HashMap<>(); public static HashMap<String, Commande> commandes = new HashMap<>();
public static HashMap<String, SlashCommand> slashCommands = new HashMap<>();
public static HashMap<String, Integer> mutualGuildCount = new HashMap<>(); public static HashMap<String, Integer> mutualGuildCount = new HashMap<>();
public static boolean roleFlag = false;
public static JDA jda; public static JDA jda;
public static boolean ready = false; public static boolean ready = false;
@ -39,11 +42,12 @@ public class MainBot {
jda = Init.initJda(config); jda = Init.initJda(config);
if (jda == null) { if (jda == null) {
System.exit(SpringApplication.exit(ctx, () -> { System.exit(SpringApplication.exit(ctx, (ExitCodeGenerator) () -> {
logger.fatal("Init error! Close application!"); logger.fatal("Init error! Close application!");
return 1; return 1;
})); }));
} }
Init.polish(jda, config); Init.polish(jda, config);
ready = true; ready = true;
} }

View File

@ -0,0 +1,44 @@
package net.Broken.RestApi;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.reflections.Reflections;
import org.reflections.util.ClasspathHelper;
import org.reflections.util.ConfigurationBuilder;
import java.util.HashMap;
import java.util.Set;
public class ApiCommandLoader {
public static HashMap<String, CommandInterface> apiCommands = new HashMap<>();
private static Logger logger = LogManager.getLogger();
public static void load() {
logger.info("Loading Api Command...");
// Reflections reflections = new Reflections("net.Broken.RestApi.Command");
Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(
"net.Broken.RestApi.Commands",
ClasspathHelper.contextClassLoader(),
ClasspathHelper.staticClassLoader()))
);
Set<Class<? extends CommandInterface>> modules =
reflections.getSubTypesOf(CommandInterface.class);
logger.info("Find " + modules.size() + " Command:");
for (Class<? extends CommandInterface> apiClass : modules) {
String reference = apiClass.getName();
String[] splited = reference.split("\\.");
String name = splited[splited.length - 1].toUpperCase();
logger.info("..." + name);
try {
apiCommands.put(name, apiClass.newInstance());
} catch (InstantiationException | IllegalAccessException e) {
logger.error("Failed to load " + name + "!");
}
}
}
}

View File

@ -0,0 +1,24 @@
package net.Broken.RestApi;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.ResponseEntity;
/**
* Represent RestApi command
*/
public interface CommandInterface {
/**
* Main action
*
* @param musicCommande Current guild music command
* @param data Received data
* @param user User who submit RestApi command
* @param guild
* @return HTTP Response
*/
ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild);
}

View File

@ -0,0 +1,19 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.WebLoadUtils;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.ResponseEntity;
/**
* Add track RestApi
*/
public class Add implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
return new WebLoadUtils(data, user, guild, true).getResponse();
}
}

View File

@ -0,0 +1,22 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.Broken.audio.TrackScheduler;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
public class AutoFlowOff implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM audioM = AudioM.getInstance(guild);
TrackScheduler scheduler = audioM.getGuildMusicManager().scheduler;
scheduler.setAutoFlow(false);
return new ResponseEntity<>(new CommandResponseData(data.command, "ok"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,23 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.Broken.audio.TrackScheduler;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
public class AutoFlowOn implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM audioM = AudioM.getInstance(guild);
TrackScheduler scheduler = audioM.getGuildMusicManager().scheduler;
scheduler.setAutoFlow(true);
return new ResponseEntity<>(new CommandResponseData(data.command, "ok"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,37 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.entities.VoiceChannel;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Connect to vocal channel RestApi command
*/
public class Connect implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM audioM = AudioM.getInstance(guild);
if (data.chanelId == null)
return new ResponseEntity<>(new CommandResponseData(data.command, "Missing chanelId"), HttpStatus.BAD_REQUEST);
VoiceChannel voiceChannel = null;
try {
voiceChannel = guild.getVoiceChannelById(data.chanelId);
} catch (NumberFormatException ignored) {
}
if (voiceChannel == null) {
return new ResponseEntity<>(new CommandResponseData(data.command, "Channel Not found"), HttpStatus.BAD_REQUEST);
}
audioM.getGuildAudioPlayer();
guild.getAudioManager().openAudioConnection(guild.getVoiceChannelById(data.chanelId));
audioM.setPlayedChanel(voiceChannel);
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,27 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Delete track RestApi command
*/
public class Dell implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
if (data.url != null) {
if (AudioM.getInstance(guild).getGuildMusicManager().scheduler.remove(data.url)) {
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
} else
return new ResponseEntity<>(new CommandResponseData(data.command, "URL not found"), HttpStatus.NOT_FOUND);
}
return new ResponseEntity<>(new CommandResponseData(data.command, "Missing URL"), HttpStatus.NOT_ACCEPTABLE);
}
}

View File

@ -0,0 +1,22 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Disconnect from vocal chanel RestApi Command
*/
public class Disconnect implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).stop();
return new ResponseEntity<>(new CommandResponseData(data.command, "Ok"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Flush playlist RestApi Command
*/
public class Flush implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).getGuildMusicManager().scheduler.flush();
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Next Track RestApi command
*/
public class Next implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).getGuildMusicManager().scheduler.nextTrack();
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Pause track RestApi command
*/
public class Pause implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).getGuildMusicManager().scheduler.pause();
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Resume (play button) RestApi command
*/
public class Play implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).getGuildMusicManager().scheduler.resume();
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,22 @@
package net.Broken.RestApi.Commands;
import net.Broken.RestApi.CommandInterface;
import net.Broken.RestApi.Data.CommandPostData;
import net.Broken.RestApi.Data.CommandResponseData;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.User;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
/**
* Stop RestApi Command
*/
public class Stop implements CommandInterface {
@Override
public ResponseEntity<CommandResponseData> action(CommandPostData data, User user, Guild guild) {
AudioM.getInstance(guild).stop(null);
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
}
}

View File

@ -0,0 +1,11 @@
package net.Broken.RestApi.Data;
public class AllMusicInfoData {
public CurrentMusicData currentMusic;
public PlaylistData playlist;
public AllMusicInfoData(CurrentMusicData currentMusic, PlaylistData playlist) {
this.currentMusic = currentMusic;
this.playlist = playlist;
}
}

View File

@ -0,0 +1,17 @@
package net.Broken.RestApi.Data;
/**
* Data for JSON Parsing
*/
public class ChanelData {
public String name;
public String id;
public int pos;
public ChanelData(String name, String id, int pos) {
this.name = name;
this.id = id;
this.pos = pos;
}
}

View File

@ -0,0 +1,13 @@
package net.Broken.RestApi.Data;
/**
* Data for JSON Parsing
*/
public class CommandPostData {
public String command;
public boolean onHead;
public String url;
public int playlistLimit;
public String chanelId;
public String name;
}

View File

@ -0,0 +1,24 @@
package net.Broken.RestApi.Data;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* Data for JSON Parsing
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CommandResponseData {
public String Commande;
public String Message;
public String error;
public CommandResponseData(String commande, String message) {
Commande = commande;
Message = message;
}
public CommandResponseData(String commande, String message, String error) {
Commande = commande;
Message = message;
this.error = error;
}
}

View File

@ -0,0 +1,43 @@
package net.Broken.RestApi.Data;
import com.fasterxml.jackson.annotation.JsonInclude;
/**
* Data for JSON Parsing
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
public class CurrentMusicData {
private final UserAudioTrackData info;
private final long currentPos;
private final String state;
private final boolean pause;
private final boolean autoflow;
public CurrentMusicData(UserAudioTrackData info, long currentPos, String state, boolean pause, boolean autoflow) {
this.info = info;
this.currentPos = currentPos;
this.state = state;
this.pause = pause;
this.autoflow = autoflow;
}
public UserAudioTrackData getInfo() {
return info;
}
public long getCurrentPos() {
return currentPos;
}
public String getState() {
if (pause)
return "PAUSE";
else
return state;
}
public boolean isAutoflow() {
return autoflow;
}
}

View File

@ -0,0 +1,11 @@
package net.Broken.RestApi.Data.Playlist;
import net.Broken.RestApi.Data.CommandPostData;
public class AddToPlaylistData extends CommandPostData {
public int playlistId;
public int pos;
}

View File

@ -0,0 +1,5 @@
package net.Broken.RestApi.Data.Playlist;
public class CreatePlaylistData {
public String name;
}

View File

@ -0,0 +1,6 @@
package net.Broken.RestApi.Data.Playlist;
public class DeleteTrackData {
public int id;
public int playlistId;
}

View File

@ -0,0 +1,10 @@
package net.Broken.RestApi.Data.Playlist;
public class MoveTrackData {
public int playlistId;
public int id;
public int newPos;
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Data.Playlist;
import com.fasterxml.jackson.annotation.JsonInclude;
import net.Broken.DB.Entity.PlaylistEntity;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class PlaylistResponseData {
public String message;
public String error;
public PlaylistEntity playlist;
public PlaylistResponseData(String message, PlaylistEntity playlist) {
this.message = message;
this.playlist = playlist;
}
public PlaylistResponseData(String message, String error) {
this.message = message;
this.error = error;
}
}

View File

@ -0,0 +1,19 @@
package net.Broken.RestApi.Data;
import java.util.List;
/**
* Data for JSON Parsing
*/
public class PlaylistData {
private List<UserAudioTrackData> list;
public PlaylistData(List<UserAudioTrackData> list) {
this.list = list;
}
public List<UserAudioTrackData> getList() {
return list;
}
}

View File

@ -0,0 +1,32 @@
package net.Broken.RestApi.Data.Settings;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public class GetSettingsData {
public String description;
public String name;
public String id;
public TYPE type;
public List<Value> values;
public String current;
public GetSettingsData() {
}
public GetSettingsData(String name, String description, String id, TYPE type, List<Value> values, String current) {
this.name = name;
this.description = description;
this.id = id;
this.type = type;
this.values = values;
this.current = current;
}
public enum TYPE {
BOOL, LIST, STRING, SELECT_LIST
}
}

View File

@ -0,0 +1,7 @@
package net.Broken.RestApi.Data.Settings;
import java.util.List;
public class ListPostSetting {
public List<PostSetSettings> settings;
}

View File

@ -0,0 +1,9 @@
package net.Broken.RestApi.Data.Settings;
import java.util.List;
public class PostSetSettings {
public String id;
public String val;
public List<String> vals;
}

View File

@ -0,0 +1,21 @@
package net.Broken.RestApi.Data.Settings;
public class Value {
public String name;
public String id;
public boolean selected;
public Value() {
}
public Value(String name, String id) {
this.name = name;
this.id = id;
}
public Value(String name, String id, boolean selected) {
this.name = name;
this.id = id;
this.selected = selected;
}
}

View File

@ -0,0 +1,38 @@
package net.Broken.RestApi.Data;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.audio.UserAudioTrack;
/**
* Data for JSON Parsing
*/
public class UserAudioTrackData {
private String user;
private AudioTrackInfo audioTrackInfo;
public UserAudioTrackData(String user, AudioTrackInfo audioTrackInfo) {
this.user = user;
this.audioTrackInfo = audioTrackInfo;
}
public UserAudioTrackData(UserAudioTrack userAudioTrack) {
this.audioTrackInfo = userAudioTrack.getAudioTrack().getInfo();
this.user = userAudioTrack.getSubmittedUser().getName();
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public AudioTrackInfo getAudioTrackInfo() {
return audioTrackInfo;
}
public void setAudioTrackInfo(AudioTrackInfo audioTrackInfo) {
this.audioTrackInfo = audioTrackInfo;
}
}

View File

@ -0,0 +1,18 @@
package net.Broken.RestApi.Data.UserManager;
/**
* Data for JSON Parsing
*/
public class CheckResposeData {
public boolean accepted;
public String name;
public String message;
public String id;
public CheckResposeData(boolean accepted, String name, String message, String id) {
this.accepted = accepted;
this.name = name;
this.message = message;
this.id = id;
}
}

View File

@ -0,0 +1,10 @@
package net.Broken.RestApi.Data.UserManager;
/**
* Data for JSON Parsing
*/
public class ConfirmData {
public String id;
public String checkToken;
}

View File

@ -0,0 +1,16 @@
package net.Broken.RestApi.Data.UserManager;
public class GuildInfo {
public String name;
public String id;
public boolean isAdmin;
public String imageUrl;
public GuildInfo(String name, String id, boolean isAdmin, String imageUrl) {
this.name = name;
this.id = id;
this.isAdmin = isAdmin;
this.imageUrl = imageUrl;
}
}

View File

@ -0,0 +1,28 @@
package net.Broken.RestApi.Data.UserManager;
/**
* Data for JSON Parsing
*/
public class UserConnectionData {
public boolean accepted;
public String token;
public String message;
public String error;
public String name;
public UserConnectionData(boolean accepted, String name, String token, String message) {
this.accepted = accepted;
this.token = token;
this.message = message;
this.name = name;
this.error = null;
}
public UserConnectionData(boolean accepted, String message, String error) {
this.accepted = accepted;
this.token = null;
this.message = message;
this.error = error;
this.name = null;
}
}

View File

@ -0,0 +1,9 @@
package net.Broken.RestApi.Data.UserManager;
/**
* Data for JSON Parsing
*/
public class UserInfoData {
public String name;
public String password;
}

View File

@ -0,0 +1,42 @@
package net.Broken.RestApi;
import net.Broken.DB.Repository.PlaylistRepository;
import net.Broken.DB.Repository.TrackRepository;
import net.Broken.DB.Repository.UserRepository;
import net.Broken.MainBot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/")
public class GeneralApiController {
private final
UserRepository userRepository;
private final
PlaylistRepository playlistRepository;
private final
TrackRepository trackRepository;
@Autowired
public GeneralApiController(UserRepository userRepository, PlaylistRepository playlistRepository, TrackRepository trackRepository) {
this.userRepository = userRepository;
this.playlistRepository = playlistRepository;
this.trackRepository = trackRepository;
}
@RequestMapping(value = "/isReady", method = RequestMethod.GET)
public ResponseEntity<String> isReady() {
if (MainBot.ready) {
return new ResponseEntity<>(HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
}
}

View File

@ -0,0 +1,239 @@
package net.Broken.RestApi;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.UserRepository;
import net.Broken.MainBot;
import net.Broken.RestApi.Data.*;
import net.Broken.Tools.CacheTools;
import net.Broken.Tools.UserManager.Exceptions.UnknownTokenException;
import net.Broken.Tools.UserManager.Stats.UserStatsUtils;
import net.Broken.Tools.UserManager.UserUtils;
import net.Broken.audio.AudioM;
import net.Broken.audio.GetVoiceChanels;
import net.Broken.audio.Youtube.SearchResult;
import net.Broken.audio.Youtube.YoutubeSearchRework;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.VoiceChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Rest Api Controller for /api/music
*/
@RestController
@RequestMapping("/api/music/")
public class MusicWebAPIController {
private final
UserRepository userRepository;
Logger logger = LogManager.getLogger();
UserUtils userUtils = UserUtils.getInstance();
@Autowired
public MusicWebAPIController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@RequestMapping("/currentMusicInfo")
public ResponseEntity<CurrentMusicData> getCurrentM(@RequestParam(value = "guild") String guildId) { //TODO security issue ???!!!
Guild guild = MainBot.jda.getGuildById(guildId);
if (guild == null) {
logger.warn("Request whit no guild!");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} else {
logger.trace("currentMusicInfo for " + guild.getName());
}
if (guild.getAudioManager().isConnected()) {
AudioPlayer player = AudioM.getInstance(guild).getGuildMusicManager().player;
AudioTrack currentTrack = player.getPlayingTrack();
if (currentTrack == null) {
return new ResponseEntity<>(new CurrentMusicData(null, 0, "STOP", false, AudioM.getInstance(guild).getGuildMusicManager().scheduler.isAutoFlow()), HttpStatus.OK);
}
UserAudioTrackData uat = new UserAudioTrackData(AudioM.getInstance(guild).getGuildMusicManager().scheduler.getCurrentPlayingTrack());
return new ResponseEntity<>(new CurrentMusicData(uat, currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused(), AudioM.getInstance(guild).getGuildMusicManager().scheduler.isAutoFlow()), HttpStatus.OK);
} else {
return new ResponseEntity<>(new CurrentMusicData(null, 0, "DISCONNECTED", false, false), HttpStatus.OK);
}
}
@RequestMapping("/getPlaylist")
public ResponseEntity<PlaylistData> getPlaylist(@RequestParam(value = "guild") String guildId) { //TODO security issue ???!!!
Guild guild = MainBot.jda.getGuildById(guildId);
if (guild == null) {
logger.warn("Request whit no guild!");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
} else {
logger.trace("getPlaylist for " + guild.getName());
}
List<UserAudioTrackData> list = null;
list = AudioM.getInstance(guild).getGuildMusicManager().scheduler.getList();
return new ResponseEntity<>(new PlaylistData(list), HttpStatus.OK);
}
@RequestMapping("/getAllInfo")
public ResponseEntity<AllMusicInfoData> getAllInfo(@RequestParam(value = "guild") String guildId, @CookieValue("token") String token) {
if (token != null) {
Guild guild = MainBot.jda.getGuildById(guildId);
if (guild == null) {
logger.warn("All info without guild!");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
try {
UserEntity user = userUtils.getUserWithApiToken(userRepository, token);
logger.trace("All info from USER: " + user.getUsername() + " GUILD: " + guild.getName());
PlaylistData list = new PlaylistData(AudioM.getInstance(guild).getGuildMusicManager().scheduler.getList());
CurrentMusicData musicData;
if (guild.getAudioManager().isConnected()) {
AudioPlayer player = AudioM.getInstance(guild).getGuildMusicManager().player;
AudioTrack currentTrack = player.getPlayingTrack();
if (currentTrack == null) {
musicData = new CurrentMusicData(null, 0, "STOP", false, AudioM.getInstance(guild).getGuildMusicManager().scheduler.isAutoFlow());
} else {
UserAudioTrackData uat = new UserAudioTrackData(AudioM.getInstance(guild).getGuildMusicManager().scheduler.getCurrentPlayingTrack());
musicData = new CurrentMusicData(uat, currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused(), AudioM.getInstance(guild).getGuildMusicManager().scheduler.isAutoFlow());
}
} else {
musicData = new CurrentMusicData(null, 0, "DISCONNECTED", false, false);
}
return new ResponseEntity<>(new AllMusicInfoData(musicData, list), HttpStatus.OK);
} catch (UnknownTokenException e) {
logger.warn("All info with unknown token");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
} else {
logger.warn("All Info without token!");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
}
@RequestMapping(value = "/command", method = RequestMethod.POST)
public ResponseEntity<CommandResponseData> command(@RequestBody CommandPostData data, HttpServletRequest request, @RequestParam(value = "guild") String guildId, @CookieValue("token") String token) {
if (data.command != null) {
if (token != null) {
Guild guild = MainBot.jda.getGuildById(guildId);
if (guild == null) {
logger.warn("Request whit no guild!");
return new ResponseEntity<>(new CommandResponseData(data.command, "Missing Guild!\nPlease Re-connect.", "token"), HttpStatus.UNAUTHORIZED);
}
try {
UserEntity user = userUtils.getUserWithApiToken(userRepository, token);
logger.info("[" + guild.getName() + "] Receive command" + data.command + " from" + request.getRemoteAddr() + " USER:" + user.getUsername() + " GUILD:" + guild.getName());
if (ApiCommandLoader.apiCommands.containsKey(data.command)) {
UserStatsUtils.getINSTANCE().addApiCount(user, guildId);
return ApiCommandLoader.apiCommands.get(data.command).action(data, MainBot.jda.getUserById(user.getDiscordId()), guild);
} else
return new ResponseEntity<>(new CommandResponseData(data.command, "Unknown Command", "command"), HttpStatus.BAD_REQUEST);
} catch (UnknownTokenException e) {
logger.warn("Command with unknown token from: " + request.getRemoteAddr());
return new ResponseEntity<>(new CommandResponseData(data.command, "Unknown Token!\nPlease Re-connect.", "token"), HttpStatus.UNAUTHORIZED);
}
} else {
logger.warn("Command without token! ip: " + request.getRemoteAddr());
return new ResponseEntity<>(new CommandResponseData(data.command, "Missing token!\nPlease Re-connect.", "token"), HttpStatus.UNAUTHORIZED);
}
} else
logger.info("Null");
return new ResponseEntity<>(new CommandResponseData(null, null), HttpStatus.NO_CONTENT);
}
@RequestMapping(value = "/getChanel", method = RequestMethod.GET)
public ResponseEntity<List<ChanelData>> getChanel(@CookieValue(name = "token", defaultValue = "") String token, @RequestParam(value = "guild") String guildId) {
if (token != null && !token.isEmpty()) {
try {
UserEntity user = userUtils.getUserWithApiToken(userRepository, token);
Guild guild = MainBot.jda.getGuildById(guildId);
if (guild == null) {
logger.warn("Request whit no guild!");
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
Member member = guild.getMember(CacheTools.getJdaUser(user));
if (member == null) {
member = guild.retrieveMember(CacheTools.getJdaUser(user)).complete();
if (member == null) {
logger.warn("Can't find member " + user.getUsername() + " for guild " + guild.getName() + ", User not in guild ?");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
}
logger.trace("getPlaylist for " + guild.getName());
List<ChanelData> temp = new ArrayList<>();
for (VoiceChannel aChanel : GetVoiceChanels.find(guild, member)) {
temp.add(new ChanelData(aChanel.getName(), aChanel.getId(), aChanel.getPosition()));
}
return new ResponseEntity<>(temp, HttpStatus.OK);
} catch (UnknownTokenException e) {
logger.warn("Get Chanel without token!");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
} else {
logger.warn("Get Chanel without token!");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
}
@RequestMapping(value = "/search", method = RequestMethod.GET)
public ResponseEntity<List<SearchResult>> search(@CookieValue(name = "token", defaultValue = "") String token, @RequestParam(value = "query") String query) {
if (token != null && !token.isEmpty()) {
try {
UserEntity user = userUtils.getUserWithApiToken(userRepository, token);
YoutubeSearchRework youtubeSearch = YoutubeSearchRework.getInstance();
List<SearchResult> result = youtubeSearch.searchVideo(query, 25, false);
return new ResponseEntity<>(result, HttpStatus.OK);
} catch (UnknownTokenException e) {
logger.warn("Search without token!");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
} catch (GoogleJsonResponseException e) {
logger.error("There was a service error: " + e.getDetails().getCode() + " : " + e.getDetails().getMessage());
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
} catch (IOException e) {
logger.catching(e);
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
} else {
logger.warn("Search without token!");
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}
}
}

View File

@ -0,0 +1,99 @@
package net.Broken.RestApi;
import net.Broken.DB.Entity.PlaylistEntity;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.PlaylistRepository;
import net.Broken.DB.Repository.TrackRepository;
import net.Broken.DB.Repository.UserRepository;
import net.Broken.RestApi.Data.Playlist.*;
import net.Broken.audio.Playlist.PlaylistManager;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/api/playlist/")
public class PlaylistAPIController {
private final
UserRepository userRepository;
private final
PlaylistRepository playlistRepository;
private final
TrackRepository trackRepository;
private Logger logger = LogManager.getLogger();
@Autowired
public PlaylistAPIController(UserRepository userRepository, PlaylistRepository playlistRepository, TrackRepository trackRepository) {
this.userRepository = userRepository;
this.playlistRepository = playlistRepository;
this.trackRepository = trackRepository;
}
// @RequestMapping("/myPlaylist")
// public List<PlaylistEntity> myPlaylist(@CookieValue(value = "token", defaultValue = "") String token) {
// if (token.isEmpty())
// return null;
// else {
// UserEntity user = userRepository.findByApiToken(token).get(0);
// return user.getPlaylists();
// }
//
// }
// @RequestMapping("/createPlaylist")
// public ResponseEntity<PlaylistResponseData> createPlaylist(@CookieValue(value = "token", defaultValue = "") String token, @RequestBody CreatePlaylistData data) {
//
// if (token.isEmpty())
// return new ResponseEntity<>(new PlaylistResponseData("Unknown Token!\nPlease Re-connect.", "token"), HttpStatus.UNAUTHORIZED);
// else {
// UserEntity user = userRepository.findByApiToken(token).get(0);
// PlaylistEntity playlistEntity = new PlaylistEntity(data.name, user);
// playlistEntity = playlistRepository.save(playlistEntity);
// user.addPlaylist(playlistEntity);
// userRepository.save(user);
// return new ResponseEntity<>(new PlaylistResponseData("Ok", playlistEntity), HttpStatus.OK);
// }
//
//
// }
@RequestMapping("/addToPlaylist")
public ResponseEntity<PlaylistResponseData> addToPlaylist(@CookieValue(value = "token", defaultValue = "") String token, @RequestBody AddToPlaylistData data) {
PlaylistManager playlistManager = PlaylistManager.getINSTANCE();
return playlistManager.addToPlaylist(token, data);
}
@RequestMapping("/dellTrack")
public ResponseEntity<PlaylistResponseData> dellTrack(@CookieValue(value = "token", defaultValue = "") String token, @RequestBody DeleteTrackData data) {
PlaylistManager playlistManager = PlaylistManager.getINSTANCE();
return playlistManager.removeTrack(token, data);
}
@RequestMapping("/moveTrack")
public ResponseEntity<PlaylistResponseData> moveTrack(@CookieValue(value = "token", defaultValue = "") String token, @RequestBody MoveTrackData data) {
PlaylistManager playlistManager = PlaylistManager.getINSTANCE();
return playlistManager.moveTrack(token, data);
}
}

View File

@ -10,6 +10,12 @@ import java.util.List;
* Interface that define command structure. * Interface that define command structure.
*/ */
public interface SlashCommand { public interface SlashCommand {
/**
* Main action of command
*
* @param args Command args.
* @param event Command MessageReceivedEvent
*/
void action(SlashCommandEvent event); void action(SlashCommandEvent event);
String getDescription(); String getDescription();

View File

@ -1,8 +1,6 @@
package net.Broken.SlashCommands; package net.Broken.SlashCommands;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.MessageBuilder;
@ -11,48 +9,41 @@ import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.http.HttpClient; import java.util.ArrayList;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List; import java.util.List;
/** /**
* Command that return a random picture of cat. * Command that return a random picture of cat.
*/ */
public class Cat implements SlashCommand { public class Cat implements SlashCommand {
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
;
@Override @Override
public void action(SlashCommandEvent event) { public void action(SlashCommandEvent event) {
try { try {
HttpRequest request = HttpRequest.newBuilder() URL urlC = new URL("http://aws.random.cat/meo");
.uri(URI.create("https://aws.random.cat/meow")) URLConnection yc = urlC.openConnection();
.GET() BufferedReader in = new BufferedReader(new InputStreamReader(
.build(); yc.getInputStream(), "UTF-8"));
String inputLine;
StringBuilder a = new StringBuilder();
while ((inputLine = in.readLine()) != null)
a.append(inputLine);
in.close();
JSONObject json = new JSONObject(a.toString());
HttpClient client = HttpClient.newHttpClient(); event.reply(json.getString("file")).queue();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
logger.warn("[CAT] Fail to fetch cat: Status Code: " + response.statusCode() + " Body:" + response.body());
throw new IOException();
}
TypeReference<HashMap<String, String>> typeRef = new TypeReference<>() {}; } catch (IOException e) {
ObjectMapper mapper = new ObjectMapper();
HashMap<String, String> json = mapper.readValue(response.body(), typeRef);
event.reply(json.get("file")).queue();
} catch (InterruptedException | IOException e) {
logger.catching(e); logger.catching(e);
event.reply(new MessageBuilder().setEmbeds(EmbedMessageUtils.getInternalError()).build()).setEphemeral(true).queue(); event.reply(new MessageBuilder().setEmbeds(EmbedMessageUtils.getInternalError()).build()).setEphemeral(true).queue();
} }

View File

@ -2,6 +2,7 @@ package net.Broken.SlashCommands;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;

View File

@ -1,9 +1,9 @@
package net.Broken.SlashCommands; package net.Broken.SlashCommands;
import net.Broken.Audio.GuildAudioBotService;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.Broken.audio.AudioM;
import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.VoiceChannel; import net.dv8tion.jda.api.entities.VoiceChannel;
@ -22,11 +22,12 @@ import java.util.List;
* Command that return a random picture of cat. * Command that return a random picture of cat.
*/ */
public class Music implements SlashCommand { public class Music implements SlashCommand {
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
;
@Override @Override
public void action(SlashCommandEvent event) { public void action(SlashCommandEvent event) {
GuildAudioBotService audio = GuildAudioBotService.getInstance(event.getGuild()); AudioM audio = AudioM.getInstance(event.getGuild());
String action = event.getSubcommandName(); String action = event.getSubcommandName();
event.deferReply().queue(); event.deferReply().queue();
switch (action) { switch (action) {

View File

@ -3,11 +3,16 @@ package net.Broken.SlashCommands.Over18;
import net.Broken.Tools.Command.Ignore; import net.Broken.Tools.Command.Ignore;
import net.Broken.Tools.Command.NoDev; import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedSlashCommand; import net.Broken.Tools.Command.NumberedSlashCommand;
import net.Broken.Tools.FindContentOnWebPage;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
@NoDev @NoDev
@Ignore @Ignore
public class Ass extends NumberedSlashCommand { public class Ass extends NumberedSlashCommand {
Logger logger = LogManager.getLogger();
public Ass() { public Ass() {
super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img"); super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img");

View File

@ -1,5 +1,6 @@
package net.Broken.SlashCommands.Over18; package net.Broken.SlashCommands.Over18;
import net.Broken.Tools.Command.Ignore;
import net.Broken.Tools.Command.NoDev; import net.Broken.Tools.Command.NoDev;
import net.Broken.Tools.Command.NumberedSlashCommand; import net.Broken.Tools.Command.NumberedSlashCommand;
import net.Broken.Tools.FindContentOnWebPage; import net.Broken.Tools.FindContentOnWebPage;
@ -10,7 +11,7 @@ import java.io.IOException;
@NoDev @NoDev
public class Madame extends NumberedSlashCommand { public class Madame extends NumberedSlashCommand {
final Logger logger = LogManager.getLogger(); Logger logger = LogManager.getLogger();
public Madame() { public Madame() {
super(LogManager.getLogger(), "https://www.bonjourmadame.fr/page/", "/"); super(LogManager.getLogger(), "https://www.bonjourmadame.fr/page/", "/");
@ -23,7 +24,7 @@ public class Madame extends NumberedSlashCommand {
* @throws StringIndexOutOfBoundsException * @throws StringIndexOutOfBoundsException
* @throws IOException * @throws IOException
*/ */
private boolean scanPageForTipeee(String url, Logger logger) throws StringIndexOutOfBoundsException, IOException, InterruptedException { private boolean scanPageForTipeee(String url, Logger logger) throws StringIndexOutOfBoundsException, IOException {
String content = FindContentOnWebPage.getSourceUrl(url); String content = FindContentOnWebPage.getSourceUrl(url);
String imgClickLink = content.substring(content.indexOf("class=\"post-content")); String imgClickLink = content.substring(content.indexOf("class=\"post-content"));
imgClickLink = imgClickLink.substring(imgClickLink.indexOf("<a")); imgClickLink = imgClickLink.substring(imgClickLink.indexOf("<a"));
@ -48,7 +49,7 @@ public class Madame extends NumberedSlashCommand {
@Override @Override
public String poll() throws IOException, InterruptedException { public String poll() throws IOException {
boolean success = false; boolean success = false;
String imgUrl = null; String imgUrl = null;
while (!success) { while (!success) {

View File

@ -1,6 +1,7 @@
package net.Broken.SlashCommands; package net.Broken.SlashCommands;
import net.Broken.BotConfigLoader; import net.Broken.BotConfigLoader;
import net.Broken.MainBot;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.SpringContext; import net.Broken.SpringContext;
import net.Broken.Tools.UserManager.Stats.UserStatsUtils; import net.Broken.Tools.UserManager.Stats.UserStatsUtils;

View File

@ -10,7 +10,7 @@ import org.apache.logging.log4j.Logger;
import java.util.List; import java.util.List;
public class CacheTools { public class CacheTools {
private static final Logger logger = LogManager.getLogger(); private static Logger logger = LogManager.getLogger();
public static void loadAllGuildMembers() { public static void loadAllGuildMembers() {
List<Guild> guilds = MainBot.jda.getGuilds(); List<Guild> guilds = MainBot.jda.getGuilds();

View File

@ -12,7 +12,7 @@ import java.util.Arrays;
*/ */
public class CommandParser { public class CommandParser {
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
/** /**
* Parse raw received string. * Parse raw received string.
@ -22,8 +22,9 @@ public class CommandParser {
* @return Readable container that contain all useful data * @return Readable container that contain all useful data
*/ */
public CommandContainer parse(String brt, MessageReceivedEvent e) { public CommandContainer parse(String brt, MessageReceivedEvent e) {
ArrayList<String> split = new ArrayList<>(); ArrayList<String> split = new ArrayList<String>();
String sansTete = brt.replaceFirst("//", ""); String brut = brt;
String sansTete = brut.replaceFirst("//", "");
String[] splitSansTete = sansTete.split(" "); String[] splitSansTete = sansTete.split(" ");
for (String s : splitSansTete) { for (String s : splitSansTete) {
@ -41,14 +42,14 @@ public class CommandParser {
logger.info("Author: " + e.getAuthor().getName() + ", Command: " + commande + ", args: " + Arrays.toString(args)); logger.info("Author: " + e.getAuthor().getName() + ", Command: " + commande + ", args: " + Arrays.toString(args));
return new CommandContainer(brt, sansTete, splitSansTete, commande, args, e); return new CommandContainer(brut, sansTete, splitSansTete, commande, args, e);
} }
/** /**
* Container * Container
*/ */
public static class CommandContainer { public class CommandContainer {
public final String brut; public final String brut;
public final String sansTete; public final String sansTete;
public final String[] splitSansTete; public final String[] splitSansTete;

View File

@ -1,18 +1,22 @@
package net.Broken.Tools.Command; package net.Broken.Tools.Command;
import net.Broken.Commande;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.Broken.Tools.FindContentOnWebPage; import net.Broken.Tools.FindContentOnWebPage;
import net.Broken.Tools.LimitChecker; import net.Broken.Tools.LimitChecker;
import net.Broken.Tools.Random.TrueRandom; import net.Broken.Tools.TrueRandom;
import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.interactions.commands.build.OptionData; import net.dv8tion.jda.api.interactions.commands.build.OptionData;
import net.dv8tion.jda.api.interactions.commands.build.SubcommandData; import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.io.IOException; import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -22,13 +26,13 @@ import java.util.concurrent.LinkedBlockingQueue;
*/ */
@Ignore @Ignore
public abstract class NumberedSlashCommand implements SlashCommand { public abstract class NumberedSlashCommand implements SlashCommand {
protected final int minNumber = 1; protected int minNumber = 1;
protected int maxNumber = -1; protected int maxNumber = -1;
protected final String baseURL; protected String baseURL;
protected final String divClass; protected String divClass;
protected final String htmlType; protected String htmlType;
protected final String urlSuffix; protected String urlSuffix;
protected final LinkedBlockingQueue<Integer> randomQueue = new LinkedBlockingQueue<>(); protected LinkedBlockingQueue<Integer> randomQueue = new LinkedBlockingQueue<>();
private Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
/** /**
@ -65,7 +69,7 @@ public abstract class NumberedSlashCommand implements SlashCommand {
try { try {
String result = poll(); String result = poll();
event.getHook().sendMessage(event.getMember().getAsMention() + "\n" + result).queue(); event.getHook().sendMessage(event.getMember().getAsMention() + "\n" + result).queue();
} catch (IOException | InterruptedException e) { } catch (IOException e) {
logger.catching(e); logger.catching(e);
MessageEmbed message = EmbedMessageUtils.getInternalError(); MessageEmbed message = EmbedMessageUtils.getInternalError();
event.getHook().setEphemeral(true).sendMessageEmbeds(message).queue(); event.getHook().setEphemeral(true).sendMessageEmbeds(message).queue();
@ -75,7 +79,7 @@ public abstract class NumberedSlashCommand implements SlashCommand {
private void fillRandomQueue() throws IOException { private void fillRandomQueue() throws IOException {
TrueRandom trueRandom = TrueRandom.getINSTANCE(); TrueRandom trueRandom = TrueRandom.getINSTANCE();
List<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber); ArrayList<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber);
randomQueue.addAll(numbers); randomQueue.addAll(numbers);
@ -89,7 +93,7 @@ public abstract class NumberedSlashCommand implements SlashCommand {
} }
} }
public String poll() throws IOException, InterruptedException { public String poll() throws IOException {
checkRandom(); checkRandom();
int randomResult = randomQueue.poll(); int randomResult = randomQueue.poll();
return FindContentOnWebPage.doYourJob(baseURL + randomResult + urlSuffix, divClass, htmlType); return FindContentOnWebPage.doYourJob(baseURL + randomResult + urlSuffix, divClass, htmlType);

View File

@ -19,7 +19,7 @@ import java.util.Set;
* Find and load bot's command * Find and load bot's command
*/ */
public class SlashCommandLoader { public class SlashCommandLoader {
private static final Logger logger = LogManager.getLogger(); private static Logger logger = LogManager.getLogger();
/** /**
* Search all implemented Command interface class and add it to MainBot.commands HashMap * Search all implemented Command interface class and add it to MainBot.commands HashMap

View File

@ -11,26 +11,46 @@ import java.util.GregorianCalendar;
* Day change listener * Day change listener
*/ */
public class DayListener extends Thread { public class DayListener extends Thread {
private static final DayListener INSTANCE = new DayListener(); private static DayListener INSTANCE = new DayListener();
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
private Calendar calendar; private Calendar calendar;
private int previousDay; private int previousDay;
/**
* List of listeners to need to be triggered
*/
private ArrayList<NewDayListener> listeners = new ArrayList<>();
private final ArrayList<NewDayListener> listeners = new ArrayList<>();
/**
* Default private constructor
*/
private DayListener() { private DayListener() {
calendar = Calendar.getInstance(); calendar = Calendar.getInstance();
previousDay = calendar.get(GregorianCalendar.DAY_OF_MONTH); previousDay = calendar.get(GregorianCalendar.DAY_OF_MONTH);
} }
/**
* Singleton
*
* @return Unique DayListener instance.
*/
public static DayListener getInstance() { public static DayListener getInstance() {
return INSTANCE; return INSTANCE;
} }
/**
* Add Listener who will be triggered
*
* @param listener
*/
public void addListener(NewDayListener listener) { public void addListener(NewDayListener listener) {
listeners.add(listener); listeners.add(listener);
} }
/**
* Trigger all listeners
*/
public void trigger() { public void trigger() {
for (NewDayListener listener : listeners) { for (NewDayListener listener : listeners) {
try { try {

View File

@ -25,8 +25,8 @@ import java.util.Optional;
*/ */
public class DailyMadame implements NewDayListener { public class DailyMadame implements NewDayListener {
private final GuildPreferenceRepository guildPreferenceRepository; private GuildPreferenceRepository guildPreferenceRepository;
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
public DailyMadame() { public DailyMadame() {
ApplicationContext context = SpringContext.getAppContext(); ApplicationContext context = SpringContext.getAppContext();
@ -78,7 +78,7 @@ public class DailyMadame implements NewDayListener {
} }
} }
} }
} catch (IOException |InterruptedException e) { } catch (IOException e) {
logger.catching(e); logger.catching(e);
} }
} }

View File

@ -1,15 +1,19 @@
package net.Broken.Tools; package net.Broken.Tools;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.Audio.UserAudioTrack;
import net.Broken.BotConfigLoader; import net.Broken.BotConfigLoader;
import net.Broken.MainBot; import net.Broken.MainBot;
import net.Broken.SpringContext; import net.Broken.SpringContext;
import net.Broken.audio.UserAudioTrack;
import net.Broken.audio.Youtube.SearchResult;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.User;
import org.springframework.context.ApplicationContext;
import java.awt.*; import java.awt.*;
import java.io.FileNotFoundException;
import java.time.Instant; import java.time.Instant;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -20,10 +24,11 @@ import java.util.Map;
public class EmbedMessageUtils { public class EmbedMessageUtils {
public static EmbedBuilder getError(String message) { public static EmbedBuilder getError(String message) {
return new EmbedBuilder() EmbedBuilder temp = new EmbedBuilder()
.setTitle(":warning: Error!") .setTitle(":warning: Error!")
.setColor(Color.red) .setColor(Color.red)
.setDescription(message); .setDescription(message);
return temp;
} }

View File

@ -3,13 +3,8 @@ package net.Broken.Tools;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
public class FindContentOnWebPage { public class FindContentOnWebPage {
/** /**
@ -21,7 +16,7 @@ public class FindContentOnWebPage {
* @return Picture URL * @return Picture URL
* @throws IOException * @throws IOException
*/ */
public static String doYourJob(String url, String divClass, String htmlType) throws IOException, InterruptedException { public static String doYourJob(String url, String divClass, String htmlType) throws IOException {
// System.out.println(url); // System.out.println(url);
String source = getSourceUrl(url); String source = getSourceUrl(url);
int divIndex = source.indexOf("class=\"" + divClass); int divIndex = source.indexOf("class=\"" + divClass);
@ -43,16 +38,18 @@ public class FindContentOnWebPage {
* @return Web page source as String * @return Web page source as String
* @throws IOException * @throws IOException
*/ */
public static String getSourceUrl(String url) throws IOException, InterruptedException { public static String getSourceUrl(String url) throws IOException {
URL urlC = new URL(url);
URLConnection yc = urlC.openConnection();
yc.setRequestProperty("User-Agent", "Googlebot/2.1 (+http://www.googlebot.com/bot.html)");
BufferedReader in = new BufferedReader(new InputStreamReader(
yc.getInputStream(), "UTF-8"));
String inputLine;
StringBuilder a = new StringBuilder();
while ((inputLine = in.readLine()) != null)
a.append(inputLine);
in.close();
HttpRequest request = HttpRequest.newBuilder() return a.toString();
.uri(URI.create(url))
.header("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
.GET()
.build();
HttpClient client = HttpClient.newHttpClient();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
return response.body();
} }
} }

View File

@ -10,7 +10,7 @@ import java.net.URL;
* Find max webPage for web site like baseURL.com/number-2/ * Find max webPage for web site like baseURL.com/number-2/
*/ */
public class LimitChecker { public class LimitChecker {
static final Logger logger = LogManager.getLogger(); static Logger logger = LogManager.getLogger();
/** /**

View File

@ -1,18 +0,0 @@
package net.Broken.Tools.Random.Data;
import com.fasterxml.jackson.annotation.JsonInclude;
import java.util.List;
@JsonInclude(JsonInclude.Include.NON_NULL)
public record RandomData(String jsonrpc, String method, int id, Params params, Error error, Result result) {
public record Params(String apiKey, int n, int min, int max, boolean replacement) {
}
public record Error(long code, String message, Object data){};
public record Result(Random random, String bitsUsed, String bitsLeft, String requestsLeft, String advisoryDelay){
public record Random(List<Integer> data, String completionTime){};
}
}

View File

@ -0,0 +1,47 @@
package net.Broken.Tools;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Scanner;
public class ResourceLoader {
private Logger logger = LogManager.getLogger();
/**
* Get file contents as string for resource folder
*
* @param fileName Requested file
* @return File contents as string
* @throws FileNotFoundException
*/
public String getFile(String fileName) throws FileNotFoundException {
StringBuilder result = new StringBuilder("");
//Get file from resources folder
ClassLoader classLoader = getClass().getClassLoader();
InputStream file = classLoader.getResourceAsStream(fileName);
if (file == null)
throw new FileNotFoundException();
try (Scanner scanner = new Scanner(file, "UTF-8")) {
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
result.append(line).append("\n");
}
scanner.close();
}
return result.toString();
}
}

View File

@ -1,14 +1,24 @@
package net.Broken.Tools; package net.Broken.Tools;
import net.Broken.DB.Entity.GuildPreferenceEntity; import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository; import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.DB.Repository.UserRepository; import net.Broken.DB.Repository.UserRepository;
import net.Broken.MainBot;
import net.Broken.RestApi.Data.Settings.GetSettingsData;
import net.Broken.RestApi.Data.Settings.PostSetSettings;
import net.Broken.RestApi.Data.Settings.Value;
import net.Broken.SpringContext; import net.Broken.SpringContext;
import net.dv8tion.jda.api.entities.Guild; import net.Broken.Tools.UserManager.UserUtils;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.*;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import java.util.ArrayList;
import java.util.List;
public class SettingsUtils { public class SettingsUtils {
private static SettingsUtils INSTANCE; private static SettingsUtils INSTANCE;
@ -27,6 +37,78 @@ public class SettingsUtils {
return (INSTANCE == null) ? new SettingsUtils() : INSTANCE; return (INSTANCE == null) ? new SettingsUtils() : INSTANCE;
} }
/**
* Check if the user have the permission to set settings
*
* @param token User token
* @param guild Guild
* @return True if user have ADMINISTRATOR permission
*/
public boolean checkPermission(String token, String guild) {
if (token == null || guild == null) {
return false;
} else {
try {
UserEntity user = UserUtils.getInstance().getUserWithApiToken(userRepository, token);
User jdaUser = MainBot.jda.getUserById(user.getDiscordId());
Guild jdaGuild = MainBot.jda.getGuildById(guild);
if (jdaGuild == null || jdaUser == null)
return false;
Member guildUser = jdaGuild.getMember(jdaUser);
if (guildUser == null)
return false;
return guildUser.hasPermission(Permission.ADMINISTRATOR);
} catch (Exception e) {
logger.debug("Unknown Token or user :" + token);
return false;
}
}
}
private List<Value> getTextChannels(Guild guild) {
List<Value> channels = new ArrayList<>();
for (TextChannel channel : guild.getTextChannels()) {
channels.add(new Value(channel.getName(), channel.getId()));
}
return channels;
}
private List<Value> getRoles(Guild guild) {
List<Value> roles = new ArrayList<>();
for (Role role : guild.getRoles()) {
roles.add(new Value(role.getName(), role.getId()));
}
return roles;
}
private List<Value> getVoiceChannels(Guild guild, List<String> selected) {
List<Value> channels = new ArrayList<>();
for (VoiceChannel voiceChannel : guild.getVoiceChannels()) {
if (selected == null)
channels.add(new Value(voiceChannel.getName(), voiceChannel.getId()));
else
channels.add(new Value(voiceChannel.getName(), voiceChannel.getId(), selected.contains(voiceChannel.getId())));
}
return channels;
}
private List<String> checkVoiceChanel(Guild guild, List<String> values) {
List<String> list = new ArrayList<>();
for (String value : values) {
if (guild.getVoiceChannelById(value) != null) {
list.add(value);
} else {
logger.error("Unknown voice channel id: " + value);
list = null;
break;
}
}
return list;
}
public GuildPreferenceEntity getPreference(Guild guild) { public GuildPreferenceEntity getPreference(Guild guild) {
return guildPreferenceRepository.findByGuildId(guild.getId()).orElseGet(()->{ return guildPreferenceRepository.findByGuildId(guild.getId()).orElseGet(()->{
logger.info("Generate default pref for " + guild.getName()); logger.info("Generate default pref for " + guild.getName());

View File

@ -1,9 +1,7 @@
package net.Broken.Tools.Random; package net.Broken.Tools;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.Broken.BotConfigLoader; import net.Broken.BotConfigLoader;
import net.Broken.SpringContext; import net.Broken.SpringContext;
import net.Broken.Tools.Random.Data.RandomData;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse; import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient; import org.apache.http.client.HttpClient;
@ -13,10 +11,11 @@ import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder; import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.charset.StandardCharsets; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TrueRandom { public class TrueRandom {
@ -32,15 +31,13 @@ public class TrueRandom {
return INSTANCE; return INSTANCE;
} }
public List<Integer> getNumbers(int min, int max) throws IOException { public ArrayList<Integer> getNumbers(int min, int max) throws IOException {
// TODO Migrate to native http client // TODO Migrate to native http client
HttpClient httpClient = HttpClientBuilder.create().build(); HttpClient httpClient = HttpClientBuilder.create().build();
RandomData postData = new RandomData("2.0", "generateIntegers", 41, new RandomData.Params(apiKey, 50, min, max, (max - min) < 50), null, null); String postVal = "{\"jsonrpc\":\"2.0\",\"method\":\"generateIntegers\",\"params\":{\"apiKey\":\"" + apiKey + "\",\"n\":50,\"min\":" + min + ",\"max\":" + max + ",\"replacement\":" + (((max - min) >= 50) ? "false" : "true") + "},\"id\":41}";
ObjectMapper mapper = new ObjectMapper(); StringEntity entity = new StringEntity(postVal, ContentType.APPLICATION_JSON);
StringEntity entity = new StringEntity(mapper.writeValueAsString(postData), ContentType.APPLICATION_JSON);
String url = "https://api.random.org/json-rpc/2/invoke"; String url = "https://api.random.org/json-rpc/2/invoke";
HttpPost request = new HttpPost(url); HttpPost request = new HttpPost(url);
request.setEntity(entity); request.setEntity(entity);
@ -57,22 +54,29 @@ public class TrueRandom {
InputStream responseIS = response.getEntity().getContent(); InputStream responseIS = response.getEntity().getContent();
String content = IOUtils.toString(responseIS, StandardCharsets.UTF_8); String content = IOUtils.toString(responseIS, "UTF-8");
logger.trace(content);
RandomData responseData = mapper.readValue(content, RandomData.class); JSONObject json = new JSONObject(content);
if (json.keySet().contains("error")) {
if (responseData.error() != null) {
logger.error("Request fail!"); logger.error("Request fail!");
logger.error("Response : " + responseData.error().message()); logger.error("Request : " + postVal);
logger.error("Response : " + content);
throw new IOException(); throw new IOException();
} }
logger.debug("Request left: " + responseData.result().requestsLeft()); logger.debug("Request left: " + json.getJSONObject("result").getInt("requestsLeft"));
logger.debug("Bits left: " + responseData.result().bitsLeft()); logger.debug("Bits left: " + json.getJSONObject("result").getInt("bitsLeft"));
logger.debug("Numbers: " + responseData.result().random().data()); logger.debug("Numbers: " + json.getJSONObject("result").getJSONObject("random").getJSONArray("data"));
return responseData.result().random().data(); List<Object> numbers = json.getJSONObject("result").getJSONObject("random").getJSONArray("data").toList();
ArrayList<Integer> converted = new ArrayList<>();
for (Object nbr : numbers) {
converted.add((Integer) nbr);
}
return converted;
} }

View File

@ -2,5 +2,16 @@ package net.Broken.Tools.UserManager.Stats;
import java.util.List; import java.util.List;
public record GuildStatsPack(int rank, GuildStats selfStats, List<GuildStats> ranking) { public class GuildStatsPack {
public int rank;
public GuildStats selfStats;
public List<GuildStats> ranking;
public GuildStatsPack(int rank, GuildStats selfStats, List<GuildStats> ranking) {
this.rank = rank;
this.selfStats = selfStats;
this.ranking = ranking;
}
} }

View File

@ -8,6 +8,8 @@ import net.Broken.MainBot;
import net.Broken.SpringContext; import net.Broken.SpringContext;
import net.Broken.Tools.CacheTools; import net.Broken.Tools.CacheTools;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.Broken.Tools.UserManager.Exceptions.UnknownTokenException;
import net.Broken.Tools.UserManager.UserUtils;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member; import net.dv8tion.jda.api.entities.Member;
@ -16,6 +18,7 @@ import net.dv8tion.jda.api.entities.User;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.security.crypto.password.PasswordEncoder;
import java.awt.*; import java.awt.*;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,22 +27,23 @@ import java.util.List;
public class UserStatsUtils { public class UserStatsUtils {
static final double XP_PER_VOICE_TIME = 0.01; static double XP_PER_VOICE_TIME = 0.01;
static final double XP_PER_MESSAGE = 4; static double XP_PER_MESSAGE = 4;
static final double XP_PER_API_COUNT = 1; static double XP_PER_API_COUNT = 1;
private static UserStatsUtils INSTANCE = new UserStatsUtils(); private static UserStatsUtils INSTANCE = new UserStatsUtils();
private final UserStatsRepository userStatsRepository; private final UserStatsRepository userStatsRepository;
private final UserRepository userRepository; private final UserRepository userRepository;
private final PasswordEncoder passwordEncoder;
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
public final HashMap<String, VoicePresenceCounter> runningCounters = new HashMap<>(); public HashMap<String, VoicePresenceCounter> runningCounters = new HashMap<>();
private UserStatsUtils() { private UserStatsUtils() {
ApplicationContext context = SpringContext.getAppContext(); ApplicationContext context = SpringContext.getAppContext();
userStatsRepository = (UserStatsRepository) context.getBean("userStatsRepository"); userStatsRepository = (UserStatsRepository) context.getBean("userStatsRepository");
userRepository = (UserRepository) context.getBean("userRepository"); userRepository = (UserRepository) context.getBean("userRepository");
passwordEncoder = (PasswordEncoder) context.getBean("passwordEncoder");
} }
@ -95,6 +99,11 @@ public class UserStatsUtils {
return userEntity.getUserStats(); return userEntity.getUserStats();
} }
public List<UserStats> getUserStats(String token) throws UnknownTokenException {
UserEntity user = UserUtils.getInstance().getUserWithApiToken(userRepository, token);
return getUserStats(user);
}
public List<UserStats> getUserStats(User user) { public List<UserStats> getUserStats(User user) {
UserEntity userEntity = userRepository.findByDiscordId(user.getId()) UserEntity userEntity = userRepository.findByDiscordId(user.getId())
.orElseGet(() -> genUserEntity(user)); .orElseGet(() -> genUserEntity(user));
@ -218,7 +227,7 @@ public class UserStatsUtils {
GuildStatsPack pack = getStatPack(userStats.getUser(), member.getGuild().getId()); GuildStatsPack pack = getStatPack(userStats.getUser(), member.getGuild().getId());
StringBuilder stringBuilder = new StringBuilder(); StringBuilder stringBuilder = new StringBuilder();
int i = 1; int i = 1;
for (GuildStats stats : pack.ranking()) { for (GuildStats stats : pack.ranking) {
if (i >= 6) { if (i >= 6) {
break; break;
} }
@ -231,15 +240,24 @@ public class UserStatsUtils {
embedBuilder.setColor(Color.yellow); embedBuilder.setColor(Color.yellow);
embedBuilder.setTitle(":trophy: " + member.getGuild().getName() + " Ranking"); embedBuilder.setTitle(":trophy: " + member.getGuild().getName() + " Ranking");
embedBuilder.addField("Top 5:", stringBuilder.toString(), false); embedBuilder.addField("Top 5:", stringBuilder.toString(), false);
String rank = switch (pack.selfStats().rank) { String rank;
case 1 -> "1st"; switch (pack.selfStats.rank) {
case 2 -> "2nd"; case 1:
case 3 -> "3rd"; rank = "1st";
default -> pack.selfStats().rank + "th"; break;
}; case 2:
rank = "2nd";
break;
case 3:
rank = "3rd";
break;
default:
rank = pack.selfStats.rank + "th";
break;
}
embedBuilder.addField("Your stats:", rank + " with " + pack.selfStats().total + " points", false); embedBuilder.addField("Your stats:", rank + " with " + pack.selfStats.total + " points", false);
return EmbedMessageUtils.buildStandar(embedBuilder); return EmbedMessageUtils.buildStandar(embedBuilder);
} }

View File

@ -1,12 +1,15 @@
package net.Broken.Tools.UserManager; package net.Broken.Tools.UserManager;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.UserRepository;
import net.Broken.Tools.UserManager.Exceptions.*;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
public class UserUtils { public class UserUtils {
private static final UserUtils INSTANCE = new UserUtils(); private static UserUtils INSTANCE = new UserUtils();
private final Logger logger = LogManager.getLogger(); private Logger logger = LogManager.getLogger();
/** /**
* Private default constructor * Private default constructor
@ -23,4 +26,21 @@ public class UserUtils {
return INSTANCE; return INSTANCE;
} }
/**
* return token's UserEntity
*
* @param userRepository User DB interface
* @param token Received token
* @return User Entity
* @throws UnknownTokenException Can't find token on User DB
*/
public UserEntity getUserWithApiToken(UserRepository userRepository, String token) throws UnknownTokenException {
// List<UserEntity> users = userRepository.findByApiToken(token);
// if (users.size() > 0) {
// return users.get(0);
// } else
// throw new UnknownTokenException();
return null;
}
} }

View File

@ -1,4 +1,4 @@
package net.Broken.Audio; package net.Broken.audio;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler; import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
@ -9,6 +9,7 @@ import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack; import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.MainBot; import net.Broken.MainBot;
import net.Broken.RestApi.Data.UserAudioTrackData;
import net.Broken.Tools.EmbedMessageUtils; import net.Broken.Tools.EmbedMessageUtils;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder; import net.dv8tion.jda.api.MessageBuilder;
@ -17,61 +18,76 @@ import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent;
import net.dv8tion.jda.api.events.interaction.SlashCommandEvent; import net.dv8tion.jda.api.events.interaction.SlashCommandEvent;
import net.dv8tion.jda.api.interactions.components.ActionRow; import net.dv8tion.jda.api.interactions.components.ActionRow;
import net.dv8tion.jda.api.interactions.components.Button; import net.dv8tion.jda.api.interactions.components.Button;
import net.dv8tion.jda.api.interactions.components.ComponentLayout;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import java.awt.*; import java.awt.*;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class GuildAudioBotService { public class AudioM {
private static final HashMap<Guild, GuildAudioBotService> INSTANCES = new HashMap<>();
private final GuildAudioManager guildAudioManager;
private final AudioPlayerManager audioPlayerManager;
private static HashMap<Guild, AudioM> INSTANCES = new HashMap<>();
/**
* Music manager for this guild
*/
private GuildMusicManager musicManager;
/**
* Audio player manager for this guild
*/
private AudioPlayerManager playerManager;
/**
* Current voice chanel (null if not connected)
*/
private VoiceChannel playedChanel;
/**
* Time out for list message
*/
private int listTimeOut = 30;
/** /**
* Extrem limit for playlist * Extrem limit for playlist
*/ */
private final int listExtremLimit = 300; private int listExtremLimit = 300;
/**
private final Guild guild; * Current guild
private final Logger logger = LogManager.getLogger(); */
private Guild guild;
private final Map<String, Boolean> addStatus = new HashMap<>(); private Logger logger = LogManager.getLogger();
private Message lastMessageWithButton; private Message lastMessageWithButton;
private GuildAudioBotService(Guild guild) { private AudioM(Guild guild) {
this.audioPlayerManager = new DefaultAudioPlayerManager(); this.playerManager = new DefaultAudioPlayerManager();
AudioSourceManagers.registerRemoteSources(audioPlayerManager); AudioSourceManagers.registerRemoteSources(playerManager);
AudioSourceManagers.registerLocalSource(audioPlayerManager); AudioSourceManagers.registerLocalSource(playerManager);
this.guildAudioManager = new GuildAudioManager(audioPlayerManager, guild);
guild.getAudioManager().setSendingHandler(guildAudioManager.getSendHandler());
this.guild = guild; this.guild = guild;
} }
public static GuildAudioBotService getInstance(Guild guild) { public static AudioM getInstance(Guild guild) {
if (!INSTANCES.containsKey(guild)) { if (!INSTANCES.containsKey(guild)) {
INSTANCES.put(guild, new GuildAudioBotService(guild)); INSTANCES.put(guild, new AudioM(guild));
} }
return INSTANCES.get(guild); return INSTANCES.get(guild);
} }
/** /**
* Load audio track from url, connect to chanel if not connected * Load audio track from url, connect to chanel if not connected
* *
* @param event
* @param voiceChannel Voice channel to connect if no connected * @param voiceChannel Voice channel to connect if no connected
* @param trackUrl Audio track url * @param trackUrl Audio track url
* @param playlistLimit Limit of playlist * @param playlistLimit Limit of playlist
* @param onHead True for adding audio track on top of playlist * @param onHead True for adding audio track on top of playlist
*/ */
public void loadAndPlay(SlashCommandEvent event, VoiceChannel voiceChannel, final String trackUrl, int playlistLimit, boolean onHead) { public void loadAndPlay(SlashCommandEvent event, VoiceChannel voiceChannel, final String trackUrl, int playlistLimit, boolean onHead) {
audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl, new AudioLoadResultHandler() { GuildMusicManager musicManager = getGuildAudioPlayer();
playedChanel = voiceChannel;
playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() {
@Override @Override
public void trackLoaded(AudioTrack track) { public void trackLoaded(AudioTrack track) {
logger.info("[" + guild + "] Single Track detected!"); logger.info("[" + guild + "] Single Track detected!");
@ -81,7 +97,7 @@ public class GuildAudioBotService {
.build(); .build();
clearLastButton(); clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
play(guild, voiceChannel, guildAudioManager, uat, onHead); play(guild, voiceChannel, musicManager, uat, onHead);
} }
@Override @Override
@ -114,43 +130,34 @@ public class GuildAudioBotService {
}); });
} }
public boolean loadAndPlaySync(String trackUrl, String userId) throws ExecutionException, InterruptedException { public void loadAndPlayAuto(String trackUrl) {
Member member = guild.getMemberById(userId); playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() {
VoiceChannel playedChanel = guild.getAudioManager().getConnectedChannel();
final String uuid = UUID.randomUUID().toString();
Future<Void> future = audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl, new AudioLoadResultHandler() {
@Override @Override
public void trackLoaded(AudioTrack track) { public void trackLoaded(AudioTrack track) {
logger.info("[" + guild + "] Auto add " + track.getInfo().title + " to playlist."); logger.info("[" + guild + "] Auto add " + track.getInfo().title + " to playlist.");
UserAudioTrack userAudioTrack = new UserAudioTrack(member.getUser(), track); UserAudioTrack userAudioTrack = new UserAudioTrack(MainBot.jda.getSelfUser(), track);
play(guild, playedChanel, guildAudioManager, userAudioTrack, true); play(guild, playedChanel, musicManager, userAudioTrack, true);
addStatus.put(uuid, true);
} }
@Override @Override
public void playlistLoaded(AudioPlaylist playlist) { public void playlistLoaded(AudioPlaylist playlist) {
AudioTrack track = playlist.getTracks().get(0); AudioTrack track = playlist.getTracks().get(0);
logger.info("[" + guild + "] Auto add " + track.getInfo().title + " to playlist."); logger.info("[" + guild + "] Auto add " + track.getInfo().title + " to playlist.");
UserAudioTrack userAudioTrack = new UserAudioTrack(member.getUser(), track); UserAudioTrack userAudioTrack = new UserAudioTrack(MainBot.jda.getSelfUser(), track);
play(guild, playedChanel, guildAudioManager, userAudioTrack, true); play(guild, playedChanel, musicManager, userAudioTrack, true);
addStatus.put(uuid, true);
} }
@Override @Override
public void noMatches() { public void noMatches() {
logger.warn("[" + guild + "] Track not found: " + trackUrl); logger.warn("[" + guild + "] Track not found: " + trackUrl);
addStatus.put(uuid, false);
} }
@Override @Override
public void loadFailed(FriendlyException exception) { public void loadFailed(FriendlyException exception) {
logger.error("[" + guild + "] Cant load media!"); logger.error("[" + guild + "] Cant load media!");
logger.error(exception.getMessage()); logger.error(exception.getMessage());
addStatus.put(uuid, false);
} }
}); });
future.get();
return addStatus.remove(uuid);
} }
@ -163,23 +170,31 @@ public class GuildAudioBotService {
* @param onHead True for adding audio track on top of playlist * @param onHead True for adding audio track on top of playlist
*/ */
public void playListLoader(AudioPlaylist playlist, int playlistLimit, User user, boolean onHead) { public void playListLoader(AudioPlaylist playlist, int playlistLimit, User user, boolean onHead) {
int i = 0;
VoiceChannel playedChanel = guild.getAudioManager().getConnectedChannel();
List<AudioTrack> tracks = playlist.getTracks(); List<AudioTrack> tracks = playlist.getTracks();
if (onHead) if (onHead)
Collections.reverse(tracks); Collections.reverse(tracks);
int i = 0;
for (AudioTrack track : playlist.getTracks()) { for (AudioTrack track : playlist.getTracks()) {
UserAudioTrack uat = new UserAudioTrack(user, track); UserAudioTrack uat = new UserAudioTrack(user, track);
play(guild, playedChanel, guildAudioManager, uat, onHead); play(guild, playedChanel, musicManager, uat, onHead);
if ((playlistLimit != -1 && i >= playlistLimit) || i > listExtremLimit)
break;
i++; i++;
if ((i >= playlistLimit && i != -1) || i > listExtremLimit)
break;
} }
} }
public GuildMusicManager getGuildAudioPlayer() {
if (musicManager == null) {
musicManager = new GuildMusicManager(playerManager, guild);
}
guild.getAudioManager().setSendingHandler(musicManager.getSendHandler());
return musicManager;
}
/** /**
* Add single track to playlist, auto-connect if not connected to vocal chanel * Add single track to playlist, auto-connect if not connected to vocal chanel
* *
@ -189,7 +204,7 @@ public class GuildAudioBotService {
* @param track Track to add to playlist * @param track Track to add to playlist
* @param onHead True for adding audio track on top of playlist * @param onHead True for adding audio track on top of playlist
*/ */
public void play(Guild guild, VoiceChannel channel, GuildAudioManager musicManager, UserAudioTrack track, boolean onHead) { public void play(Guild guild, VoiceChannel channel, GuildMusicManager musicManager, UserAudioTrack track, boolean onHead) {
if (!guild.getAudioManager().isConnected()) if (!guild.getAudioManager().isConnected())
guild.getAudioManager().openAudioConnection(channel); guild.getAudioManager().openAudioConnection(channel);
if (!onHead) if (!onHead)
@ -198,21 +213,32 @@ public class GuildAudioBotService {
musicManager.scheduler.addNext(track); musicManager.scheduler.addNext(track);
} }
public void add(SlashCommandEvent event, String url, int playListLimit, boolean onHead) { /**
if (guild.getAudioManager().isConnected()) { * Skip current track
loadAndPlay(event, guild.getAudioManager().getConnectedChannel(), url, playListLimit, onHead); *
} else { * @param event
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicError("Not connected to vocal chanel !")).build(); */
event.getHook().setEphemeral(true).sendMessage(message).queue(); public void skipTrack(GenericInteractionCreateEvent event) {
} GuildMusicManager musicManager = getGuildAudioPlayer();
} musicManager.scheduler.nextTrack();
Message message = new MessageBuilder().setEmbeds(
public void connect(VoiceChannel voiceChannel) { EmbedMessageUtils.buildStandar(
guild.getAudioManager().openAudioConnection(voiceChannel); new EmbedBuilder()
.setTitle(":track_next: Next Track")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
} }
/**
* Pause current track
*
* @param event
*/
public void pause(GenericInteractionCreateEvent event) { public void pause(GenericInteractionCreateEvent event) {
pause(); GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.pause();
Message message = new MessageBuilder().setEmbeds( Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
@ -221,23 +247,27 @@ public class GuildAudioBotService {
)).build(); )).build();
clearLastButton(); clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
} }
public void pause() { /**
guildAudioManager.scheduler.pause(); * Resume paused track
} *
* @param event
*/
public void resume(GenericInteractionCreateEvent event) { public void resume(GenericInteractionCreateEvent event) {
GuildMusicManager musicManager = getGuildAudioPlayer();
Message message; Message message;
if (guildAudioManager.player.getPlayingTrack() == null) { if(musicManager.player.getPlayingTrack() == null){
message = new MessageBuilder().setEmbeds( message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":warning: Nothing to play, playlist is empty !") .setTitle(":warning: Nothing to play, playlist is empty !")
.setColor(Color.green) .setColor(Color.green)
)).build(); )).build();
} else { }else{
resume(); musicManager.scheduler.resume();
message = new MessageBuilder().setEmbeds( message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
@ -249,73 +279,23 @@ public class GuildAudioBotService {
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
} }
public void resume() { /**
guildAudioManager.scheduler.resume(); * Print current played track info
} *
* @param event
public void skipTrack(GenericInteractionCreateEvent event) { */
skipTrack();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":track_next: Next Track")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
public void skipTrack() {
guildAudioManager.scheduler.nextTrack();
}
public void stop(GenericInteractionCreateEvent event) {
stop();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":stop_button: Playback stopped")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
public void stop() {
guildAudioManager.scheduler.stop();
guildAudioManager.scheduler.flush();
clearLastButton();
}
public void disconnect(GenericInteractionCreateEvent event) {
disconnect();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":eject: Disconnected")
.setColor(Color.green)
)).build();
clearLastButton();
event.getHook().sendMessage(message).queue();
}
public void disconnect() {
guildAudioManager.scheduler.stop();
guildAudioManager.scheduler.flush();
guild.getAudioManager().closeAudioConnection();
clearLastButton();
}
public void info(GenericInteractionCreateEvent event) { public void info(GenericInteractionCreateEvent event) {
AudioTrackInfo info = guildAudioManager.scheduler.getInfo(); GuildMusicManager musicManager = getGuildAudioPlayer();
UserAudioTrack userAudioTrack = guildAudioManager.scheduler.getCurrentPlayingTrack(); AudioTrackInfo info = musicManager.scheduler.getInfo();
UserAudioTrack userAudioTrack = musicManager.scheduler.getCurrentPlayingTrack();
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicInfo(info, userAudioTrack)).build(); Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicInfo(info, userAudioTrack)).build();
clearLastButton(); clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
} }
public void flush(GenericInteractionCreateEvent event) { public void flush(GenericInteractionCreateEvent event) {
guildAudioManager.scheduler.flush(); GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.flush();
Message message = new MessageBuilder().setEmbeds( Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
@ -332,7 +312,8 @@ public class GuildAudioBotService {
* @param event * @param event
*/ */
public void list(GenericInteractionCreateEvent event) { public void list(GenericInteractionCreateEvent event) {
List<UserAudioTrack> list = guildAudioManager.scheduler.getList(); GuildMusicManager musicManager = getGuildAudioPlayer();
List<UserAudioTrackData> list = musicManager.scheduler.getList();
if (list.size() == 0) { if (list.size() == 0) {
Message message = new MessageBuilder().setEmbeds( Message message = new MessageBuilder().setEmbeds(
@ -346,11 +327,11 @@ public class GuildAudioBotService {
} else { } else {
StringBuilder resp = new StringBuilder(); StringBuilder resp = new StringBuilder();
int i = 0; int i = 0;
for (UserAudioTrack trackInfo : list) { for (UserAudioTrackData trackInfo : list) {
resp.append(":arrow_right: "); resp.append(":arrow_right: ");
resp.append(trackInfo.getAudioTrack().getInfo().title); resp.append(trackInfo.getAudioTrackInfo().title);
resp.append(" - "); resp.append(" - ");
resp.append(trackInfo.getAudioTrack().getInfo().author); resp.append(trackInfo.getAudioTrackInfo().author);
resp.append("\n\n"); resp.append("\n\n");
if (i >= 5) { if (i >= 5) {
resp.append(":arrow_forward: And "); resp.append(":arrow_forward: And ");
@ -372,41 +353,123 @@ public class GuildAudioBotService {
} }
/**
* Called by //add, only if already connected
*
* @param event
* @param url Audio track url
* @param playListLimit Limit of playlist
* @param onHead True for adding audio track on top of playlist
*/
public void add(SlashCommandEvent event, String url, int playListLimit, boolean onHead) {
if (playedChanel != null) {
loadAndPlay(event, playedChanel, url, playListLimit, onHead);
} else {
Message message = new MessageBuilder().setEmbeds(EmbedMessageUtils.getMusicError("Not connected to vocal chanel !")).build();
event.getHook().setEphemeral(true).sendMessage(message).queue();
}
}
/**
* Stop current playing track and flush playlist
*
* @param event
*/
public void stop(GenericInteractionCreateEvent event) {
musicManager.scheduler.stop();
musicManager.scheduler.flush();
if (event != null) {
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":stop_button: Playback stopped")
.setColor(Color.green)
)).build();
clearLastButton();
lastMessageWithButton = event.getHook().sendMessage(message).addActionRow(getActionButton()).complete();
}
}
public void disconect(GenericInteractionCreateEvent event){
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.stop();
musicManager.scheduler.flush();
playedChanel = null;
guild.getAudioManager().closeAudioConnection();
clearLastButton();
Message message = new MessageBuilder().setEmbeds(
EmbedMessageUtils.buildStandar(
new EmbedBuilder()
.setTitle(":eject: Disconnected")
.setColor(Color.green)
)).build();
clearLastButton();
event.getHook().sendMessage(message).queue();
}
/**
* Stop current playing track and flush playlist (no confirmation message)
*/
public void stop() {
GuildMusicManager musicManager = getGuildAudioPlayer();
musicManager.scheduler.stop();
musicManager.scheduler.flush();
playedChanel = null;
guild.getAudioManager().closeAudioConnection();
clearLastButton();
}
public GuildMusicManager getGuildMusicManager() {
if (musicManager == null)
musicManager = getGuildAudioPlayer();
return musicManager;
}
public Guild getGuild() { public Guild getGuild() {
return guild; return guild;
} }
public GuildAudioManager getGuidAudioManager() { public AudioPlayerManager getPlayerManager() {
return guildAudioManager; return playerManager;
} }
public VoiceChannel getPlayedChanel() {
return playedChanel;
}
public void setPlayedChanel(VoiceChannel playedChanel) {
this.playedChanel = playedChanel;
}
public void clearLastButton() { public void clearLastButton() {
if (lastMessageWithButton != null) { if (lastMessageWithButton != null){
this.lastMessageWithButton.editMessageComponents(new ArrayList<>()).queue(); this.lastMessageWithButton.editMessageComponents(new ArrayList<>()).queue();
this.lastMessageWithButton = null; this.lastMessageWithButton = null;
} }
} }
public void updateLastButton(){
public void updateLastButton() {
if (lastMessageWithButton != null) if (lastMessageWithButton != null)
lastMessageWithButton = lastMessageWithButton.editMessageComponents(ActionRow.of(getActionButton())).complete(); lastMessageWithButton = lastMessageWithButton.editMessageComponents(ActionRow.of(getActionButton())).complete();
} }
private List<Button> getActionButton() { private List<Button> getActionButton(){
ArrayList<Button> buttonArrayList = new ArrayList<>(); ArrayList<Button> buttonArrayList = new ArrayList<>();
if (guildAudioManager.player.getPlayingTrack() == null) { if(musicManager.player.getPlayingTrack() == null){
buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️")).withDisabled(true)); buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️")).withDisabled(true));
buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️")).withDisabled(true)); buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️")).withDisabled(true));
buttonArrayList.add(Button.primary("stop", Emoji.fromUnicode("⏹️")).withDisabled(true)); buttonArrayList.add(Button.primary("stop", Emoji.fromUnicode("⏹️")).withDisabled(true));
buttonArrayList.add(Button.danger("disconnect", Emoji.fromUnicode("⏏️"))); buttonArrayList.add(Button.danger("disconnect", Emoji.fromUnicode("⏏️")));
return buttonArrayList; return buttonArrayList;
} }
if (guildAudioManager.player.isPaused()) { if(musicManager.player.isPaused()){
buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️"))); buttonArrayList.add(Button.success("play", Emoji.fromUnicode("▶️")));
} else { }
else{
buttonArrayList.add(Button.success("pause", Emoji.fromUnicode("⏸️"))); buttonArrayList.add(Button.success("pause", Emoji.fromUnicode("⏸️")));
} }
buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️"))); buttonArrayList.add(Button.primary("next", Emoji.fromUnicode("⏭️")));

View File

@ -1,4 +1,4 @@
package net.Broken.Audio; package net.Broken.audio;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame; import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame;
@ -33,7 +33,7 @@ public class AudioPlayerSendHandler implements AudioSendHandler {
@Override @Override
public ByteBuffer provide20MsAudio() { public ByteBuffer provide20MsAudio() {
return buffer.flip(); return (ByteBuffer) buffer.flip();
} }
@Override @Override

View File

@ -0,0 +1,47 @@
package net.Broken.audio;
import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.Tools.SettingsUtils;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.GuildChannel;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.VoiceChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
/**
* Used to find general voice channels
*/
public class GetVoiceChanels {
private static final Logger logger = LogManager.getLogger();
/**
* Search for all voice channel where the user can connect
*
* @param guild Current guild
* @return General Category
*/
public static List<VoiceChannel> find(Guild guild, Member member) {
ArrayList<VoiceChannel> list = new ArrayList<>();
VoiceChannel afk = guild.getAfkChannel();
GuildPreferenceEntity pref = SettingsUtils.getInstance().getPreference(guild);
String autoVoice = pref.getAutoVoiceChannelID();
for (VoiceChannel channel : guild.getVoiceChannels()) {
if (channel != afk && !channel.getId().equals(autoVoice) && member.getPermissions(channel).contains(Permission.VOICE_CONNECT)) {
list.add(channel);
}
}
list.sort(Comparator.comparingInt(GuildChannel::getPositionRaw));
return list;
}
}

View File

@ -1,4 +1,4 @@
package net.Broken.Audio; package net.Broken.audio;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer; import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager; import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
@ -7,7 +7,7 @@ import net.dv8tion.jda.api.entities.Guild;
/** /**
* Holder for both the player and a track scheduler for one guild. * Holder for both the player and a track scheduler for one guild.
*/ */
public class GuildAudioManager { public class GuildMusicManager {
/** /**
* Audio player for the guild. * Audio player for the guild.
*/ */
@ -24,7 +24,7 @@ public class GuildAudioManager {
* *
* @param manager Audio player manager to use for creating the player. * @param manager Audio player manager to use for creating the player.
*/ */
public GuildAudioManager(AudioPlayerManager manager, Guild guild) { public GuildMusicManager(AudioPlayerManager manager, Guild guild) {
player = manager.createPlayer(); player = manager.createPlayer();
scheduler = new TrackScheduler(player, guild); scheduler = new TrackScheduler(player, guild);
player.addListener(scheduler); player.addListener(scheduler);

View File

@ -0,0 +1,8 @@
package net.Broken.audio;
/**
* Not connected Exception (Voice Channel)
*/
public class NotConnectedException extends Exception {
}

View File

@ -0,0 +1,7 @@
package net.Broken.audio;
/**
* Null music manager
*/
public class NullMusicManager extends Exception {
}

View File

@ -0,0 +1,4 @@
package net.Broken.audio.Playlist.Exception;
public class PlaylistNotFoundException extends Exception {
}

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