Compare commits

...

13 commits
1.0.0 ... main

13 changed files with 176 additions and 50 deletions

View file

@ -4,5 +4,5 @@
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="adopt-openj9-1.8" project-jdk-type="JavaSDK" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="adopt-openj9-1.8" project-jdk-type="JavaSDK" />
</project>

102
README.md
View file

@ -1,29 +1,83 @@
**MISSINGIDENTIFIER a Utility Discord Bot**
# MissingIdentifier
This is a Utility Discord providing some helpfull and some not so helpfull features.
It uses the [JDA](https://github.com/DV8FromTheWorld/JDA) wrapper.
This is a Utility Discord providing some helpful and some not so helpful features. It uses the [JDA wrapper](https://github.com/DV8FromTheWorld/JDA).
**Features:**
* ANNOY Members without a role will get messaged once a day with a custom text
* FOLD Shows some statistics for a given [Folding@Home](https://foldingathome.org/) team
* SHUFFLEROLE A given role gets a new color one a while
* LOBBY Temporary voicechannels
* QUOTE Save quotes and show random quotes
* RANDOMRESPONSE Response if text contains a trigger word
* AUTOSELECT Give members roles by reacting
* DICE Role a dice
* PRUGE Delete Messages
* LOVECALC Calculate chances between two members
* WELCOME Welcome new members with a custom text
* STATS Show some Serverstats
* ONLINEHIGHLIGHT Gives User a given Role if they are playing one of a given set of games
* SECRETCHANNEL Add Users to Secretchat if they mention given keywords
* VOICELOBBY Moves Users joining a given Voicechannel to a temporary VoiceChannel
## Features
**INVITE**
[CLICK](https://discordapp.com/oauth2/authorize?client_id=550770123946983440&scope=bot&permissions=285961296)
* ANNOY: Sends a message to guild members who did not choose a role yet
* AUTOSELECT: Grands users a role when they react to a given reaction
* DICE: Rolles a dice
* FOLD: Show some statistics about a [Folding@home](https://foldingathome.org) team.
* LOVECALC: Chances of two users falling in love (no guarantee)
* ONLINEHIGHLIGHT: Gives users a role who play a certain game
* PURGE: Bulk delete messages
* QUOTE: Saves quotes and displays them randomly
* RANDOMRESPONDE: Answer to given trigger words
* SECRETCHANNEL: Grants members access to channels if they mention keywords
* SHUFFLE: Color changing role
* STATS: Some guild stats
* VOICELOBBY: Temporary voice channels via command or joining certain channels
* WELCOME: Messages for new members
note: on default only the Guildowner is able to use the bot! he have to set a Admin/Modrole, so others can configurate the bot! `!admin setmodrole @role`
## How to use MissingIdentifier
**COMMANDS**
Please use `!help` to get a full command list
### Using my Bot hosted by me
1. Invite bot to your Discord guild using this [LINK](https://discordapp.com/oauth2/authorize?client_id=550770123946983440&scope=bot&permissions=285961296) (You may want to adjust the preset bot permissions to your linking).
2. Change bot prefix if other bots use the same (and use it from now on instead of `!`):
```
!admin setprefix <PREFIX>
```
3. Set a Mod-Role so non guild owner are able to configure this bot (preferably the admin role)
```
!admin setmodrole <@MODROLE>
```
4. Use the `help` command to get an overview of the available modules and commands.
5. Activate modules to your liking:
```
!admin <MODULE>
```
6. Reenter the `help` command to get overview of new settings and commands available
### Self host the bot
1. Create Discord Bot-User
1. Go to the [Discord developer](https://discord.com/developers/applications) page
2. Create a new application and edit it to your liking
3. navigate to `BOT` and hit `add bot`
4. may activate `Privileged Gateway Intents` (right now bot uses them, may a non presence mode be implemented)
5. Copy bot token
2. Copy release .jar executable
3. Copy sample config to .jar location
4. Enter bot token from step one into config file
5. run bot (`java -jar <filename>.jar`)
#### Updating
Just replace the .jar executable
### Building the bot your self
1. Clone Repo
2. Run `gradle fatJar`
3. .jar executable is located in ./build/libs/
(run the bot via `gradle run` should work fine too)
## Contributing
Uhm may just ask me to get started (COMING SOON)
## Bug report
(COMING SOON)
## Contact
Well find me ... i am using the name `Hiajen`
or just text me via [Matrix](https://matrix.to/#/@hiajen:matrix.hiajen.de) (`@hiajen:matrix.hiajen.de`)

View file

@ -5,31 +5,33 @@ plugins {
group 'BOT'
version '1.0.0'
version '1.0.1'
def jdaVersion = '4.2.0_225'
def jdaVersion = '4.4.0_350'
def jsonsimpleVersion = '1.1.1'
def jodatimeVersion = '2.10.6'
def self4JVersion = '1.7.30'
def log4jVersion = '2.13.3'
def JSON = '4.12.0'
def jodatimeVersion = '2.10.13'
def self4JVersion = '1.7.32'
def JSON = '4.13.0'
mainClassName = 'MissingIDent'
sourceCompatibility = 1.8
compileJava.options.encoding = 'UTF-8'
repositories {
jcenter()
mavenCentral()
maven {
name 'm2-dv8tion'
url 'https://m2.dv8tion.net/releases'
}
}
dependencies {
compile "net.dv8tion:JDA:$jdaVersion"
compile group: 'com.googlecode.json-simple', name: 'json-simple', version: jsonsimpleVersion
compile group: 'joda-time', name: 'joda-time', version: jodatimeVersion
compile group: 'org.slf4j', name: 'slf4j-api', version: self4JVersion
compile group: 'org.slf4j', name: 'slf4j-log4j12', version: self4JVersion
compile group: 'org.apache.logging.log4j', name: 'log4j-api', version: log4jVersion
compile group: 'com.cedarsoftware', name: 'json-io', version: JSON
implementation "net.dv8tion:JDA:$jdaVersion"
implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: jsonsimpleVersion
implementation group: 'joda-time', name: 'joda-time', version: jodatimeVersion
implementation group: 'org.slf4j', name: 'slf4j-api', version: self4JVersion
implementation group: 'org.slf4j', name: 'slf4j-jdk14', version: self4JVersion
implementation group: 'com.cedarsoftware', name: 'json-io', version: JSON
}
//create a single Jar with all dependencies

View file

@ -18,7 +18,7 @@ public class Admin extends SuperModule {
public static final String command = "admin";
public Admin(GuildController guildController) {
super(command, guildController, null);
super(command, guildController);
}
@Override

View file

@ -4,6 +4,7 @@ import IO.JSON;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.events.GenericEvent;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.events.ShutdownEvent;
import net.dv8tion.jda.api.events.guild.GenericGuildEvent;
import net.dv8tion.jda.api.events.guild.GuildJoinEvent;
import net.dv8tion.jda.api.events.guild.GuildLeaveEvent;
@ -98,6 +99,9 @@ public class Controller extends ListenerAdapter {
@Override
public void onGenericEvent(@NotNull GenericEvent event){
if (guilds == null)
return;
if (event instanceof GuildJoinEvent)
onGuildJoin((GuildJoinEvent) event);
else if (event instanceof GuildLeaveEvent)
@ -133,6 +137,7 @@ public class Controller extends ListenerAdapter {
reload(event.getJDA());
}
@Override
public void onGuildJoin(@NotNull GuildJoinEvent event){
//Check if guild exists
for (GuildController guildController : guilds){
@ -156,6 +161,7 @@ public class Controller extends ListenerAdapter {
}
@Override
public void onGuildLeave(@NotNull GuildLeaveEvent event){
JSONArray guilds = JSON.loadJson(GUILD_CONFIG_FILE);
@ -170,4 +176,12 @@ public class Controller extends ListenerAdapter {
}
JSON.saveJson(guilds, GUILD_CONFIG_FILE);
}
@Override
public void onShutdown(@NotNull ShutdownEvent shutdownEvent){
for (GuildController guildController: guilds){
guildController.shutdown();
}
logger.debug("Shutdown complete");
}
}

View file

@ -103,7 +103,6 @@ public class GuildController {
if (checkForActivate(Purge.COMMAND))
modules.add(new Purge(this));
if (checkForActivate(Quote.command))
modules.add(new Quote(this));
@ -141,6 +140,14 @@ public class GuildController {
modules.add(new Help(this));
}
protected void shutdown(){
for (Module module: modules){
if (module instanceof SuperModule)
((SuperModule) module).shutdown();
}
logger.debug("Shutdown Modules for Guild: " + getGUILD_ID());
}
private boolean checkForActivate(String moduleName){
if (moduleConf.containsKey(moduleName)){
logger.info("activate " + moduleName + " in " +getGUILD_ID());

View file

@ -14,7 +14,7 @@ public class Help extends SuperModule {
public static final String command = "help";
public Help( GuildController guildController){
super(command, guildController, null);
super(command, guildController);
}
@Override

View file

@ -5,6 +5,9 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import org.json.simple.JSONObject;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -13,6 +16,10 @@ public abstract class SuperModule implements Module {
private GuildController guildController;
private JSONObject config;
private final String command;
/**
* May temporary data but save worthy (active timer etc)
*/
private Map<String, Object> temporaryData;
/**
* Construcker of a Module
@ -23,12 +30,24 @@ public abstract class SuperModule implements Module {
this.command = command;
this.guildController = guildController;
this.config = config;
temporaryData = (Map<String, Object>)config.get("TemporaryData");
if (temporaryData != null) {
this.config.remove("TemporaryData");
safeConfig();
} else {
temporaryData = new HashMap<>();
}
}
public SuperModule(String command, GuildController guildController){
this.command = command;
this.guildController = guildController;
this.config = null;
temporaryData = new HashMap<>();
}
/**
@ -118,4 +137,16 @@ public abstract class SuperModule implements Module {
protected void safeConfig(){
safeConfig(getConfig());
}
/**
* On shutdown safe temporary data what should be saved
*/
protected void shutdown(){
getConfig().put("TemporaryData", temporaryData);
safeConfig();
}
protected Map<String, Object> getTemporaryData(){
return temporaryData;
}
}

View file

@ -1,5 +1,4 @@
import Controll.Controller;
import net.dv8tion.jda.api.AccountType;
import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder;
import net.dv8tion.jda.api.entities.Activity;
@ -11,6 +10,8 @@ import org.json.simple.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.logging.LogManager;
/**
* @author https://www.Hiajen.de
*/
@ -23,6 +24,9 @@ public class MissingIDent {
***************************************/
public static void main(String[] args) throws Exception {
LogManager loggerMG = java.util.logging.LogManager.getLogManager();
loggerMG.readConfiguration(MissingIDent.class.getClassLoader().getResourceAsStream("logging.properties"));
Logger logger = LoggerFactory.getLogger(MissingIDent.class);
logger.info("Bot Started");

View file

@ -36,7 +36,7 @@ public class Fold extends SuperModule{
userFile = "/home/bots/MissingIdentifier/MissingIdent/user_summary.txt";
public Fold(GuildController guildController){
super(COMMAND, guildController, null);
super(COMMAND, guildController);
}
@Override

View file

@ -19,7 +19,7 @@ public class Purge extends SuperModule{
public static final String COMMAND = "purge";
public Purge(GuildController guildController){
super(COMMAND, guildController, null);
super(COMMAND, guildController);
}
@Override

View file

@ -31,7 +31,6 @@ public class VoiceLobby extends SuperModule {
private long groupCategory;
private long launchpadChannel;
private HashSet<Long> tmpChannel = new HashSet<>();
private Logger logger = LoggerFactory.getLogger(this.getClass());
@ -98,7 +97,7 @@ public class VoiceLobby extends SuperModule {
// move User
event.getGuild().moveVoiceMember(((GuildMessageReceivedEvent) event).getMember(), newChannel).queue();
tmpChannel.add(newChannel.getIdLong());
((HashSet<Long>)getTemporaryData().get("tmpChannel")).add(newChannel.getIdLong());
} else {
thisEvent.getChannel().sendMessage("Please Join a Voice Channel first!").queue(e -> e.delete().queueAfter(1, TimeUnit.MINUTES));
@ -185,7 +184,7 @@ public class VoiceLobby extends SuperModule {
//check if user left a temp channel
if ((thisEvent.getChannelLeft() != null && thisEvent.getChannelLeft().getParent().getIdLong() == groupCategory)) {
//check if channel is now empty
if (thisEvent.getChannelLeft().getMembers().size() < 1 && tmpChannel.contains(thisEvent.getChannelLeft().getIdLong())) {
if (thisEvent.getChannelLeft().getMembers().size() < 1 && ((HashSet<Long>)getTemporaryData().get("tmpChannel")).contains(thisEvent.getChannelLeft().getIdLong())) {
logger.debug("may remove channel: " + thisEvent.getChannelLeft().getId());
//wait for 30 seconds and check again
@ -197,7 +196,7 @@ public class VoiceLobby extends SuperModule {
logger.debug("remove channel: " + thisEvent.getChannelLeft().getId());
thisEvent.getChannelLeft().delete().queue();
tmpChannel.remove(thisEvent.getChannelLeft().getIdLong());
((HashSet<Long>)getTemporaryData().get("tmpChannel")).remove(thisEvent.getChannelLeft().getIdLong());
} else {
logger.debug("dont remove channel: " + thisEvent.getChannelLeft().getId());
}
@ -215,7 +214,7 @@ public class VoiceLobby extends SuperModule {
// move User
event.getGuild().moveVoiceMember(thisEvent.getEntity(), newChannel).queue();
tmpChannel.add(newChannel.getIdLong());
((HashSet<Long>)getTemporaryData().get("tmpChannel")).add(newChannel.getIdLong());
}
}
}

View file

@ -0,0 +1,15 @@
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
java.util.logging.FileHandler.level=ALL
java.util.logging.FileHandler.limit=10485760
java.util.logging.FileHandler.count=2
java.util.logging.FileHandler.append=true
java.util.logging.FileHandler.pattern=MissingIdent%g.log
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.ConsoleHandler.level=ALL
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
java.util.logging.SimpleFormatter.format=[%1$TF-%1$TT][%2$s][%4$s] : %5$s %6$s %n
net.dv8tion.jda.level=WARNING