Merge branch 'devel'
This commit is contained in:
commit
58fb7a197b
11
README.md
11
README.md
@ -68,5 +68,14 @@ Devel: <br/>[![Build Status](https://jenkins.seb6596.ovh/buildStatus/icon?job=Br
|
|||||||
> internal:
|
> internal:
|
||||||
> external: false
|
> external: false
|
||||||
> ```
|
> ```
|
||||||
> Docker hub [repo](https://hub.docker.com/r/brokenfire/brokendiscordbot/)
|
> Docker hub [repo](https://hub.docker.com/r/brokenfire/brokendiscordbot/)
|
||||||
|
|
||||||
|
#### Jenkisfile
|
||||||
|
`git config --global merge.ours.driver true`
|
||||||
|
|
||||||
|
```
|
||||||
|
[merge "ours"]
|
||||||
|
name = "Keep ours merge"
|
||||||
|
driver = true
|
||||||
|
```
|
||||||
|
|
||||||
|
@ -3,8 +3,9 @@ package net.Broken.RestApi;
|
|||||||
import net.Broken.Commands.Music;
|
import net.Broken.Commands.Music;
|
||||||
import net.Broken.RestApi.Data.CommandPostData;
|
import net.Broken.RestApi.Data.CommandPostData;
|
||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public interface CommandInterface {
|
public interface CommandInterface {
|
||||||
ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data);
|
ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user);
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,12 @@ import net.Broken.RestApi.CommandInterface;
|
|||||||
import net.Broken.RestApi.Data.CommandPostData;
|
import net.Broken.RestApi.Data.CommandPostData;
|
||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.WebLoadUtils;
|
import net.Broken.audio.WebLoadUtils;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Add implements CommandInterface {
|
public class Add implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
return new WebLoadUtils(musicCommande ,data).getResponse();
|
return new WebLoadUtils(musicCommande ,data, user).getResponse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ import net.Broken.RestApi.CommandInterface;
|
|||||||
import net.Broken.RestApi.Data.CommandPostData;
|
import net.Broken.RestApi.Data.CommandPostData;
|
||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.AudioM;
|
import net.Broken.audio.AudioM;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Connect implements CommandInterface{
|
public class Connect implements CommandInterface{
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
AudioM audioM = musicCommande.getAudioManager();
|
AudioM audioM = musicCommande.getAudioManager();
|
||||||
if(data.chanelId == null)
|
if(data.chanelId == null)
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command,"Missing chanelId"),HttpStatus.BAD_REQUEST);
|
return new ResponseEntity<>(new CommandResponseData(data.command,"Missing chanelId"),HttpStatus.BAD_REQUEST);
|
||||||
|
@ -6,12 +6,13 @@ import net.Broken.RestApi.Data.CommandPostData;
|
|||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.NotConectedException;
|
import net.Broken.audio.NotConectedException;
|
||||||
import net.Broken.audio.NullMusicManager;
|
import net.Broken.audio.NullMusicManager;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Dell implements CommandInterface {
|
public class Dell implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
if(data.url != null) {
|
if(data.url != null) {
|
||||||
try {
|
try {
|
||||||
if(musicCommande.getAudioManager().getMusicManager().scheduler.remove(data.url)){
|
if(musicCommande.getAudioManager().getMusicManager().scheduler.remove(data.url)){
|
||||||
|
@ -6,12 +6,13 @@ import net.Broken.RestApi.Data.CommandPostData;
|
|||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.NotConectedException;
|
import net.Broken.audio.NotConectedException;
|
||||||
import net.Broken.audio.NullMusicManager;
|
import net.Broken.audio.NullMusicManager;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Flush implements CommandInterface {
|
public class Flush implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
try {
|
try {
|
||||||
musicCommande.getAudioManager().getMusicManager().scheduler.flush();
|
musicCommande.getAudioManager().getMusicManager().scheduler.flush();
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
||||||
|
@ -6,12 +6,13 @@ import net.Broken.RestApi.Data.CommandPostData;
|
|||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.NotConectedException;
|
import net.Broken.audio.NotConectedException;
|
||||||
import net.Broken.audio.NullMusicManager;
|
import net.Broken.audio.NullMusicManager;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Next implements CommandInterface {
|
public class Next implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
try {
|
try {
|
||||||
musicCommande.getAudioManager().getMusicManager().scheduler.nextTrack();
|
musicCommande.getAudioManager().getMusicManager().scheduler.nextTrack();
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
||||||
|
@ -6,12 +6,13 @@ import net.Broken.RestApi.Data.CommandPostData;
|
|||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.NotConectedException;
|
import net.Broken.audio.NotConectedException;
|
||||||
import net.Broken.audio.NullMusicManager;
|
import net.Broken.audio.NullMusicManager;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Pause implements CommandInterface {
|
public class Pause implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
try {
|
try {
|
||||||
musicCommande.getAudioManager().getMusicManager().scheduler.pause();
|
musicCommande.getAudioManager().getMusicManager().scheduler.pause();
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
||||||
|
@ -6,12 +6,13 @@ import net.Broken.RestApi.Data.CommandPostData;
|
|||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
import net.Broken.audio.NotConectedException;
|
import net.Broken.audio.NotConectedException;
|
||||||
import net.Broken.audio.NullMusicManager;
|
import net.Broken.audio.NullMusicManager;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Play implements CommandInterface {
|
public class Play implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
try {
|
try {
|
||||||
musicCommande.getAudioManager().getMusicManager().scheduler.resume();
|
musicCommande.getAudioManager().getMusicManager().scheduler.resume();
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
||||||
|
@ -4,13 +4,14 @@ import net.Broken.Commands.Music;
|
|||||||
import net.Broken.RestApi.CommandInterface;
|
import net.Broken.RestApi.CommandInterface;
|
||||||
import net.Broken.RestApi.Data.CommandPostData;
|
import net.Broken.RestApi.Data.CommandPostData;
|
||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
public class Stop implements CommandInterface {
|
public class Stop implements CommandInterface {
|
||||||
@Override
|
@Override
|
||||||
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data) {
|
public ResponseEntity<CommandResponseData> action(Music musicCommande, CommandPostData data, User user) {
|
||||||
musicCommande.getAudioManager().stop((MessageReceivedEvent) null);
|
musicCommande.getAudioManager().stop((MessageReceivedEvent) null);
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Accepted"), HttpStatus.OK);
|
||||||
|
|
||||||
|
@ -8,20 +8,20 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrackState;
|
|||||||
|
|
||||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
public class CurrentMusicData {
|
public class CurrentMusicData {
|
||||||
private final AudioTrackInfo info;
|
private final UserAudioTrackData info;
|
||||||
private final long currentPos;
|
private final long currentPos;
|
||||||
private final String state;
|
private final String state;
|
||||||
private final boolean pause;
|
private final boolean pause;
|
||||||
|
|
||||||
|
|
||||||
public CurrentMusicData(AudioTrackInfo info, long currentPos, String state, boolean pause) {
|
public CurrentMusicData(UserAudioTrackData info, long currentPos, String state, boolean pause) {
|
||||||
this.info = info;
|
this.info = info;
|
||||||
this.currentPos = currentPos;
|
this.currentPos = currentPos;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.pause = pause;
|
this.pause = pause;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioTrackInfo getInfo() {
|
public UserAudioTrackData getInfo() {
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,13 +6,13 @@ import java.util.List;
|
|||||||
|
|
||||||
public class PlaylistData {
|
public class PlaylistData {
|
||||||
|
|
||||||
private List<AudioTrackInfo> list;
|
private List<UserAudioTrackData> list;
|
||||||
|
|
||||||
public PlaylistData(List<AudioTrackInfo> list) {
|
public PlaylistData(List<UserAudioTrackData> list) {
|
||||||
this.list = list;
|
this.list = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AudioTrackInfo> getList() {
|
public List<UserAudioTrackData> getList() {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
package net.Broken.RestApi.Data;
|
||||||
|
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||||
|
import net.Broken.audio.UserAudioTrack;
|
||||||
|
|
||||||
|
public class UserAudioTrackData {
|
||||||
|
private String user;
|
||||||
|
private AudioTrackInfo audioTrackInfo;
|
||||||
|
|
||||||
|
public UserAudioTrackData(String user, AudioTrackInfo audioTrackInfo) {
|
||||||
|
this.user = user;
|
||||||
|
this.audioTrackInfo = audioTrackInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserAudioTrackData(UserAudioTrack userAudioTrack){
|
||||||
|
this.audioTrackInfo = userAudioTrack.getAudioTrack().getInfo();
|
||||||
|
this.user = userAudioTrack.getSubmitedUser().getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(String user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioTrackInfo getAudioTrackInfo() {
|
||||||
|
return audioTrackInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAudioTrackInfo(AudioTrackInfo audioTrackInfo) {
|
||||||
|
this.audioTrackInfo = audioTrackInfo;
|
||||||
|
}
|
||||||
|
}
|
@ -57,7 +57,8 @@ public class MusicWebAPIController {
|
|||||||
{
|
{
|
||||||
return new CurrentMusicData(null,0, "STOP",false);
|
return new CurrentMusicData(null,0, "STOP",false);
|
||||||
}
|
}
|
||||||
return new CurrentMusicData(currentTrack.getInfo(),currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused());
|
UserAudioTrackData uat = new UserAudioTrackData(musicCommande.audio.getMusicManager().scheduler.getCurrentPlayingTrack());
|
||||||
|
return new CurrentMusicData(uat, currentTrack.getPosition(), currentTrack.getState().toString(), player.isPaused());
|
||||||
} catch (NullMusicManager | NotConectedException nullMusicManager) {
|
} catch (NullMusicManager | NotConectedException nullMusicManager) {
|
||||||
return new CurrentMusicData(null,0, "STOP",false);
|
return new CurrentMusicData(null,0, "STOP",false);
|
||||||
}
|
}
|
||||||
@ -70,7 +71,7 @@ public class MusicWebAPIController {
|
|||||||
@RequestMapping("/getPlaylist")
|
@RequestMapping("/getPlaylist")
|
||||||
public PlaylistData getPlaylist(){
|
public PlaylistData getPlaylist(){
|
||||||
Music musicCommande = (Music) MainBot.commandes.get("music");
|
Music musicCommande = (Music) MainBot.commandes.get("music");
|
||||||
List<AudioTrackInfo> list = null;
|
List<UserAudioTrackData> list = null;
|
||||||
try {
|
try {
|
||||||
list = musicCommande.getAudioManager().getMusicManager().scheduler.getList();
|
list = musicCommande.getAudioManager().getMusicManager().scheduler.getList();
|
||||||
return new PlaylistData(list);
|
return new PlaylistData(list);
|
||||||
@ -90,7 +91,7 @@ public class MusicWebAPIController {
|
|||||||
Music musicCommande = (Music) MainBot.commandes.get("music");
|
Music musicCommande = (Music) MainBot.commandes.get("music");
|
||||||
|
|
||||||
if (ApiCommandLoader.apiCommands.containsKey(data.command))
|
if (ApiCommandLoader.apiCommands.containsKey(data.command))
|
||||||
return ApiCommandLoader.apiCommands.get(data.command).action(musicCommande, data);
|
return ApiCommandLoader.apiCommands.get(data.command).action(musicCommande, data, MainBot.jda.getUserById(user.getJdaId()));
|
||||||
else
|
else
|
||||||
return new ResponseEntity<>(new CommandResponseData(data.command, "Unknown Command", "command"), HttpStatus.BAD_REQUEST);
|
return new ResponseEntity<>(new CommandResponseData(data.command, "Unknown Command", "command"), HttpStatus.BAD_REQUEST);
|
||||||
|
|
||||||
|
@ -4,21 +4,25 @@ import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
|
|||||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||||
|
import com.sedmelluq.discord.lavaplayer.source.youtube.YoutubeAudioSourceManager;
|
||||||
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||||
import net.Broken.MainBot;
|
import net.Broken.MainBot;
|
||||||
|
import net.Broken.RestApi.Data.UserAudioTrackData;
|
||||||
import net.Broken.Tools.EmbedMessageUtils;
|
import net.Broken.Tools.EmbedMessageUtils;
|
||||||
import net.Broken.Tools.MessageTimeOut;
|
import net.Broken.Tools.MessageTimeOut;
|
||||||
import net.dv8tion.jda.core.entities.Guild;
|
import net.dv8tion.jda.core.entities.Guild;
|
||||||
import net.dv8tion.jda.core.entities.Message;
|
import net.dv8tion.jda.core.entities.Message;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||||
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceLeaveEvent;
|
import net.dv8tion.jda.core.events.guild.voice.GuildVoiceLeaveEvent;
|
||||||
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
import net.dv8tion.jda.core.events.message.MessageReceivedEvent;
|
||||||
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 javax.jws.soap.SOAPBinding;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -51,7 +55,7 @@ public class AudioM {
|
|||||||
@Override
|
@Override
|
||||||
public void trackLoaded(AudioTrack track) {
|
public void trackLoaded(AudioTrack track) {
|
||||||
logger.info("Single Track detected!");
|
logger.info("Single Track detected!");
|
||||||
|
UserAudioTrack uat = new UserAudioTrack(event.getAuthor(), track);
|
||||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk("Ajout de "+track.getInfo().title+" à la file d'attente!")).complete();
|
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk("Ajout de "+track.getInfo().title+" à la file d'attente!")).complete();
|
||||||
List<Message> messages = new ArrayList<Message>(){{
|
List<Message> messages = new ArrayList<Message>(){{
|
||||||
add(message);
|
add(message);
|
||||||
@ -59,7 +63,7 @@ public class AudioM {
|
|||||||
}};
|
}};
|
||||||
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
||||||
|
|
||||||
play(guild, voiceChannel, musicManager, track, onHead);
|
play(guild, voiceChannel, musicManager, uat, onHead);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -74,7 +78,7 @@ public class AudioM {
|
|||||||
}};
|
}};
|
||||||
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
new MessageTimeOut(messages, MainBot.messageTimeOut).start();
|
||||||
|
|
||||||
playListLoader(playlist, playlistLimit, onHead);
|
playListLoader(playlist, playlistLimit ,event.getAuthor() , onHead);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -105,14 +109,15 @@ public class AudioM {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void playListLoader(AudioPlaylist playlist,int playlistLimit, boolean onHead){
|
public void playListLoader(AudioPlaylist playlist, int playlistLimit, User user, boolean onHead){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
List<AudioTrack> tracks = playlist.getTracks();
|
List<AudioTrack> tracks = playlist.getTracks();
|
||||||
if(onHead)
|
if(onHead)
|
||||||
Collections.reverse(tracks);
|
Collections.reverse(tracks);
|
||||||
|
|
||||||
for(AudioTrack track : playlist.getTracks()){
|
for(AudioTrack track : playlist.getTracks()){
|
||||||
play(guild, playedChanel, musicManager, track, onHead);
|
UserAudioTrack uat = new UserAudioTrack(user, track);
|
||||||
|
play(guild, playedChanel, musicManager, uat, onHead);
|
||||||
i++;
|
i++;
|
||||||
if((i>=playlistLimit && i!=-1) || i>listExtremLimit)
|
if((i>=playlistLimit && i!=-1) || i>listExtremLimit)
|
||||||
break;
|
break;
|
||||||
@ -130,7 +135,7 @@ public class AudioM {
|
|||||||
return musicManager;
|
return musicManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void play(Guild guild, VoiceChannel channel, GuildMusicManager musicManager, AudioTrack track,boolean onHead) {
|
public void play(Guild guild, VoiceChannel channel, GuildMusicManager musicManager, UserAudioTrack track,boolean onHead) {
|
||||||
if(!guild.getAudioManager().isConnected())
|
if(!guild.getAudioManager().isConnected())
|
||||||
guild.getAudioManager().openAudioConnection(channel);
|
guild.getAudioManager().openAudioConnection(channel);
|
||||||
if(!onHead)
|
if(!onHead)
|
||||||
@ -178,8 +183,9 @@ public class AudioM {
|
|||||||
public void info(MessageReceivedEvent event){
|
public void info(MessageReceivedEvent event){
|
||||||
GuildMusicManager musicManager = getGuildAudioPlayer(event.getGuild());
|
GuildMusicManager musicManager = getGuildAudioPlayer(event.getGuild());
|
||||||
AudioTrackInfo info = musicManager.scheduler.getInfo();
|
AudioTrackInfo info = musicManager.scheduler.getInfo();
|
||||||
|
UserAudioTrack userAudioTrack = musicManager.scheduler.getCurrentPlayingTrack();
|
||||||
|
|
||||||
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk(info.title+"\n"+info.uri)).complete();
|
Message message = event.getTextChannel().sendMessage(EmbedMessageUtils.getMusicOk(info.title+"\n"+info.uri+"\nSubmitted by: "+userAudioTrack.getSubmitedUser().getName())).complete();
|
||||||
List<Message> messages = new ArrayList<Message>(){{
|
List<Message> messages = new ArrayList<Message>(){{
|
||||||
add(message);
|
add(message);
|
||||||
add(event.getMessage());
|
add(event.getMessage());
|
||||||
@ -200,16 +206,16 @@ public class AudioM {
|
|||||||
|
|
||||||
public void list(MessageReceivedEvent event){
|
public void list(MessageReceivedEvent event){
|
||||||
GuildMusicManager musicManager = getGuildAudioPlayer(event.getGuild());
|
GuildMusicManager musicManager = getGuildAudioPlayer(event.getGuild());
|
||||||
List<AudioTrackInfo> list = musicManager.scheduler.getList();
|
List<UserAudioTrackData> list = musicManager.scheduler.getList();
|
||||||
StringBuilder resp = new StringBuilder();
|
StringBuilder resp = new StringBuilder();
|
||||||
if(list.size() == 0){
|
if(list.size() == 0){
|
||||||
resp.append("Oh mon dieux!\nElle est vide! \n:astonished: ");
|
resp.append("Oh mon dieux!\nElle est vide! \n:astonished: ");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for(AudioTrackInfo trackInfo : list){
|
for(UserAudioTrackData trackInfo : list){
|
||||||
resp.append("- ");
|
resp.append("- ");
|
||||||
resp.append(trackInfo.title);
|
resp.append(trackInfo.getAudioTrackInfo().title);
|
||||||
resp.append("\n");
|
resp.append("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
|
|||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
|
||||||
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrackInfo;
|
||||||
|
import net.Broken.RestApi.Data.UserAudioTrackData;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
@ -20,7 +21,8 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
*/
|
*/
|
||||||
public class TrackScheduler extends AudioEventAdapter {
|
public class TrackScheduler extends AudioEventAdapter {
|
||||||
private final AudioPlayer player;
|
private final AudioPlayer player;
|
||||||
private final BlockingDeque<AudioTrack> queue;
|
private final BlockingDeque<UserAudioTrack> queue;
|
||||||
|
private UserAudioTrack currentPlayingTrack;
|
||||||
Logger logger = LogManager.getLogger();
|
Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -30,6 +32,7 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||||||
this.player = player;
|
this.player = player;
|
||||||
player.setVolume(25);
|
player.setVolume(25);
|
||||||
this.queue = new LinkedBlockingDeque<>();
|
this.queue = new LinkedBlockingDeque<>();
|
||||||
|
this.currentPlayingTrack = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,21 +40,27 @@ 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(AudioTrack 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 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
|
// 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, true)) {
|
if (!player.startTrack(track.getAudioTrack(), true)) {
|
||||||
queue.offer(track);
|
queue.offer(track);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
currentPlayingTrack = track;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
public void addNext(AudioTrack 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 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
|
// 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, true)) {
|
if (!player.startTrack(track.getAudioTrack(), true)) {
|
||||||
queue.addFirst(track);
|
queue.addFirst(track);
|
||||||
}
|
}
|
||||||
|
else{
|
||||||
|
currentPlayingTrack = track;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void pause() {
|
public void pause() {
|
||||||
@ -65,6 +74,7 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||||||
|
|
||||||
public void stop(){
|
public void stop(){
|
||||||
player.stopTrack();
|
player.stopTrack();
|
||||||
|
this.currentPlayingTrack = null;
|
||||||
player.destroy();
|
player.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,14 +82,14 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||||||
queue.clear();
|
queue.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<AudioTrackInfo> getList(){
|
public List<UserAudioTrackData> getList(){
|
||||||
// AudioTrack[] test = (AudioTrack[]) queue.toArray();
|
// AudioTrack[] test = (AudioTrack[]) queue.toArray();
|
||||||
|
|
||||||
List<AudioTrackInfo> temp = new ArrayList<>();
|
List<UserAudioTrackData> temp = new ArrayList<>();
|
||||||
Object[] test = queue.toArray();
|
Object[] test = queue.toArray();
|
||||||
for(Object track: test){
|
for(Object track: test){
|
||||||
AudioTrack casted = (AudioTrack) track;
|
UserAudioTrack casted = (UserAudioTrack) track;
|
||||||
temp.add(casted.getInfo());
|
temp.add(new UserAudioTrackData(casted.getSubmitedUser().getName(), casted.getAudioTrack().getInfo()));
|
||||||
}
|
}
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
@ -88,9 +98,13 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||||||
return player.getPlayingTrack().getInfo();
|
return player.getPlayingTrack().getInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public UserAudioTrack getCurrentPlayingTrack() {
|
||||||
|
return currentPlayingTrack;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean remove(String uri){
|
public boolean remove(String uri){
|
||||||
for(AudioTrack track : queue){
|
for(UserAudioTrack track : queue){
|
||||||
if(track.getInfo().uri.equals(uri)){
|
if(track.getAudioTrack().getInfo().uri.equals(uri)){
|
||||||
if(!queue.remove(track)) {
|
if(!queue.remove(track)) {
|
||||||
logger.info("Delete failure!");
|
logger.info("Delete failure!");
|
||||||
return false;
|
return false;
|
||||||
@ -110,7 +124,9 @@ public class TrackScheduler extends AudioEventAdapter {
|
|||||||
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. In case queue was empty, we are
|
||||||
// giving null to startTrack, which is a valid argument and will simply stop the player.
|
// giving null to startTrack, which is a valid argument and will simply stop the player.
|
||||||
player.startTrack(queue.poll(), false);
|
UserAudioTrack track = queue.poll();
|
||||||
|
this.currentPlayingTrack = track;
|
||||||
|
player.startTrack(track.getAudioTrack(), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
22
src/main/java/net/Broken/audio/UserAudioTrack.java
Normal file
22
src/main/java/net/Broken/audio/UserAudioTrack.java
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
package net.Broken.audio;
|
||||||
|
|
||||||
|
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
|
|
||||||
|
public class UserAudioTrack{
|
||||||
|
private User user;
|
||||||
|
private AudioTrack audioTrack;
|
||||||
|
|
||||||
|
public UserAudioTrack(User user, AudioTrack audioTrack) {
|
||||||
|
this.user = user;
|
||||||
|
this.audioTrack = audioTrack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User getSubmitedUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioTrack getAudioTrack() {
|
||||||
|
return audioTrack;
|
||||||
|
}
|
||||||
|
}
|
@ -8,6 +8,7 @@ import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
|
|||||||
import net.Broken.Commands.Music;
|
import net.Broken.Commands.Music;
|
||||||
import net.Broken.RestApi.Data.CommandPostData;
|
import net.Broken.RestApi.Data.CommandPostData;
|
||||||
import net.Broken.RestApi.Data.CommandResponseData;
|
import net.Broken.RestApi.Data.CommandResponseData;
|
||||||
|
import net.dv8tion.jda.core.entities.User;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@ -17,7 +18,7 @@ public class WebLoadUtils {
|
|||||||
ResponseEntity<CommandResponseData> response;
|
ResponseEntity<CommandResponseData> response;
|
||||||
Logger logger = LogManager.getLogger();
|
Logger logger = LogManager.getLogger();
|
||||||
|
|
||||||
public WebLoadUtils(Music musicCommande, CommandPostData data){
|
public WebLoadUtils(Music musicCommande, CommandPostData data, User user){
|
||||||
AudioPlayerManager playerM = musicCommande.getAudioManager().getPlayerManager();
|
AudioPlayerManager playerM = musicCommande.getAudioManager().getPlayerManager();
|
||||||
try {
|
try {
|
||||||
|
|
||||||
@ -28,7 +29,8 @@ public class WebLoadUtils {
|
|||||||
logger.info("Single Track detected from web!");
|
logger.info("Single Track detected from web!");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
audioM.play(audioM.getGuild(), audioM.getPlayedChanel(), audioM.getMusicManager(), track, data.onHead);
|
UserAudioTrack userAudioTrack = new UserAudioTrack(user, track); //TODO
|
||||||
|
audioM.play(audioM.getGuild(), audioM.getPlayedChanel(), audioM.getMusicManager(), userAudioTrack, data.onHead);
|
||||||
response = new ResponseEntity<>(new CommandResponseData("ADD", "Loaded"), HttpStatus.OK);
|
response = new ResponseEntity<>(new CommandResponseData("ADD", "Loaded"), HttpStatus.OK);
|
||||||
} catch (NullMusicManager | NotConectedException nullMusicManager) {
|
} catch (NullMusicManager | NotConectedException nullMusicManager) {
|
||||||
nullMusicManager.printStackTrace();
|
nullMusicManager.printStackTrace();
|
||||||
@ -40,7 +42,7 @@ public class WebLoadUtils {
|
|||||||
public void playlistLoaded(AudioPlaylist playlist) {
|
public void playlistLoaded(AudioPlaylist playlist) {
|
||||||
|
|
||||||
logger.info("Playlist detected from web! Limit: " + data.playlistLimit);
|
logger.info("Playlist detected from web! Limit: " + data.playlistLimit);
|
||||||
audioM.playListLoader(playlist,data.playlistLimit,data.onHead);
|
audioM.playListLoader(playlist, data.playlistLimit, user, data.onHead);
|
||||||
response = new ResponseEntity<>(new CommandResponseData("ADD", "Loaded"), HttpStatus.OK);
|
response = new ResponseEntity<>(new CommandResponseData("ADD", "Loaded"), HttpStatus.OK);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ $(document).ready(function() {
|
|||||||
setInterval("getCurentMusic()",1000);
|
setInterval("getCurentMusic()",1000);
|
||||||
// the "href" attribute of the modal trigger must specify the modal ID that wants to be triggered
|
// the "href" attribute of the modal trigger must specify the modal ID that wants to be triggered
|
||||||
$('#modalAdd').modal();
|
$('#modalAdd').modal();
|
||||||
|
$('#modal_current_info').modal();
|
||||||
|
|
||||||
$('#modalChanels').modal({
|
$('#modalChanels').modal({
|
||||||
dismissible: false // Modal can be dismissed by clicking outside of the modal
|
dismissible: false // Modal can be dismissed by clicking outside of the modal
|
||||||
@ -292,10 +293,11 @@ function getPlayList() {
|
|||||||
template.removeAttr("id");
|
template.removeAttr("id");
|
||||||
template.removeAttr("style");
|
template.removeAttr("style");
|
||||||
var content = template.html();
|
var content = template.html();
|
||||||
content = content.replace("@title", element.title);
|
content = content.replace("@title", element.audioTrackInfo.title);
|
||||||
content = content.replace("@author", element.author);
|
content = content.replace("@author", element.audioTrackInfo.author);
|
||||||
content = content.replace("@lenght", msToTime(element.length));
|
content = content.replace("@lenght", msToTime(element.audioTrackInfo.length));
|
||||||
content = content.replace(/@url/g, element.uri);
|
content = content.replace(/@url/g, element.audioTrackInfo.uri);
|
||||||
|
content = content.replace(/@user/g, element.user);
|
||||||
template.html(content);
|
template.html(content);
|
||||||
|
|
||||||
$('#playlist_list').append(template);
|
$('#playlist_list').append(template);
|
||||||
@ -349,18 +351,19 @@ function getChannels(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateModal(data){
|
function updateModal(data){
|
||||||
$('#modal_title').text("Title: "+ data.info.title);
|
$('#modal_title').text("Title: "+ data.info.audioTrackInfo.title);
|
||||||
$('#modal_author').text("Author: "+ data.info.author);
|
$('#modal_author').text("Author: "+ data.info.author);
|
||||||
$('#modal_lenght').text("Duration: "+ msToTime(data.info.length));
|
$('#modal_lenght').text("Duration: "+ msToTime(data.info.audioTrackInfo.length));
|
||||||
$('#modal_url').text("URL: "+ data.info.uri);
|
$('#modal_url').text("URL: "+ data.info.audioTrackInfo.uri);
|
||||||
|
$('#modal_submit').text("Submitted by: "+ data.info.user);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateControl(data){
|
function updateControl(data){
|
||||||
$('#music_text').text(data.info.title);
|
$('#music_text').text(data.info.audioTrackInfo.title);
|
||||||
var percent = (data.currentPos / data.info.length) * 100;
|
var percent = (data.currentPos / data.info.audioTrackInfo.length) * 100;
|
||||||
// console.log(percent)
|
// console.log(percent)
|
||||||
if (!$('#music_progress').hasClass("indeterminate")) {
|
if (!$('#music_progress').hasClass("indeterminate")) {
|
||||||
$('#music_progress').addClass("determinate").removeClass("indeterminate");
|
$('#music_progress').addClass("determinate").removeClass("indeterminate");
|
||||||
@ -412,9 +415,9 @@ function updateControl(data){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$('#music_img').attr("src","https://img.youtube.com/vi/"+data.info.identifier+"/hqdefault.jpg");
|
$('#music_img').attr("src","https://img.youtube.com/vi/"+data.info.audioTrackInfo.identifier+"/hqdefault.jpg");
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
$('#total_time').text(msToTime(data.info.length));
|
$('#total_time').text(msToTime(data.info.audioTrackInfo.length));
|
||||||
$('#current_time').text(msToTime(data.currentPos));
|
$('#current_time').text(msToTime(data.currentPos));
|
||||||
updateModal(data);
|
updateModal(data);
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@
|
|||||||
<div class="row center">
|
<div class="row center">
|
||||||
|
|
||||||
<div class="col offset-s5 s2 center">
|
<div class="col offset-s5 s2 center">
|
||||||
<a class="btn blue-grey darken-4 z-depth-3 waves-effect waves-light modal-trigger" href="#modal1" id="btn_info">
|
<a class="btn blue-grey darken-4 z-depth-3 waves-effect waves-light modal-trigger" href="#modal_current_info" id="btn_info">
|
||||||
<i class="material-icons">info</i>
|
<i class="material-icons">info</i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@ -232,13 +232,14 @@
|
|||||||
|
|
||||||
|
|
||||||
<!-- Music -->
|
<!-- Music -->
|
||||||
<div id="modal1" class="modal bottom-sheet">
|
<div id="modal_current_info" class="modal bottom-sheet">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<ul class="collection">
|
<ul class="collection">
|
||||||
<li class="collection-item " id="modal_title"></li>
|
<li class="collection-item " id="modal_title"></li>
|
||||||
<li class="collection-item " id="modal_author"></li>
|
<li class="collection-item " id="modal_author"></li>
|
||||||
<li class="collection-item " id="modal_lenght"></li>
|
<li class="collection-item " id="modal_lenght"></li>
|
||||||
<li class="collection-item " id="modal_url"></li>
|
<li class="collection-item " id="modal_url"></li>
|
||||||
|
<li class="collection-item " id="modal_submit"></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -255,6 +256,7 @@
|
|||||||
<li class="collection-item">Author: @author</li>
|
<li class="collection-item">Author: @author</li>
|
||||||
<li class="collection-item">Duration: @lenght</li>
|
<li class="collection-item">Duration: @lenght</li>
|
||||||
<li class="collection-item">URL: <a target="_blank" href="@url">@url</a></li>
|
<li class="collection-item">URL: <a target="_blank" href="@url">@url</a></li>
|
||||||
|
<li class="collection-item">Submitted by: @user</li>
|
||||||
<li class="collection-item center">
|
<li class="collection-item center">
|
||||||
<a class="btn red darken-4 z-depth-3 waves-effect waves-light btn_dell_playlist" data_url="@url">
|
<a class="btn red darken-4 z-depth-3 waves-effect waves-light btn_dell_playlist" data_url="@url">
|
||||||
<i class="material-icons medium">delete</i>
|
<i class="material-icons medium">delete</i>
|
||||||
|
Loading…
Reference in New Issue
Block a user