com.omertron.slackbot.SlackBot.java Source code

Java tutorial

Introduction

Here is the source code for com.omertron.slackbot.SlackBot.java

Source

/*
 *      Copyright (c) 2017 Stuart Boston
 *
 *      This file is part of the BGG Slack Bot.
 *
 *      The BGG Slack Bot is free software: you can redistribute it and/or modify
 *      it under the terms of the GNU General Public License as published by
 *      the Free Software Foundation, either version 3 of the License, or
 *      any later version.
 *
 *      The BGG Slack Bot 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 General Public License for more details.
 *
 *      You should have received a copy of the GNU General Public License
 *      along with the BGG Slack Bot.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.omertron.slackbot;

import com.omertron.slackbot.enumeration.ExitCode;
import com.omertron.slackbot.functions.BotStatistics;
import com.omertron.slackbot.functions.BotWelcome;
import com.omertron.slackbot.functions.scheduler.BotTaskExecutor;
import com.omertron.slackbot.listeners.BoardGameListener;
import com.omertron.slackbot.listeners.GoogleSheetsListener;
import com.omertron.slackbot.listeners.HelpListener;
import com.omertron.slackbot.utils.PropertiesUtil;
import com.ullink.slack.simpleslackapi.SlackChannel;
import com.ullink.slack.simpleslackapi.SlackPersona;
import com.ullink.slack.simpleslackapi.SlackSession;
import com.ullink.slack.simpleslackapi.SlackUser;
import com.ullink.slack.simpleslackapi.impl.SlackSessionFactory;
import com.ullink.slack.simpleslackapi.listeners.SlackMessagePostedListener;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SlackBot {

    private static final Logger LOG = LoggerFactory.getLogger(SlackBot.class);
    private static final String DEFAULT_PROPERTIES_FILE = "application.properties";
    private static final List<SlackUser> BOT_ADMINS = new ArrayList<>();
    private static BotTaskExecutor executor;
    private static final List<SlackMessagePostedListener> LISTENER_MP = new ArrayList<>();

    private SlackBot() {
        // No need for a constructor in the main class
    }

    public static void main(String[] args) throws Exception {
        LOG.info("Starting {} v{} ...", Constants.BOT_NAME, Constants.BOT_VERSION);

        // Load the properties
        PropertiesUtil.setPropertiesStreamName(DEFAULT_PROPERTIES_FILE);

        LOG.info("Starting session...");
        SlackSession session;

        String proxyURL = PropertiesUtil.getProperty(Constants.PROXY_HOST);
        if (StringUtils.isNotBlank(proxyURL)) {
            int proxyPort = Integer.parseInt(PropertiesUtil.getProperty(Constants.PROXY_PORT, "80"));
            session = SlackSessionFactory.getSlackSessionBuilder(Constants.BOT_TOKEN)
                    .withProxy(Proxy.Type.HTTP, proxyURL, proxyPort).build();
        } else {
            session = SlackSessionFactory
                    .createWebSocketSlackSession(PropertiesUtil.getProperty(Constants.BOT_TOKEN));
        }

        session.connect();

        // Populate the BOT admins
        populateBotAdmins(session);

        // Notify BOT admins
        notifyStartup(session);

        // Add the listeners to the session
        addListeners(session);

        LOG.info("Session connected: {}", session.isConnected());
        LOG.info("\tConnected to {} ({})", session.getTeam().getName(), session.getTeam().getId());
        LOG.info("\tFound {} channels and {} users", session.getChannels().size(), session.getUsers().size());

        outputBotAdminsMessage();

        LOG.info("Starting the Task Executor");
        executor = new BotTaskExecutor(session);

        LOG.info("Checking for users welcomed list");
        BotWelcome.readFile();

        LOG.info("Checking for stats file");
        BotStatistics.readFile();
        LOG.info("Stats read:\n{}", BotStatistics.generateStatistics(false, true));

        Thread.sleep(Long.MAX_VALUE);
    }

    /**
     * Add the listeners to the session.
     *
     * @param session SlackSession
     */
    private static synchronized void addListeners(SlackSession session) {
        // Only add the listeners once
        if (LISTENER_MP.isEmpty()) {
            // Add board game listner
            LISTENER_MP.add(new BoardGameListener());
            // Add Wirral Biscuits and Boardgames 
            LISTENER_MP.add(new GoogleSheetsListener());
            // Add help listener
            LISTENER_MP.add(new HelpListener());

            for (SlackMessagePostedListener l : LISTENER_MP) {
                session.addMessagePostedListener(l);
            }
        }
    }

    /**
     * Output log messages about the bot admins
     */
    private static void outputBotAdminsMessage() {
        switch (BOT_ADMINS.size()) {
        case 0:
            LOG.warn("\tThere are no BOT Admins found! Please add at least 1 in the properties file!");
            LOG.warn("\tUser the property '{}' to add them", Constants.BOT_ADMINS);
            break;
        case 1:
            LOG.info("\tThere is 1 BOT admin: {}", StringUtils.join(BOT_ADMINS, ","));
            break;
        default:
            List<String> names = new ArrayList<>();
            BOT_ADMINS.forEach(su -> names.add(su.getUserName()));
            LOG.info("\tThere are {} BOT admins: {}", BOT_ADMINS.size(), StringUtils.join(names, ","));
        }
    }

    /**
     * Shut down the bot with the given exit code.
     *
     * @param exitCode
     */
    public static void shutdown(ExitCode exitCode) {
        if (executor != null) {
            executor.stopAll();
        }
        System.exit(exitCode.getValue());
    }

    /**
     * Send a start up message to all BOT admins to inform them of the bot's
     * restart
     *
     * @param session
     */
    private static void notifyStartup(SlackSession session) {
        String message = String.format("%1$s started at %2$s", Constants.BOT_NAME,
                DateFormatUtils.format(new Date(), "dd-MM-yyyy HH:mm:ss"));
        messageAdmins(session, message);
    }

    /**
     * Send a message to all admins
     *
     * @param session
     * @param message
     */
    public static void messageAdmins(SlackSession session, String message) {
        LOG.info("Sending message to admins: '{}'", message);
        for (SlackUser user : BOT_ADMINS) {
            LOG.info("\tSent to '{}'", user.getUserName());
            session.sendMessageToUser(user, message, null);
        }
    }

    /**
     * Populate the list of BOT Administrators from the property file.
     *
     * @param session
     */
    private static void populateBotAdmins(SlackSession session) {
        String users = PropertiesUtil.getProperty(Constants.BOT_ADMINS, "");

        if (StringUtils.isNotBlank(users)) {
            SlackUser sUser;
            for (String user : StringUtils.split(users, ",")) {
                sUser = session.findUserByUserName(StringUtils.trimToEmpty(user));
                if (sUser != null) {
                    LOG.info("Adding {} ({}) to {} admins", sUser.getUserName(), sUser.getRealName(),
                            Constants.BOT_NAME);
                    // Add the uername to the list
                    BOT_ADMINS.add(sUser);
                } else {
                    LOG.warn("Username '{}' was not found in the list of slack users!", user);
                }
            }
        }
    }

    /**
     * List of the bot admins
     *
     * @return admin names
     */
    public static List<SlackUser> getBotAdmins() {
        return BOT_ADMINS;
    }

    /**
     * Determine if the user is one of the BOT administrators
     *
     * @param user
     * @return
     */
    public static boolean isBotAdmin(SlackUser user) {
        return BOT_ADMINS.contains(user);
    }

    /**
     * Create a formatted username string
     *
     * @param persona
     * @return
     */
    public static String formatUsernameLink(SlackPersona persona) {
        return formatLink("@", persona.getId(), persona.getUserName());
    }

    /**
     * Create a formatted channel string
     *
     * @param channel
     * @return
     */
    public static String formatChannelLink(SlackChannel channel) {
        return formatLink("#", channel.getId(), channel.getName());
    }

    /**
     * Create a Slack formatted URL link
     *
     * @param url URL
     * @param text Text to display
     * @return
     */
    public static String formatLink(String url, String text) {
        return formatLink(null, url, text);
    }

    /**
     * Format a link
     *
     * @param preMarker
     * @param url
     * @param text
     * @return
     */
    private static String formatLink(String preMarker, String url, String text) {
        StringBuilder formatted = new StringBuilder("<");
        if (preMarker != null) {
            formatted.append(preMarker);
        }
        formatted.append(url).append("|").append(text).append(">");
        return formatted.toString();
    }
}