Java tutorial
/* * Copyright (C) 2014 Matej Kormuth <http://matejkormuth.eu> * * This program 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 (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 General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program. If not, see * <http://www.gnu.org/licenses/>. */ package eu.matejkormuth.ts3bot; import java.io.File; import java.util.ArrayList; import java.util.List; import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.PropertiesConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.eventbus.EventBus; import eu.matejkormuth.ts3bot.teamspeak.QueryConnection; import eu.matejkormuth.ts3bot.teamspeak.QueryCreditnals; import eu.matejkormuth.ts3bot.teamspeak.VirtualServer; /** * Specifies main bot class. */ public class Bot { private static Bot instance; /** * Returns instance of currently running Bot. * * @return Bot instance */ public static Bot getInstance() { return Bot.instance; } private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final List<Service> services = new ArrayList<Service>(); private final EventBus eventBus = new EventBus(); PropertiesConfiguration configuration; private QueryConnection queryConnection; private ConsoleReader consoleReader; /** * Creates a new bot. */ public Bot() { Bot.instance = this; } /** * Boots up Bot. */ public void boot() { if (this.configuration != null) { throw new RuntimeException("Bot is already booted up!"); } this.logger.info("Booting up..."); this.logger.info("Reading configuration..."); try { this.configuration = new PropertiesConfiguration("bot.properties"); } catch (ConfigurationException e) { this.logger.error("Error while loading configuration from bot.properties: {}", e.getMessage()); try { this.configuration = new PropertiesConfiguration( this.getClass().getClassLoader().getResource("bot.properties")); } catch (ConfigurationException e2) { this.logger.error("Error while loading configuration from jar: {}", e2.getMessage()); this.configuration = new PropertiesConfiguration(); this.configuration.setHeader("TS3 Bot configuration."); this.configuration.setFileName("bot.properties"); } } // Connect to teamspeak server. String name = this.configuration.getString("query.login"); String pass = this.configuration.getString("query.password"); String ip = this.configuration.getString("server.ip"); if (name == null || pass == null || ip == null) { // Can't continue without these values. throw new RuntimeException( "Can't get query login, query password or server ip address from config! Can't continue!"); } boolean flood = this.configuration.getBoolean("server.preventflood", false); boolean autoRegister = this.configuration.getBoolean("server.autoRegisterChannelEvents", true); String nickname = this.configuration.getString("bot.name", "TS3Bot"); this.logger.info("Connecting to teamspeak server {}...", ip); QueryCreditnals creds = new QueryCreditnals(name, pass); this.queryConnection = new QueryConnection(creds, ip, nickname, flood, autoRegister); // nickname will never be null... // Connect to server. this.queryConnection.connect(); // Some default services. List<Object> services = this.configuration.getList("bot.services"); // In case we have only one service. if (services.size() == 0) { if (this.configuration.getString("bot.service") != null) { services.add(this.configuration.getString("bot.service")); } } // Create all services. this.logger.info("Loading services..."); for (Object o : services) { try { Class<?> clazz = Class.forName(o.toString()); if (Service.class.isAssignableFrom(clazz)) { Service service = (Service) clazz.getConstructor().newInstance(); this.services.add(service); } else { this.logger.error( "Specified service " + o.toString() + " does not extend Service class! Can't load it."); } } catch (Exception e) { this.logger.error("Can't load service {}! Problem: {}", o.toString(), e.getMessage()); this.logger.error(e.toString()); } } this.logger.info("Starting services..."); // Start services. for (Service service : this.services) { if (service.isAsynchronous()) { this.logger.info("Enabling service asynchronously " + service.getClass().getSimpleName() + "..."); final Service s = service; // Start thread for service. new Thread(new Runnable() { public void run() { s.setBot(Bot.this); Bot.this.eventBus.register(s); s.enable(); } }, "service/" + service.getClass().getSimpleName()).run(); } else { try { this.logger .info("Enabling service synchronously " + service.getClass().getSimpleName() + "..."); service.setBot(this); this.eventBus.register(service); service.enable(); } catch (Exception e) { this.logger.error("Can't enable service! Problem: {}", e.getMessage()); this.logger.error(e.toString()); } } } this.logger.info("Finished loading!"); // Start reading commands from console. this.consoleReader = new ConsoleReader(); this.consoleReader.setBot(this); this.consoleReader.enable(); } /** * Shutdowns all services and disconnects from ServerQuery. */ public void shutdown() { // Disable reading of commands. this.consoleReader.disable(); this.logger.info("Shutting down..."); try { if (this.configuration.getBoolean("config.useExternal", true)) { this.configuration.setFile(new File("/bot.properties")); this.configuration.save(); this.logger.info("Configuration saved!"); } } catch (ConfigurationException e) { this.logger.error("Couldn't save configuration: {}", e.getMessage()); } this.logger.info("Shutting down services..."); // Shutdown services. for (Service service : this.services) { try { this.eventBus.unregister(service); service.disable(); } catch (Exception e) { this.logger.error("Can't disable service! Problem: {}", e.getMessage()); this.logger.error(e.toString()); } } this.logger.info("Disconnecting..."); // Close connection. this.queryConnection.disconnect(); // Bye! this.logger.info("Thanks for using!"); this.logger.info("Bye!"); } /** * Returns this bot {@link QueryConnection}. * * @return currently used query connection */ public QueryConnection getQueryConnection() { return this.queryConnection; } /** * Returns configuration of this bot. * * @return this bot's configuration */ public Configuration getConfiguration() { return this.configuration; } /** * Returns list of all {@link Service}s used by this bot. * * @return all services */ public List<Service> getServices() { return this.services; } /** * Returns this bot's logger. * * @return logger instance */ public Logger getLogger() { return this.logger; } /** * Returns event bus. * * @return event bus */ public EventBus getEventBus() { return this.eventBus; } /** * Returns {@link VirtualServer} that is query currently connected to. Same as calling {@link #getQueryConnection()} * and then {@link QueryConnection#getVirtualServer()}. * * @return {@link VirtualServer} instance that is query connected to */ public VirtualServer getVirtualServer() { return this.queryConnection.getVirtualServer(); } }