com.github.flawedbliss.dicebotr3.DicebotR3.java Source code

Java tutorial

Introduction

Here is the source code for com.github.flawedbliss.dicebotr3.DicebotR3.java

Source

/*The MIT License (MIT)
*
*Copyright (c) 2015 Merlin von Rssing
*
*Permission is hereby granted, free of charge, to any person obtaining a copy
*of this software and associated documentation files (the "Software"), to deal
*in the Software without restriction, including without limitation the rights
*to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
*copies of the Software, and to permit persons to whom the Software is
*furnished to do so, subject to the following conditions:
*
*The above copyright notice and this permission notice shall be included in all
*copies or substantial portions of the Software.
*
*THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
*FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
*AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
*LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
*OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
*SOFTWARE.
*/

package com.github.flawedbliss.dicebotr3;

import com.github.theholywaffle.teamspeak3.TS3Api;
import com.github.theholywaffle.teamspeak3.TS3Config;
import com.github.theholywaffle.teamspeak3.TS3Query;
import com.github.theholywaffle.teamspeak3.TS3Query.FloodRate;
import com.github.theholywaffle.teamspeak3.api.TextMessageTargetMode;
import com.github.theholywaffle.teamspeak3.api.event.ChannelCreateEvent;
import com.github.theholywaffle.teamspeak3.api.event.ChannelDeletedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ChannelDescriptionEditedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ChannelEditedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ChannelMovedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ChannelPasswordChangedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ClientJoinEvent;
import com.github.theholywaffle.teamspeak3.api.event.ClientLeaveEvent;
import com.github.theholywaffle.teamspeak3.api.event.ClientMovedEvent;
import com.github.theholywaffle.teamspeak3.api.event.ServerEditedEvent;
import com.github.theholywaffle.teamspeak3.api.event.TS3EventType;
import com.github.theholywaffle.teamspeak3.api.event.TS3Listener;
import com.github.theholywaffle.teamspeak3.api.event.TextMessageEvent;
import com.github.theholywaffle.teamspeak3.api.wrapper.Client;
import com.github.theholywaffle.teamspeak3.api.wrapper.ClientInfo;
import com.jolbox.bonecp.BoneCP;
import com.jolbox.bonecp.BoneCPConfig;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
 *
 * @author Daiya
 */
public class DicebotR3 {

    private static final Logger log = Logger.getLogger(DicebotR3.class.getName());
    public static final String version = "R3 260715-F";
    private static TS3Api myApi = null;
    private static TS3Query myQuery = null;
    private DicebotConfig cfg = new DicebotConfig();
    private DicebotStatus status = DicebotStatus.GOOD;
    BoneCP cp;

    private String motd;

    public DicebotR3(String instanceName) {
        cfg.setInstanceName(instanceName);
        Handler[] handlers = log.getHandlers();
        for (Handler h : handlers) {
            log.removeHandler(h);
        }
        log.setUseParentHandlers(false);
        LogHandler h = new LogHandler(true);
        log.addHandler(h);
        cfg.addHandler(h);
        log.setLevel(Level.ALL);
        log.info("Loading DicebotR3 version " + version);

        try {
            cfg.initFromFile("./" + cfg.getInstanceName() + "/config.properties");
        } catch (FileNotFoundException ex) {
            if (cfg.writeDefaultConfig()) {
                log.warning("Config file for instance " + cfg.getInstanceName() + "not found. A default"
                        + " configuration file has been created, please configure it.");
                this.status = DicebotStatus.FATAL;
                return;
            } else {
                this.status = DicebotStatus.FATAL;
                return;
            }
        } catch (IOException ex) {
            log.severe("Config file for instance " + cfg.getInstanceName() + " could not be read. Start failed.");
            this.status = DicebotStatus.FATAL;
            return;
        }

        if (cfg.isMotdEnabled()) {
            File f = new File("./" + cfg.getInstanceName() + "/motd.txt");
            if (!f.exists()) {
                cfg.setMotdEnabled(false);
                log.warning("MOTD file not found. MOTD disabled.");
            } else {
                try {
                    byte[] encoded = Files.readAllBytes(Paths.get(f.getPath()));
                    motd = new String(encoded, Charset.defaultCharset());
                } catch (IOException ex) {
                    cfg.setMotdEnabled(false);
                    log.warning("Failed to read the MOTD file. MOTD disabled");
                }
            }
        }

        if (!cfg.getTs3Server().matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")) {
            try {
                cfg.setTs3Server(InetAddress.getByName(cfg.getTs3Server()).getHostAddress());
            } catch (UnknownHostException ex) {
                log.severe("Unable to resolve Hostname. Start failed");
                this.status = DicebotStatus.FATAL;
                return;
            }
        }

        BoneCPConfig cpCfg = new BoneCPConfig();
        cpCfg.setJdbcUrl("jdbc:mysql://" + cfg.getMysqlHost() + "/" + cfg.getMysqlDatabase());
        cpCfg.setUsername(cfg.getMysqlUser());
        cpCfg.setPassword(cfg.getMysqlPassword());

        try {
            this.cp = new BoneCP(cpCfg);
        } catch (SQLException ex) {
            log.severe("Could not connect to the MySQL database. Start failed.");
            this.status = DicebotStatus.FATAL;
            return;
        }

        final TS3Config myConfig = new TS3Config();
        myConfig.setHost(cfg.getTs3Server());
        myConfig.setQueryPort(cfg.getTs3QueryPort());
        myConfig.setLoginCredentials(cfg.getTs3QueryUser(), cfg.getTs3QueryPassword());
        myConfig.setFloodRate(FloodRate.UNLIMITED);

        myQuery = new TS3Query(myConfig);
        myQuery.connect();
        myApi = myQuery.getApi();

        myApi.selectVirtualServerByPort(cfg.getTs3Port());

        List<Client> clientList = myApi.getClients();
        for (Client c : clientList) {
            if (c.getNickname().equals(cfg.getTs3Nickname())) {
                myApi.kickClientFromServer("This nickname is reserved!", c.getId());
            }
        }

        myApi.setNickname(cfg.getTs3Nickname());
        myApi.sendServerMessage(cfg.getTs3Nickname() + " is now online! Version " + version);
        myApi.registerEvent(TS3EventType.SERVER);
        myApi.registerEvent(TS3EventType.CHANNEL);
        myApi.registerEvent(TS3EventType.TEXT_CHANNEL);
        myApi.registerEvent(TS3EventType.TEXT_PRIVATE);
        myApi.registerEvent(TS3EventType.TEXT_SERVER);

        Timer noticeTimer = new Timer();
        noticeTimer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                sendNotices();
            }
        }, 0, 1000 * 60 * cfg.getNoticeInterval());

        myApi.addTS3Listeners(new TS3Listener() {
            String helpMsg = "Available commands:\n"
                    + "[color=red]!roll <max> <times>[/color] - Rolls a dice with <max> sides for <times> times. "
                    + "This requires the bot to be in your channel. [color=green][CHANNEL][/color]\n"
                    + "[color=red]!enabledice[/color] - Makes the bot join your channel "
                    + "[color=green][SERVER|PRIV][/color]\n" + "[color=red]!dicehelp[/color] - Displays this help "
                    + "[color=green][SERVER|CHANNEL|PRIV][/color]\n"
                    + "[color=red]!diceinfo[/color] - Displays information [color=green][PRIV][/color]\n"
                    + "[color=red]!premium[/color] <code> Assigns you the premium membergroup by using the"
                    + " code you got after donating [color=green][PRIV][/color]\n"
                    + "[color=red]!confirm[/color] <noticeId> - Marks the notice as confirmed and you will stop"
                    + " receiving it.\n[color=green][PRIV][/color]\n"
                    + "Brackets display available chat methods - a command marked with [color=green]"
                    + "[CHAN|PRIV][/color] can be used in a channel(if the bot is in it) and as private message.";
            String adminHelpMsg = "Available admin commands:\n"
                    + "[color=red]!stick[/color] - Sticks the bot to the channel. Use !stick again to free it."
                    + "[color=green][CHANNEL][/color]\n"
                    + "[color=red]!mirror[/color] - Toggles Mirrormode: Mirrors ever message send in channelchat."
                    + "[color=green][CHANNEL][/color]\n"
                    + "[color=red]!spam[/color] <name> <msg msg etc> <times> - Messages a user once a "
                    + "second with <msg> for <times> times[color=green][CHAN|PRIV][/color]\n"
                    + "[color=red]!addnotice[/color] <days until expiration> <special(1/0)> <message> - "
                    + "Adds a persistent notice which is sent to all usery periodically until they mark it as read."
                    + "[color=green][PRIV][/color]\n"
                    + "[color=red]!deactivatenotice[/color] <noticeId> - deactivates the notice and it will stop "
                    + "being sent to users.[color=green][PRIV][/color]\n"
                    + "[color=red]!shutdown[/color] - Forcibly shuts down the entire bot and all instances."
                    + "[color=green][PRIV][/color]";

            @Override
            public void onTextMessage(TextMessageEvent e) {
                final String[] args = e.getMessage().split(" ");
                boolean isSticky = false;
                boolean mirrorEnabled = false;

                if (e.getTargetMode() == TextMessageTargetMode.SERVER) {
                    switch (e.getMessage().toUpperCase()) {
                    case "!ENABLEDICE":
                        if (!isSticky) {
                            myApi.moveClient(myApi.getClientByUId(e.getInvokerUserId()).getChannelId());
                            myApi.sendChannelMessage(
                                    "has joined the channel. " + "Channel commands are now available.");
                        } else {
                            myApi.sendPrivateMessage(e.getInvokerId(),
                                    "I am currently stuck to channel "
                                            + myApi.getClientByName(cfg.getTs3Nickname()).get(0).getChannelId()
                                            + " - please unstick me first.");
                        }
                        break;
                    case "!DICEHELP":
                        myApi.sendPrivateMessage(e.getInvokerId(), helpMsg);
                        break;
                    }
                } else if (e.getTargetMode() == TextMessageTargetMode.CHANNEL) {
                    if (args[0].toUpperCase().equals("!ROLL")) {
                        if (args.length != 3) {
                            myApi.sendChannelMessage("Error: Invalid arguments. Usage: !roll <max> <times>");
                            return;
                        }
                        if (!isInteger(args[1]) || !isInteger(args[2])) {
                            myApi.sendChannelMessage("Error: You can't roll letters! Maybe in the future.");
                            return;
                        }
                        if (Integer.parseInt(args[2]) > 20) {
                            myApi.sendChannelMessage(
                                    "Error: You may only roll up to a maximum of 20 times at" + " a time.");
                            return;
                        }
                        if (Integer.parseInt(args[1]) <= 0) {
                            myApi.sendChannelMessage("Error: You can't roll negative numbers or zero.");
                            return;
                        }

                        for (int i = 0; i < Integer.parseInt(args[2]); i++) {
                            int result = (int) (Math.random() * (Integer.parseInt(args[1])) + 1);
                            myApi.sendChannelMessage("Roll " + (i + 1) + ": " + result);
                        }
                    } else if (e.getMessage().toUpperCase().equals("!STICK")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            if (isSticky) {
                                myApi.sendChannelMessage(cfg.getTs3Nickname() + " is a free elf!");
                                isSticky = false;
                            } else {
                                myApi.sendChannelMessage(
                                        "I am now stuck to this channel. Use !stick again to " + "free me.");
                                isSticky = true;
                            }
                        }
                    } else if (e.getMessage().toUpperCase().equals("!DICEHELP")) {
                        myApi.sendChannelMessage(helpMsg);
                    } else if (args[0].toUpperCase().equals("!SPAM")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            spam(args);
                        }
                    } else if (e.getMessage().toUpperCase().equals("!MIRROR")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            mirrorEnabled = !mirrorEnabled;
                            if (mirrorEnabled) {
                                myApi.sendChannelMessage("Mirrormode enabled.");
                            } else {
                                myApi.sendChannelMessage("Mirrormode disabled.");
                            }
                        } else if (e.getMessage().toUpperCase().equals("!ADMINHELP")) {
                            if (isAdmin(e.getInvokerUserId())) {
                                myApi.sendPrivateMessage(e.getInvokerId(), adminHelpMsg);
                            }
                        } else if (mirrorEnabled) {
                            myApi.sendChannelMessage(e.getMessage());
                        }
                    }
                } else if (e.getTargetMode() == TextMessageTargetMode.CLIENT) {
                    if (e.getMessage().toUpperCase().equals("!ENABLEDICE")) {
                        if (!isSticky) {
                            myApi.moveClient(myApi.getClientByUId(e.getInvokerUserId()).getChannelId());
                            myApi.sendChannelMessage(
                                    "has joined the channel. " + "Channel commands are now available.");
                        } else {
                            myApi.sendPrivateMessage(e.getInvokerId(),
                                    "I am currently stuck to channel "
                                            + myApi.getClientByName(cfg.getTs3Nickname()).get(0).getChannelId()
                                            + " - please unstick me first.");
                        }
                    } else if (args[0].toUpperCase().equals("!SPAM")) {
                        spam(args);
                    } else if (e.getMessage().toUpperCase().equals("!DICEHELP")) {
                        myApi.sendPrivateMessage(e.getInvokerId(), helpMsg);
                    } else if (e.getMessage().toUpperCase().equals("!SHUTDOWN")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            myApi.sendPrivateMessage(e.getInvokerId(), "Shut down requested.");
                            log.info("Shutdown requested by " + e.getInvokerName() + ". The bot will now"
                                    + " terminate");
                            System.exit(1);
                        }
                    } else if (e.getMessage().toUpperCase().equals("!DICEINFO")) {
                        myApi.sendPrivateMessage(e.getInvokerId(), "DicebotR3 by WG FlawedBliss. Uses the "
                                + "Teamspeak3 Java API by TheHolyWaffle (http://github.com/TheHolyWaffle) \n"
                                + "Found a bug? Need help? Contact WG FlawedBliss!");
                    } else if (args[0].toUpperCase().equals("!PREMIUM")) {
                        if (isPremium(e.getInvokerUserId())) {
                            myApi.sendPrivateMessage(e.getInvokerId(), "You are premium already!");
                        } else {
                            if (args.length != 2) {
                                myApi.sendPrivateMessage(e.getInvokerId(), "Invalid syntax: !premium <code>");
                            } else {
                                Connection connect = null;
                                Statement statement = null;
                                PreparedStatement preparedStatement = null;
                                ResultSet resultSet = null;
                                try {
                                    connect = cp.getConnection();
                                    statement = connect.createStatement();
                                    resultSet = statement.executeQuery("SELECT * FROM " + cfg.getMysqlPremiumTable()
                                            + " WHERE code='" + args[1] + "'");
                                    if (!resultSet.isBeforeFirst()) {
                                        myApi.sendPrivateMessage(e.getInvokerId(), "Invalid code.");
                                    } else {
                                        while (resultSet.next()) {
                                            if (resultSet.getBoolean("used")) {
                                                myApi.sendPrivateMessage(e.getInvokerId(),
                                                        "That code has been used already.");
                                            } else {
                                                Date date = new Date();
                                                SimpleDateFormat sdf = new SimpleDateFormat(
                                                        "yyyy-MM-dd " + "HH:mm:ss");
                                                String currentTime = sdf.format(date);

                                                preparedStatement = connect.prepareStatement("UPDATE "
                                                        + cfg.getMysqlPremiumTable() + " SET used='1', date_used=?,"
                                                        + " used_by=? WHERE code=?");
                                                preparedStatement.setString(1, currentTime);
                                                preparedStatement.setString(2, e.getInvokerUserId());
                                                preparedStatement.setString(3, args[1]);
                                                preparedStatement.executeUpdate();
                                                preparedStatement.close();
                                                myApi.addClientToServerGroup(cfg.getPremiumGID(),
                                                        myApi.getClientInfo(e.getInvokerId()).getDatabaseId());
                                                myApi.sendPrivateMessage(e.getInvokerId(), "Success!");
                                                log.info("Premium code " + args[1] + " used by "
                                                        + e.getInvokerUserId());
                                            }
                                        }
                                        resultSet.close();
                                        statement.close();
                                        connect.close();

                                    }
                                } catch (SQLException ex) {
                                    myApi.sendPrivateMessage(e.getInvokerId(), "Sorry, I have encountered a "
                                            + "database error. Please try again at a later time.");
                                    log.warning("SQLException while trying to process premium code " + args[1]
                                            + "of " + e.getInvokerUserId());
                                    ex.printStackTrace();
                                }
                            }
                        }
                    } else if (e.getMessage().toUpperCase().equals("!ADMINHELP")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            myApi.sendPrivateMessage(e.getInvokerId(), adminHelpMsg);
                        }
                    } else if (args[0].toUpperCase().equals("!ADDNOTICE")) {
                        if (isAdmin(e.getInvokerUserId())) {
                            if (args.length < 4) {
                                myApi.sendPrivateMessage(e.getInvokerId(), "Invalid syntax: !addnotice <days until"
                                        + "expiration> <special(1/0)> <message>");
                            } else if (!isInteger(args[1]) || !isInteger(args[2])
                                    || Integer.parseInt(args[2]) != 1 && Integer.parseInt(args[2]) != 0) {
                                myApi.sendPrivateMessage(e.getInvokerId(), "Invalid syntax: Days until expiration "
                                        + "needs to be a number and special needs to be either 1 or 0.");
                            } else {
                                String message = "";
                                for (int i = 3; i < args.length; i++) {
                                    message += args[i] + " ";
                                }

                                Notice notice = new Notice();
                                notice.setActive(true);
                                notice.setSpecial(Boolean.parseBoolean(args[3]));
                                notice.setMessage(message);
                                notice.setExpirationDate(
                                        new DateTime(new java.util.Date()).plusDays(Integer.parseInt(args[1])));

                                if (addNotice(notice)) {
                                    myApi.sendPrivateMessage(e.getInvokerId(), "Notice has been added.");
                                } else {
                                    myApi.sendPrivateMessage(e.getInvokerId(), "Sorry, I have encountered"
                                            + "a database error while trying to add your notice. Please try again at"
                                            + "a later time.");
                                }
                            }
                        }
                    } else if (args[0].toUpperCase().equals("!DEACTIVATENOTICE")) {
                        if (args.length != 2) {
                            myApi.sendPrivateMessage(e.getInvokerId(),
                                    "Invalid syntax: !deactivatenotice" + " <noticeId>");
                        } else if (!isInteger(args[1])) {
                            myApi.sendPrivateMessage(e.getInvokerId(),
                                    "Invalid syntax: noticeId needs to be a " + "number.");
                        } else {
                            if (deactivateNotice(Integer.parseInt(args[1]))) {
                                myApi.sendPrivateMessage(e.getInvokerId(), "The notice corresponding to Id "
                                        + args[1] + " has been deactivated successfully.");
                            } else {
                                myApi.sendPrivateMessage(e.getInvokerId(), "Sorry, I could not deactivate the "
                                        + "notice corresponding to Id " + args[1] + ". This could be caused by a"
                                        + " database error, an invalid noticeId or maybe the notice is deactivated"
                                        + " already.");
                            }
                        }

                    } else if (args[0].toUpperCase().equals("!CONFIRM")) {
                        if (args.length != 2) {
                            myApi.sendPrivateMessage(e.getInvokerId(), "Invalid syntax: !confirm <noticeId>");
                        } else if (!isInteger(args[1])) {
                            myApi.sendPrivateMessage(e.getInvokerId(),
                                    "Invalid syntax: noticeId has to be a" + " number");
                        } else {
                            if (hasConfirmedNotice(e.getInvokerUserId(), Integer.parseInt(args[1]))) {
                                myApi.sendPrivateMessage(e.getInvokerId(),
                                        "Sorry, you already confirmed that " + "notice.");
                            } else {
                                if (confirmNotice(e.getInvokerUserId(), Integer.parseInt(args[1]))) {
                                    myApi.sendPrivateMessage(e.getInvokerId(),
                                            "You have successfully " + "confirmed notice " + args[1]);
                                } else {
                                    myApi.sendPrivateMessage(e.getInvokerId(), "Sorry, I could not confirm"
                                            + "the notice. Please try again at a later time.");
                                }
                            }
                        }
                    }
                }
            }

            @Override
            public void onServerEdit(ServerEditedEvent e) {

            }

            @Override
            public void onClientMoved(ClientMovedEvent e) {

            }

            @Override
            public void onClientLeave(ClientLeaveEvent e) {

            }

            @Override
            public void onClientJoin(ClientJoinEvent e) {
                if (e.getClientType() == 0) {
                    final String uid = myApi.getClientInfo(e.getClientId()).getUniqueIdentifier();
                    if (cfg.isMotdEnabled()) {
                        for (int i : cfg.getMotdGIDs()) {
                            if (clientHasServergroup(myApi.getClientInfo(e.getClientId()), i)) {
                                myApi.sendPrivateMessage(e.getClientId(), motd);
                                break;
                            }
                        }
                    }

                    if (clientHasServergroup(myApi.getClientInfo(e.getClientId()), cfg.getFriendlyInactiveDays())) {
                        if (checkInactivity(myApi.getClientInfo(e.getClientId()).getUniqueIdentifier(),
                                cfg.getFriendlyInactiveDays())) {
                            myApi.removeClientFromServerGroup(cfg.getFriendlyGID(), e.getClientId());
                            myApi.sendPrivateMessage(e.getClientId(), "Because of your recent inactivity"
                                    + " your friendly status has been revoked.");
                        }
                    } else {
                        checkInactivity(myApi.getClientInfo(e.getClientId()).getUniqueIdentifier(),
                                cfg.getInactiveDays());
                    }
                    updateLastlogin(uid);

                    if (isPremium(uid)) {
                        checkPremiumExpired(uid, e.getClientId());
                    }
                }
            }

            @Override
            public void onChannelPasswordChanged(ChannelPasswordChangedEvent e) {

            }

            @Override
            public void onChannelMoved(ChannelMovedEvent e) {

            }

            @Override
            public void onChannelDeleted(ChannelDeletedEvent e) {

            }

            @Override
            public void onChannelCreate(ChannelCreateEvent e) {

            }

            @Override
            public void onChannelDescriptionChanged(ChannelDescriptionEditedEvent e) {

            }

            @Override
            public void onChannelEdit(ChannelEditedEvent e) {

            }

        });

    }

    private void checkPremiumExpired(String uid, int clId) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;

        try {
            connect = cp.getConnection();
            preparedStatement = connect.prepareStatement("SELECT * FROM premium WHERE used_by=?");
            preparedStatement.setString(1, uid);
            resultSet = preparedStatement.executeQuery();
            DateTime today = new DateTime(new Date());
            DateTime latest = new DateTime(new Date());
            latest = latest.minusYears(1);
            if (resultSet.isBeforeFirst()) {
                while (resultSet.next()) {
                    DateTime resultSetDate = new DateTime(resultSet.getDate("date_used"));
                    if (resultSetDate.isAfter(latest)) {
                        latest = resultSetDate;
                    }
                }

                Days d = Days.daysBetween(latest, today);
                if (d.getDays() > cfg.getPremiumDays()) {
                    myApi.removeClientFromServerGroup(cfg.getPremiumGID(),
                            myApi.getClientByUId(uid).getDatabaseId());
                    myApi.sendPrivateMessage(clId, "Your premium has expired.");
                }
            }
        } catch (SQLException ex) {
            log.warning("SQLException when trying to check premium of" + uid);
            ex.printStackTrace();
        }
    }

    private void updateLastlogin(String uid) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement2 = null;
        ResultSet resultSet = null;
        DateTime date = new DateTime(new Date());
        DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

        try {
            connect = cp.getConnection();
            preparedStatement = connect.prepareStatement("SELECT * FROM lastlogin WHERE uid=?");
            preparedStatement.setString(1, uid);
            resultSet = preparedStatement.executeQuery();
            if (resultSet.isBeforeFirst()) {
                preparedStatement2 = connect.prepareStatement("UPDATE lastlogin SET lastlogin=? WHERE " + "uid=?");
                preparedStatement2.setString(1, dtf.print(date));
                preparedStatement2.setString(2, uid);
                preparedStatement2.executeUpdate();
            } else {
                preparedStatement2 = connect
                        .prepareStatement("INSERT INTO lastlogin (uid, lastlogin)" + " VALUES (?, ?)");
                preparedStatement2.setString(1, uid);
                preparedStatement2.setString(2, dtf.print(date));
                preparedStatement2.executeUpdate();
            }
            preparedStatement2.close();
            resultSet.close();
            preparedStatement.close();
            connect.close();
        } catch (SQLException ex) {
            log.warning("SQLException when trying to update lastlogin of " + uid);
        }
    }

    private boolean checkInactivity(String uid, int days) {
        if (cfg.getInactiveGID() == -1) {
            return false;
        }
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connect = cp.getConnection();
            preparedStatement = connect.prepareStatement("SELECT * FROM lastlogin WHERE uid=?");
            preparedStatement.setString(1, uid);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                DateTime today = new DateTime(new Date());
                DateTime lastlogin = new DateTime(resultSet.getDate("lastlogin"));
                Days d = Days.daysBetween(today, lastlogin);
                if (d.getDays() > days) {
                    myApi.addClientToServerGroup(cfg.getInactiveGID(), myApi.getClientByUId(uid).getDatabaseId());
                    return true;
                }
            }
            resultSet.close();
            preparedStatement.close();
            connect.close();
        } catch (SQLException ex) {
            log.warning("SQLException while checking inactivity of " + uid);
        }
        return false;
    }

    private boolean clientHasServergroup(ClientInfo clInfo, int gid) {
        for (int i : clInfo.getServerGroups()) {
            if (i == gid) {
                return true;
            }
        }
        return false;
    }

    private boolean confirmNotice(String uid, int noticeId) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        try {
            connect = cp.getConnection();
            preparedStatement = connect
                    .prepareStatement("INSERT INTO confirmNotice (noticeId, uid)" + "VALUES (?, ?)");
            preparedStatement.setInt(1, noticeId);
            preparedStatement.setString(2, uid);
            preparedStatement.executeUpdate();
            preparedStatement.close();
            connect.close();
            return true;
        } catch (SQLException ex) {
            log.warning("SQLException when confirming notice with uid " + uid + " and id " + noticeId);
            return false;
        }
    }

    private boolean hasConfirmedNotice(String uid, int noticeId) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        ResultSet resultSet = null;
        try {
            connect = cp.getConnection();
            preparedStatement = connect.prepareStatement("SELECT * FROM confirmNotice WHERE uid=? " + "AND id=?");
            preparedStatement.setString(1, uid);
            preparedStatement.setInt(2, noticeId);
            resultSet = preparedStatement.executeQuery();
            boolean confirmed = resultSet.isBeforeFirst();
            resultSet.close();
            preparedStatement.close();
            connect.close();
            return confirmed;
        } catch (SQLException ex) {
            log.warning("SQLException when checking for confirmed notice with uid " + uid + " and id " + noticeId);
            return false;
        }
    }

    private ArrayList<Notice> getActiveNotices() {
        Connection connect = null;
        Statement statement = null;
        ResultSet resultSet = null;
        ArrayList<Notice> notices = new ArrayList<>();
        try {
            connect = cp.getConnection();
            statement = connect.createStatement();
            resultSet = statement.executeQuery("SELECT * FROM " + cfg.getMysqlNoticeTable() + " WHERE active=1");
            while (resultSet.next()) {
                if (resultSet.getDate("expirationDate").before(new java.util.Date())) {
                    deactivateNotice(resultSet.getInt("noticeId"));
                } else {
                    Notice notice = new Notice();
                    notice.setActive(true);
                    notice.setSpecial(resultSet.getBoolean("special"));
                    notice.setMessage(resultSet.getString("message"));
                    notice.setExpirationDate(new DateTime(resultSet.getDate("expirationDate")));
                    notice.setId(resultSet.getInt("noticeId"));
                    notices.add(notice);
                }
            }
            resultSet.close();
            statement.close();
            connect.close();
            return notices;

        } catch (SQLException ex) {
            log.warning("SQLException while trying to fetch active notices.");
            return null;
        }
    }

    private boolean deactivateNotice(int noticeId) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;
        PreparedStatement preparedStatement2 = null;
        ResultSet resultSet = null;
        try {
            connect = cp.getConnection();
            preparedStatement = connect
                    .prepareStatement("SELECT * FROM " + cfg.getMysqlNoticeTable() + " WHERE noticeId=?");
            preparedStatement.setInt(1, noticeId);
            resultSet = preparedStatement.executeQuery();
            if (!resultSet.isBeforeFirst()) {
                return false;
            } else {
                while (resultSet.next()) {
                    if (!resultSet.getBoolean("active")) {
                        resultSet.close();
                        preparedStatement.close();
                        connect.close();
                        return false;
                    } else {
                        preparedStatement2 = connect.prepareStatement(
                                "UPDATE " + cfg.getMysqlNoticeTable() + " SET active=0 WHERE noticeId=?");
                        preparedStatement2.setInt(1, noticeId);
                        preparedStatement2.executeUpdate();
                        preparedStatement2.close();
                        resultSet.close();
                        preparedStatement.close();
                        connect.close();
                        return true;
                    }
                }
            }
        } catch (SQLException ex) {
            log.warning("SQLException while trying to deactivate notice " + noticeId);
            return false;
        }
        return false;
    }

    private boolean addNotice(Notice notice) {
        Connection connect = null;
        PreparedStatement preparedStatement = null;

        DateTimeFormatter dtf = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

        try {
            connect = cp.getConnection();
            preparedStatement = connect.prepareStatement("INSERT INTO " + cfg.getMysqlNoticeTable()
                    + "(message, expirationDate, special) VALUES (?, ?, ?)");
            preparedStatement.setString(1, notice.getMessage());
            preparedStatement.setString(2, dtf.print(notice.getExpirationDate()));
            preparedStatement.setBoolean(3, notice.isSpecial());
            preparedStatement.executeUpdate();
            preparedStatement.close();
            connect.close();
            return true;
        } catch (SQLException ex) {
            log.warning("SQLException while trying to add a new notice.");
            return false;
        }
    }

    private void spam(final String[] args) {
        if (args.length < 4) {
            myApi.sendChannelMessage("Error: Invalid Arguments. Usage: !spam <username> " + "<text> <times>");
            return;
        }
        if (!isInteger(args[args.length - 1])) {
            myApi.sendChannelMessage("Error: Invalid Arguments. <times> can only be a number.");
            return;
        }
        if (Integer.parseInt(args[args.length - 1]) > 60) {
            myApi.sendChannelMessage("Error: Invalid Arguments. You can only spam 60 times at " + "a time."); // http://z0r.de/L/z0r-de_6210.swf I'll just leave this here
            return;
        }
        String clName = "";
        for (int i = 0; i < args.length - 3; i++) {
            if (i != args.length - 4) {
                clName += args[i + 1] + " ";
            } else {
                clName += args[i + 1];
            }
        }
        final String fClName = clName;
        if (myApi.getClientByName(clName).size() > 1) {
            myApi.sendChannelMessage("Sorry, I could not identify " + clName);
            return;
        } else if (myApi.getClientByName(clName).size() < 1) {
            myApi.sendChannelMessage("Sorry, I could not find " + clName);
            return;
        }
        final Timer timer = new Timer();
        Timer endTimer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                myApi.sendPrivateMessage(myApi.getClientByName(fClName).get(0).getId(), args[args.length - 2]);
            }
        }, 0, 1000);
        endTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                timer.cancel();
                timer.purge();
            }
        }, Integer.parseInt(args[args.length - 1]) * 1000);

    }

    private boolean isAdmin(String uid) {
        return cfg.getAdminUIDs().contains(uid);
    }

    private boolean isPremium(String uid) {
        int[] GIDs = myApi.getClientByUId(uid).getServerGroups();
        for (int i : GIDs) {
            if (i == cfg.getPremiumGID()) {
                return true;
            }
        }
        return false;
    }

    private boolean isInteger(String s) {
        try {
            Integer.parseInt(s);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    public DicebotStatus getStatus() {
        return status;
    }

    public void sendNotices() {
        if (myApi.getClients() != null) {
            List<Notice> notices = getActiveNotices();
            for (Client c : myApi.getClients()) {
                for (int i : c.getServerGroups()) {
                    if (cfg.getNoticeGIDs().contains(i)) {
                        for (Notice n : notices) {
                            if (!n.isSpecial()) {
                                myApi.sendPrivateMessage(c.getId(),
                                        "NoticeId: " + n.getId() + "\n" + n.getMessage());
                            }
                        }
                        break;
                    }
                }
                for (int i : c.getServerGroups()) {
                    if (cfg.getSpecialNoticeGIDs().contains(i)) {
                        for (Notice n : notices) {
                            if (n.isSpecial()) {
                                myApi.sendPrivateMessage(c.getId(),
                                        "NoticeId: " + n.getId() + "\n" + n.getMessage());
                            }
                            break;
                        }
                    }
                }
            }
        }
    }

    public String getInstanceName() {
        return cfg.getInstanceName();
    }

    public void sendServerMessage(String msg) {
        myApi.sendServerMessage(msg);
    }

    public void exit() {
        myApi.sendServerMessage("Shutting down....");
        if (myApi != null) {
            myApi.quit();
        }
        if (myQuery != null) {
            myQuery.exit();
        }
        cp.shutdown();
        this.status = DicebotStatus.CLOSING;
    }

}