Skip to content

Commit

Permalink
Split botlistener in multiple classes (Closes #146) (#155)
Browse files Browse the repository at this point in the history
* Split botlistener in multiple classes

* Move audio loader to its own class

* Rename param

* Add check for patrons that already have the role

* Add check for bot joining VC on it's own
  • Loading branch information
duncte123 authored and ramidzkh committed Dec 14, 2018
1 parent b62ed5d commit e74d99e
Show file tree
Hide file tree
Showing 19 changed files with 1,171 additions and 901 deletions.
753 changes: 0 additions & 753 deletions src/main/java/ml/duncte123/skybot/BotListener.java

This file was deleted.

15 changes: 13 additions & 2 deletions src/main/java/ml/duncte123/skybot/EventManager.java
Expand Up @@ -21,6 +21,10 @@
import fredboat.audio.player.LavalinkManager;
import me.duncte123.botcommons.text.TextColor;
import ml.duncte123.skybot.commands.mod.DeHoistListener;
import ml.duncte123.skybot.listeners.GuildListener;
import ml.duncte123.skybot.listeners.GuildMemberListener;
import ml.duncte123.skybot.listeners.MessageListener;
import ml.duncte123.skybot.listeners.ReadyShutdownListener;
import net.dv8tion.jda.core.JDA;
import net.dv8tion.jda.core.events.Event;
import net.dv8tion.jda.core.hooks.EventListener;
Expand Down Expand Up @@ -50,9 +54,16 @@ public class EventManager
private final List<EventListener> listeners = new ArrayList<>();

EventManager(Variables variables) {
BotListener botListener = new BotListener(variables);
MessageListener messageListener = new MessageListener(variables);
GuildMemberListener guildMemberListener = new GuildMemberListener(variables);
GuildListener guildListener = new GuildListener(variables);
ReadyShutdownListener readyShutdownListener = new ReadyShutdownListener(variables);
DeHoistListener deHoistListener = new DeHoistListener(variables);
this.listeners.add(botListener);

this.listeners.add(messageListener);
this.listeners.add(guildMemberListener);
this.listeners.add(guildListener);
this.listeners.add(readyShutdownListener);
this.listeners.add(deHoistListener);
this.listeners.add(reactionHandler);

Expand Down
178 changes: 178 additions & 0 deletions src/main/java/ml/duncte123/skybot/audio/AudioLoader.java
@@ -0,0 +1,178 @@
/*
* Skybot, a multipurpose discord bot
* Copyright (C) 2017 - 2018 Duncan "duncte123" Sterken & Ramid "ramidzkh" Khan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package ml.duncte123.skybot.audio;

import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import ml.duncte123.skybot.CommandManager;
import ml.duncte123.skybot.commands.music.RadioCommand;
import ml.duncte123.skybot.objects.RadioStream;
import ml.duncte123.skybot.objects.TrackUserData;
import ml.duncte123.skybot.objects.command.CommandContext;
import ml.duncte123.skybot.utils.AudioUtils;
import ml.duncte123.skybot.utils.GuildSettingsUtils;
import net.dv8tion.jda.core.entities.TextChannel;
import net.dv8tion.jda.core.entities.User;
import org.apache.commons.lang3.exception.ExceptionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static me.duncte123.botcommons.messaging.EmbedUtils.embedField;
import static me.duncte123.botcommons.messaging.MessageUtils.sendEmbed;

public class AudioLoader implements AudioLoadResultHandler {

private final CommandContext ctx;
private final TextChannel channel;
private final User requester;
private final GuildMusicManager mng;
private final boolean announce;
private final boolean addPlaylist;
private final String trackUrl;
private final AudioUtils audioUtils;

public AudioLoader(CommandContext ctx, GuildMusicManager mng, boolean announce,
boolean addPlaylist, String trackUrl, AudioUtils audioUtils) {
this.ctx = ctx;
this.channel = ctx.getChannel();
this.requester = ctx.getAuthor();
this.mng = mng;
this.announce = announce;
this.addPlaylist = addPlaylist;
this.trackUrl = trackUrl;
this.audioUtils = audioUtils;
}

@Override
public void trackLoaded(AudioTrack track) {
String title = track.getInfo().title;
title = getSteamTitle(track, title, ctx.getCommandManager());

track.setUserData(new TrackUserData(requester.getIdLong()));

mng.scheduler.queue(track);

if (announce) {
String msg = "Adding to queue: " + title;
if (mng.player.getPlayingTrack() == null) {
msg += "\nand the Player has started playing;";
}

sendEmbed(channel, embedField(audioUtils.embedTitle, msg));
}
}

@Override
public void playlistLoaded(AudioPlaylist playlist) {
AudioTrack firstTrack = playlist.getSelectedTrack();
List<AudioTrack> tracks = new ArrayList<>();

for (final AudioTrack track : playlist.getTracks()) {
track.setUserData(new TrackUserData(requester.getIdLong()));
tracks.add(track);
}

if (tracks.isEmpty()) {
sendEmbed(channel, embedField(audioUtils.embedTitle, "Error: This playlist is empty."));
return;

} else if (firstTrack == null) {
firstTrack = playlist.getTracks().get(0);
}

if (addPlaylist) {
tracks.forEach(mng.scheduler::queue);
} else {
mng.scheduler.queue(firstTrack);
}

if (announce) {
String msg;

if (addPlaylist) {
msg = "Adding **" + playlist.getTracks().size() + "** tracks to queue from playlist: " + playlist.getName();

if (mng.player.getPlayingTrack() == null) {
msg += "\nand the Player has started playing;";
}
} else {
String prefix = GuildSettingsUtils.getGuild(channel.getGuild(), ctx.getVariables()).getCustomPrefix();
msg = "**Hint:** Use `" + prefix + "pplay <playlist link>` to add a playlist." +
"\n\nAdding to queue " + firstTrack.getInfo().title + " (first track of playlist " + playlist.getName() + ")";

if (mng.player.getPlayingTrack() == null) {
msg += "\nand the Player has started playing;";
}
}
sendEmbed(channel, embedField(audioUtils.embedTitle, msg));
}
}

@Override
public void noMatches() {
if (announce) {
sendEmbed(channel, embedField(audioUtils.embedTitle, "Nothing found by _" + trackUrl + "_"));
}
}

@Override
public void loadFailed(FriendlyException exception) {
if (!announce) {
return;
}

if (exception.getMessage().endsWith("Playback on other websites has been disabled by the video owner.")) {
sendEmbed(channel, embedField(audioUtils.embedTitle, "Could not play: " + trackUrl
+ "\nExternal playback of this video was blocked by YouTube."));
return;
}

Throwable root = ExceptionUtils.getRootCause(exception);

if (root == null) {
// It can return null so shush
// noinspection UnusedAssignment
root = exception;
return;
}

sendEmbed(channel, embedField(audioUtils.embedTitle, "Could not play: " + root.getMessage()
+ "\nIf this happens often try another link or join our [support guild](https://discord.gg/NKM9Xtk) for more!"));

}

static String getSteamTitle(AudioTrack track, String rawTitle, CommandManager commandManager) {
String title = rawTitle;

if (track.getInfo().isStream) {
Optional<RadioStream> stream = ((RadioCommand) commandManager.getCommand("radio"))
.getRadioStreams().stream().filter(s -> s.getUrl().equals(track.getInfo().uri)).findFirst();

if (stream.isPresent()) {
title = stream.get().getName();
}
}

return title;
}
}
Expand Up @@ -77,8 +77,10 @@ boolean isAnnounceTracks() {
}

TextChannel getLatestChannel() {
if (this.latestChannel == -1 || this.latestChannel == 0)
if (this.latestChannel == -1 || this.latestChannel == 0) {
return null;
}

return SkyBot.getInstance().getShardManager().getTextChannelById(this.latestChannel);
}
}
14 changes: 5 additions & 9 deletions src/main/java/ml/duncte123/skybot/audio/TrackScheduler.java
Expand Up @@ -29,9 +29,7 @@
import me.duncte123.botcommons.text.TextColor;
import ml.duncte123.skybot.Author;
import ml.duncte123.skybot.Variables;
import ml.duncte123.skybot.commands.music.RadioCommand;
import ml.duncte123.skybot.objects.ConsoleUser;
import ml.duncte123.skybot.objects.RadioStream;
import ml.duncte123.skybot.objects.TrackUserData;
import ml.duncte123.skybot.unstable.utils.ComparatingUtils;
import net.dv8tion.jda.core.entities.Guild;
Expand All @@ -41,7 +39,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;

import static ml.duncte123.skybot.SkyBot.getInstance;

Expand Down Expand Up @@ -200,12 +201,7 @@ private void announceNextTrack(AudioTrack track, boolean repeated) {
if (guildMusicManager.isAnnounceTracks()) {
String title = track.getInfo().title;
TrackUserData userData = (TrackUserData) track.getUserData();
if (track.getInfo().isStream) {
Optional<RadioStream> stream = ((RadioCommand) variables.getCommandManager().getCommand("radio"))
.getRadioStreams().stream().filter(s -> s.getUrl().equals(track.getInfo().uri)).findFirst();
if (stream.isPresent())
title = stream.get().getName();
}
title = AudioLoader.getSteamTitle(track, title, variables.getCommandManager());
User user = userData != null ? getInstance().getShardManager().getUserById(userData.getUserId()) : new ConsoleUser();
final String message = String.format("Now playing: %s %s%nRequester: %#s", title, (repeated ? "(repeated)" : ""), user);
MessageUtils.sendMsg(guildMusicManager.getLatestChannel(), message);
Expand Down
109 changes: 109 additions & 0 deletions src/main/java/ml/duncte123/skybot/listeners/BaseListener.java
@@ -0,0 +1,109 @@
/*
* Skybot, a multipurpose discord bot
* Copyright (C) 2017 - 2018 Duncan "duncte123" Sterken & Ramid "ramidzkh" Khan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package ml.duncte123.skybot.listeners;

import gnu.trove.list.TLongList;
import gnu.trove.list.array.TLongArrayList;
import me.duncte123.botcommons.text.TextColor;
import ml.duncte123.skybot.Variables;
import ml.duncte123.skybot.utils.GuildUtils;
import ml.duncte123.skybot.utils.SpamFilter;
import net.dv8tion.jda.core.entities.Guild;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static me.duncte123.botcommons.messaging.MessageUtils.sendMsg;

public class BaseListener extends ListenerAdapter {

public static boolean isUpdating = false;
protected static boolean shuttingDown = false;
protected final Logger logger;
protected final SpamFilter spamFilter;
protected final Variables variables;
// A list of servers that list bots
private final TLongList botLists = new TLongArrayList(
new long[]{
110373943822540800L, // Dbots
264445053596991498L, // Dbl
374071874222686211L, // Bots for discord
112319935652298752L, // Carbon
439866052684283905L, // Discord Boats
387812458661937152L, // Botlist.space
483344253963993113L, // AutomaCord
454933217666007052L, // Divine Discord Bot List
446682534135201793L, // Discords best bots
477792727577395210L, // discordbotlist.xyz
475571221946171393L, // bots.discordlist.app
}
);

public BaseListener(Variables variables) {
this.logger = LoggerFactory.getLogger(getClass());
this.variables = variables;
this.spamFilter = new SpamFilter(variables);
}

protected boolean isBotfarm(Guild guild) {

if (botLists.contains(guild.getIdLong())) {
return false;
}

// How many members should we at least have in the server
// before starting to conciser it as a botfarm
int minTotalMembers = 30;
// What percentage of bots do we allow
double maxBotPercentage = 70;

double[] botToUserRatio = GuildUtils.getBotRatio(guild);
long[] counts = GuildUtils.getBotAndUserCount(guild);
long totalMembers = guild.getMemberCache().size();

// if (!(botToUserRatio[1] >= maxBotPercentage && totalMembers > 30))
logger.debug("totalMembers > minTotalMembers " + (totalMembers > minTotalMembers));
logger.debug("botToUserRatio[1] <= maxBotPercentage " + (botToUserRatio[1] <= maxBotPercentage));
if (!(botToUserRatio[1] >= maxBotPercentage && totalMembers > minTotalMembers)) {
return false;
}

sendMsg(GuildUtils.getPublicChannel(guild),
String.format("Hello %s, this server is now blacklisted as botfarm and the bot will leave the guild (%s humans / %s bots).",
guild.getOwner().getAsMention(),
counts[0],
counts[1]
),
message -> guild.leave().queue(),
er -> guild.leave().queue()
);

logger.info("{}Botfarm found: {} {}% bots ({} humans / {} bots){}",
TextColor.RED,
guild,
botToUserRatio[1],
counts[0],
counts[1],
TextColor.RESET
);

return true;
}

}

0 comments on commit e74d99e

Please sign in to comment.