Spring boot 3

This commit is contained in:
sclement 2023-12-14 17:21:23 +01:00
parent 252ee8f3be
commit 57b4583fd7
64 changed files with 670 additions and 780 deletions

View File

@ -1,4 +1,7 @@
{ {
"java.configuration.updateBuildConfiguration": "automatic", "java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "disabled" "java.compile.nullAnalysis.mode": "disabled",
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
} }

View File

@ -23,60 +23,60 @@ public class AudioController {
this.audioService = audioService; this.audioService = audioService;
} }
@GetMapping("/{guildId}/status") @GetMapping("/{guildId}/status")
@PreAuthorize("isInGuild(#guildId)") @PreAuthorize("@webSecurity.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());
} }
@PostMapping("/{guildId}/connect") @PostMapping("/{guildId}/connect")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId, #body)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId, #body)")
public ResponseEntity<Status> connect(@PathVariable String guildId, @RequestBody Connect body, Authentication authentication) { public ResponseEntity<Status> connect(@PathVariable String guildId, @RequestBody Connect body,
Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.connect(guildId, body, principal.user().getDiscordId()); return audioService.connect(guildId, body, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/disconnect") @PostMapping("/{guildId}/disconnect")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> disconnect(@PathVariable String guildId, Authentication authentication) { public ResponseEntity<Status> disconnect(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.disconnect(guildId, principal.user().getDiscordId()); return audioService.disconnect(guildId, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/resume") @PostMapping("/{guildId}/resume")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> resume(@PathVariable String guildId, Authentication authentication) { public ResponseEntity<Status> resume(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.resume(guildId, principal.user().getDiscordId()); return audioService.resume(guildId, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/pause") @PostMapping("/{guildId}/pause")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> pause(@PathVariable String guildId, Authentication authentication) { public ResponseEntity<Status> pause(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.pause(guildId, principal.user().getDiscordId()); return audioService.pause(guildId, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/skip") @PostMapping("/{guildId}/skip")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> skip(@PathVariable String guildId, Authentication authentication) { public ResponseEntity<Status> skip(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.skip(guildId, principal.user().getDiscordId()); return audioService.skip(guildId, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/stop") @PostMapping("/{guildId}/stop")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> stop(@PathVariable String guildId, Authentication authentication) { public ResponseEntity<Status> stop(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.stop(guildId, principal.user().getDiscordId()); return audioService.stop(guildId, principal.user().getDiscordId());
} }
@PostMapping("/{guildId}/add") @PostMapping("/{guildId}/add")
@PreAuthorize("isInGuild(#guildId) && canInteractWithVoiceChannel(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canInteractWithVoiceChannel(#guildId)")
public ResponseEntity<Status> add(@PathVariable String guildId, @RequestBody Add body, Authentication authentication) throws ExecutionException, InterruptedException { public ResponseEntity<Status> add(@PathVariable String guildId, @RequestBody Add body,
Authentication authentication) throws ExecutionException, InterruptedException {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return audioService.add(guildId, principal.user().getDiscordId(), body); return audioService.add(guildId, principal.user().getDiscordId(), body);
} }

View File

@ -19,7 +19,8 @@ public class AuthController {
private final JwtService jwtService; private final JwtService jwtService;
public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository, JwtService jwtService) { public AuthController(AuthenticationManager authenticationManager, UserRepository userRepository,
JwtService jwtService) {
this.authenticationManager = authenticationManager; this.authenticationManager = authenticationManager;
this.jwtService = jwtService; this.jwtService = jwtService;
} }
@ -27,14 +28,12 @@ public class AuthController {
@PostMapping("/discord") @PostMapping("/discord")
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()));
);
UserEntity user = (UserEntity) authentication.getPrincipal(); UserEntity user = (UserEntity) authentication.getPrincipal();
String jwt = jwtService.buildJwt(user); String jwt = jwtService.buildJwt(user);
return new JwtResponse(jwt); return new JwtResponse(jwt);
} }
} }

View File

@ -8,7 +8,6 @@ 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;
@RestController @RestController
@RequestMapping("/api/v2") @RequestMapping("/api/v2")
@CrossOrigin(origins = "*", maxAge = 3600) @CrossOrigin(origins = "*", maxAge = 3600)
@ -18,10 +17,7 @@ public class CrossOptionController {
/** /**
* For cross preflight request send by axios * For cross preflight request send by axios
*/ */
@RequestMapping( @RequestMapping(value = "/**", method = RequestMethod.OPTIONS)
value = "/**",
method = RequestMethod.OPTIONS
)
public ResponseEntity<String> handle() { public ResponseEntity<String> handle() {
return new ResponseEntity<>("", HttpStatus.OK); return new ResponseEntity<>("", HttpStatus.OK);
} }

View File

@ -41,21 +41,21 @@ public class GuildController {
} }
@GetMapping("/{guildId}/voiceChannels") @GetMapping("/{guildId}/voiceChannels")
@PreAuthorize("isInGuild(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId)")
public List<Channel> getVoiceChannels(@PathVariable String guildId, Authentication authentication) { public List<Channel> getVoiceChannels(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return guildService.getVoiceChannel(guildId, principal.user().getDiscordId()); return guildService.getVoiceChannel(guildId, principal.user().getDiscordId());
} }
@GetMapping("/{guildId}/textChannels") @GetMapping("/{guildId}/textChannels")
@PreAuthorize("isInGuild(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId)")
public List<Channel> getTextChannels(@PathVariable String guildId, Authentication authentication) { public List<Channel> getTextChannels(@PathVariable String guildId, Authentication authentication) {
JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal(); JwtPrincipal principal = (JwtPrincipal) authentication.getPrincipal();
return guildService.getTextChannel(guildId, principal.user().getDiscordId()); return guildService.getTextChannel(guildId, principal.user().getDiscordId());
} }
@GetMapping("/{guildId}/roles") @GetMapping("/{guildId}/roles")
@PreAuthorize("isInGuild(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId)")
public List<Role> getRoles(@PathVariable String guildId) { public List<Role> getRoles(@PathVariable String guildId) {
return guildService.getRole(guildId); return guildService.getRole(guildId);
} }

View File

@ -26,13 +26,13 @@ public class SettingController {
} }
@GetMapping("/{guildId}/values") @GetMapping("/{guildId}/values")
@PreAuthorize("isInGuild(#guildId) && canManageGuild(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.canManageGuild(#guildId)")
public List<Value> getSettingValues(@PathVariable String guildId) { public List<Value> getSettingValues(@PathVariable String guildId) {
return settingService.getValues(guildId); return settingService.getValues(guildId);
} }
@PostMapping("/{guildId}/values") @PostMapping("/{guildId}/values")
@PreAuthorize("isInGuild(#guildId) && canManageGuild(#guildId)") @PreAuthorize("@webSecurity.isInGuild(#guildId) && @webSecurity.anManageGuild(#guildId)")
public List<Value> getSettingValues(@PathVariable String guildId, @RequestBody List<Value> values) { public List<Value> getSettingValues(@PathVariable String guildId, @RequestBody List<Value> values) {
GuildPreferenceEntity pref = settingService.saveValue(guildId, values); GuildPreferenceEntity pref = settingService.saveValue(guildId, values);
return new SettingValueBuilder(pref).build(); return new SettingValueBuilder(pref).build();

View File

@ -1,6 +1,6 @@
package net.Broken.Api.Data; package net.Broken.Api.Data;
import javax.validation.constraints.NotBlank; import jakarta.validation.constraints.NotBlank;
public record Login( public record Login(
@NotBlank String code, @NotBlank String redirectUri) { @NotBlank String code, @NotBlank String redirectUri) {

View File

@ -7,6 +7,5 @@ public record PlayBackInfo(
Boolean paused, Boolean paused,
Boolean stopped, Boolean stopped,
Long progress, Long progress,
TrackInfo trackInfo TrackInfo trackInfo) {
) {
} }

View File

@ -11,6 +11,5 @@ public record Status(
Channel channel, Channel channel,
Boolean canView, Boolean canView,
Boolean canInteract, Boolean canInteract,
PlayBackInfo playBackInfo PlayBackInfo playBackInfo) {
) {
} }

View File

@ -7,7 +7,8 @@ import net.Broken.Audio.UserAudioTrack;
public record TrackInfo(UserInfo submitter, AudioTrackInfo detail) { public record TrackInfo(UserInfo submitter, AudioTrackInfo 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()),
userAudioTrack.getAudioTrack().getInfo()); userAudioTrack.getAudioTrack().getInfo());
} }
} }

View File

@ -7,8 +7,7 @@ public record SettingDescriber(
String id, String id,
String name, String name,
String description, String description,
TYPE type TYPE type) {
) {
public enum TYPE { public enum TYPE {
BOOL, LIST, STRING, ROLE, TEXT_CHANNEL, VOICE_CHANNEL BOOL, LIST, STRING, ROLE, TEXT_CHANNEL, VOICE_CHANNEL

View File

@ -8,6 +8,5 @@ import java.util.List;
public record SettingGroup( public record SettingGroup(
String name, String name,
SettingDescriber mainField, SettingDescriber mainField,
List<SettingDescriber> fields List<SettingDescriber> fields) {
) {
} }

View File

@ -28,8 +28,8 @@ public class OpenApiConfig {
new SecurityScheme().name(securitySchemeName) new SecurityScheme().name(securitySchemeName)
.type(SecurityScheme.Type.HTTP) .type(SecurityScheme.Type.HTTP)
.scheme("bearer") .scheme("bearer")
.bearerFormat("JWT")) .bearerFormat("JWT")))
).addServersItem(new Server().url("/").description("Default")) .addServersItem(new Server().url("/").description("Default"))
.info(new Info().title("ClaptrapBot API").version(versionLoader.getVersion())); .info(new Info().title("ClaptrapBot API").version(versionLoader.getVersion()));
} }
} }

View File

@ -29,10 +29,12 @@ public class DiscordAuthenticationProvider implements AuthenticationProvider {
String token = discordOauthService.getAccessToken(code, redirectUri); String token = discordOauthService.getAccessToken(code, redirectUri);
DiscordOauthUserInfo discordOauthUserInfo = discordOauthService.getUserInfo(token); DiscordOauthUserInfo discordOauthUserInfo = discordOauthService.getUserInfo(token);
discordOauthService.revokeToken(token); discordOauthService.revokeToken(token);
DiscordOauthService.LoginOrRegisterResponse<UserEntity> loginOrRegisterResponse = discordOauthService.loginOrRegisterDiscordUser(discordOauthUserInfo); DiscordOauthService.LoginOrRegisterResponse<UserEntity> loginOrRegisterResponse = discordOauthService
.loginOrRegisterDiscordUser(discordOauthUserInfo);
UserEntity userEntity = loginOrRegisterResponse.response(); UserEntity userEntity = loginOrRegisterResponse.response();
if (!loginOrRegisterResponse.created()) { if (!loginOrRegisterResponse.created()) {
userEntity = discordOauthService.updateUserInfo(discordOauthUserInfo, loginOrRegisterResponse.response()); userEntity = discordOauthService.updateUserInfo(discordOauthUserInfo,
loginOrRegisterResponse.response());
} }
return new UsernamePasswordAuthenticationToken(userEntity, null, new ArrayList<>()); return new UsernamePasswordAuthenticationToken(userEntity, null, new ArrayList<>());
} catch (OAuthLoginFail e) { } catch (OAuthLoginFail e) {

View File

@ -1,15 +1,17 @@
package net.Broken.Api.Security.Components; package net.Broken.Api.Security.Components;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
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.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException; 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.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -19,7 +21,9 @@ 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

@ -9,4 +9,3 @@ public record DiscordOauthUserInfo(
String discriminator, String discriminator,
String avatar) { String avatar) {
} }

View File

@ -1,25 +0,0 @@
package net.Broken.Api.Security.Expression;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.security.core.Authentication;
public class CustomMethodSecurityExpressionHandler
extends DefaultMethodSecurityExpressionHandler {
private final AuthenticationTrustResolver trustResolver =
new AuthenticationTrustResolverImpl();
@Override
protected MethodSecurityExpressionOperations createSecurityExpressionRoot(
Authentication authentication, MethodInvocation invocation) {
CustomMethodSecurityExpressionRoot root =
new CustomMethodSecurityExpressionRoot(authentication);
root.setPermissionEvaluator(getPermissionEvaluator());
root.setTrustResolver(this.trustResolver);
root.setRoleHierarchy(getRoleHierarchy());
return root;
}
}

View File

@ -1,102 +0,0 @@
package net.Broken.Api.Security.Expression;
import net.Broken.Api.Data.Music.Connect;
import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.MainBot;
import net.Broken.Tools.CacheTools;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion;
import org.springframework.security.access.expression.SecurityExpressionRoot;
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations;
import org.springframework.security.core.Authentication;
public class CustomMethodSecurityExpressionRoot
extends SecurityExpressionRoot
implements MethodSecurityExpressionOperations {
private Object filterObject;
private Object returnObject;
/**
* Creates a new instance
*
* @param authentication the {@link Authentication} to use. Cannot be null.
*/
public CustomMethodSecurityExpressionRoot(Authentication authentication) {
super(authentication);
}
public boolean isInGuild(String guildId){
JwtPrincipal jwtPrincipal = (JwtPrincipal) authentication.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
return CacheTools.getJdaUser(jwtPrincipal.user()).getMutualGuilds().contains(guild);
}
public boolean canManageGuild(String guildId){
JwtPrincipal jwtPrincipal = (JwtPrincipal) authentication.getPrincipal();
Member member = MainBot.jda.getGuildById(guildId).getMemberById(jwtPrincipal.user().getDiscordId());
return member.hasPermission(
Permission.MANAGE_SERVER,
Permission.MANAGE_PERMISSIONS,
Permission.MANAGE_CHANNEL
);
}
public boolean canInteractWithVoiceChannel(String guildId, Connect connectPayload){
JwtPrincipal jwtPrincipal = (JwtPrincipal) authentication.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
Member member = guild.getMemberById(jwtPrincipal.user().getDiscordId());
VoiceChannel channel = guild.getVoiceChannelById(connectPayload.channelId());
if( channel == null){
return false;
}
return (member.hasPermission(channel, Permission.VOICE_CONNECT)
|| member.getVoiceState() != null
&& member.getVoiceState().getChannel() == channel)
&& member.hasPermission(channel, Permission.VOICE_SPEAK);
}
public boolean canInteractWithVoiceChannel(String guildId) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) authentication.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
AudioChannelUnion 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
public void setFilterObject(Object filterObject) {
this.filterObject = filterObject;
}
@Override
public Object getFilterObject() {
return this.filterObject;
}
@Override
public void setReturnObject(Object returnObject) {
this.returnObject = returnObject;
}
@Override
public Object getReturnObject() {
return this.returnObject;
}
@Override
public Object getThis() {
return this;
}
}

View File

@ -0,0 +1,69 @@
package net.Broken.Api.Security.Expression;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import net.Broken.MainBot;
import net.Broken.Api.Data.Music.Connect;
import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.Tools.CacheTools;
import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.channel.concrete.VoiceChannel;
import net.dv8tion.jda.api.entities.channel.unions.AudioChannelUnion;
@Service
public class WebSecurity {
public boolean isInGuild(String guildId) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
return CacheTools.getJdaUser(jwtPrincipal.user()).getMutualGuilds().contains(guild);
}
public boolean canManageGuild(String guildId) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
Member member = MainBot.jda.getGuildById(guildId).getMemberById(jwtPrincipal.user().getDiscordId());
return member.hasPermission(
Permission.MANAGE_SERVER,
Permission.MANAGE_PERMISSIONS,
Permission.MANAGE_CHANNEL);
}
public boolean canInteractWithVoiceChannel(String guildId, Connect connectPayload) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
Member member = guild.getMemberById(jwtPrincipal.user().getDiscordId());
VoiceChannel channel = guild.getVoiceChannelById(connectPayload.channelId());
if (channel == null) {
return false;
}
return (member.hasPermission(channel, Permission.VOICE_CONNECT)
|| member.getVoiceState() != null
&& member.getVoiceState().getChannel() == channel)
&& member.hasPermission(channel, Permission.VOICE_SPEAK);
}
public boolean canInteractWithVoiceChannel(String guildId) {
JwtPrincipal jwtPrincipal = (JwtPrincipal) SecurityContextHolder.getContext().getAuthentication()
.getPrincipal();
Guild guild = MainBot.jda.getGuildById(guildId);
AudioChannelUnion 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);
}
}

View File

@ -2,6 +2,10 @@ package net.Broken.Api.Security.Filters;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws; import io.jsonwebtoken.Jws;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import net.Broken.Api.Security.Data.JwtPrincipal; import net.Broken.Api.Security.Data.JwtPrincipal;
import net.Broken.Api.Security.Services.JwtService; import net.Broken.Api.Security.Services.JwtService;
import net.Broken.BotConfigLoader; import net.Broken.BotConfigLoader;
@ -15,10 +19,6 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -32,7 +32,8 @@ public class JwtFilter extends OncePerRequestFilter {
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
@Override @Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
String authHeader = request.getHeader("Authorization"); String authHeader = request.getHeader("Authorization");
if (authHeader != null && authHeader.startsWith("Bearer ")) { if (authHeader != null && authHeader.startsWith("Bearer ")) {
String token = authHeader.replace("Bearer ", ""); String token = authHeader.replace("Bearer ", "");
@ -42,13 +43,13 @@ public class JwtFilter extends OncePerRequestFilter {
if (config.mode().equals("DEV")) { if (config.mode().equals("DEV")) {
user = userRepository.findByDiscordId(token).orElseThrow(); user = userRepository.findByDiscordId(token).orElseThrow();
principal = new JwtPrincipal("DEV", user); principal = new JwtPrincipal("DEV", user);
} } else {
else {
Jws<Claims> jwt = jwtService.verifyAndParseJwt(token); Jws<Claims> jwt = jwtService.verifyAndParseJwt(token);
user = jwtService.getUserWithJwt(jwt); user = jwtService.getUserWithJwt(jwt);
principal = new JwtPrincipal(jwt.getBody().getId(), user); principal = new JwtPrincipal(jwt.getPayload().getId(), user);
} }
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(principal, null, new ArrayList<>()); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
principal, null, new ArrayList<>());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authenticationToken); SecurityContextHolder.getContext().setAuthentication(authenticationToken);
} catch (Exception e) { } catch (Exception e) {

View File

@ -6,6 +6,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
@ -16,6 +17,7 @@ import net.Broken.Api.Security.Components.UnauthorizedHandler;
import net.Broken.Api.Security.Filters.JwtFilter; import net.Broken.Api.Security.Filters.JwtFilter;
@EnableWebSecurity @EnableWebSecurity
@EnableMethodSecurity
@Configuration @Configuration
public class SecurityConfig { public class SecurityConfig {
private final UnauthorizedHandler unauthorizedHandler; private final UnauthorizedHandler unauthorizedHandler;
@ -30,12 +32,12 @@ public class SecurityConfig {
.exceptionHandling(handling -> handling.authenticationEntryPoint(unauthorizedHandler)) .exceptionHandling(handling -> handling.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .sessionManagement(management -> management.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(requests -> requests .authorizeHttpRequests(requests -> requests
.antMatchers("/api/v2/auth/**").permitAll() .requestMatchers("/api/v2/auth/**").permitAll()
.antMatchers("/api/v2/guild/inviteLink").permitAll() .requestMatchers("/api/v2/guild/inviteLink").permitAll()
.antMatchers("/swagger-ui/**").permitAll() .requestMatchers("/swagger-ui/**").permitAll()
.antMatchers("/swagger-ui.html").permitAll() .requestMatchers("/swagger-ui.html").permitAll()
.antMatchers("/v3/api-docs/**").permitAll() .requestMatchers("/v3/api-docs/**").permitAll()
.antMatchers("/actuator/**").permitAll() .requestMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()); .anyRequest().authenticated());
http.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class); http.addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class);

View File

@ -1,31 +1,30 @@
package net.Broken.Api.Security.Services; package net.Broken.Api.Security.Services;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.UserRepository;
import org.springframework.stereotype.Service;
import java.security.Key;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.UUID; import java.util.UUID;
import javax.crypto.SecretKey;
import org.springframework.stereotype.Service;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Repository.UserRepository;
@Service @Service
public class JwtService { public class JwtService {
private final Key jwtKey; private final SecretKey jwtKey;
private final UserRepository userRepository; private final UserRepository userRepository;
public JwtService(UserRepository userRepository) { public JwtService(UserRepository userRepository) {
this.userRepository = userRepository; this.userRepository = userRepository;
this.jwtKey = Keys.secretKeyFor(SignatureAlgorithm.HS256); this.jwtKey = Jwts.SIG.HS256.key().build();
} }
public String buildJwt(UserEntity user) { public String buildJwt(UserEntity user) {
@ -36,33 +35,29 @@ public class JwtService {
Date exp = expCal.getTime(); Date exp = expCal.getTime();
UUID uuid = UUID.randomUUID(); UUID uuid = UUID.randomUUID();
return Jwts.builder() return Jwts.builder()
.setSubject(user.getUsername()) .subject(user.getUsername())
.claim("discord_id", user.getDiscordId()) .claim("discord_id", user.getDiscordId())
.claim("avatar", user.getAvatar()) .claim("avatar", user.getAvatar())
.claim("discriminator", user.getDiscriminator()) .claim("discriminator", user.getDiscriminator())
.setId(uuid.toString()) .id(uuid.toString())
.setIssuedAt(iat) .issuedAt(iat)
.setNotBefore(nbf) .notBefore(nbf)
.setExpiration(exp) .expiration(exp)
.signWith(this.jwtKey) .signWith(this.jwtKey)
.compact(); .compact();
} }
public Jws<Claims> verifyAndParseJwt(String token) { public Jws<Claims> verifyAndParseJwt(String token) {
return Jwts.parserBuilder() return Jwts.parser()
.setSigningKey(this.jwtKey) .verifyWith(this.jwtKey)
.build() .build()
.parseClaimsJws(token); .parseSignedClaims(token);
} }
public UserEntity getUserWithJwt(Jws<Claims> jwt) throws NoSuchElementException { public UserEntity getUserWithJwt(Jws<Claims> jwt) throws NoSuchElementException {
String discordId = jwt.getBody().get("discord_id", String.class); String discordId = jwt.getPayload().get("discord_id", String.class);
return userRepository.findByDiscordId(discordId) return userRepository.findByDiscordId(discordId)
.orElseThrow(); .orElseThrow();
} }

View File

@ -29,13 +29,13 @@ public class AudioService {
Guild guild = MainBot.jda.getGuildById(guildId); Guild guild = MainBot.jda.getGuildById(guildId);
Member member = guild.getMemberById(userId); Member member = guild.getMemberById(userId);
AudioChannelUnion channel = guild.getAudioManager().getConnectedChannel(); AudioChannelUnion channel = guild.getAudioManager().getConnectedChannel();
ConnectionStatus status = guild.getAudioManager().getConnectionStatus(); 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
// -> OR He can *not* view the voice channel, but he is connected to this voice channel // -> OR He can *not* view the voice channel, but he is connected to this voice
// channel
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);
@ -51,13 +51,13 @@ public class AudioService {
&& member.getVoiceState().getChannel() == channel) && member.getVoiceState().getChannel() == channel)
&& member.hasPermission(channel, Permission.VOICE_SPEAK); && member.hasPermission(channel, Permission.VOICE_SPEAK);
boolean stopped = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack() == null; boolean stopped = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack() == null;
PlayBackInfo playBackInfo; PlayBackInfo playBackInfo;
if (!stopped) { if (!stopped) {
boolean paused = guildAudioBotService.getGuidAudioManager().player.isPaused(); boolean paused = guildAudioBotService.getGuidAudioManager().player.isPaused();
long position = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack().getPosition(); long position = guildAudioBotService.getGuidAudioManager().player.getPlayingTrack().getPosition();
UserAudioTrack userAudioTrack = guildAudioBotService.getGuidAudioManager().scheduler.getCurrentPlayingTrack(); UserAudioTrack userAudioTrack = guildAudioBotService.getGuidAudioManager().scheduler
.getCurrentPlayingTrack();
playBackInfo = new PlayBackInfo(paused, false, position, new TrackInfo(userAudioTrack)); playBackInfo = new PlayBackInfo(paused, false, position, new TrackInfo(userAudioTrack));
@ -90,7 +90,6 @@ public class AudioService {
return new ResponseEntity<>(status, HttpStatus.OK); return new ResponseEntity<>(status, HttpStatus.OK);
} }
public ResponseEntity<Status> pause(String guildId, String userId) { public ResponseEntity<Status> pause(String guildId, String userId) {
Guild guild = MainBot.jda.getGuildById(guildId); Guild guild = MainBot.jda.getGuildById(guildId);
GuildAudioBotService.getInstance(guild).pause(); GuildAudioBotService.getInstance(guild).pause();
@ -119,7 +118,8 @@ public class AudioService {
return new ResponseEntity<>(status, HttpStatus.OK); return new ResponseEntity<>(status, HttpStatus.OK);
} }
public ResponseEntity<Status> add(String guildId, String userId, Add body) throws ExecutionException, InterruptedException { public ResponseEntity<Status> add(String guildId, String userId, Add body)
throws ExecutionException, InterruptedException {
Guild guild = MainBot.jda.getGuildById(guildId); Guild guild = MainBot.jda.getGuildById(guildId);
boolean success = GuildAudioBotService.getInstance(guild).loadAndPlaySync(body.url(), userId); boolean success = GuildAudioBotService.getInstance(guild).loadAndPlaySync(body.url(), userId);
if (success) { if (success) {

View File

@ -27,8 +27,7 @@ public class GuildService {
boolean canManage = guild.getMember(discordUser).hasPermission( boolean canManage = guild.getMember(discordUser).hasPermission(
Permission.MANAGE_SERVER, Permission.MANAGE_SERVER,
Permission.MANAGE_PERMISSIONS, Permission.MANAGE_PERMISSIONS,
Permission.MANAGE_CHANNEL Permission.MANAGE_CHANNEL);
);
guildList.add(new Guild(guild.getId(), guild.getName(), guild.getIconUrl(), canManage)); guildList.add(new Guild(guild.getId(), guild.getName(), guild.getIconUrl(), canManage));
} }
return guildList; return guildList;
@ -69,9 +68,9 @@ public class GuildService {
return roles; return roles;
} }
public String getInviteLink() { public String getInviteLink() {
return MainBot.jda.setRequiredScopes("applications.commands").getInviteUrl(Permission.getPermissions(1644971949399L)); return MainBot.jda.setRequiredScopes("applications.commands")
.getInviteUrl(Permission.getPermissions(1644971949399L));
} }
} }

View File

@ -19,7 +19,6 @@ public class SettingService {
public final GuildPreferenceRepository preferenceRepository; public final GuildPreferenceRepository preferenceRepository;
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
public SettingService(GuildPreferenceRepository preferenceRepository) { public SettingService(GuildPreferenceRepository preferenceRepository) {
this.preferenceRepository = preferenceRepository; this.preferenceRepository = preferenceRepository;
} }
@ -28,7 +27,6 @@ public class SettingService {
return new SettingDescriptionBuilder().build(); return new SettingDescriptionBuilder().build();
} }
public List<Value> getValues(String guildId) { public List<Value> getValues(String guildId) {
GuildPreferenceEntity pref = preferenceRepository.findByGuildId(guildId).orElseGet(() -> { GuildPreferenceEntity pref = preferenceRepository.findByGuildId(guildId).orElseGet(() -> {
logger.info("[API] : Generate default guild pref"); logger.info("[API] : Generate default guild pref");

View File

@ -1,14 +1,17 @@
package net.Broken.Audio; package net.Broken.Audio;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame;
import net.dv8tion.jda.api.audio.AudioSendHandler;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.playback.MutableAudioFrame;
import net.dv8tion.jda.api.audio.AudioSendHandler;
/** /**
* This is a wrapper around AudioPlayer which makes it behave as an AudioSendHandler for JDA. As JDA calls canProvide * This is a wrapper around AudioPlayer which makes it behave as an
* before every call to provide20MsAudio(), we pull the frame in canProvide() and use the frame we already pulled in * AudioSendHandler for JDA. As JDA calls canProvide
* before every call to provide20MsAudio(), we pull the frame in canProvide()
* and use the frame we already pulled in
* provide20MsAudio(). * provide20MsAudio().
*/ */
public class AudioPlayerSendHandler implements AudioSendHandler { public class AudioPlayerSendHandler implements AudioSendHandler {

View File

@ -80,7 +80,8 @@ public class GuildAudioBotService {
* @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(SlashCommandInteractionEvent event, AudioChannel voiceChannel, final String trackUrl, int playlistLimit, boolean onHead) { public void loadAndPlay(SlashCommandInteractionEvent event, AudioChannel voiceChannel, final String trackUrl,
int playlistLimit, boolean onHead) {
audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl, new AudioLoadResultHandler() { audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl, new AudioLoadResultHandler() {
@Override @Override
public void trackLoaded(AudioTrack track) { public void trackLoaded(AudioTrack track) {
@ -110,7 +111,8 @@ public class GuildAudioBotService {
@Override @Override
public void noMatches() { public void noMatches() {
logger.warn("[{}] Cant find media!", guild); logger.warn("[{}] Cant find media!", guild);
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getMusicError("Video not found !")).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getMusicError("Video not found !")).build();
event.getHook().setEphemeral(true).sendMessage(message).queue(); event.getHook().setEphemeral(true).sendMessage(message).queue();
} }
@ -118,7 +120,8 @@ public class GuildAudioBotService {
public void loadFailed(FriendlyException exception) { public void loadFailed(FriendlyException exception) {
logger.error("[{}] Can't load media!", guild); logger.error("[{}] Can't load media!", guild);
logger.error(exception.getMessage()); logger.error(exception.getMessage());
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getMusicError("Playback error !")).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getMusicError("Playback error !")).build();
event.getHook().setEphemeral(true).sendMessage(message).queue(); event.getHook().setEphemeral(true).sendMessage(message).queue();
} }
}); });
@ -128,7 +131,8 @@ public class GuildAudioBotService {
Member member = guild.getMemberById(userId); Member member = guild.getMemberById(userId);
AudioChannelUnion playedChanel = guild.getAudioManager().getConnectedChannel(); AudioChannelUnion playedChanel = guild.getAudioManager().getConnectedChannel();
final String uuid = UUID.randomUUID().toString(); final String uuid = UUID.randomUUID().toString();
Future<Void> future = audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl, new AudioLoadResultHandler() { Future<Void> future = audioPlayerManager.loadItemOrdered(guildAudioManager, trackUrl,
new AudioLoadResultHandler() {
@Override @Override
public void trackLoaded(AudioTrack track) { public void trackLoaded(AudioTrack track) {
logger.info("[{}] Auto add {} to playlist.", guild, track.getInfo().title); logger.info("[{}] Auto add {} to playlist.", guild, track.getInfo().title);
@ -163,7 +167,6 @@ public class GuildAudioBotService {
return addStatus.remove(uuid); return addStatus.remove(uuid);
} }
/** /**
* Load playlist to playlist * Load playlist to playlist
* *
@ -189,7 +192,6 @@ public class GuildAudioBotService {
} }
} }
/** /**
* 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
* *
@ -199,7 +201,8 @@ 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, AudioChannel channel, GuildAudioManager musicManager, UserAudioTrack track, boolean onHead) { public void play(Guild guild, AudioChannel channel, GuildAudioManager 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)
@ -212,7 +215,8 @@ public class GuildAudioBotService {
if (guild.getAudioManager().isConnected()) { if (guild.getAudioManager().isConnected()) {
loadAndPlay(event, guild.getAudioManager().getConnectedChannel(), url, playListLimit, onHead); loadAndPlay(event, guild.getAudioManager().getConnectedChannel(), url, playListLimit, onHead);
} else { } else {
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getMusicError("Not connected to vocal chanel !")).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getMusicError("Not connected to vocal chanel !")).build();
event.getHook().setEphemeral(true).sendMessage(message).queue(); event.getHook().setEphemeral(true).sendMessage(message).queue();
} }
} }
@ -227,8 +231,8 @@ public class GuildAudioBotService {
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":pause_button: Playback paused") .setTitle(":pause_button: Playback paused")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
} }
@ -244,16 +248,16 @@ public class GuildAudioBotService {
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(); resume();
message = new MessageCreateBuilder().setEmbeds( message = new MessageCreateBuilder().setEmbeds(
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":arrow_forward: Playback resumed") .setTitle(":arrow_forward: Playback resumed")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
} }
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
@ -269,8 +273,8 @@ public class GuildAudioBotService {
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":track_next: Next Track") .setTitle(":track_next: Next Track")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
} }
@ -285,8 +289,8 @@ public class GuildAudioBotService {
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":stop_button: Playback stopped") .setTitle(":stop_button: Playback stopped")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
@ -304,8 +308,8 @@ public class GuildAudioBotService {
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":eject: Disconnected") .setTitle(":eject: Disconnected")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
clearLastButton(); clearLastButton();
hook.sendMessage(message).queue(); hook.sendMessage(message).queue();
} }
@ -316,10 +320,12 @@ public class GuildAudioBotService {
guild.getAudioManager().closeAudioConnection(); guild.getAudioManager().closeAudioConnection();
clearLastButton(); clearLastButton();
} }
public void info(InteractionHook hook) { public void info(InteractionHook hook) {
AudioTrackInfo info = guildAudioManager.scheduler.getInfo(); AudioTrackInfo info = guildAudioManager.scheduler.getInfo();
UserAudioTrack userAudioTrack = guildAudioManager.scheduler.getCurrentPlayingTrack(); UserAudioTrack userAudioTrack = guildAudioManager.scheduler.getCurrentPlayingTrack();
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getMusicInfo(info, userAudioTrack)).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getMusicInfo(info, userAudioTrack)).build();
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
} }
@ -330,8 +336,8 @@ public class GuildAudioBotService {
EmbedMessageUtils.buildStandar( EmbedMessageUtils.buildStandar(
new EmbedBuilder() new EmbedBuilder()
.setTitle(":wastebasket: Playlist flushed") .setTitle(":wastebasket: Playlist flushed")
.setColor(Color.green) .setColor(Color.green)))
)).build(); .build();
clearLastButton(); clearLastButton();
lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete(); lastMessageWithButton = hook.sendMessage(message).addActionRow(getActionButton()).complete();
} }
@ -350,8 +356,8 @@ public class GuildAudioBotService {
new EmbedBuilder() new EmbedBuilder()
.setTitle(":scroll: Playlist") .setTitle(":scroll: Playlist")
.setColor(Color.green) .setColor(Color.green)
.setDescription("Oh no ! The playlist is empty !") .setDescription("Oh no ! The playlist is empty !")))
)).build(); .build();
hook.sendMessage(message).queue(); hook.sendMessage(message).queue();
} else { } else {
StringBuilder resp = new StringBuilder(); StringBuilder resp = new StringBuilder();
@ -375,8 +381,8 @@ public class GuildAudioBotService {
new EmbedBuilder() new EmbedBuilder()
.setTitle(":scroll: Playlist") .setTitle(":scroll: Playlist")
.setColor(Color.green) .setColor(Color.green)
.setDescription(resp.toString()) .setDescription(resp.toString())))
)).build(); .build();
hook.sendMessage(message).queue(); hook.sendMessage(message).queue();
} }
@ -390,7 +396,6 @@ public class GuildAudioBotService {
return guildAudioManager; return guildAudioManager;
} }
public void clearLastButton() { public void clearLastButton() {
if (lastMessageWithButton != null) { if (lastMessageWithButton != null) {
this.lastMessageWithButton.editMessageComponents(new ArrayList<>()).queue(); this.lastMessageWithButton.editMessageComponents(new ArrayList<>()).queue();
@ -401,10 +406,10 @@ public class GuildAudioBotService {
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 (guildAudioManager.player.getPlayingTrack() == null) {

View File

@ -19,7 +19,8 @@ import net.Broken.MainBot;
import net.dv8tion.jda.api.entities.Guild; import net.dv8tion.jda.api.entities.Guild;
/** /**
* This class schedules tracks for the audio player. It contains the queue of tracks. * This class schedules tracks for the audio player. It contains the queue of
* tracks.
*/ */
public class TrackScheduler extends AudioEventAdapter { public class TrackScheduler extends AudioEventAdapter {
private final AudioPlayer player; private final AudioPlayer player;
@ -46,8 +47,10 @@ public class TrackScheduler extends AudioEventAdapter {
* @param track The track to play or add to queue. * @param track The track to play or add to queue.
*/ */
public void queue(UserAudioTrack track) { public void queue(UserAudioTrack track) {
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If // Calling startTrack with the noInterrupt set to true will start the track only
// something is playing, it returns false and does nothing. In that case the player was already playing so this // if nothing is currently playing. If
// something is playing, it returns false and does nothing. In that case the
// player was already playing so this
// track goes to the queue instead. // track goes to the queue instead.
if (track.getSubmittedUser() != MainBot.jda.getSelfUser()) { if (track.getSubmittedUser() != MainBot.jda.getSelfUser()) {
logger.debug("[" + guild + "] Flush history"); logger.debug("[" + guild + "] Flush history");
@ -66,8 +69,10 @@ public class TrackScheduler extends AudioEventAdapter {
* @param track * @param track
*/ */
public void addNext(UserAudioTrack track) { public void addNext(UserAudioTrack track) {
// Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If // Calling startTrack with the noInterrupt set to true will start the track only
// something is playing, it returns false and does nothing. In that case the player was already playing so this // if nothing is currently playing. If
// something is playing, it returns false and does nothing. In that case the
// player was already playing so this
// track goes to the queue instead. // track goes to the queue instead.
if (!player.startTrack(track.getAudioTrack(), true)) { if (!player.startTrack(track.getAudioTrack(), true)) {
queue.addFirst(track); queue.addFirst(track);
@ -134,8 +139,10 @@ public class TrackScheduler extends AudioEventAdapter {
* Start the next track, stopping the current one if it is playing. * Start the next track, stopping the current one if it is playing.
*/ */
public void nextTrack() { public void nextTrack() {
// Start the next track, regardless of if something is already playing or not. In case queue was empty, we are // Start the next track, regardless of if something is already playing or not.
// giving null to startTrack, which is a valid argument and will simply stop the player. // In case queue was empty, we are
// giving null to startTrack, which is a valid argument and will simply stop the
// player.
UserAudioTrack track = queue.poll(); UserAudioTrack track = queue.poll();
if (track != null) { if (track != null) {
this.currentPlayingTrack = track; this.currentPlayingTrack = track;
@ -145,7 +152,8 @@ public class TrackScheduler extends AudioEventAdapter {
@Override @Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) { public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
// Only start the next track if the end reason is suitable for it (FINISHED or LOAD_FAILED) // Only start the next track if the end reason is suitable for it (FINISHED or
// LOAD_FAILED)
if (endReason.mayStartNext) { if (endReason.mayStartNext) {
if (queue.isEmpty()) { if (queue.isEmpty()) {
logger.debug("[" + guild.getName() + "] End of track, Playlist empty."); logger.debug("[" + guild.getName() + "] End of track, Playlist empty.");
@ -155,7 +163,6 @@ public class TrackScheduler extends AudioEventAdapter {
nextTrack(); nextTrack();
} }
} }
} }

View File

@ -1,13 +1,11 @@
package net.Broken; package net.Broken;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;
@ConfigurationProperties(prefix = "discord.bot") @ConfigurationProperties(prefix = "discord.bot")
@ConstructorBinding
public record BotConfigLoader( public record BotConfigLoader(
String token, String token,
String url, String url,
String mode, String mode,
String randomApiKey String randomApiKey) {
){} }

View File

@ -1,6 +1,5 @@
package net.Broken; package net.Broken;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
/** /**
@ -43,5 +42,4 @@ public interface Commande {
*/ */
boolean isNSFW(); boolean isNSFW();
} }

View File

@ -1,6 +1,10 @@
package net.Broken.DB.Entity; package net.Broken.DB.Entity;
import javax.persistence.*; import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
@Entity @Entity
public class GuildPreferenceEntity { public class GuildPreferenceEntity {
@ -27,7 +31,6 @@ public class GuildPreferenceEntity {
private String autoVoiceChannelID; private String autoVoiceChannelID;
private String autoVoiceChannelTitle; private String autoVoiceChannelTitle;
public GuildPreferenceEntity(String guildId, public GuildPreferenceEntity(String guildId,
boolean welcome, boolean welcome,
String welcomeMessage, String welcomeMessage,
@ -53,9 +56,9 @@ public class GuildPreferenceEntity {
public GuildPreferenceEntity() { public GuildPreferenceEntity() {
} }
public static GuildPreferenceEntity getDefault(String guildId) { public static GuildPreferenceEntity getDefault(String guildId) {
return new GuildPreferenceEntity(guildId, false, "Welcome to this awesome server @name! ", null, false, null, true, false, null, null); return new GuildPreferenceEntity(guildId, false, "Welcome to this awesome server @name! ", null, false, null,
true, false, null, null);
} }
public Integer getId() { public Integer getId() {

View File

@ -1,12 +1,19 @@
package net.Broken.DB.Entity; package net.Broken.DB.Entity;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToMany;
import net.Broken.Api.Security.Data.DiscordOauthUserInfo; 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 java.util.List;
/** /**
* Entity for DB. Represent confirmed user account. * Entity for DB. Represent confirmed user account.
*/ */
@ -51,7 +58,6 @@ public class UserEntity {
this.avatar = discordOauthUserInfo.avatar(); this.avatar = discordOauthUserInfo.avatar();
} }
public Integer getId() { public Integer getId() {
return id; return id;
} }

View File

@ -2,7 +2,12 @@ package net.Broken.DB.Entity;
import org.hibernate.annotations.ColumnDefault; import org.hibernate.annotations.ColumnDefault;
import javax.persistence.*; import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
@Entity @Entity
public class UserStats { public class UserStats {
@ -11,7 +16,6 @@ public class UserStats {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
private String guildId; private String guildId;
@ManyToOne @ManyToOne

View File

@ -1,9 +1,10 @@
package net.Broken.DB.Repository; package net.Broken.DB.Repository;
import net.Broken.DB.Entity.GuildPreferenceEntity; import java.util.Optional;
import org.springframework.data.repository.CrudRepository; import org.springframework.data.repository.CrudRepository;
import java.util.Optional; import net.Broken.DB.Entity.GuildPreferenceEntity;
public interface GuildPreferenceRepository extends CrudRepository<GuildPreferenceEntity, Integer> { public interface GuildPreferenceRepository extends CrudRepository<GuildPreferenceEntity, Integer> {
Optional<GuildPreferenceEntity> findByGuildId(String id); Optional<GuildPreferenceEntity> findByGuildId(String id);

View File

@ -16,12 +16,11 @@ 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;
public class Init { public class Init {
static private final Logger logger = LogManager.getLogger(); static private final Logger logger = LogManager.getLogger();
private Init() {} private Init() {
}
static JDA initJda(BotConfigLoader config) { static JDA initJda(BotConfigLoader config) {
logger.info("-----------------------INIT-----------------------"); logger.info("-----------------------INIT-----------------------");
@ -55,7 +54,6 @@ public class Init {
} }
} }
static void polish(JDA jda, BotConfigLoader config) { static void polish(JDA jda, BotConfigLoader config) {
logger.info("Check database..."); logger.info("Check database...");
checkDatabase(); checkDatabase();
@ -71,7 +69,6 @@ public class Init {
logger.info("-----------------------END INIT-----------------------"); logger.info("-----------------------END INIT-----------------------");
} }
private static void checkDatabase() { private static void checkDatabase() {
ApplicationContext context = SpringContext.getAppContext(); ApplicationContext context = SpringContext.getAppContext();
logger.debug("Stats..."); logger.debug("Stats...");
@ -110,6 +107,5 @@ public class Init {
} }
} }
} }
} }

View File

@ -10,6 +10,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import java.util.HashMap; import java.util.HashMap;
@ -28,7 +29,6 @@ public class MainBot {
public static int messageTimeOut = 10; public static int messageTimeOut = 10;
public static int gifMessageTimeOut = 30; public static int gifMessageTimeOut = 30;
private static final Logger logger = LogManager.getLogger(); private static final Logger logger = LogManager.getLogger();
public static void main(String[] args) { public static void main(String[] args) {
@ -56,8 +56,7 @@ public class MainBot {
@Bean @Bean
public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() { public static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
PropertySourcesPlaceholderConfigurer propsConfig PropertySourcesPlaceholderConfigurer propsConfig = new PropertySourcesPlaceholderConfigurer();
= new PropertySourcesPlaceholderConfigurer();
propsConfig.setLocation(new ClassPathResource("git.properties")); propsConfig.setLocation(new ClassPathResource("git.properties"));
propsConfig.setIgnoreResourceNotFound(true); propsConfig.setIgnoreResourceNotFound(true);
propsConfig.setIgnoreUnresolvablePlaceholders(true); propsConfig.setIgnoreUnresolvablePlaceholders(true);

View File

@ -54,7 +54,8 @@ public class Cat implements SlashCommand {
} catch (InterruptedException | IOException e) { } catch (InterruptedException | IOException e) {
logger.catching(e); logger.catching(e);
event.reply(new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getInternalError()).build()).setEphemeral(true) event.reply(new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getInternalError()).build())
.setEphemeral(true)
.queue(); .queue();
} }

View File

@ -16,7 +16,6 @@ import net.dv8tion.jda.api.interactions.commands.build.SubcommandData;
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder; import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
import net.dv8tion.jda.api.utils.messages.MessageCreateData; import net.dv8tion.jda.api.utils.messages.MessageCreateData;
public class Clear implements SlashCommand { public class Clear implements SlashCommand {
@Override @Override
public void action(SlashCommandInteractionEvent event) { public void action(SlashCommandInteractionEvent event) {
@ -26,7 +25,9 @@ public class Clear implements SlashCommand {
MessageChannel chanel = event.getChannel(); MessageChannel chanel = event.getChannel();
chanel.getIterableHistory().takeAsync((int) n).thenAccept(chanel::purgeMessages); chanel.getIterableHistory().takeAsync((int) n).thenAccept(chanel::purgeMessages);
} else { } else {
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getFlushError("You are not a supreme being, you cannot do that !")).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getFlushError("You are not a supreme being, you cannot do that !"))
.build();
event.reply(message).setEphemeral(true).queue(); event.reply(message).setEphemeral(true).queue();
} }
} }
@ -68,5 +69,4 @@ public class Clear implements SlashCommand {
return DefaultMemberPermissions.enabledFor(Permission.MESSAGE_MANAGE); return DefaultMemberPermissions.enabledFor(Permission.MESSAGE_MANAGE);
} }
} }

View File

@ -1,6 +1,5 @@
package net.Broken.SlashCommands; package net.Broken.SlashCommands;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -46,7 +45,8 @@ public class Music implements SlashCommand {
audio.loadAndPlay(event, voiceChanel, url.getAsString(), (int) limit, false); audio.loadAndPlay(event, voiceChanel, url.getAsString(), (int) limit, false);
} }
} else { } else {
MessageCreateData message = new MessageCreateBuilder().setEmbeds(EmbedMessageUtils.getMusicError("You are not in a voice channel !")).build(); MessageCreateData message = new MessageCreateBuilder()
.setEmbeds(EmbedMessageUtils.getMusicError("You are not in a voice channel !")).build();
event.getHook().setEphemeral(true).sendMessage(message).queue(); event.getHook().setEphemeral(true).sendMessage(message).queue();
} }
break; break;
@ -103,11 +103,14 @@ public class Music implements SlashCommand {
ArrayList<SubcommandData> subCommandList = new ArrayList<>(); ArrayList<SubcommandData> subCommandList = new ArrayList<>();
subCommandList.add(new SubcommandData("play", "Play music") subCommandList.add(new SubcommandData("play", "Play music")
.addOption(OptionType.STRING, "url", "The URL of the video to play", true) .addOption(OptionType.STRING, "url", "The URL of the video to play", true)
.addOption(OptionType.INTEGER, PLAYLIST_LIMIT, "If a playlist is loaded, enter the max number of loaded tracks (default to 30)")); .addOption(OptionType.INTEGER, PLAYLIST_LIMIT,
"If a playlist is loaded, enter the max number of loaded tracks (default to 30)"));
subCommandList.add(new SubcommandData("add", "Add track to queue") subCommandList.add(new SubcommandData("add", "Add track to queue")
.addOption(OptionType.STRING, "url", " The URL of the video to play", true) .addOption(OptionType.STRING, "url", " The URL of the video to play", true)
.addOption(OptionType.BOOLEAN, "next", "If true, track will be added on top of the playlist and will be the next to play") .addOption(OptionType.BOOLEAN, "next",
.addOption(OptionType.INTEGER, PLAYLIST_LIMIT, "If a playlist is loaded, enter the max number of loaded tracks (default to 30)")); "If true, track will be added on top of the playlist and will be the next to play")
.addOption(OptionType.INTEGER, PLAYLIST_LIMIT,
"If a playlist is loaded, enter the max number of loaded tracks (default to 30)"));
subCommandList.add(new SubcommandData("pause", "Pause playback")); subCommandList.add(new SubcommandData("pause", "Pause playback"));
subCommandList.add(new SubcommandData("resume", "Resume playback")); subCommandList.add(new SubcommandData("resume", "Resume playback"));
subCommandList.add(new SubcommandData("stop", "Stop playback")); subCommandList.add(new SubcommandData("stop", "Stop playback"));
@ -118,7 +121,6 @@ public class Music implements SlashCommand {
return subCommandList; return subCommandList;
} }
/** /**
* Determines if the command is usable only by bot level admin user * Determines if the command is usable only by bot level admin user
* *
@ -144,5 +146,4 @@ public class Music implements SlashCommand {
return DefaultMemberPermissions.ENABLED; return DefaultMemberPermissions.ENABLED;
} }
} }

View File

@ -1,13 +1,13 @@
package net.Broken.SlashCommands.Over18; package net.Broken.SlashCommands.Over18;
import org.apache.logging.log4j.LogManager;
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.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import org.apache.logging.log4j.LogManager;
@NoDev @NoDev
@Ignore @Ignore
public class Ass extends NumberedSlashCommand { public class Ass extends NumberedSlashCommand {
@ -16,7 +16,6 @@ public class Ass extends NumberedSlashCommand {
super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img"); super(LogManager.getLogger(), "http://les400culs.com/", "-2/", "featured-img", "img");
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "Return random image from les400culs.com"; return "Return random image from les400culs.com";

View File

@ -6,7 +6,6 @@ import net.Broken.Tools.Command.NumberedSlashCommand;
import net.dv8tion.jda.api.Permission; import net.dv8tion.jda.api.Permission;
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions; import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -19,7 +18,6 @@ public class Boobs extends NumberedSlashCommand {
super(LogManager.getLogger(), "http://lesaintdesseins.fr/", "-2/", "featured-img", "img"); super(LogManager.getLogger(), "http://lesaintdesseins.fr/", "-2/", "featured-img", "img");
} }
@Override @Override
public String getDescription() { public String getDescription() {
return "Return random image from les400culs.com"; return "Return random image from les400culs.com";

View File

@ -17,6 +17,7 @@ public class Madame extends NumberedSlashCommand {
public Madame() { public Madame() {
super(LogManager.getLogger(), "https://www.bonjourmadame.fr/page/", "/"); super(LogManager.getLogger(), "https://www.bonjourmadame.fr/page/", "/");
} }
/** /**
* Detect if picture link go to Tepeee * Detect if picture link go to Tepeee
* *
@ -25,7 +26,8 @@ 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, InterruptedException {
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 +50,6 @@ public class Madame extends NumberedSlashCommand {
return url; return url;
} }
@Override @Override
public String poll() throws IOException, InterruptedException { public String poll() throws IOException, InterruptedException {
boolean success = false; boolean success = false;
@ -61,7 +62,6 @@ public class Madame extends NumberedSlashCommand {
logger.debug("URL: {}", url); logger.debug("URL: {}", url);
if (scanPageForTipeee(url, logger)) { if (scanPageForTipeee(url, logger)) {
logger.debug("Advertisement detected! Retry! ({})", url); logger.debug("Advertisement detected! Retry! ({})", url);
} else { } else {

View File

@ -1,5 +1,8 @@
package net.Broken.SlashCommands; package net.Broken.SlashCommands;
import java.util.Collections;
import java.util.List;
import net.Broken.BotConfigLoader; import net.Broken.BotConfigLoader;
import net.Broken.SlashCommand; import net.Broken.SlashCommand;
import net.Broken.SpringContext; import net.Broken.SpringContext;
@ -11,9 +14,6 @@ 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 net.dv8tion.jda.api.interactions.components.buttons.Button; import net.dv8tion.jda.api.interactions.components.buttons.Button;
import java.util.Collections;
import java.util.List;
public class Rank implements SlashCommand { public class Rank implements SlashCommand {
@Override @Override
public void action(SlashCommandInteractionEvent event) { public void action(SlashCommandInteractionEvent event) {
@ -22,8 +22,7 @@ public class Rank implements SlashCommand {
UserStatsUtils userStats = UserStatsUtils.getINSTANCE(); UserStatsUtils userStats = UserStatsUtils.getINSTANCE();
MessageEmbed messageEmbed = userStats.getRankMessage(event.getMember()); MessageEmbed messageEmbed = userStats.getRankMessage(event.getMember());
event.getHook().sendMessageEmbeds(messageEmbed).addActionRow( event.getHook().sendMessageEmbeds(messageEmbed).addActionRow(
Button.link("https://" + url + "/rank", "More stats") Button.link("https://" + url + "/rank", "More stats")).queue();
).queue();
} }
@Override @Override

View File

@ -1,6 +1,5 @@
package net.Broken.Tools; package net.Broken.Tools;
import static net.Broken.MainBot.jda; import static net.Broken.MainBot.jda;
import java.util.HashMap; import java.util.HashMap;

View File

@ -1,12 +1,13 @@
package net.Broken.Tools.Command; package net.Broken.Tools.Command;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
/** /**
* *
*/ */
@ -38,7 +39,6 @@ public class CommandParser {
for (int i = 0; i < args.length; i++) for (int i = 0; i < args.length; i++)
args[i] = args[i].replace('$', ' '); args[i] = args[i].replace('$', ' ');
logger.info("Author: {}, Command: {}, args: {}", e.getAuthor().getName(), commande, Arrays.toString(args)); logger.info("Author: {}, Command: {}, args: {}", e.getAuthor().getName(), commande, Arrays.toString(args));
return new CommandContainer(brt, sansTete, splitSansTete, commande, args, e); return new CommandContainer(brt, sansTete, splitSansTete, commande, args, e);
@ -56,7 +56,8 @@ public class CommandParser {
public final String[] args; public final String[] args;
public final MessageReceivedEvent event; public final MessageReceivedEvent event;
public CommandContainer(String brut, String sansTete, String[] splitSansTete, String commande, String[] args, MessageReceivedEvent e) { public CommandContainer(String brut, String sansTete, String[] splitSansTete, String commande, String[] args,
MessageReceivedEvent e) {
this.brut = brut; this.brut = brut;
this.sansTete = sansTete; this.sansTete = sansTete;
this.splitSansTete = splitSansTete; this.splitSansTete = splitSansTete;

View File

@ -19,7 +19,8 @@ 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;
/** /**
* Abstact class used for all command that need to find the max number of page on a web site. * Abstact class used for all command that need to find the max number of page
* on a web site.
*/ */
@Ignore @Ignore
public abstract class NumberedSlashCommand implements SlashCommand { public abstract class NumberedSlashCommand implements SlashCommand {
@ -73,7 +74,6 @@ 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); List<Integer> numbers = trueRandom.getNumbers(minNumber, maxNumber);

View File

@ -16,25 +16,25 @@ import net.dv8tion.jda.api.interactions.commands.build.Commands;
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData; import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction; import net.dv8tion.jda.api.requests.restaction.CommandListUpdateAction;
/** /**
* 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 final Logger logger = LogManager.getLogger();
private SlashCommandLoader() {} private SlashCommandLoader() {
}
/** /**
* 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
*/ */
public static void load(BotConfigLoader config) { public static void load(BotConfigLoader config) {
logger.info("Loading Slash Command..."); logger.info("Loading Slash Command...");
Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage( Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(
"net.Broken.SlashCommands", "net.Broken.SlashCommands",
ClasspathHelper.contextClassLoader(), ClasspathHelper.contextClassLoader(),
ClasspathHelper.staticClassLoader())) ClasspathHelper.staticClassLoader())));
);
Set<Class<? extends SlashCommand>> modules = reflections.getSubTypesOf(SlashCommand.class); Set<Class<? extends SlashCommand>> modules = reflections.getSubTypesOf(SlashCommand.class);
logger.info("Find {} Command:", modules.size()); logger.info("Find {} Command:", modules.size());
@ -51,8 +51,8 @@ public class SlashCommandLoader {
} else { } else {
try { try {
MainBot.slashCommands.put(name, command.getDeclaredConstructor().newInstance()); MainBot.slashCommands.put(name, command.getDeclaredConstructor().newInstance());
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | } catch (InstantiationException | IllegalAccessException | InvocationTargetException
NoSuchMethodException e) { | NoSuchMethodException e) {
logger.error("Failed to load {} !", name); logger.error("Failed to load {} !", name);
} }
} }

View File

@ -1,12 +1,12 @@
package net.Broken.Tools.DayListener; package net.Broken.Tools.DayListener;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/** /**
* Day change listener * Day change listener
*/ */
@ -42,7 +42,6 @@ public class DayListener extends Thread {
} }
} }
/** /**
* Thread loop * Thread loop
*/ */

View File

@ -1,19 +1,5 @@
package net.Broken.Tools.DayListener.Listeners; package net.Broken.Tools.DayListener.Listeners;
import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.MainBot;
import net.Broken.SlashCommands.Over18.Madame;
import net.Broken.SpringContext;
import net.Broken.Tools.DayListener.NewDayListener;
import net.Broken.Tools.FindContentOnWebPage;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import java.io.IOException; import java.io.IOException;
import java.time.LocalDate; import java.time.LocalDate;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
@ -21,6 +7,20 @@ import java.util.Calendar;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import net.Broken.MainBot;
import net.Broken.SpringContext;
import net.Broken.DB.Entity.GuildPreferenceEntity;
import net.Broken.DB.Repository.GuildPreferenceRepository;
import net.Broken.SlashCommands.Over18.Madame;
import net.Broken.Tools.FindContentOnWebPage;
import net.Broken.Tools.DayListener.NewDayListener;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel;
/** /**
* Daily Listener for DailyMadame * Daily Listener for DailyMadame
*/ */
@ -52,7 +52,6 @@ public class DailyMadame implements NewDayListener {
imgUrl = command.poll(); imgUrl = command.poll();
} }
for (Guild guild : guilds) { for (Guild guild : guilds) {
TextChannel chanel = null; TextChannel chanel = null;
logger.debug(guild.getName()); logger.debug(guild.getName());

View File

@ -1,19 +1,20 @@
package net.Broken.Tools; package net.Broken.Tools;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo; import java.awt.Color;
import net.Broken.Audio.UserAudioTrack;
import net.Broken.BotConfigLoader;
import net.Broken.MainBot;
import net.Broken.SpringContext;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
import java.awt.*;
import java.time.Instant; import java.time.Instant;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
import net.Broken.BotConfigLoader;
import net.Broken.MainBot;
import net.Broken.SpringContext;
import net.Broken.Audio.UserAudioTrack;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.MessageEmbed;
/** /**
* Pre build Message Embed * Pre build Message Embed
*/ */
@ -26,7 +27,6 @@ public class EmbedMessageUtils {
.setDescription(message); .setDescription(message);
} }
public static MessageEmbed getMusicError(String message) { public static MessageEmbed getMusicError(String message) {
return buildStandar(new EmbedBuilder() return buildStandar(new EmbedBuilder()
.setTitle(":warning: Musique Error") .setTitle(":warning: Musique Error")
@ -63,8 +63,7 @@ public class EmbedMessageUtils {
if (playlistSize != -1) { if (playlistSize != -1) {
temp.addField("Loaded tracks", Integer.toString(playlistSize), true) temp.addField("Loaded tracks", Integer.toString(playlistSize), true)
.setTitle(":loud_sound: Playlist added to queue"); .setTitle(":loud_sound: Playlist added to queue");
} } else {
else {
temp.setTitle(":loud_sound: Track added to queue"); temp.setTitle(":loud_sound: Track added to queue");
} }
temp.addField("URL", info.uri, false); temp.addField("URL", info.uri, false);
@ -78,10 +77,10 @@ public class EmbedMessageUtils {
.setColor(Color.red)); .setColor(Color.red));
} }
public static MessageEmbed getInternalError() { public static MessageEmbed getInternalError() {
return buildStandar( return buildStandar(
getError("I... I... I don't feel so good ~~mr stark~~... :thermometer_face: \nPlease contact my developer!") getError(
"I... I... I don't feel so good ~~mr stark~~... :thermometer_face: \nPlease contact my developer!")
.setImage("https://i.imgur.com/anKv8U5.gif")); .setImage("https://i.imgur.com/anKv8U5.gif"));
} }
@ -94,7 +93,8 @@ public class EmbedMessageUtils {
} }
public static MessageEmbed getUnautorized() { public static MessageEmbed getUnautorized() {
return buildStandar(getError("You're not powerful enough to do that slave !").setImage("https://i.imgur.com/0OSsdvW.gif")); return buildStandar(
getError("You're not powerful enough to do that slave !").setImage("https://i.imgur.com/0OSsdvW.gif"));
} }
public static MessageEmbed getLastMessageFromTextChannel(HashMap<String, String> message) { public static MessageEmbed getLastMessageFromTextChannel(HashMap<String, String> message) {
@ -118,5 +118,4 @@ public class EmbedMessageUtils {
.build(); .build();
} }
} }

View File

@ -16,7 +16,8 @@ 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, InterruptedException {
// 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);
@ -42,7 +43,8 @@ public class FindContentOnWebPage {
HttpRequest request = HttpRequest.newBuilder() HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url)) .uri(URI.create(url))
.header("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)") .header("User-Agent",
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
.GET() .GET()
.build(); .build();
HttpClient client = HttpClient.newHttpClient(); HttpClient client = HttpClient.newHttpClient();

View File

@ -11,7 +11,6 @@ import org.apache.logging.log4j.Logger;
public class LimitChecker { public class LimitChecker {
static final Logger logger = LogManager.getLogger(); static final Logger logger = LogManager.getLogger();
/** /**
* Check max page url for web site like baseURL.com/number-2/ * Check max page url for web site like baseURL.com/number-2/
* *
@ -74,6 +73,5 @@ public class LimitChecker {
logger.debug("Final pass: " + number); logger.debug("Final pass: " + number);
return number; return number;
} }
} }

View File

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

View File

@ -1,9 +1,10 @@
package net.Broken.Tools.Random; package net.Broken.Tools.Random;
import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException;
import net.Broken.BotConfigLoader; import java.io.InputStream;
import net.Broken.SpringContext; import java.nio.charset.StandardCharsets;
import net.Broken.Tools.Random.Data.RandomData; import java.util.List;
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;
@ -14,16 +15,18 @@ 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 java.io.IOException; import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.InputStream;
import java.nio.charset.StandardCharsets; import net.Broken.BotConfigLoader;
import java.util.List; import net.Broken.SpringContext;
import net.Broken.Tools.Random.Data.RandomData;
public class TrueRandom { public class TrueRandom {
private static final TrueRandom INSTANCE = new TrueRandom(); private static final TrueRandom INSTANCE = new TrueRandom();
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
private final String apiKey; private final String apiKey;
private TrueRandom() { private TrueRandom() {
apiKey = SpringContext.getAppContext().getBean(BotConfigLoader.class).randomApiKey(); apiKey = SpringContext.getAppContext().getBean(BotConfigLoader.class).randomApiKey();
} }
@ -37,7 +40,8 @@ public class TrueRandom {
// 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); RandomData postData = new RandomData("2.0", "generateIntegers", 41,
new RandomData.Params(apiKey, 50, min, max, (max - min) < 50), null, null);
ObjectMapper mapper = new ObjectMapper(); ObjectMapper mapper = new ObjectMapper();
StringEntity entity = new StringEntity(mapper.writeValueAsString(postData), ContentType.APPLICATION_JSON); StringEntity entity = new StringEntity(mapper.writeValueAsString(postData), ContentType.APPLICATION_JSON);
@ -55,7 +59,6 @@ public class TrueRandom {
throw new IOException(); throw new IOException();
} }
InputStream responseIS = response.getEntity().getContent(); InputStream responseIS = response.getEntity().getContent();
String content = IOUtils.toString(responseIS, StandardCharsets.UTF_8); String content = IOUtils.toString(responseIS, StandardCharsets.UTF_8);

View File

@ -38,5 +38,4 @@ public class Redirection {
return urlReturn; return urlReturn;
} }
} }

View File

@ -1,11 +1,11 @@
package net.Broken.Tools.Settings; package net.Broken.Tools.Settings;
import net.Broken.Api.Data.Settings.SettingDescriber;
import net.Broken.Api.Data.Settings.SettingGroup;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.Broken.Api.Data.Settings.SettingDescriber;
import net.Broken.Api.Data.Settings.SettingGroup;
public class SettingDescriptionBuilder { public class SettingDescriptionBuilder {
public List<SettingGroup> build() { public List<SettingGroup> build() {
List<SettingGroup> toReturn = new ArrayList<>(); List<SettingGroup> toReturn = new ArrayList<>();
@ -15,28 +15,25 @@ public class SettingDescriptionBuilder {
toReturn.add(getDailyGroup()); toReturn.add(getDailyGroup());
return toReturn; return toReturn;
} }
private SettingGroup getWelcomeGroup() { private SettingGroup getWelcomeGroup() {
SettingDescriber mainField = new SettingDescriber( SettingDescriber mainField = new SettingDescriber(
"welcome_enable", "welcome_enable",
"Enable Welcome Message", "Enable Welcome Message",
null, null,
SettingDescriber.TYPE.BOOL SettingDescriber.TYPE.BOOL);
);
List<SettingDescriber> fields = new ArrayList<>(); List<SettingDescriber> fields = new ArrayList<>();
fields.add(new SettingDescriber( fields.add(new SettingDescriber(
"welcome_chanel_id", "welcome_chanel_id",
"Welcome Message chanel", "Welcome Message chanel",
null, null,
SettingDescriber.TYPE.TEXT_CHANNEL SettingDescriber.TYPE.TEXT_CHANNEL));
));
fields.add(new SettingDescriber( fields.add(new SettingDescriber(
"welcome_message", "welcome_message",
"Welcome Message", "Welcome Message",
null, null,
SettingDescriber.TYPE.STRING SettingDescriber.TYPE.STRING));
));
return new SettingGroup( return new SettingGroup(
"Welcome Message", "Welcome Message",
@ -49,16 +46,14 @@ public class SettingDescriptionBuilder {
"default_role", "default_role",
"Enable Default Role", "Enable Default Role",
null, null,
SettingDescriber.TYPE.BOOL SettingDescriber.TYPE.BOOL);
);
List<SettingDescriber> fields = new ArrayList<>(); List<SettingDescriber> fields = new ArrayList<>();
fields.add(new SettingDescriber( fields.add(new SettingDescriber(
"default_role_id", "default_role_id",
"Default Role", "Default Role",
null, null,
SettingDescriber.TYPE.ROLE SettingDescriber.TYPE.ROLE));
));
return new SettingGroup( return new SettingGroup(
"Default Role", "Default Role",
@ -72,8 +67,7 @@ public class SettingDescriptionBuilder {
"daily_madame", "daily_madame",
"[NSFW] Enable Daily Madame Message", "[NSFW] Enable Daily Madame Message",
null, null,
SettingDescriber.TYPE.BOOL SettingDescriber.TYPE.BOOL));
));
return new SettingGroup( return new SettingGroup(
"Daily", "Daily",
@ -86,22 +80,19 @@ public class SettingDescriptionBuilder {
"auto_voice", "auto_voice",
"Enable Auto Create Voice Chanel", "Enable Auto Create Voice Chanel",
null, null,
SettingDescriber.TYPE.BOOL SettingDescriber.TYPE.BOOL);
);
List<SettingDescriber> fields = new ArrayList<>(); List<SettingDescriber> fields = new ArrayList<>();
fields.add(new SettingDescriber( fields.add(new SettingDescriber(
"auto_voice_base_channel", "auto_voice_base_channel",
"Base Voice Channel For Auto Create", "Base Voice Channel For Auto Create",
"If someone joint this channel, a new voice channel will be created with the same settings.", "If someone joint this channel, a new voice channel will be created with the same settings.",
SettingDescriber.TYPE.VOICE_CHANNEL SettingDescriber.TYPE.VOICE_CHANNEL));
));
fields.add(new SettingDescriber( fields.add(new SettingDescriber(
"auto_voice_channel_title", "auto_voice_channel_title",
"Auto Created Voice Channel title", "Auto Created Voice Channel title",
"Auto created voice channel will use this title, @count will be replaced by the channel count.", "Auto created voice channel will use this title, @count will be replaced by the channel count.",
SettingDescriber.TYPE.STRING SettingDescriber.TYPE.STRING));
));
return new SettingGroup( return new SettingGroup(
"Auto Voice Channel", "Auto Voice Channel",

View File

@ -1,12 +1,13 @@
package net.Broken.Tools.Settings; package net.Broken.Tools.Settings;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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;
import net.Broken.DB.Repository.GuildPreferenceRepository; import net.Broken.DB.Repository.GuildPreferenceRepository;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.List;
public class SettingSaver { public class SettingSaver {
private final GuildPreferenceRepository guildPreferenceRepository; private final GuildPreferenceRepository guildPreferenceRepository;

View File

@ -1,11 +1,11 @@
package net.Broken.Tools.Settings; package net.Broken.Tools.Settings;
import net.Broken.Api.Data.Settings.Value;
import net.Broken.DB.Entity.GuildPreferenceEntity;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.Broken.Api.Data.Settings.Value;
import net.Broken.DB.Entity.GuildPreferenceEntity;
public class SettingValueBuilder { public class SettingValueBuilder {
private final GuildPreferenceEntity guildPreference; private final GuildPreferenceEntity guildPreference;
@ -25,19 +25,13 @@ public class SettingValueBuilder {
List<Value> toReturn = new ArrayList<>(); List<Value> toReturn = new ArrayList<>();
toReturn.add(new Value( toReturn.add(new Value(
"welcome_enable", "welcome_enable",
pref.isWelcome() pref.isWelcome()));
)
);
toReturn.add(new Value( toReturn.add(new Value(
"welcome_chanel_id", "welcome_chanel_id",
pref.getWelcomeChanelID() pref.getWelcomeChanelID()));
)
);
toReturn.add(new Value( toReturn.add(new Value(
"welcome_message", "welcome_message",
pref.getWelcomeMessage() pref.getWelcomeMessage()));
)
);
return toReturn; return toReturn;
} }
@ -45,14 +39,10 @@ public class SettingValueBuilder {
List<Value> toReturn = new ArrayList<>(); List<Value> toReturn = new ArrayList<>();
toReturn.add(new Value( toReturn.add(new Value(
"default_role", "default_role",
pref.isDefaultRole() pref.isDefaultRole()));
)
);
toReturn.add(new Value( toReturn.add(new Value(
"default_role_id", "default_role_id",
pref.getDefaultRoleId() pref.getDefaultRoleId()));
)
);
return toReturn; return toReturn;
} }
@ -60,9 +50,7 @@ public class SettingValueBuilder {
List<Value> toReturn = new ArrayList<>(); List<Value> toReturn = new ArrayList<>();
toReturn.add(new Value( toReturn.add(new Value(
"daily_madame", "daily_madame",
pref.isDailyMadame() pref.isDailyMadame()));
)
);
return toReturn; return toReturn;
} }
@ -70,19 +58,13 @@ public class SettingValueBuilder {
List<Value> toReturn = new ArrayList<>(); List<Value> toReturn = new ArrayList<>();
toReturn.add(new Value( toReturn.add(new Value(
"auto_voice", "auto_voice",
pref.isAutoVoice() pref.isAutoVoice()));
)
);
toReturn.add(new Value( toReturn.add(new Value(
"auto_voice_base_channel", "auto_voice_base_channel",
pref.getAutoVoiceChannelID() pref.getAutoVoiceChannelID()));
)
);
toReturn.add(new Value( toReturn.add(new Value(
"auto_voice_channel_title", "auto_voice_channel_title",
pref.getAutoVoiceChannelTitle() pref.getAutoVoiceChannelTitle()));
)
);
return toReturn; return toReturn;
} }

View File

@ -1,10 +1,10 @@
package net.Broken.Tools; package net.Broken.Tools;
import java.util.ArrayList;
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.util.ArrayList;
public class TimeConvertor { public class TimeConvertor {
static Logger logger = LogManager.getLogger(); static Logger logger = LogManager.getLogger();

View File

@ -1,11 +1,20 @@
package net.Broken.Tools.UserManager.Stats; package net.Broken.Tools.UserManager.Stats;
import java.awt.Color;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import net.Broken.MainBot;
import net.Broken.SpringContext;
import net.Broken.DB.Entity.UserEntity; import net.Broken.DB.Entity.UserEntity;
import net.Broken.DB.Entity.UserStats; import net.Broken.DB.Entity.UserStats;
import net.Broken.DB.Repository.UserRepository; import net.Broken.DB.Repository.UserRepository;
import net.Broken.DB.Repository.UserStatsRepository; import net.Broken.DB.Repository.UserStatsRepository;
import net.Broken.MainBot;
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.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
@ -13,14 +22,6 @@ 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.MessageEmbed; import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.User; import net.dv8tion.jda.api.entities.User;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.ApplicationContext;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class UserStatsUtils { public class UserStatsUtils {
@ -28,7 +29,6 @@ public class UserStatsUtils {
static final double XP_PER_MESSAGE = 4; static final double XP_PER_MESSAGE = 4;
static final double XP_PER_API_COUNT = 1; static final 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;
@ -40,7 +40,6 @@ public class UserStatsUtils {
userStatsRepository = (UserStatsRepository) context.getBean("userStatsRepository"); userStatsRepository = (UserStatsRepository) context.getBean("userStatsRepository");
userRepository = (UserRepository) context.getBean("userRepository"); userRepository = (UserRepository) context.getBean("userRepository");
} }
public static UserStatsUtils getINSTANCE() { public static UserStatsUtils getINSTANCE() {
@ -60,7 +59,8 @@ public class UserStatsUtils {
logger.debug(userEntity); logger.debug(userEntity);
logger.debug(userEntity.getUserStats()); logger.debug(userEntity.getUserStats());
if (userEntity.getUserStats() == null || userEntity.getUserStats().isEmpty() || userEntity.getUserStats().size() < jdaUser.getMutualGuilds().size()) { if (userEntity.getUserStats() == null || userEntity.getUserStats().isEmpty()
|| userEntity.getUserStats().size() < jdaUser.getMutualGuilds().size()) {
logger.debug("Stats not found for {}", userEntity.getUsername()); logger.debug("Stats not found for {}", userEntity.getUsername());
List<UserStats> stats; List<UserStats> stats;
@ -102,14 +102,14 @@ public class UserStatsUtils {
} }
public UserStats getGuildUserStats(Member member) { public UserStats getGuildUserStats(Member member) {
UserEntity userEntity = userRepository.findByDiscordId(member.getUser().getId()) UserEntity userEntity = userRepository.findByDiscordId(member.getUser().getId())
.orElseGet(() -> genUserEntity(member.getUser())); .orElseGet(() -> genUserEntity(member.getUser()));
List<UserStats> userStatsList = userStatsRepository.findByUserAndGuildId(userEntity, member.getGuild().getId()); List<UserStats> userStatsList = userStatsRepository.findByUserAndGuildId(userEntity, member.getGuild().getId());
if (userStatsList.isEmpty()) { if (userStatsList.isEmpty()) {
logger.debug("User stats not found for user {} guild: {}", userEntity.getUsername(), member.getGuild().getId()); logger.debug("User stats not found for user {} guild: {}", userEntity.getUsername(),
member.getGuild().getId());
getUserStats(userEntity); getUserStats(userEntity);
userStatsList = userStatsRepository.findByUserAndGuildId(userEntity, member.getGuild().getId()); userStatsList = userStatsRepository.findByUserAndGuildId(userEntity, member.getGuild().getId());
} }
@ -127,41 +127,33 @@ public class UserStatsUtils {
return userStatsList.get(0); return userStatsList.get(0);
} }
public void addMessageCount(Member member) { public void addMessageCount(Member member) {
UserStats userStats = getGuildUserStats(member); UserStats userStats = getGuildUserStats(member);
userStats.setMessageCount(userStats.getMessageCount() + 1); userStats.setMessageCount(userStats.getMessageCount() + 1);
userStatsRepository.save(userStats); userStatsRepository.save(userStats);
} }
public void addApiCount(UserEntity userEntity, String guildId) { public void addApiCount(UserEntity userEntity, String guildId) {
UserStats userStats = getGuildUserStats(userEntity, guildId); UserStats userStats = getGuildUserStats(userEntity, guildId);
userStats.setApiCommandCount(userStats.getApiCommandCount() + 1); userStats.setApiCommandCount(userStats.getApiCommandCount() + 1);
userStatsRepository.save(userStats); userStatsRepository.save(userStats);
} }
private void addVocalCount(Member member) { private void addVocalCount(Member member) {
UserStats userStats = getGuildUserStats(member); UserStats userStats = getGuildUserStats(member);
userStats.setVocalTime(userStats.getVocalTime() + 10); userStats.setVocalTime(userStats.getVocalTime() + 10);
userStatsRepository.save(userStats); userStatsRepository.save(userStats);
} }
private UserEntity genUserEntity(User user) { private UserEntity genUserEntity(User user) {
UserEntity userEntity = new UserEntity(user); UserEntity userEntity = new UserEntity(user);
return userRepository.save(userEntity); return userRepository.save(userEntity);
} }
public GuildStatsPack getStatPack(UserEntity userEntity, String guildId) { public GuildStatsPack getStatPack(UserEntity userEntity, String guildId) {
GuildStats selfGuildStats = null; GuildStats selfGuildStats = null;
@ -176,7 +168,8 @@ public class UserStatsUtils {
continue; continue;
} }
String avatar = member.getUser().getAvatarUrl(); String avatar = member.getUser().getAvatarUrl();
GuildStats temp = new GuildStats(stats.getUser().getUsername(), 0, avatar, stats.getVocalTime(), stats.getMessageCount(), stats.getApiCommandCount()); GuildStats temp = new GuildStats(stats.getUser().getUsername(), 0, avatar, stats.getVocalTime(),
stats.getMessageCount(), stats.getApiCommandCount());
if (stats.getUser().getId().equals(userEntity.getId())) { if (stats.getUser().getId().equals(userEntity.getId())) {
selfGuildStats = temp; selfGuildStats = temp;
} }
@ -188,11 +181,13 @@ public class UserStatsUtils {
for (UserStats stats : needCache) { for (UserStats stats : needCache) {
Member member = guild.getMemberById(stats.getUser().getDiscordId()); Member member = guild.getMemberById(stats.getUser().getDiscordId());
if (member == null) { if (member == null) {
logger.warn("Can't find member '{}'after load, User leave the guild ?", stats.getUser().getUsername()); logger.warn("Can't find member '{}'after load, User leave the guild ?",
stats.getUser().getUsername());
continue; continue;
} }
String avatar = member.getUser().getAvatarUrl(); String avatar = member.getUser().getAvatarUrl();
GuildStats temp = new GuildStats(stats.getUser().getUsername(), 0, avatar, stats.getVocalTime(), stats.getMessageCount(), stats.getApiCommandCount()); GuildStats temp = new GuildStats(stats.getUser().getUsername(), 0, avatar, stats.getVocalTime(),
stats.getMessageCount(), stats.getApiCommandCount());
if (stats.getUser().getId().equals(userEntity.getId())) { if (stats.getUser().getId().equals(userEntity.getId())) {
selfGuildStats = temp; selfGuildStats = temp;
} }
@ -211,7 +206,6 @@ public class UserStatsUtils {
} }
public MessageEmbed getRankMessage(Member member) { public MessageEmbed getRankMessage(Member member) {
UserStats userStats = getGuildUserStats(member); UserStats userStats = getGuildUserStats(member);
GuildStatsPack pack = getStatPack(userStats.getUser(), member.getGuild().getId()); GuildStatsPack pack = getStatPack(userStats.getUser(), member.getGuild().getId());
@ -221,7 +215,8 @@ public class UserStatsUtils {
if (i >= 6) { if (i >= 6) {
break; break;
} }
stringBuilder.append(i).append(". ").append(stats.userName).append(" with ").append(stats.total).append(" points!").append("\n"); stringBuilder.append(i).append(". ").append(stats.userName).append(" with ").append(stats.total)
.append(" points!").append("\n");
i++; i++;
} }
@ -237,7 +232,6 @@ public class UserStatsUtils {
default -> pack.selfStats().rank + "th"; default -> pack.selfStats().rank + "th";
}; };
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);
@ -259,7 +253,6 @@ public class UserStatsUtils {
if (member.getGuild().getAfkChannel() != member.getVoiceState().getChannel()) if (member.getGuild().getAfkChannel() != member.getVoiceState().getChannel())
UserStatsUtils.getINSTANCE().addVocalCount(member); UserStatsUtils.getINSTANCE().addVocalCount(member);
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -268,5 +261,4 @@ public class UserStatsUtils {
} }
} }
} }

View File

@ -244,37 +244,6 @@ databaseChangeLog:
name: playlist_entity_id name: playlist_entity_id
type: INT type: INT
tableName: track_entity tableName: track_entity
- changeSet:
id: 1653065037086-8
author: seb65 (generated)
changes:
- createTable:
columns:
- column:
autoIncrement: true
constraints:
nullable: false
primaryKey: true
name: id
type: INT
- column:
name: api_token
type: VARCHAR(255)
- column:
name: jda_id
type: VARCHAR(255)
- column:
name: name
type: VARCHAR(255)
- column:
name: password
type: VARCHAR(255)
- column:
constraints:
nullable: false
name: is_bot_admin
type: BIT
tableName: user_entity
- changeSet: - changeSet:
id: 1653065037086-10 id: 1653065037086-10