Code formmating, tabs to spaces, etc.

This commit is contained in:
Erik C. Thauvin 2016-07-16 18:15:14 -07:00
parent e90992a7f6
commit ad36c18124
29 changed files with 4375 additions and 5286 deletions

View file

@ -1,23 +1,23 @@
Some very basic instructions: Some very basic instructions:
{ clone with git or download the ZIP } { clone with git or download the ZIP }
git clone git://github.com/ethauvin/mobibot.git git clone git://github.com/ethauvin/mobibot.git
cd mobibot cd mobibot
{ build with gradle } { build with gradle }
./gradlew ./gradlew
cd deploy cd deploy
{ configure the properties } { configure the properties }
vi *.properties vi *.properties
{ help } { help }
java -jar mobibot.jar -h java -jar mobibot.jar -h
{ twitter oauth token request } { twitter oauth token request }
java -cp mobibot.jar net.thauvin.erik.mobibot.TwitterOAuth <consumerKey> <consumerSecret> java -cp mobibot.jar net.thauvin.erik.mobibot.TwitterOAuth <consumerKey> <consumerSecret>
{ launch } { launch }
/usr/bin/nohup java -jar mobibot.jar & /usr/bin/nohup java -jar mobibot.jar &

View file

@ -1,6 +1,6 @@
plugins { plugins {
id "com.ewerk.gradle.plugins.annotation-processor" version "1.0.2" id "com.ewerk.gradle.plugins.annotation-processor" version "1.0.2"
id "com.github.ben-manes.versions" version "0.12.0" id "com.github.ben-manes.versions" version "0.12.0"
} }
apply plugin: 'java' apply plugin: 'java'
@ -13,29 +13,27 @@ def packageName = 'net.thauvin.erik.mobibot'
def deployDir = 'deploy' def deployDir = 'deploy'
def isRelease = 'release' in gradle.startParameter.taskNames def isRelease = 'release' in gradle.startParameter.taskNames
def getVersion(isIncrement = false) def getVersion(isIncrement = false) {
{ def propsFile = 'version.properties'
def propsFile = 'version.properties' def majorKey = 'version.major'
def majorKey = 'version.major' def minorKey = 'version.minor'
def minorKey = 'version.minor' def patchKey = 'version.patch'
def patchKey = 'version.patch' def metaKey = 'version.buildmeta'
def metaKey = 'version.buildmeta' def preKey = 'version.prerelease'
def preKey = 'version.prerelease' if (isIncrement) {
if (isIncrement) ant.propertyfile(file: propsFile) {
{ entry(key: patchKey,
ant.propertyfile(file: propsFile) { type: 'int',
entry(key: patchKey, default: '-1',
type: 'int', operation: '+')
default: '-1', }
operation: '+') }
} def p = new Properties()
} file(propsFile).withInputStream { stream -> p.load(stream) }
def p = new Properties() def metadata = p.getProperty(metaKey, '')
file(propsFile).withInputStream { stream -> p.load(stream) } def prerelease = p.getProperty(preKey, '')
def metadata = p.getProperty(metaKey, '') return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') +
def prerelease = p.getProperty(preKey, '') (prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : ''))
return (p.getProperty(majorKey, '1') + '.' + p.getProperty(minorKey, '0') + '.' + p.getProperty(patchKey, '0') +
(prerelease.length() > 0 ? '-' + prerelease : '') + (metadata.length() > 0 ? '+' + metadata : ''))
} }
version = getVersion() version = getVersion()
@ -44,100 +42,100 @@ mainClassName = packageName + '.Mobibot'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8' [compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
repositories { repositories {
mavenLocal() mavenLocal()
mavenCentral() mavenCentral()
jcenter() jcenter()
} }
dependencies { dependencies {
compile 'log4j:log4j:1.2.17@jar' compile 'log4j:log4j:1.2.17@jar'
compile 'pircbot:pircbot:1.5.0' compile 'pircbot:pircbot:1.5.0'
compile 'commons-codec:commons-codec:1.10' compile 'commons-codec:commons-codec:1.10'
compile 'commons-logging:commons-logging:1.2' compile 'commons-logging:commons-logging:1.2'
compile 'commons-net:commons-net:3.5' compile 'commons-net:commons-net:3.5'
compile 'commons-cli:commons-cli:1.3.1' compile 'commons-cli:commons-cli:1.3.1'
compile 'commons-httpclient:commons-httpclient:3.1' compile 'commons-httpclient:commons-httpclient:3.1'
compile 'oro:oro:2.0.8' compile 'oro:oro:2.0.8'
compile 'org.jsoup:jsoup:1.9.2' compile 'org.jsoup:jsoup:1.9.2'
compile 'com.rometools:rome:1.6.1' compile 'com.rometools:rome:1.6.1'
compile 'org.slf4j:slf4j-log4j12:1.7.21' compile 'org.slf4j:slf4j-log4j12:1.7.21'
compile 'org.json:json:20160212' compile 'org.json:json:20160212'
compile 'org.ostermiller:utils:1.07.00' compile 'org.ostermiller:utils:1.07.00'
compile 'net.sourceforge.jweather:jweather:0.3.0@jar' compile 'net.sourceforge.jweather:jweather:0.3.0@jar'
compile 'net.objecthunter:exp4j:0.4.7' compile 'net.objecthunter:exp4j:0.4.7'
compile 'org.twitter4j:twitter4j-core:4.0.4' compile 'org.twitter4j:twitter4j-core:4.0.4'
compile 'net.sf.delicious-java:delicious:1.14' compile 'net.sf.delicious-java:delicious:1.14'
compileOnly 'net.thauvin.erik:semver:0.9.6-beta' compileOnly 'net.thauvin.erik:semver:0.9.6-beta'
} }
annotationProcessor { annotationProcessor {
project.version = getVersion(isRelease) project.version = getVersion(isRelease)
library 'net.thauvin.erik:semver:0.9.6-beta' library 'net.thauvin.erik:semver:0.9.6-beta'
processor 'net.thauvin.erik.semver.VersionProcessor' processor 'net.thauvin.erik.semver.VersionProcessor'
} }
compileJava { compileJava {
options.compilerArgs << '-proc:none' << '-Xlint:unchecked' << '-Xlint:deprecation' options.compilerArgs << '-proc:none' << '-Xlint:unchecked' << '-Xlint:deprecation'
} }
javadoc { javadoc {
options.tags = ['created'] options.tags = ['created']
} }
jar { jar {
manifest.attributes('Main-Class': mainClassName, manifest.attributes('Main-Class': mainClassName,
'Class-Path': '. ./lib/' + configurations.compile.collect { it.getName() }.join(' ./lib/')) 'Class-Path': '. ./lib/' + configurations.compile.collect { it.getName() }.join(' ./lib/'))
version = null version = null
} }
clean { clean {
delete deployDir delete deployDir
} }
run { run {
args '--v' args '--v'
} }
task wrapper(type: Wrapper) { task wrapper(type: Wrapper) {
gradleVersion = gradle.gradleVersion gradleVersion = gradle.gradleVersion
} }
task copyToDeploy(type: Copy) { task copyToDeploy(type: Copy) {
from('properties') { from('properties') {
include '*.properties' include '*.properties'
} }
from jar from jar
into deployDir into deployDir
} }
task copyToDeployLib(type: Copy) { task copyToDeployLib(type: Copy) {
from configurations.runtime from configurations.runtime
into deployDir + '/lib' into deployDir + '/lib'
} }
task deploy(dependsOn: ['build']) { task deploy(dependsOn: ['build']) {
description = 'Copies all needed files to the ${deployDir} directory.' description = 'Copies all needed files to the ${deployDir} directory.'
group = 'Publishing' group = 'Publishing'
outputs.dir deployDir outputs.dir deployDir
inputs.files copyToDeploy inputs.files copyToDeploy
inputs.files copyToDeployLib inputs.files copyToDeployLib
doLast { doLast {
file(deployDir + '/logs').mkdir() file(deployDir + '/logs').mkdir()
} }
mustRunAfter clean mustRunAfter clean
} }
task release(dependsOn: ['wrapper', 'clean', 'deploy']) << { task release(dependsOn: ['wrapper', 'clean', 'deploy']) << {
group = 'Publishing' group = 'Publishing'
description = 'Releases new version.' description = 'Releases new version.'
isRelease = true isRelease = true
} }

View file

@ -13,8 +13,8 @@ import java.util.Date;
* Annotation Processor</a> * Annotation Processor</a>
*/ */
public final class ReleaseInfo { public final class ReleaseInfo {
private final static String buildmeta = "006"; private final static String buildmeta = "008";
private final static Date date = new Date(1468655027549L); private final static Date date = new Date(1468718052505L);
private final static int major = 0; private final static int major = 0;
private final static int minor = 7; private final static int minor = 7;
private final static int patch = 0; private final static int patch = 0;

View file

@ -38,131 +38,129 @@ package net.thauvin.erik.mobibot;
* @created 2014-04-26 * @created 2014-04-26
* @since 1.0 * @since 1.0
*/ */
final class Commands final class Commands {
{ /**
/** * The add (back)log command.
* The add (back)log command. */
*/ public static final String ADDLOG_CMD = "addlog";
public static final String ADDLOG_CMD = "addlog";
/** /**
* The cycle command. * The cycle command.
*/ */
public static final String CYCLE_CMD = "cycle"; public static final String CYCLE_CMD = "cycle";
/** /**
* Debug command line argument. * Debug command line argument.
*/ */
public static final String DEBUG_ARG = "debug"; public static final String DEBUG_ARG = "debug";
/** /**
* The debug command. * The debug command.
*/ */
public static final String DEBUG_CMD = "debug"; public static final String DEBUG_CMD = "debug";
/** /**
* The die command. * The die command.
*/ */
public static final String DIE_CMD = "die"; public static final String DIE_CMD = "die";
/** /**
* Help command line argument. * Help command line argument.
*/ */
public static final String HELP_ARG = "help"; public static final String HELP_ARG = "help";
/** /**
* The help command. * The help command.
*/ */
public static final String HELP_CMD = "help"; public static final String HELP_CMD = "help";
/** /**
* The help on posting keyword. * The help on posting keyword.
*/ */
public static final String HELP_POSTING_KEYWORD = "posting"; public static final String HELP_POSTING_KEYWORD = "posting";
/** /**
* The help on tags keyword. * The help on tags keyword.
*/ */
public static final String HELP_TAGS_KEYWORD = "tags"; public static final String HELP_TAGS_KEYWORD = "tags";
/** /**
* The ignore command. * The ignore command.
*/ */
public static final String IGNORE_CMD = "ignore"; public static final String IGNORE_CMD = "ignore";
/** /**
* The ignore <code>me</code> keyword. * The ignore <code>me</code> keyword.
*/ */
public static final String IGNORE_ME_KEYWORD = "me"; public static final String IGNORE_ME_KEYWORD = "me";
/** /**
* The info command. * The info command.
*/ */
public static final String INFO_CMD = "info"; public static final String INFO_CMD = "info";
/** /**
* The link command. * The link command.
*/ */
public static final String LINK_CMD = "L"; public static final String LINK_CMD = "L";
/** /**
* The me command. * The me command.
*/ */
public static final String ME_CMD = "me"; public static final String ME_CMD = "me";
/** /**
* The msg command. * The msg command.
*/ */
public static final String MSG_CMD = "msg"; public static final String MSG_CMD = "msg";
/** /**
* The nick command. * The nick command.
*/ */
public static final String NICK_CMD = "nick"; public static final String NICK_CMD = "nick";
/** /**
* Properties command line argument. * Properties command line argument.
*/ */
public static final String PROPS_ARG = "properties"; public static final String PROPS_ARG = "properties";
/** /**
* The recap command. * The recap command.
*/ */
public static final String RECAP_CMD = "recap"; public static final String RECAP_CMD = "recap";
/** /**
* The say command. * The say command.
*/ */
public static final String SAY_CMD = "say"; public static final String SAY_CMD = "say";
/** /**
* The users command. * The users command.
*/ */
public static final String USERS_CMD = "users"; public static final String USERS_CMD = "users";
/** /**
* Properties version line argument. * Properties version line argument.
*/ */
public static final String VERSION_ARG = "version"; public static final String VERSION_ARG = "version";
/** /**
* The version command. * The version command.
*/ */
public static final String VERSION_CMD = "version"; public static final String VERSION_CMD = "version";
/** /**
* The view command. * The view command.
*/ */
public static final String VIEW_CMD = "view"; public static final String VIEW_CMD = "view";
/** /**
* Disables the default constructor. * Disables the default constructor.
* *
* @throws UnsupportedOperationException If the constructor is called. * @throws UnsupportedOperationException If the constructor is called.
*/ */
private Commands() private Commands()
throws UnsupportedOperationException throws UnsupportedOperationException {
{ throw new UnsupportedOperationException("Illegal constructor call.");
throw new UnsupportedOperationException("Illegal constructor call."); }
}
} }

View file

@ -42,120 +42,103 @@ import javax.swing.*;
* @created Mar 5, 2005 * @created Mar 5, 2005
* @since 1.0 * @since 1.0
*/ */
class DeliciousPoster class DeliciousPoster {
{ private final Delicious delicious;
private final Delicious delicious; private final String ircServer;
private final String ircServer; /**
* Creates a new {@link DeliciousPoster} instance.
*
* @param username The del.icio.us user name.
* @param password The del.icio.us password.
* @param ircServer The IRC server.
*/
public DeliciousPoster(final String username, final String password, final String ircServer) {
delicious = new Delicious(username, password);
this.ircServer = ircServer;
}
/** /**
* Creates a new {@link DeliciousPoster} instance. * Adds a post to del.icio.us.
* *
* @param username The del.icio.us user name. * @param entry The entry to add.
* @param password The del.icio.us password. */
* @param ircServer The IRC server. public final void addPost(final EntryLink entry) {
*/ final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
public DeliciousPoster(final String username, final String password, final String ircServer) @Override
{ protected Boolean doInBackground()
delicious = new Delicious(username, password); throws Exception {
this.ircServer = ircServer; return delicious.addPost(entry.getLink(),
} entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
entry.getDate());
}
};
/** worker.execute();
* Adds a post to del.icio.us. }
*
* @param entry The entry to add.
*/
public final void addPost(final EntryLink entry)
{
final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>()
{
@Override
protected Boolean doInBackground()
throws Exception
{
return delicious.addPost(entry.getLink(),
entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
entry.getDate());
}
};
worker.execute(); /**
} * Deletes a post to del.icio.us.
*
* @param entry The entry to delete.
*/
public final void deletePost(final EntryLink entry) {
final String link = entry.getLink();
/** final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
* Returns he del.icio.us extended attribution line. @Override
* protected Boolean doInBackground()
* @param entry The entry. throws Exception {
* return delicious.deletePost(link);
* @return The extended attribution line. }
*/ };
private String postedBy(final EntryLink entry)
{
return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + ircServer + ')';
}
/** worker.execute();
* Deletes a post to del.icio.us. }
*
* @param entry The entry to delete.
*/
public final void deletePost(final EntryLink entry)
{
final String link = entry.getLink();
final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() /**
{ * Returns he del.icio.us extended attribution line.
@Override *
protected Boolean doInBackground() * @param entry The entry.
throws Exception * @return The extended attribution line.
{ */
return delicious.deletePost(link); private String postedBy(final EntryLink entry) {
} return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + ircServer + ')';
}; }
worker.execute(); /**
} * Updates a post to del.icio.us.
*
* @param oldUrl The old post URL.
* @param entry The entry to add.
*/
public final void updatePost(final String oldUrl, final EntryLink entry) {
final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground()
throws Exception {
if (!oldUrl.equals(entry.getLink())) {
delicious.deletePost(oldUrl);
/** return delicious.addPost(entry.getLink(),
* Updates a post to del.icio.us. entry.getTitle(),
* postedBy(entry),
* @param oldUrl The old post URL. entry.getDeliciousTags(),
* @param entry The entry to add. entry.getDate());
*/ } else {
public final void updatePost(final String oldUrl, final EntryLink entry) return delicious.addPost(entry.getLink(),
{ entry.getTitle(),
final SwingWorker<Boolean, Void> worker = new SwingWorker<Boolean, Void>() postedBy(entry),
{ entry.getDeliciousTags(),
@Override entry.getDate(),
protected Boolean doInBackground() true,
throws Exception true);
{ }
if (!oldUrl.equals(entry.getLink())) }
{ };
delicious.deletePost(oldUrl);
return delicious.addPost(entry.getLink(), worker.execute();
entry.getTitle(), }
postedBy(entry),
entry.getDeliciousTags(),
entry.getDate());
}
else
{
return delicious.addPost(entry.getLink(),
entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
entry.getDate(),
true,
true);
}
}
};
worker.execute();
}
} }

View file

@ -48,310 +48,270 @@ import java.util.List;
* @created 2014-04-28 * @created 2014-04-28
* @since 1.0 * @since 1.0
*/ */
final class EntriesMgr final class EntriesMgr {
{ /**
/** * The name of the file containing the current entries.
* The name of the file containing the current entries. */
*/ public static final String CURRENT_XML = "current.xml";
public static final String CURRENT_XML = "current.xml";
/** /**
* The name of the file containing the backlog entries. * The name of the file containing the backlog entries.
*/ */
public static final String NAV_XML = "nav.xml"; public static final String NAV_XML = "nav.xml";
/** /**
* The .xml extension * The .xml extension
*/ */
public static final String XML_EXT = ".xml"; public static final String XML_EXT = ".xml";
/** /**
* The maximum number of backlogs to keep. * The maximum number of backlogs to keep.
*/ */
private static final int MAX_BACKLOGS = 10; private static final int MAX_BACKLOGS = 10;
/** /**
* Disables the default constructor. * Disables the default constructor.
* *
* @throws UnsupportedOperationException If the constructor is called. * @throws UnsupportedOperationException If the constructor is called.
*/ */
private EntriesMgr() private EntriesMgr()
throws UnsupportedOperationException throws UnsupportedOperationException {
{ throw new UnsupportedOperationException("Illegal constructor call.");
throw new UnsupportedOperationException("Illegal constructor call."); }
}
/** /**
* Loads the backlogs. * Loads the backlogs.
* *
* @param file The file containing the backlogs. * @param file The file containing the backlogs.
* @param history The history list. * @param history The history list.
* * @throws IOException If the file was not found or could not be read.
* @throws IOException If the file was not found or could not be read. * @throws FeedException If an error occurred while reading the feed.
* @throws FeedException If an error occurred while reading the feed. */
*/ public static void loadBacklogs(final String file, final List<String> history)
public static void loadBacklogs(final String file, final List<String> history) throws IOException, FeedException {
throws IOException, FeedException history.clear();
{
history.clear();
final SyndFeedInput input = new SyndFeedInput(); final SyndFeedInput input = new SyndFeedInput();
try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(file)))) try (final InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(file)))) {
{
final SyndFeed feed = input.build(reader); final SyndFeed feed = input.build(reader);
final List items = feed.getEntries(); final List items = feed.getEntries();
SyndEntry item; SyndEntry item;
for (int i = items.size() - 1; i >= 0; i--) for (int i = items.size() - 1; i >= 0; i--) {
{ item = (SyndEntryImpl) items.get(i);
item = (SyndEntryImpl) items.get(i); history.add(item.getTitle());
history.add(item.getTitle()); }
} }
} }
}
/** /**
* Loads the current entries. * Loads the current entries.
* *
* @param file The file containing the current entries. * @param file The file containing the current entries.
* @param channel The channel * @param channel The channel
* @param entries The entries. * @param entries The entries.
* * @return The feed's last published date.
* @return The feed's last published date. * @throws IOException If the file was not found or could not be read.
* * @throws FeedException If an error occurred while reading the feed.
* @throws IOException If the file was not found or could not be read. */
* @throws FeedException If an error occurred while reading the feed. @SuppressWarnings("unchecked")
*/ public static String loadEntries(final String file, final String channel, final List<EntryLink> entries)
@SuppressWarnings("unchecked") throws IOException, FeedException {
public static String loadEntries(final String file, final String channel, final List<EntryLink> entries) entries.clear();
throws IOException, FeedException
{
entries.clear();
final SyndFeedInput input = new SyndFeedInput(); final SyndFeedInput input = new SyndFeedInput();
final String today; final String today;
try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(file)))) try (InputStreamReader reader = new InputStreamReader(new FileInputStream(new File(file)))) {
{ final SyndFeed feed = input.build(reader);
final SyndFeed feed = input.build(reader);
today = Utils.ISO_SDF.format(feed.getPublishedDate()); today = Utils.ISO_SDF.format(feed.getPublishedDate());
final List items = feed.getEntries(); final List items = feed.getEntries();
SyndEntry item; SyndEntry item;
SyndContent description; SyndContent description;
String[] comments; String[] comments;
String author; String author;
EntryLink entry; EntryLink entry;
for (int i = items.size() - 1; i >= 0; i--) for (int i = items.size() - 1; i >= 0; i--) {
{ item = (SyndEntryImpl) items.get(i);
item = (SyndEntryImpl) items.get(i); author = item.getAuthor()
author = item.getAuthor() .substring(item.getAuthor().lastIndexOf('(') + 1, item.getAuthor().length() - 1);
.substring(item.getAuthor().lastIndexOf('(') + 1, item.getAuthor().length() - 1); entry = new EntryLink(item.getLink(),
entry = new EntryLink(item.getLink(), item.getTitle(),
item.getTitle(), author,
author, channel,
channel, item.getPublishedDate(),
item.getPublishedDate(), item.getCategories());
item.getCategories()); description = item.getDescription();
description = item.getDescription(); comments = description.getValue().split("<br/>");
comments = description.getValue().split("<br/>");
int split; int split;
for (final String comment : comments) for (final String comment : comments) {
{ split = comment.indexOf(": ");
split = comment.indexOf(": ");
if (split != -1) if (split != -1) {
{ entry.addComment(comment.substring(split + 2).trim(), comment.substring(0, split).trim());
entry.addComment(comment.substring(split + 2).trim(), comment.substring(0, split).trim()); }
} }
}
entries.add(entry); entries.add(entry);
} }
} }
return today; return today;
} }
/** /**
* Saves the entries. * Saves the entries.
* *
* @param bot The bot object. * @param bot The bot object.
* @param entries The entries array. * @param entries The entries array.
* @param history The history array. * @param history The history array.
* @param isDayBackup Set the true if the daily backup file should also be created. * @param isDayBackup Set the true if the daily backup file should also be created.
*/ */
public static void saveEntries(final Mobibot bot, final List<EntryLink> entries, final List<String> history, public static void saveEntries(final Mobibot bot, final List<EntryLink> entries, final List<String> history,
final boolean isDayBackup) final boolean isDayBackup) {
{ if (bot.getLogger().isDebugEnabled()) {
if (bot.getLogger().isDebugEnabled()) bot.getLogger().debug("Saving the feeds...");
{ }
bot.getLogger().debug("Saving the feeds...");
}
if (Utils.isValidString(bot.getLogsDir()) && Utils.isValidString(bot.getWeblogUrl())) if (Utils.isValidString(bot.getLogsDir()) && Utils.isValidString(bot.getWeblogUrl())) {
{ FileWriter fw = null;
FileWriter fw = null;
try try {
{ fw = new FileWriter(new File(bot.getLogsDir() + CURRENT_XML));
fw = new FileWriter(new File(bot.getLogsDir() + CURRENT_XML));
SyndFeed rss = new SyndFeedImpl(); SyndFeed rss = new SyndFeedImpl();
rss.setFeedType("rss_2.0"); rss.setFeedType("rss_2.0");
rss.setTitle(bot.getChannel() + " IRC Links"); rss.setTitle(bot.getChannel() + " IRC Links");
rss.setDescription("Links from " + bot.getIrcServer() + " on " + bot.getChannel()); rss.setDescription("Links from " + bot.getIrcServer() + " on " + bot.getChannel());
rss.setLink(bot.getWeblogUrl()); rss.setLink(bot.getWeblogUrl());
rss.setPublishedDate(Calendar.getInstance().getTime()); rss.setPublishedDate(Calendar.getInstance().getTime());
rss.setLanguage("en"); rss.setLanguage("en");
EntryLink entry; EntryLink entry;
StringBuffer buff; StringBuffer buff;
EntryComment comment; EntryComment comment;
final List<SyndEntry> items = new ArrayList<>(0); final List<SyndEntry> items = new ArrayList<>(0);
SyndEntry item; SyndEntry item;
SyndContent description; SyndContent description;
for (int i = (entries.size() - 1); i >= 0; --i) for (int i = (entries.size() - 1); i >= 0; --i) {
{ entry = entries.get(i);
entry = entries.get(i);
buff = new StringBuffer( buff = new StringBuffer(
"Posted by <b>" + entry.getNick() + "</b> on <a href=\"irc://" + bot.getIrcServer() + '/' "Posted by <b>" + entry.getNick() + "</b> on <a href=\"irc://" + bot.getIrcServer() + '/'
+ entry.getChannel() + "\"><b>" + entry.getChannel() + "</b></a>"); + entry.getChannel() + "\"><b>" + entry.getChannel() + "</b></a>");
if (entry.getCommentsCount() > 0) if (entry.getCommentsCount() > 0) {
{ buff.append(" <br/><br/>");
buff.append(" <br/><br/>");
final EntryComment[] comments = entry.getComments(); final EntryComment[] comments = entry.getComments();
for (int j = 0; j < comments.length; j++) for (int j = 0; j < comments.length; j++) {
{ comment = comments[j];
comment = comments[j];
if (j > 0) if (j > 0) {
{ buff.append(" <br/>");
buff.append(" <br/>"); }
}
buff.append(comment.getNick()).append(": ").append(comment.getComment()); buff.append(comment.getNick()).append(": ").append(comment.getComment());
} }
} }
item = new SyndEntryImpl(); item = new SyndEntryImpl();
item.setLink(entry.getLink()); item.setLink(entry.getLink());
description = new SyndContentImpl(); description = new SyndContentImpl();
description.setValue(buff.toString()); description.setValue(buff.toString());
item.setDescription(description); item.setDescription(description);
item.setTitle(entry.getTitle()); item.setTitle(entry.getTitle());
item.setPublishedDate(entry.getDate()); item.setPublishedDate(entry.getDate());
item.setAuthor( item.setAuthor(
bot.getChannel().substring(1) + '@' + bot.getIrcServer() + " (" + entry.getNick() + ')'); bot.getChannel().substring(1) + '@' + bot.getIrcServer() + " (" + entry.getNick() + ')');
item.setCategories(entry.getTags()); item.setCategories(entry.getTags());
items.add(item); items.add(item);
} }
rss.setEntries(items); rss.setEntries(items);
if (bot.getLogger().isDebugEnabled()) if (bot.getLogger().isDebugEnabled()) {
{ bot.getLogger().debug("Writing the entries feed.");
bot.getLogger().debug("Writing the entries feed."); }
}
final SyndFeedOutput output = new SyndFeedOutput(); final SyndFeedOutput output = new SyndFeedOutput();
output.output(rss, fw); output.output(rss, fw);
fw.close(); fw.close();
fw = new FileWriter(new File(bot.getLogsDir() + bot.getToday() + XML_EXT)); fw = new FileWriter(new File(bot.getLogsDir() + bot.getToday() + XML_EXT));
output.output(rss, fw); output.output(rss, fw);
if (isDayBackup) if (isDayBackup) {
{ if (Utils.isValidString(bot.getBacklogsUrl())) {
if (Utils.isValidString(bot.getBacklogsUrl())) if (history.indexOf(bot.getToday()) == -1) {
{ history.add(bot.getToday());
if (history.indexOf(bot.getToday()) == -1)
{
history.add(bot.getToday());
while (history.size() > MAX_BACKLOGS) while (history.size() > MAX_BACKLOGS) {
{ history.remove(0);
history.remove(0); }
} }
}
fw.close(); fw.close();
fw = new FileWriter(new File(bot.getLogsDir() + NAV_XML)); fw = new FileWriter(new File(bot.getLogsDir() + NAV_XML));
rss = new SyndFeedImpl(); rss = new SyndFeedImpl();
rss.setFeedType("rss_2.0"); rss.setFeedType("rss_2.0");
rss.setTitle(bot.getChannel() + " IRC Links Backlogs"); rss.setTitle(bot.getChannel() + " IRC Links Backlogs");
rss.setDescription("Backlogs of Links from " + bot.getIrcServer() + " on " + bot.getChannel()); rss.setDescription("Backlogs of Links from " + bot.getIrcServer() + " on " + bot.getChannel());
rss.setLink(bot.getBacklogsUrl()); rss.setLink(bot.getBacklogsUrl());
rss.setPublishedDate(Calendar.getInstance().getTime()); rss.setPublishedDate(Calendar.getInstance().getTime());
String date; String date;
items.clear(); items.clear();
for (int i = (history.size() - 1); i >= 0; --i) for (int i = (history.size() - 1); i >= 0; --i) {
{ date = history.get(i);
date = history.get(i);
item = new SyndEntryImpl(); item = new SyndEntryImpl();
item.setLink(bot.getBacklogsUrl() + date + ".xml"); item.setLink(bot.getBacklogsUrl() + date + ".xml");
item.setTitle(date); item.setTitle(date);
description = new SyndContentImpl(); description = new SyndContentImpl();
description.setValue("Links for " + date); description.setValue("Links for " + date);
item.setDescription(description); item.setDescription(description);
items.add(item); items.add(item);
} }
rss.setEntries(items); rss.setEntries(items);
if (bot.getLogger().isDebugEnabled()) if (bot.getLogger().isDebugEnabled()) {
{ bot.getLogger().debug("Writing the backlog feed.");
bot.getLogger().debug("Writing the backlog feed."); }
}
output.output(rss, fw); output.output(rss, fw);
} } else {
else bot.getLogger().warn("Unable to generate the backlogs feed. No property configured.");
{ }
bot.getLogger().warn("Unable to generate the backlogs feed. No property configured."); }
} } catch (Exception e) {
} bot.getLogger().warn("Unable to generate the entries feed.", e);
} } finally {
catch (Exception e) try {
{ if (fw != null) {
bot.getLogger().warn("Unable to generate the entries feed.", e); fw.close();
} }
finally } catch (Exception ignore) {
{ ; // Do nothing
try }
{ }
if (fw != null) } else {
{ bot.getLogger()
fw.close(); .warn("Unable to generate the entries feed. At least one of the required property is missing.");
} }
} }
catch (Exception ignore)
{
; // Do nothing
}
}
}
else
{
bot.getLogger()
.warn("Unable to generate the entries feed. At least one of the required property is missing.");
}
}
} }

View file

@ -42,92 +42,83 @@ import java.util.Date;
* @created Jan 31, 2004 * @created Jan 31, 2004
* @since 1.0 * @since 1.0
*/ */
public class EntryComment implements Serializable public class EntryComment implements Serializable {
{ /**
/** * The serial version UID.
* The serial version UID. */
*/ static final long serialVersionUID = 6957415292233553224L;
static final long serialVersionUID = 6957415292233553224L;
/** /**
* The creation date. * The creation date.
*/ */
private final Date date = Calendar.getInstance().getTime(); private final Date date = Calendar.getInstance().getTime();
private String comment = ""; private String comment = "";
private String nick = "";
private String nick = ""; /**
* Creates a new comment.
*
* @param comment The new comment.
* @param nick The nickname of the comment's author.
*/
public EntryComment(final String comment, final String nick) {
this.comment = comment;
this.nick = nick;
}
/** /**
* Creates a new comment. * Creates a new comment.
* */
* @param comment The new comment. @SuppressWarnings("UnusedDeclaration")
* @param nick The nickname of the comment's author. protected EntryComment() {
*/ ; // Required for serialization.
public EntryComment(final String comment, final String nick) }
{
this.comment = comment;
this.nick = nick;
}
/** /**
* Creates a new comment. * Returns the comment.
*/ *
@SuppressWarnings("UnusedDeclaration") * @return The comment.
protected EntryComment() */
{ public final String getComment() {
; // Required for serialization. return comment;
} }
/** /**
* Returns the comment. * Sets the comment.
* *
* @return The comment. * @param comment The actual comment.
*/ */
public final String getComment() @SuppressWarnings("UnusedDeclaration")
{ public final void setComment(final String comment) {
return comment; this.comment = comment;
} }
/** /**
* Sets the comment. * Returns the comment's creation date.
* *
* @param comment The actual comment. * @return The date.
*/ */
@SuppressWarnings("UnusedDeclaration") @SuppressWarnings("UnusedDeclaration")
public final void setComment(final String comment) public final Date getDate() {
{ return date;
this.comment = comment; }
}
/** /**
* Returns the comment's creation date. * Returns the nickname of the author of the comment.
* *
* @return The date. * @return The nickname.
*/ */
@SuppressWarnings("UnusedDeclaration") public final String getNick() {
public final Date getDate() return nick;
{ }
return date;
}
/** /**
* Returns the nickname of the author of the comment. * Sets the nickname of the author of the comment.
* *
* @return The nickname. * @param nick The new nickname.
*/ */
public final String getNick() public final void setNick(final String nick) {
{ this.nick = nick;
return nick; }
}
/**
* Sets the nickname of the author of the comment.
*
* @param nick The new nickname.
*/
public final void setNick(final String nick)
{
this.nick = nick;
}
} }

View file

@ -47,391 +47,348 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @created Jan 31, 2004 * @created Jan 31, 2004
* @since 1.0 * @since 1.0
*/ */
public class EntryLink implements Serializable public class EntryLink implements Serializable {
{ /**
/** * The serial version UID.
* The serial version UID. */
*/ static final long serialVersionUID = 3676245542270899086L;
static final long serialVersionUID = 3676245542270899086L;
// The link's comments // The link's comments
private final List<EntryComment> comments = new CopyOnWriteArrayList<>(); private final List<EntryComment> comments = new CopyOnWriteArrayList<>();
// The tags/categories // The tags/categories
private final List<SyndCategory> tags = new CopyOnWriteArrayList<>(); private final List<SyndCategory> tags = new CopyOnWriteArrayList<>();
// The channel // The channel
private String channel = ""; private String channel = "";
// The creation date // The creation date
private Date date = Calendar.getInstance().getTime(); private Date date = Calendar.getInstance().getTime();
// The link's URL // The link's URL
private String link = ""; private String link = "";
// The author's login // The author's login
private String login = ""; private String login = "";
// The author's nickname // The author's nickname
private String nick = ""; private String nick = "";
// The link's title // The link's title
private String title = ""; private String title = "";
/** /**
* Creates a new entry. * Creates a new entry.
* *
* @param link The new entry's link. * @param link The new entry's link.
* @param title The new entry's title. * @param title The new entry's title.
* @param nick The nickname of the author of the link. * @param nick The nickname of the author of the link.
* @param login The login of the author of the link. * @param login The login of the author of the link.
* @param channel The channel. * @param channel The channel.
* @param tags The entry's tags/categories. * @param tags The entry's tags/categories.
*/ */
public EntryLink(final String link, final String title, final String nick, final String login, final String channel, public EntryLink(final String link, final String title, final String nick, final String login, final String channel,
final String tags) final String tags) {
{ this.link = link;
this.link = link; this.title = title;
this.title = title; this.nick = nick;
this.nick = nick; this.login = login;
this.login = login; this.channel = channel;
this.channel = channel;
setTags(tags); setTags(tags);
} }
/** /**
* Sets the tags. * Creates a new entry.
* *
* @param tags The space-delimited tags. * @param link The new entry's link.
*/ * @param title The new entry's title.
public final void setTags(final String tags) * @param nick The nickname of the author of the link.
{ * @param channel The channel.
if (tags != null) * @param date The entry date.
{ * @param tags The entry's tags/categories.
final String[] parts = tags.replaceAll(", ", " ").replaceAll(",", " ").split(" "); */
public EntryLink(final String link, final String title, final String nick, final String channel, final Date date,
final List<SyndCategory> tags) {
this.link = link;
this.title = title;
this.nick = nick;
this.channel = channel;
this.date = date;
SyndCategoryImpl tag; setTags(tags);
String part; }
char mod;
for (final String rawPart : parts) /**
{ * Adds a new comment.
part = rawPart.trim(); *
* @param comment The actual comment.
* @param nick The nickname of the author of the comment.
* @return The total number of comments for this entry.
*/
public final int addComment(final String comment, final String nick) {
comments.add(new EntryComment(comment, nick));
if (part.length() >= 2) return (comments.size() - 1);
{ }
tag = new SyndCategoryImpl();
tag.setName(part.substring(1).toLowerCase());
mod = part.charAt(0); /**
* Deletes a specific comment.
*
* @param index The index of the comment to delete.
*/
public final void deleteComment(final int index) {
if (index < comments.size()) {
comments.remove(index);
}
}
if (mod == '-') /**
{ * Returns the channel the link was posted on.
// Don't remove the channel tag, if any. *
if (!tag.getName().equals(channel.substring(1))) * @return The channel
{ */
this.tags.remove(tag); public final String getChannel() {
} return channel;
} }
else if (mod == '+')
{
if (!this.tags.contains(tag))
{
this.tags.add(tag);
}
}
else
{
tag.setName(part.trim().toLowerCase());
if (!this.tags.contains(tag)) /**
{ * Sets the channel.
this.tags.add(tag); *
} * @param channel The channel.
} */
} @SuppressWarnings("UnusedDeclaration")
} public final void setChannel(final String channel) {
} this.channel = channel;
} }
/** /**
* Creates a new entry. * Returns a comment.
* *
* @param link The new entry's link. * @param index The comment's index.
* @param title The new entry's title. * @return The specific comment.
* @param nick The nickname of the author of the link. */
* @param channel The channel. public final EntryComment getComment(final int index) {
* @param date The entry date. return (comments.get(index));
* @param tags The entry's tags/categories. }
*/
public EntryLink(final String link, final String title, final String nick, final String channel, final Date date,
final List<SyndCategory> tags)
{
this.link = link;
this.title = title;
this.nick = nick;
this.channel = channel;
this.date = date;
setTags(tags); /**
} * Returns all the comments.
*
* @return The comments.
*/
public final EntryComment[] getComments() {
return (comments.toArray(new EntryComment[comments.size()]));
}
/** /**
* Adds a new comment. * Returns the total number of comments.
* *
* @param comment The actual comment. * @return The count of comments.
* @param nick The nickname of the author of the comment. */
* public final int getCommentsCount() {
* @return The total number of comments for this entry. return comments.size();
*/ }
public final int addComment(final String comment, final String nick)
{
comments.add(new EntryComment(comment, nick));
return (comments.size() - 1); /**
} * Returns the comment's creation date.
*
* @return The date.
*/
public final Date getDate() {
return date;
}
/** /**
* Deletes a specific comment. * Returns the tags formatted for del.icio.us.
* *
* @param index The index of the comment to delete. * @return The tags as a comma-delimited string.
*/ */
public final void deleteComment(final int index) public final String getDeliciousTags() {
{ final StringBuilder tags = new StringBuilder(nick);
if (index < comments.size())
{
comments.remove(index);
}
}
/** for (final Object tag : this.tags) {
* Returns the channel the link was posted on. tags.append(',');
* tags.append(((SyndCategoryImpl) tag).getName());
* @return The channel }
*/
public final String getChannel()
{
return channel;
}
/** return tags.toString();
* Sets the channel. }
*
* @param channel The channel.
*/
@SuppressWarnings("UnusedDeclaration")
public final void setChannel(final String channel)
{
this.channel = channel;
}
/** /**
* Returns a comment. * Returns the comment's link.
* *
* @param index The comment's index. * @return The link.
* */
* @return The specific comment. public final String getLink() {
*/ return link;
public final EntryComment getComment(final int index) }
{
return (comments.get(index));
}
/** /**
* Returns all the comments. * Sets the comment's link.
* *
* @return The comments. * @param link The new link.
*/ */
public final EntryComment[] getComments() public final void setLink(final String link) {
{ this.link = link;
return (comments.toArray(new EntryComment[comments.size()])); }
}
/** /**
* Returns the total number of comments. * Returns the comment's author login.
* *
* @return The count of comments. * @return The login;
*/ */
public final int getCommentsCount() public final String getLogin() {
{ return login;
return comments.size(); }
}
/** /**
* Returns the comment's creation date. * Sets the comment's author login.
* *
* @return The date. * @param login The new login.
*/ */
public final Date getDate() @SuppressWarnings("UnusedDeclaration")
{ public final void setLogin(final String login) {
return date; this.login = login;
} }
/** /**
* Returns the tags formatted for del.icio.us. * Returns the comment's author nickname.
* *
* @return The tags as a comma-delimited string. * @return The nickname.
*/ */
public final String getDeliciousTags() public final String getNick() {
{ return nick;
final StringBuilder tags = new StringBuilder(nick); }
for (final Object tag : this.tags) /**
{ * Sets the comment's author nickname.
tags.append(','); *
tags.append(((SyndCategoryImpl) tag).getName()); * @param nick The new nickname.
} */
public final void setNick(final String nick) {
this.nick = nick;
}
return tags.toString(); /**
} * Returns the tags.
*
* @return The tags.
*/
public final List<SyndCategory> getTags() {
return tags;
}
/** /**
* Returns the comment's link. * Sets the tags.
* *
* @return The link. * @param tags The tags.
*/ */
public final String getLink() private void setTags(final List<SyndCategory> tags) {
{ this.tags.addAll(tags);
return link; }
}
/** /**
* Sets the comment's link. * Returns the comment's title.
* *
* @param link The new link. * @return The title.
*/ */
public final void setLink(final String link) public final String getTitle() {
{ return title;
this.link = link; }
}
/** /**
* Returns the comment's author login. * Sets the comment's title.
* *
* @return The login; * @param title The new title.
*/ */
public final String getLogin() public final void setTitle(final String title) {
{ this.title = title;
return login; }
}
/** /**
* Sets the comment's author login. * Returns true if the entry has comments.
* *
* @param login The new login. * @return true if there are comments, false otherwise.
*/ */
@SuppressWarnings("UnusedDeclaration") public final boolean hasComments() {
public final void setLogin(final String login) return (!comments.isEmpty());
{ }
this.login = login;
}
/** /**
* Returns the comment's author nickname. * Returns true if the entry has tags.
* *
* @return The nickname. * @return true if there are tags, false otherwise.
*/ */
public final String getNick() public final boolean hasTags() {
{ return (!tags.isEmpty());
return nick; }
}
/** /**
* Sets the comment's author nickname. * /** Sets a comment.
* *
* @param nick The new nickname. * @param index The comment's index.
*/ * @param comment The actual comment.
public final void setNick(final String nick) * @param nick The nickname of the author of the comment.
{ */
this.nick = nick; public final void setComment(final int index, final String comment, final String nick) {
} if (index < comments.size()) {
comments.set(index, new EntryComment(comment, nick));
}
}
/** /**
* Returns the tags. * Sets the tags.
* *
* @return The tags. * @param tags The space-delimited tags.
*/ */
public final List<SyndCategory> getTags() public final void setTags(final String tags) {
{ if (tags != null) {
return tags; final String[] parts = tags.replaceAll(", ", " ").replaceAll(",", " ").split(" ");
}
/** SyndCategoryImpl tag;
* Sets the tags. String part;
* char mod;
* @param tags The tags.
*/
private void setTags(final List<SyndCategory> tags)
{
this.tags.addAll(tags);
}
/** for (final String rawPart : parts) {
* Returns the comment's title. part = rawPart.trim();
*
* @return The title.
*/
public final String getTitle()
{
return title;
}
/** if (part.length() >= 2) {
* Sets the comment's title. tag = new SyndCategoryImpl();
* tag.setName(part.substring(1).toLowerCase());
* @param title The new title.
*/
public final void setTitle(final String title)
{
this.title = title;
}
/** mod = part.charAt(0);
* Returns true if the entry has comments.
*
* @return true if there are comments, false otherwise.
*/
public final boolean hasComments()
{
return (!comments.isEmpty());
}
/** if (mod == '-') {
* Returns true if the entry has tags. // Don't remove the channel tag, if any.
* if (!tag.getName().equals(channel.substring(1))) {
* @return true if there are tags, false otherwise. this.tags.remove(tag);
*/ }
public final boolean hasTags() } else if (mod == '+') {
{ if (!this.tags.contains(tag)) {
return (!tags.isEmpty()); this.tags.add(tag);
} }
} else {
tag.setName(part.trim().toLowerCase());
/** if (!this.tags.contains(tag)) {
* /** Sets a comment. this.tags.add(tag);
* }
* @param index The comment's index. }
* @param comment The actual comment. }
* @param nick The nickname of the author of the comment. }
*/ }
public final void setComment(final int index, final String comment, final String nick) }
{
if (index < comments.size())
{
comments.set(index, new EntryComment(comment, nick));
}
}
/** /**
* Returns a string representation of the object. * Returns a string representation of the object.
* *
* @return A string representation of the object. * @return A string representation of the object.
*/ */
public final String toString() public final String toString() {
{
return super.toString() + "[ channel -> '" + channel + '\'' + ", comments -> " + comments + ", date -> " + date return super.toString() + "[ channel -> '" + channel + '\'' + ", comments -> " + comments + ", date -> " + date
+ ", link -> '" + link + '\'' + ", login -> '" + login + '\'' + ", nick -> '" + nick + '\'' + ", link -> '" + link + '\'' + ", login -> '" + login + '\'' + ", nick -> '" + nick + '\''
+ ", tags -> " + tags + ", title -> '" + title + '\'' + " ]"; + ", tags -> " + tags + ", title -> '" + title + '\'' + " ]";
} }
} }

View file

@ -48,76 +48,67 @@ import java.util.List;
* @created Feb 1, 2004 * @created Feb 1, 2004
* @since 1.0 * @since 1.0
*/ */
class FeedReader implements Runnable class FeedReader implements Runnable {
{ /**
/** * The maximum number of feed items to display.
* The maximum number of feed items to display. */
*/ private static final int MAX_ITEMS = 5;
private static final int MAX_ITEMS = 5;
/** /**
* The tab indent (4 spaces). * The tab indent (4 spaces).
*/ */
private static final String TAB_INDENT = " "; private static final String TAB_INDENT = " ";
/** /**
* The bot. * The bot.
*/ */
private final Mobibot bot; private final Mobibot bot;
/** /**
* The nick of the person who sent the message. * The nick of the person who sent the message.
*/ */
private final String sender; private final String sender;
/** /**
* The URL to fetch. * The URL to fetch.
*/ */
private final String url; private final String url;
/** /**
* Creates a new {@link FeedReader} instance. * Creates a new {@link FeedReader} instance.
* *
* @param bot The bot's instance. * @param bot The bot's instance.
* @param sender The nick of the person who sent the message. * @param sender The nick of the person who sent the message.
* @param url The URL to fetch. * @param url The URL to fetch.
*/ */
public FeedReader(final Mobibot bot, final String sender, final String url) public FeedReader(final Mobibot bot, final String sender, final String url) {
{ this.bot = bot;
this.bot = bot; this.sender = sender;
this.sender = sender; this.url = url;
this.url = url; }
}
/** /**
* Fetches the Feed's items. * Fetches the Feed's items.
*/ */
public final void run() public final void run() {
{ try {
try final SyndFeedInput input = new SyndFeedInput();
{ final SyndFeed feed = input.build(new XmlReader(new URL(url)));
final SyndFeedInput input = new SyndFeedInput();
final SyndFeed feed = input.build(new XmlReader(new URL(url)));
SyndEntry item; SyndEntry item;
final List items = feed.getEntries(); final List items = feed.getEntries();
for (int i = 0; (i < items.size()) && (i < MAX_ITEMS); i++) for (int i = 0; (i < items.size()) && (i < MAX_ITEMS); i++) {
{ item = (SyndEntryImpl) items.get(i);
item = (SyndEntryImpl) items.get(i); bot.send(sender, item.getTitle());
bot.send(sender, item.getTitle()); bot.send(sender, TAB_INDENT + Utils.green(item.getLink()));
bot.send(sender, TAB_INDENT + Utils.green(item.getLink())); }
} } catch (MalformedURLException e) {
} bot.getLogger().debug("Invalid feed URL.", e);
catch (MalformedURLException e) bot.send(sender, "The feed URL is invalid.");
{ } catch (Exception e) {
bot.getLogger().debug("Invalid feed URL.", e); bot.getLogger().debug("Unable to fetch the feed.", e);
bot.send(sender, "The feed URL is invalid."); bot.send(sender, "An error has occurred while fetching the feed: " + e.getMessage());
} }
catch (Exception e) }
{
bot.getLogger().debug("Unable to fetch the feed.", e);
bot.send(sender, "An error has occurred while fetching the feed: " + e.getMessage());
}
}
} }

File diff suppressed because it is too large Load diff

View file

@ -41,389 +41,317 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @created 2016-07-02 * @created 2016-07-02
* @since 1.0 * @since 1.0
*/ */
public class Tell public class Tell {
{ /**
/** * The all keyword.
* The all keyword. */
*/ public static final String TELL_ALL_KEYWORD = "all";
public static final String TELL_ALL_KEYWORD = "all";
/** /**
* The tell command. * The tell command.
*/ */
public static final String TELL_CMD = "tell"; public static final String TELL_CMD = "tell";
/** /**
* The delete command. * The delete command.
*/ */
public static final String TELL_DEL_KEYWORD = "del"; public static final String TELL_DEL_KEYWORD = "del";
/** /**
* The default maximum number of days to keep messages. * The default maximum number of days to keep messages.
*/ */
private static final int DEFAULT_TELL_MAX_DAYS = 7;
private static final int DEFAULT_TELL_MAX_DAYS = 7; /**
* The default message max queue size.
*/
private static final int DEFAULT_TELL_MAX_SIZE = 50;
/** /**
* The default message max queue size. * The serialized object file extension.
*/ */
private static final int DEFAULT_TELL_MAX_SIZE = 50; private static final String SER_EXT = ".ser";
/** /**
* The serialized object file extension. * The bot instance.
*/ */
private static final String SER_EXT = ".ser"; final private Mobibot bot;
/** /**
* The bot instance. * The maximum number of days to keep messages.
*/ */
final private Mobibot bot; final private int maxDays;
/** /**
* The maximum number of days to keep messages. * The message maximum queue size.
*/ */
final private int maxDays; final private int maxSize;
/** /**
* The message maximum queue size. * The messages queue.
*/ */
final private int maxSize; private final List<TellMessage> messages = new CopyOnWriteArrayList<>();
/** /**
* The messages queue. * The serialized object file.
*/ */
private final List<TellMessage> messages = new CopyOnWriteArrayList<>(); private final String serializedObject;
/** public Tell(final Mobibot bot, final String maxDays, final String maxSize) {
* The serialized object file. this.bot = bot;
*/ this.maxDays = Utils.getIntProperty(maxDays, DEFAULT_TELL_MAX_DAYS);
private final String serializedObject; this.maxSize = Utils.getIntProperty(maxSize, DEFAULT_TELL_MAX_SIZE);
public Tell(final Mobibot bot, final String maxDays, final String maxSize) // Load the message queue.
{ serializedObject = bot.getLogsDir() + bot.getName() + SER_EXT;
this.bot = bot; messages.addAll(TellMessagesMgr.load(serializedObject, bot.getLogger()));
this.maxDays = Utils.getIntProperty(maxDays, DEFAULT_TELL_MAX_DAYS);
this.maxSize = Utils.getIntProperty(maxSize, DEFAULT_TELL_MAX_SIZE);
// Load the message queue. if (clean()) {
serializedObject = bot.getLogsDir() + bot.getName() + SER_EXT; save();
messages.addAll(TellMessagesMgr.load(serializedObject, bot.getLogger())); }
}
if (clean()) /**
{ * Cleans the messages queue.
save(); *
} * @return <code>True</code> if the queue was cleaned.
} */
private boolean clean() {
if (bot.getLogger().isDebugEnabled()) {
bot.getLogger().debug("Cleaning the messages.");
}
/** return TellMessagesMgr.clean(messages, maxDays);
* Cleans the messages queue. }
*
* @return <code>True</code> if the queue was cleaned.
*/
private boolean clean()
{
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Cleaning the messages.");
}
return TellMessagesMgr.clean(messages, maxDays); /**
} * Responds with help.
*
* @param sender The sender.
*/
public void helpResponse(final String sender) {
bot.send(sender, "To send a message to someone when they join the channel:");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TELL_CMD + " <nick> <message>"));
/** bot.send(sender, "To view queued and sent messages:");
* Saves the messages queue. bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TELL_CMD + ' ' + Commands.VIEW_CMD));
*/
private void save()
{
TellMessagesMgr.save(serializedObject, messages, bot.getLogger());
}
/** bot.send(sender, "Messages are kept for " + Utils.bold(maxDays) + Utils.plural(maxDays, " day.", " days."));
* Processes the commands. }
*
* @param sender The sender's nick.
* @param cmds The commands string.
*/
public void response(final String sender, final String cmds)
{
if (!Utils.isValidString(cmds))
{
helpResponse(sender);
}
else if (cmds.startsWith(Commands.VIEW_CMD))
{
if (bot.isOp(sender) && cmds.equals(Commands.VIEW_CMD + ' ' + TELL_ALL_KEYWORD))
{
if (messages.size() > 0)
{
for (final TellMessage message : messages)
{
bot.send(sender,
Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient())
+ " [ID: " + message.getId() + ", " + (message.isReceived() ? "DELIVERED" : "QUEUED")
+ ']',
true);
}
}
else
{
bot.send(sender, "There are no messages in the queue.", true);
}
}
else
{
boolean hasMessage = false;
for (final TellMessage message : messages) /**
{ * Returns <code>true</code> if enabled.
if (message.isMatch(sender)) *
{ * @return <code>true</code> or <code>false</code>
if (!hasMessage) */
{ public boolean isEnabled() {
hasMessage = true; return maxSize > 0 && maxDays > 0;
bot.send(sender, "Here are your messages: ", true); }
}
if (message.isReceived()) /**
{ * Processes the commands.
bot.send(sender, *
Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient()) * @param sender The sender's nick.
+ " [" + Utils.UTC_SDF.format(message.getReceived()) + ", ID: " + message.getId() * @param cmds The commands string.
+ ", DELIVERED]", */
true); public void response(final String sender, final String cmds) {
if (!Utils.isValidString(cmds)) {
helpResponse(sender);
} else if (cmds.startsWith(Commands.VIEW_CMD)) {
if (bot.isOp(sender) && cmds.equals(Commands.VIEW_CMD + ' ' + TELL_ALL_KEYWORD)) {
if (messages.size() > 0) {
for (final TellMessage message : messages) {
bot.send(sender, Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient())
+ " [ID: " + message.getId() + ", "
+ (message.isReceived() ? "DELIVERED" : "QUEUED") + ']',
true);
}
} else {
bot.send(sender, "There are no messages in the queue.", true);
}
} else {
boolean hasMessage = false;
} for (final TellMessage message : messages) {
else if (message.isMatch(sender)) {
{ if (!hasMessage) {
bot.send(sender, hasMessage = true;
Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient()) bot.send(sender, "Here are your messages: ", true);
+ " [" + Utils.UTC_SDF.format(message.getQueued()) + ", ID: " + message.getId() }
+ ", QUEUED]",
true);
}
bot.send(sender, bot.helpIndent(message.getMessage(), false), true); if (message.isReceived()) {
} bot.send(sender,
} Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient())
+ " [" + Utils.UTC_SDF.format(message.getReceived()) + ", ID: "
+ message.getId() + ", DELIVERED]",
true);
if (!hasMessage) } else {
{ bot.send(sender,
bot.send(sender, "You have no messages in the queue.", true); Utils.bold(message.getSender()) + " --> " + Utils.bold(message.getRecipient())
} + " [" + Utils.UTC_SDF.format(message.getQueued()) + ", ID: "
else + message.getId() + ", QUEUED]",
{ true);
bot.send(sender, "To delete one or all delivered messages:"); }
bot.send(sender,
bot.helpIndent(bot.getNick() + ": " + TELL_CMD + ' ' + TELL_DEL_KEYWORD + " <id|"
+ TELL_ALL_KEYWORD + '>'));
bot.send(sender,
"Messages are kept for " + Utils.bold(maxDays) + Utils.plural(maxDays, " day.", " days."));
}
}
}
else if (cmds.startsWith(TELL_DEL_KEYWORD + ' '))
{
final String[] split = cmds.split(" ");
if (split.length == 2) bot.send(sender, bot.helpIndent(message.getMessage(), false), true);
{ }
final String id = split[1]; }
boolean deleted = false;
if (id.equalsIgnoreCase(TELL_ALL_KEYWORD)) if (!hasMessage) {
{ bot.send(sender, "You have no messages in the queue.", true);
for (final TellMessage message : messages) } else {
{ bot.send(sender, "To delete one or all delivered messages:");
if (message.getSender().equalsIgnoreCase(sender) && message.isReceived()) bot.send(sender,
{ bot.helpIndent(bot.getNick() + ": " + TELL_CMD + ' ' + TELL_DEL_KEYWORD + " <id|"
messages.remove(message); + TELL_ALL_KEYWORD + '>'));
deleted = true; bot.send(sender, "Messages are kept for " + Utils.bold(maxDays)
} + Utils.plural(maxDays, " day.", " days."));
} }
}
} else if (cmds.startsWith(TELL_DEL_KEYWORD + ' ')) {
final String[] split = cmds.split(" ");
if (deleted) if (split.length == 2) {
{ final String id = split[1];
save(); boolean deleted = false;
bot.send(sender, "Delivered messages have been deleted.", true);
}
else
{
bot.send(sender, "No delivered messages were found.", true);
}
} if (id.equalsIgnoreCase(TELL_ALL_KEYWORD)) {
else for (final TellMessage message : messages) {
{ if (message.getSender().equalsIgnoreCase(sender) && message.isReceived()) {
boolean found = false; messages.remove(message);
deleted = true;
}
}
for (final TellMessage message : messages) if (deleted) {
{ save();
found = message.isMatchId(id); bot.send(sender, "Delivered messages have been deleted.", true);
} else {
bot.send(sender, "No delivered messages were found.", true);
}
if (found && (message.getSender().equalsIgnoreCase(sender) || bot.isOp(sender))) } else {
{ boolean found = false;
messages.remove(message);
save(); for (final TellMessage message : messages) {
bot.send(sender, "Your message was deleted from the queue.", true); found = message.isMatchId(id);
deleted = true;
break;
}
}
if (!deleted) if (found && (message.getSender().equalsIgnoreCase(sender) || bot.isOp(sender))) {
{ messages.remove(message);
if (found)
{
bot.send(sender, "Only messages that you sent can be deleted.", true);
}
else
{
bot.send(sender, "The specified message [ID " + id + "] could not be found.", true);
}
}
}
}
else
{
helpResponse(sender);
}
}
else
{
final String[] split = cmds.split(" ", 2);
if (split.length == 2 && (Utils.isValidString(split[1]) && split[1].contains(" "))) save();
{ bot.send(sender, "Your message was deleted from the queue.", true);
if (messages.size() < maxSize) deleted = true;
{ break;
final TellMessage message = new TellMessage(sender, split[0], split[1].trim()); }
}
messages.add(message); if (!deleted) {
if (found) {
bot.send(sender, "Only messages that you sent can be deleted.", true);
} else {
bot.send(sender, "The specified message [ID " + id + "] could not be found.", true);
}
}
}
} else {
helpResponse(sender);
}
} else {
final String[] split = cmds.split(" ", 2);
save(); if (split.length == 2 && (Utils.isValidString(split[1]) && split[1].contains(" "))) {
if (messages.size() < maxSize) {
final TellMessage message = new TellMessage(sender, split[0], split[1].trim());
bot.send(sender, messages.add(message);
"Message [ID " + message.getId() + "] was queued for " + Utils
.bold(message.getRecipient()), true);
}
else
{
bot.send(sender, "Sorry, the messages queue is currently full.", true);
}
}
else
{
helpResponse(sender);
}
}
if (clean()) save();
{
save();
}
}
/** bot.send(sender, "Message [ID " + message.getId() + "] was queued for "
* Responds with help. + Utils.bold(message.getRecipient()), true);
* } else {
* @param sender The sender. bot.send(sender, "Sorry, the messages queue is currently full.", true);
*/ }
public void helpResponse(final String sender) } else {
{ helpResponse(sender);
bot.send(sender, "To send a message to someone when they join the channel:"); }
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TELL_CMD + " <nick> <message>")); }
bot.send(sender, "To view queued and sent messages:"); if (clean()) save();
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TELL_CMD + ' ' + Commands.VIEW_CMD)); }
bot.send(sender, "Messages are kept for " + Utils.bold(maxDays) + Utils.plural(maxDays, " day.", " days.")); /**
} * Saves the messages queue.
*/
private void save() {
TellMessagesMgr.save(serializedObject, messages, bot.getLogger());
}
/** /**
* Checks and sends messages. * Checks and sends messages.
* *
* @param nickname The user's nickname. * @param nickname The user's nickname.
*/ * @param isMessage The message flag.
public void send(final String nickname) */
{ public void send(final String nickname, final boolean isMessage) {
send(nickname, false); if (!nickname.equals(bot.getNick()) && isEnabled()) {
} messages.stream().filter(message -> message.isMatch(nickname)).forEach(
message -> {
if (message.getRecipient().equalsIgnoreCase(nickname) && !message.isReceived()) {
if (message.getSender().equals(nickname)) {
if (!isMessage) {
bot.send(nickname, Utils.bold("You") + " wanted me to remind you: "
+ Utils.reverseColor(message.getMessage()),
true);
/** message.setIsReceived();
* Checks and sends messages. message.setIsNotified();
*
* @param nickname The user's nickname.
* @param isMessage The message flag.
*/
public void send(final String nickname, final boolean isMessage)
{
if (!nickname.equals(bot.getNick()) && isEnabled())
{
messages.stream().filter(message -> message.isMatch(nickname)).forEach(message -> {
if (message.getRecipient().equalsIgnoreCase(nickname) && !message.isReceived())
{
if (message.getSender().equals(nickname))
{
if (!isMessage)
{
bot.send(nickname,
Utils.bold("You") + " wanted me to remind you: " + Utils
.reverseColor(message.getMessage()),
true);
message.setIsReceived(); save();
message.setIsNotified(); }
} else {
bot.send(nickname, message.getSender() + " wanted me to tell you: "
+ Utils.reverseColor(message.getMessage()),
true);
save(); message.setIsReceived();
}
}
else
{
bot.send(nickname,
message.getSender() + " wanted me to tell you: " + Utils
.reverseColor(message.getMessage()),
true);
message.setIsReceived(); save();
}
} else if (message.getSender().equalsIgnoreCase(nickname) && message.isReceived()
&& !message.isNotified()) {
bot.send(nickname,
"Your message "
+ Utils.reverseColor("[ID " + message.getId() + ']') + " was sent to "
+ Utils.bold(message.getRecipient()) + " on "
+ Utils.UTC_SDF.format(message.getReceived()),
true);
save(); message.setIsNotified();
}
}
else if (message.getSender().equalsIgnoreCase(nickname) && message.isReceived() && !message
.isNotified())
{
bot.send(nickname,
"Your message " + Utils.reverseColor("[ID " + message.getId() + ']') + " was sent to "
+ Utils.bold(message.getRecipient()) + " on " + Utils.UTC_SDF
.format(message.getReceived()),
true);
message.setIsNotified(); save();
}
});
}
}
save(); /**
} * Checks and sends messages.
}); *
} * @param nickname The user's nickname.
} */
public void send(final String nickname) {
send(nickname, false);
}
/** /**
* Returns <code>true</code> if enabled. * Returns the messages queue size.
* *
* @return <code>true</code> or <code>false</code> * @return The size.
*/ */
public boolean isEnabled() public int size() {
{ return messages.size();
return maxSize > 0 && maxDays > 0; }
}
/**
* Returns the messages queue size.
*
* @return The size.
*/
public int size()
{
return messages.size();
}
} }

View file

@ -42,162 +42,138 @@ import java.util.Date;
* @created 2014-04-24 * @created 2014-04-24
* @since 1.0 * @since 1.0
*/ */
public class TellMessage implements Serializable public class TellMessage implements Serializable {
{ private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L; private final String id;
private final String message;
final private Date queued;
private final String recipient;
private final String sender;
private boolean isNotified;
private boolean isReceived;
private Date received;
private final String id; /**
* Create a new message.
*
* @param sender The sender's nick.
* @param recipient The recipient's nick.
* @param message The message.
*/
public TellMessage(final String sender, final String recipient, final String message) {
this.sender = sender;
this.recipient = recipient;
this.message = message;
private final String message; this.queued = Calendar.getInstance().getTime();
this.id = Utils.TIMESTAMP_SDF.format(this.queued);
final private Date queued; }
private final String recipient; /**
* Returns the message id.
*
* @return The message id.
*/
public String getId() {
return id;
}
private final String sender; /**
* Returns the message text.
*
* @return The text of the message.
*/
public String getMessage() {
return message;
}
private boolean isNotified; /**
* Returns the state of the queue flag.
*
* @return <code>true</code> if the message is queued.
*/
public Date getQueued() {
return queued;
}
private boolean isReceived; /**
* Returns the state of the received flag.
*
* @return <code>true</code> if the message has been received.
*/
public Date getReceived() {
return received;
}
private Date received; /**
* Returns the message's recipient.
*
* @return The recipient of the message.
*/
public String getRecipient() {
return recipient;
}
/** /**
* Create a new message. * Returns the message's sender.
* *
* @param sender The sender's nick. * @return The sender of the message.
* @param recipient The recipient's nick. */
* @param message The message. public String getSender() {
*/ return sender;
public TellMessage(final String sender, final String recipient, final String message) }
{
this.sender = sender;
this.recipient = recipient;
this.message = message;
this.queued = Calendar.getInstance().getTime(); /**
this.id = Utils.TIMESTAMP_SDF.format(this.queued); * Matches the message sender or recipient.
*
* @param nick The nickname to match with.
* @return <code>true</code> if the nickname matches.
*/
public boolean isMatch(final String nick) {
return (sender.equalsIgnoreCase(nick) || recipient.equalsIgnoreCase(nick));
}
} /**
* Match the message ID.
*
* @param id The ID to match with.
* @return <code>true</code> if the id matches.
*/
public boolean isMatchId(final String id) {
return this.id.equals(id);
}
/** /**
* Returns the message id. * Returns the notification flag state.
* *
* @return The message id. * @return <code>true</code> if the sender has been notified.
*/ */
public String getId() public boolean isNotified() {
{ return isNotified;
return id; }
}
/** /**
* Returns the message text. * Returns the received flag state.
* *
* @return The text of the message. * @return <code>true</code> if the message was received.
*/ */
public String getMessage() public boolean isReceived() {
{ return isReceived;
return message; }
}
/** /**
* Returns the state of the queue flag. * Sets the notified flag.
* */
* @return <code>true</code> if the message is queued. public void setIsNotified() {
*/ isNotified = true;
public Date getQueued() }
{
return queued;
}
/** /**
* Returns the state of the received flag. * Sets the received flag.
* */
* @return <code>true</code> if the message has been received. public void setIsReceived() {
*/ received = Calendar.getInstance().getTime();
public Date getReceived() isReceived = true;
{ }
return received;
}
/**
* Returns the message's recipient.
*
* @return The recipient of the message.
*/
public String getRecipient()
{
return recipient;
}
/**
* Returns the message's sender.
*
* @return The sender of the message.
*/
public String getSender()
{
return sender;
}
/**
* Matches the message sender or recipient.
*
* @param nick The nickname to match with.
*
* @return <code>true</code> if the nickname matches.
*/
public boolean isMatch(final String nick)
{
return (sender.equalsIgnoreCase(nick) || recipient.equalsIgnoreCase(nick));
}
/**
* Match the message ID.
*
* @param id The ID to match with.
*
* @return <code>true</code> if the id matches.
*/
public boolean isMatchId(final String id)
{
return this.id.equals(id);
}
/**
* Returns the notification flag state.
*
* @return <code>true</code> if the sender has been notified.
*/
public boolean isNotified()
{
return isNotified;
}
/**
* Returns the received flag state.
*
* @return <code>true</code> if the message was received.
*/
public boolean isReceived()
{
return isReceived;
}
/**
* Sets the notified flag.
*/
public void setIsNotified()
{
isNotified = true;
}
/**
* Sets the received flag.
*/
public void setIsReceived()
{
received = Calendar.getInstance().getTime();
isReceived = true;
}
} }

View file

@ -46,113 +46,90 @@ import java.util.List;
* @created 2014-04-26 * @created 2014-04-26
* @since 1.0 * @since 1.0
*/ */
final class TellMessagesMgr final class TellMessagesMgr {
{ /**
/** * Disables the default constructor.
* Disables the default constructor. *
* * @throws UnsupportedOperationException If the constructor is called.
* @throws UnsupportedOperationException If the constructor is called. */
*/ private TellMessagesMgr()
private TellMessagesMgr() throws UnsupportedOperationException {
throws UnsupportedOperationException throw new UnsupportedOperationException("Illegal constructor call.");
{ }
throw new UnsupportedOperationException("Illegal constructor call.");
}
/** /**
* Cleans the messages queue * Cleans the messages queue
* *
* @param tellMessages The messages list. * @param tellMessages The messages list.
* @param tellMaxDays The maximum number of days to keep messages for. * @param tellMaxDays The maximum number of days to keep messages for.
* * @return <code>True</code> if the queue was cleaned.
* @return <code>True</code> if the queue was cleaned. */
*/ public static boolean clean(final List<TellMessage> tellMessages, final int tellMaxDays) {
public static boolean clean(final List<TellMessage> tellMessages, final int tellMaxDays) final Calendar maxDate = Calendar.getInstance();
{ final Date today = new Date();
final Calendar maxDate = Calendar.getInstance(); boolean cleaned = false;
final Date today = new Date();
boolean cleaned = false;
for (final TellMessage message : tellMessages) for (final TellMessage message : tellMessages) {
{ maxDate.setTime(message.getQueued());
maxDate.setTime(message.getQueued()); maxDate.add(Calendar.DATE, tellMaxDays);
maxDate.add(Calendar.DATE, tellMaxDays);
if (maxDate.getTime().before(today)) if (maxDate.getTime().before(today)) {
{ tellMessages.remove(message);
tellMessages.remove(message); cleaned = true;
cleaned = true; }
} }
}
return cleaned; return cleaned;
} }
/** /**
* Loads the messages. * Loads the messages.
* *
* @param file The serialized objects file. * @param file The serialized objects file.
* @param logger The logger. * @param logger The logger.
* * @return The {@link net.thauvin.erik.mobibot.TellMessage} array.
* @return The {@link net.thauvin.erik.mobibot.TellMessage} array. */
*/ @SuppressWarnings("unchecked")
@SuppressWarnings("unchecked") public static List<TellMessage> load(final String file, final Log4JLogger logger) {
public static List<TellMessage> load(final String file, final Log4JLogger logger) try {
{
try
{
try (ObjectInput input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) try (ObjectInput input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
{ if (logger.isDebugEnabled()) {
if (logger.isDebugEnabled()) logger.debug("Loading the messages.");
{ }
logger.debug("Loading the messages.");
}
return ((List<TellMessage>) input.readObject()); return ((List<TellMessage>) input.readObject());
} }
} } catch (FileNotFoundException ignore) {
catch (FileNotFoundException ignore) ; // Do nothing.
{ } catch (IOException e) {
; // Do nothing. logger.error("An IO error occurred loading the messages queue.", e);
} } catch (Exception e) {
catch (IOException e) logger.getLogger().error("An error occurred loading the messages queue.", e);
{ }
logger.error("An IO error occurred loading the messages queue.", e);
}
catch (Exception e)
{
logger.getLogger().error("An error occurred loading the messages queue.", e);
}
return new ArrayList<>(); return new ArrayList<>();
} }
/** /**
* Saves the messages. * Saves the messages.
* *
* @param file The serialized objects file. * @param file The serialized objects file.
* @param messages The {@link net.thauvin.erik.mobibot.TellMessage} array. * @param messages The {@link net.thauvin.erik.mobibot.TellMessage} array.
* @param logger The logger. * @param logger The logger.
*/ */
public static void save(final String file, final List<TellMessage> messages, final Log4JLogger logger) public static void save(final String file, final List<TellMessage> messages, final Log4JLogger logger) {
{ try {
try
{
try (ObjectOutput output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) try (ObjectOutput output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
{ if (logger.isDebugEnabled()) {
if (logger.isDebugEnabled()) logger.debug("Saving the messages.");
{ }
logger.debug("Saving the messages.");
}
output.writeObject(messages); output.writeObject(messages);
} }
} } catch (IOException e) {
catch (IOException e) logger.error("Unable to save messages queue.", e);
{ }
logger.error("Unable to save messages queue.", e); }
}
}
} }

View file

@ -9,68 +9,61 @@ import java.io.BufferedReader;
import java.io.InputStreamReader; import java.io.InputStreamReader;
/** /**
* The <code>TwitterOAuth</code> class. <p> Go to <a href="http://twitter.com/oauth_clients/new">http://twitter.com/oauth_clients/new</a> * The <code>TwitterOAuth</code> class.
* to register your bot. </p> Then execute: <p> <code>java -cp "mobibot.jar:lib/*" * <p>
* net.thauvin.erik.mobibot.TwitterOAuth * Go to <a href="http://twitter.com/oauth_clients/new">http://twitter.com/oauth_clients/new</a> to register your bot.
* &lt;consumerKey&gt; &lt;consumerSecret&gt;</code> </p> and follow the prompts/instructions. * </p>
* Then execute:
* <p>
* <code>
* java -cp "mobibot.jar:lib/*"net.thauvin.erik.mobibot.TwitterOAuth &lt;consumerKey&gt; &lt;consumerSecret&gt;
* </code>
* </p>
* and follow the prompts/instructions.
* *
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a> * @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @author <a href="http://twitter4j.org/en/code-examples.html#oauth">http://twitter4j.org/en/code-examples.html#oauth</a> * @author <a href="http://twitter4j.org/en/code-examples.html#oauth">http://twitter4j.org/en/code-examples.html#oauth</a>
* @created Sep 13, 2010 * @created Sep 13, 2010
* @since 1.0 * @since 1.0
*/ */
public final class TwitterOAuth public final class TwitterOAuth {
{ public static void main(final String[] args)
public static void main(final String[] args) throws Exception {
throws Exception if (args.length == 2) {
{ final twitter4j.Twitter twitter = new TwitterFactory().getInstance();
if (args.length == 2) twitter.setOAuthConsumer(args[0], args[1]);
{ final RequestToken requestToken = twitter.getOAuthRequestToken();
final twitter4j.Twitter twitter = new TwitterFactory().getInstance(); AccessToken accessToken = null;
twitter.setOAuthConsumer(args[0], args[1]); final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
final RequestToken requestToken = twitter.getOAuthRequestToken(); while (null == accessToken) {
AccessToken accessToken = null; System.out.println("Open the following URL and grant access to your account:");
final BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); System.out.println(requestToken.getAuthorizationURL());
while (null == accessToken) System.out.print("Enter the PIN (if available) or just hit enter.[PIN]:");
{ final String pin = br.readLine();
System.out.println("Open the following URL and grant access to your account:"); try {
System.out.println(requestToken.getAuthorizationURL()); if (pin.length() > 0) {
System.out.print("Enter the PIN (if available) or just hit enter.[PIN]:"); accessToken = twitter.getOAuthAccessToken(requestToken, pin);
final String pin = br.readLine(); } else {
try accessToken = twitter.getOAuthAccessToken();
{ }
if (pin.length() > 0)
{
accessToken = twitter.getOAuthAccessToken(requestToken, pin);
}
else
{
accessToken = twitter.getOAuthAccessToken();
}
System.out.println( System.out.println(
"Please add the following to the bot's property file:" + "\n\n" + "twitter-consumerKey=" "Please add the following to the bot's property file:" + "\n\n" + "twitter-consumerKey="
+ args[0] + '\n' + "twitter-consumerSecret=" + args[1] + '\n' + "twitter-token=" + args[0] + '\n' + "twitter-consumerSecret=" + args[1] + '\n' + "twitter-token="
+ accessToken.getToken() + '\n' + "twitter-tokenSecret=" + accessToken.getTokenSecret()); + accessToken.getToken() + '\n' + "twitter-tokenSecret=" + accessToken
} .getTokenSecret());
catch (TwitterException te) } catch (TwitterException te) {
{ if (401 == te.getStatusCode()) {
if (401 == te.getStatusCode()) System.out.println("Unable to get the access token.");
{ } else {
System.out.println("Unable to get the access token."); te.printStackTrace();
} }
else }
{ }
te.printStackTrace(); } else {
} System.out.println("Usage: " + TwitterOAuth.class.getName() + " <consumerKey> <consumerSecret>");
} }
}
}
else
{
System.out.println("Usage: " + TwitterOAuth.class.getName() + " <consumerKey> <consumerSecret>");
}
System.exit(0); System.exit(0);
} }
} }

View file

@ -44,288 +44,235 @@ import java.util.Calendar;
* @created 2014-04-26 * @created 2014-04-26
* @since 1.0 * @since 1.0
*/ */
final public class Utils final public class Utils {
{ /**
/** * The ISO (YYYY-MM-DD) simple date format.
* The ISO (YYYY-MM-DD) simple date format. */
*/ public static final SimpleDateFormat ISO_SDF = new SimpleDateFormat("yyyy-MM-dd");
public static final SimpleDateFormat ISO_SDF = new SimpleDateFormat("yyyy-MM-dd"); /**
* The timestamp simple date format.
*/
public static final SimpleDateFormat TIMESTAMP_SDF = new SimpleDateFormat("yyyyMMddHHmmss");
/**
* The UTC (yyyy-MM-dd HH:mm) simple date format.
*/
public static final SimpleDateFormat UTC_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm");
/** /**
* The timestamp simple date format. * Disables the default constructor.
*/ *
public static final SimpleDateFormat TIMESTAMP_SDF = new SimpleDateFormat("yyyyMMddHHmmss"); * @throws UnsupportedOperationException If the constructor is called.
*/
private Utils()
throws UnsupportedOperationException {
throw new UnsupportedOperationException("Illegal constructor call.");
}
/** /**
* The UTC (yyyy-MM-dd HH:mm) simple date format. * Makes the given int bold.
*/ *
public static final SimpleDateFormat UTC_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm"); * @param i The int.
* @return The bold string.
*/
public static String bold(final int i) {
return bold(Integer.toString(i));
}
/** /**
* Disables the default constructor. * Makes the given string bold.
* *
* @throws UnsupportedOperationException If the constructor is called. * @param s The string.
*/ * @return The bold string.
private Utils() */
throws UnsupportedOperationException public static String bold(final String s) {
{ return Colors.BOLD + s + Colors.BOLD;
throw new UnsupportedOperationException("Illegal constructor call."); }
}
/** /**
* Makes the given int bold. * Builds an entry's comment for display on the channel.
* *
* @param i The int. * @param entryIndex The entry's index.
* * @param commentIndex The comment's index.
* @return The bold string. * @param comment The {@link net.thauvin.erik.mobibot.EntryComment comment} object.
*/ * @return The entry's comment.
public static String bold(final int i) */
{ static String buildComment(final int entryIndex, final int commentIndex, final EntryComment comment) {
return bold(Integer.toString(i)); return (Commands.LINK_CMD + (entryIndex + 1) + '.' + (commentIndex + 1) + ": [" + comment.getNick() + "] "
} + comment.getComment());
}
/** /**
* Makes the given string bold. * Builds an entry's link for display on the channel.
* *
* @param s The string. * @param index The entry's index.
* * @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object.
* @return The bold string. * @return The entry's link.
*/ * @see #buildLink(int, net.thauvin.erik.mobibot.EntryLink, boolean)
public static String bold(final String s) */
{ static String buildLink(final int index, final EntryLink entry) {
return Colors.BOLD + s + Colors.BOLD; return buildLink(index, entry, false);
} }
/** /**
* Builds an entry's comment for display on the channel. * Builds an entry's link for display on the channel.
* *
* @param entryIndex The entry's index. * @param index The entry's index.
* @param commentIndex The comment's index. * @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object.
* @param comment The {@link net.thauvin.erik.mobibot.EntryComment comment} object. * @param isView Set to true to display the number of comments.
* * @return The entry's link.
* @return The entry's comment. */
*/ static String buildLink(final int index, final EntryLink entry, final boolean isView) {
static String buildComment(final int entryIndex, final int commentIndex, final EntryComment comment) final StringBuilder buff = new StringBuilder(Commands.LINK_CMD + (index + 1) + ": ");
{
return (Commands.LINK_CMD + (entryIndex + 1) + '.' + (commentIndex + 1) + ": [" + comment.getNick() + "] "
+ comment.getComment());
}
/** buff.append('[').append(entry.getNick()).append(']');
* Builds an entry's link for display on the channel.
*
* @param index The entry's index.
* @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object.
*
* @return The entry's link.
*
* @see #buildLink(int, net.thauvin.erik.mobibot.EntryLink, boolean)
*/
static String buildLink(final int index, final EntryLink entry)
{
return buildLink(index, entry, false);
}
/** if (isView && entry.hasComments()) {
* Builds an entry's link for display on the channel. buff.append("[+").append(entry.getCommentsCount()).append(']');
* }
* @param index The entry's index.
* @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object.
* @param isView Set to true to display the number of comments.
*
* @return The entry's link.
*/
static String buildLink(final int index, final EntryLink entry, final boolean isView)
{
final StringBuilder buff = new StringBuilder(Commands.LINK_CMD + (index + 1) + ": ");
buff.append('[').append(entry.getNick()).append(']'); buff.append(' ');
if (isView && entry.hasComments()) if (Mobibot.NO_TITLE.equals(entry.getTitle())) {
{ buff.append(entry.getTitle());
buff.append("[+").append(entry.getCommentsCount()).append(']'); } else {
} buff.append(bold(entry.getTitle()));
}
buff.append(' '); buff.append(" ( ").append(Utils.green(entry.getLink())).append(" )");
if (Mobibot.NO_TITLE.equals(entry.getTitle())) return buff.toString();
{ }
buff.append(entry.getTitle());
}
else
{
buff.append(bold(entry.getTitle()));
}
buff.append(" ( ").append(Utils.green(entry.getLink())).append(" )"); /**
* Build an entry's tags/categories for display on the channel.
*
* @param entryIndex The entry's index.
* @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object.
* @return The entry's tags.
*/
static String buildTags(final int entryIndex, final EntryLink entry) {
return (Commands.LINK_CMD + (entryIndex + 1) + "T: " + entry.getDeliciousTags().replaceAll(",", ", "));
}
return buff.toString(); /**
} * Ensures that the given location (File/URL) has a trailing slash (<code>/</code>) to indicate a directory.
*
* @param location The File or URL location.
* @param isUrl Set to true if the location is a URL
* @return The location ending with a slash.
*/
static String ensureDir(final String location, final boolean isUrl) {
if (isUrl) {
if (location.charAt(location.length() - 1) == '/') {
return location;
} else {
return location + '/';
}
} else {
if (location.charAt(location.length() - 1) == File.separatorChar) {
return location;
} else {
return location + File.separatorChar;
}
}
}
/** /**
* Makes the given string green. * Returns a property as an int.
* *
* @param s The string. * @param property The port property value.
* * @param def The default property value.
* @return The bold string. * @return The port or default value if invalid.
*/ */
public static String green(final String s) public static int getIntProperty(final String property, final int def) {
{ int prop;
return Colors.DARK_GREEN + s + Colors.NORMAL;
}
/** try {
* Build an entry's tags/categories for display on the channel. prop = Integer.parseInt(property);
* } catch (NumberFormatException ignore) {
* @param entryIndex The entry's index. prop = def;
* @param entry The {@link net.thauvin.erik.mobibot.EntryLink entry} object. }
*
* @return The entry's tags.
*/
static String buildTags(final int entryIndex, final EntryLink entry)
{
return (Commands.LINK_CMD + (entryIndex + 1) + "T: " + entry.getDeliciousTags().replaceAll(",", ", "));
}
/** return prop;
* Ensures that the given location (File/URL) has a trailing slash (<code>/</code>) to indicate a directory. }
*
* @param location The File or URL location.
* @param isUrl Set to true if the location is a URL
*
* @return The location ending with a slash.
*/
static String ensureDir(final String location, final boolean isUrl)
{
if (isUrl)
{
if (location.charAt(location.length() - 1) == '/')
{
return location;
}
else
{
return location + '/';
}
}
else
{
if (location.charAt(location.length() - 1) == File.separatorChar)
{
return location;
}
else
{
return location + File.separatorChar;
}
}
}
/** /**
* Returns a property as an int. * Makes the given string green.
* *
* @param property The port property value. * @param s The string.
* @param def The default property value. * @return The bold string.
* */
* @return The port or default value if invalid. public static String green(final String s) {
*/ return Colors.DARK_GREEN + s + Colors.NORMAL;
public static int getIntProperty(final String property, final int def) }
{
int prop;
try /**
{ * Returns <code>true</code> if the given string is <em>not</em> blank or null.
prop = Integer.parseInt(property); *
} * @param s The string to check.
catch (NumberFormatException ignore) * @return <code>true</code> if the string is valid, <code>false</code> otherwise.
{ */
prop = def; public static boolean isValidString(final CharSequence s) {
} final int len;
if (s == null || (len = s.length()) == 0) {
return false;
}
for (int i = 0; i < len; i++) {
if (!Character.isWhitespace(s.charAt(i))) {
return true;
}
}
return false;
}
return prop; /**
} * Returns the plural form of a word, if count &gt; 1.
*
* @param count The count.
* @param word The word.
* @param plural The plural word.
*/
public static String plural(final long count, final String word, final String plural) {
if (count > 1) {
return plural;
} else {
return word;
}
}
/** /**
* Returns <code>true</code> if the given string is <em>not</em> blank or null. * Makes the given string reverse color.
* *
* @param s The string to check. * @param s The string.
* * @return The reverse color string.
* @return <code>true</code> if the string is valid, <code>false</code> otherwise. */
*/ public static String reverseColor(final String s) {
public static boolean isValidString(final CharSequence s) return Colors.REVERSE + s + Colors.REVERSE;
{ }
final int len;
if (s == null || (len = s.length()) == 0)
{
return false;
}
for (int i = 0; i < len; i++)
{
if (!Character.isWhitespace(s.charAt(i)))
{
return true;
}
}
return false;
}
/** /**
* Returns the plural form of a word, if count &gt; 1. * Returns today's date.
* *
* @param count The count. * @return Today's date in {@link #ISO_SDF ISO} format.
* @param word The word. */
* @param plural The plural word. public static String today() {
*/ return ISO_SDF.format(Calendar.getInstance().getTime());
public static String plural(final long count, final String word, final String plural) }
{
if (count > 1)
{
return plural;
}
else
{
return word;
}
}
/** /**
* Makes the given string reverse color. * Converts XML/XHTML entities to plain text.
* *
* @param s The string. * @param str The string to unescape.
* * @return The unescaped string.
* @return The reverse color string. */
*/ public static String unescapeXml(final String str) {
public static String reverseColor(final String s) String s = str.replaceAll("&amp;", "&");
{ s = s.replaceAll("&lt;", "<");
return Colors.REVERSE + s + Colors.REVERSE; s = s.replaceAll("&gt;", ">");
} s = s.replaceAll("&quot;", "\"");
s = s.replaceAll("&apos;", "'");
s = s.replaceAll("&#39;", "'");
/** return s;
* Returns today's date. }
*
* @return Today's date in {@link #ISO_SDF ISO} format.
*/
public static String today()
{
return ISO_SDF.format(Calendar.getInstance().getTime());
}
/**
* Converts XML/XHTML entities to plain text.
*
* @param str The string to unescape.
*
* @return The unescaped string.
*/
public static String unescapeXml(final String str)
{
String s = str.replaceAll("&amp;", "&");
s = s.replaceAll("&lt;", "<");
s = s.replaceAll("&gt;", ">");
s = s.replaceAll("&quot;", "\"");
s = s.replaceAll("&apos;", "'");
s = s.replaceAll("&#39;", "'");
return s;
}
} }

View file

@ -43,118 +43,105 @@ import java.util.*;
* @created 2016-07-01 * @created 2016-07-01
* @since 1.0 * @since 1.0
*/ */
public abstract class AbstractModule public abstract class AbstractModule {
{ final List<String> commands = new ArrayList<>();
final Map<String, String> properties = new HashMap<>();
final List<String> commands = new ArrayList<>(); /**
* Responds to a command.
*
* @param bot The bot's instance.
* @param sender The sender.
* @param args The command arguments.
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
*/
public abstract void commandResponse(final Mobibot bot,
final String sender,
final String args,
final boolean isPrivate);
final Map<String, String> properties = new HashMap<>(); /**
* Returns the module's commands, if any.
*
* @return The commands.
*/
public List<String> getCommands() {
return commands;
}
/** /**
* Responds to a command. * Returns the module's property keys.
* *
* @param bot The bot's instance. * @return The keys.
* @param sender The sender. */
* @param args The command arguments. public Set<String> getPropertyKeys() {
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. return properties.keySet();
*/ }
public abstract void commandResponse(final Mobibot bot,
final String sender,
final String args,
final boolean isPrivate);
/** /**
* Returns the module's commands, if any. * Returns <code>true</code> if the module has properties.
* *
* @return The commands. * @return <code>true</code> or <code>false</code> .
*/ */
public List<String> getCommands() public boolean hasProperties() {
{ return !properties.isEmpty();
return commands; }
}
/** /**
* Returns the module's property keys. * Responds with the module's help.
* *
* @return The keys. * @param bot The bot's instance.
*/ * @param sender The sender.
public Set<String> getPropertyKeys() * @param args The help arguments.
{ * @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
return properties.keySet(); */
} public abstract void helpResponse(final Mobibot bot,
final String sender,
final String args,
final boolean isPrivate);
/** /**
* Returns <code>true</code> if the module has properties. * Returns <code>true</code> if the module is enabled.
* *
* @return <code>true</code> or <code>false</code> . * @return <code>true</code> or <code>false</code>
*/ */
public boolean hasProperties() public boolean isEnabled() {
{ return true;
return !properties.isEmpty(); }
}
/** /**
* Responds with the module's help. * Returns <codde>true</codde> if the module responds to private messages.
* *
* @param bot The bot's instance. * @return <code>true</code> or <code>false</code>
* @param sender The sender. */
* @param args The help arguments. public boolean isPrivateMsgEnabled() {
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. return false;
*/ }
public abstract void helpResponse(final Mobibot bot,
final String sender,
final String args,
final boolean isPrivate);
/** /**
* Returns <code>true</code> if the module is enabled. * Ensures that all properties have values.
* *
* @return <code>true</code> or <code>false</code> * @return <code>true</code> if the properties are valid, <code>false</code> otherwise.
*/ */
public boolean isEnabled() public boolean isValidProperties() {
{ for (final String s : getPropertyKeys()) {
return true; if (!Utils.isValidString(properties.get(s))) {
} return false;
}
}
/** return true;
* Returns <codde>true</codde> if the module responds to private messages. }
*
* @return <code>true</code> or <code>false</code>
*/
public boolean isPrivateMsgEnabled()
{
return false;
}
/** /**
* Ensures that all properties have values. * Sets a property key and value.
* *
* @return <code>true</code> if the properties are valid, <code>false</code> otherwise. * @param key The key.
*/ * @param value The value.
public boolean isValidProperties() */
{ public void setProperty(final String key, final String value) {
for (final String s : getPropertyKeys()) if (Utils.isValidString(key)) {
{ properties.put(key, value);
if (!Utils.isValidString(properties.get(s))) }
{ }
return false;
}
}
return true;
}
/**
* Sets a property key and value.
*
* @param key The key.
* @param value The value.
*/
public void setProperty(final String key, final String value)
{
if (Utils.isValidString(key))
{
properties.put(key, value);
}
}
} }

View file

@ -45,54 +45,43 @@ import java.text.DecimalFormat;
* @created 2016-07-01 * @created 2016-07-01
* @since 1.0 * @since 1.0
*/ */
public class Calc extends AbstractModule public class Calc extends AbstractModule {
{ /**
/** * The Calc command.
* The Calc command. */
*/ private static final String CALC_CMD = "calc";
private static final String CALC_CMD = "calc";
/** /**
* The default constructor. * The default constructor.
*/ */
public Calc() public Calc() {
{ commands.add(CALC_CMD);
commands.add(CALC_CMD); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ if (Utils.isValidString(args)) {
if (Utils.isValidString(args)) final DecimalFormat decimalFormat = new DecimalFormat("#.##");
{
final DecimalFormat decimalFormat = new DecimalFormat("#.##");
try try {
{ final Expression calc = new ExpressionBuilder(args).build();
final Expression calc = new ExpressionBuilder(args).build(); bot.send(bot.getChannel(), args.replaceAll(" ", "") + " = " + decimalFormat.format(calc.evaluate()));
bot.send(bot.getChannel(), args.replaceAll(" ", "") + " = " + decimalFormat.format(calc.evaluate())); } catch (Exception e) {
} if (bot.getLogger().isDebugEnabled()) {
catch (Exception e) bot.getLogger().debug("Unable to calculate: " + args, e);
{ }
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Unable to calculate: " + args, e);
}
bot.send(bot.getChannel(), "No idea. This is the kind of math I don't get."); bot.send(bot.getChannel(), "No idea. This is the kind of math I don't get.");
} }
} } else {
else helpResponse(bot, sender, args, isPrivate);
{ }
helpResponse(bot, sender, args, isPrivate);
}
} }
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To solve a mathematical calculation:");
bot.send(sender, "To solve a mathematical calculation:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CALC_CMD + " <calculation>"));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CALC_CMD + " <calculation>")); }
}
} }

View file

@ -54,188 +54,154 @@ import java.util.TreeMap;
* @created Feb 11, 2004 * @created Feb 11, 2004
* @since 1.0 * @since 1.0
*/ */
final public class CurrencyConverter extends AbstractModule final public class CurrencyConverter extends AbstractModule {
{ /**
/** * The currency command.
* The currency command. */
*/ private static final String CURRENCY_CMD = "currency";
private static final String CURRENCY_CMD = "currency";
/** /**
* The rates keyword. * The rates keyword.
*/ */
private static final String CURRENCY_RATES_KEYWORD = "rates"; private static final String CURRENCY_RATES_KEYWORD = "rates";
/** /**
* The exchange rates. * The exchange rates.
*/ */
private static final Map<String, String> EXCHANGE_RATES = new TreeMap<>(); private static final Map<String, String> EXCHANGE_RATES = new TreeMap<>();
/** /**
* The exchange rates table URL. * The exchange rates table URL.
*/ */
private static final String EXCHANGE_TABLE_URL = "http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml"; private static final String EXCHANGE_TABLE_URL = "http://www.ecb.int/stats/eurofxref/eurofxref-daily.xml";
/** /**
* The last exchange rates table publication date. * The last exchange rates table publication date.
*/ */
private String pubDate = ""; private static String pubDate = "";
/** /**
* Creates a new {@link CurrencyConverter} instance. * Creates a new {@link CurrencyConverter} instance.
*/ */
public CurrencyConverter() public CurrencyConverter() {
{ commands.add(CURRENCY_CMD);
commands.add(CURRENCY_CMD); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ synchronized (this) {
synchronized (this) if (!pubDate.equals(Utils.today())) {
{ EXCHANGE_RATES.clear();
if (!pubDate.equals(Utils.today())) }
{ }
EXCHANGE_RATES.clear();
}
}
new Thread(() -> run(bot, sender, args)).start(); new Thread(() -> run(bot, sender, args)).start();
} }
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To convert from one currency to another:");
bot.send(sender, "To convert from one currency to another:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD + " [100 USD to EUR]"));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD + " [100 USD to EUR]"));
if (args.endsWith(CURRENCY_CMD)) if (args.endsWith(CURRENCY_CMD)) {
{ bot.send(sender, "For a listing of currency rates:");
bot.send(sender, "For a listing of currency rates:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD) + ' ' + CURRENCY_RATES_KEYWORD);
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD) + ' ' + CURRENCY_RATES_KEYWORD); bot.send(sender, "For a listing of supported currencies:");
bot.send(sender, "For a listing of supported currencies:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + CURRENCY_CMD)); }
} }
}
/** /**
* Converts the specified currencies. * Converts the specified currencies.
*/ */
private void run(final Mobibot bot, final String sender, final String query) private void run(final Mobibot bot, final String sender, final String query) {
{ if (Utils.isValidString(sender)) {
if (Utils.isValidString(sender)) if (EXCHANGE_RATES.isEmpty()) {
{ try {
if (EXCHANGE_RATES.isEmpty()) final SAXBuilder builder = new SAXBuilder();
{ builder.setIgnoringElementContentWhitespace(true);
try
{
final SAXBuilder builder = new SAXBuilder();
builder.setIgnoringElementContentWhitespace(true);
final Document doc = builder.build(new URL(EXCHANGE_TABLE_URL)); final Document doc = builder.build(new URL(EXCHANGE_TABLE_URL));
final Element root = doc.getRootElement(); final Element root = doc.getRootElement();
final Namespace ns = root.getNamespace(""); final Namespace ns = root.getNamespace("");
final Element cubeRoot = root.getChild("Cube", ns); final Element cubeRoot = root.getChild("Cube", ns);
final Element cubeTime = cubeRoot.getChild("Cube", ns); final Element cubeTime = cubeRoot.getChild("Cube", ns);
pubDate = cubeTime.getAttribute("time").getValue(); pubDate = cubeTime.getAttribute("time").getValue();
final List cubes = cubeTime.getChildren(); final List cubes = cubeTime.getChildren();
Element cube; Element cube;
for (final Object rawCube : cubes) for (final Object rawCube : cubes) {
{ cube = (Element) rawCube;
cube = (Element) rawCube; EXCHANGE_RATES.put(
EXCHANGE_RATES.put( cube.getAttribute("currency").getValue(),
cube.getAttribute("currency").getValue(), cube.getAttribute("rate").getValue());
cube.getAttribute("rate").getValue()); }
}
EXCHANGE_RATES.put("EUR", "1"); EXCHANGE_RATES.put("EUR", "1");
} } catch (JDOMException e) {
catch (JDOMException e) bot.getLogger().debug("Unable to parse the exchange rates table.", e);
{ bot.send(sender, "An error has occurred while parsing the exchange rates table.");
bot.getLogger().debug("Unable to parse the exchange rates table.", e); } catch (IOException e) {
bot.send(sender, "An error has occurred while parsing the exchange rates table."); bot.getLogger().debug("Unable to fetch the exchange rates table.", e);
} bot.send(sender,
catch (IOException e) "An error has occurred while fetching the exchange rates table: " + e.getMessage());
{ }
bot.getLogger().debug("Unable to fetch the exchange rates table.", e); }
bot.send(sender,
"An error has occurred while fetching the exchange rates table: " + e.getMessage());
}
}
if (EXCHANGE_RATES.isEmpty()) if (EXCHANGE_RATES.isEmpty()) {
{ bot.getLogger().debug("The exchange rate table is empty.");
bot.getLogger().debug("The exchange rate table is empty."); bot.send(sender, "Sorry, but the exchange rate table is empty.");
bot.send(sender, "Sorry, but the exchange rate table is empty."); } else if (Utils.isValidString(query)) {
} if (!EXCHANGE_RATES.isEmpty()) {
else if (Utils.isValidString(query)) if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+")) {
{ final String[] cmds = query.split(" ");
if (!EXCHANGE_RATES.isEmpty())
{
if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+"))
{
final String[] cmds = query.split(" ");
if (cmds.length == 4) if (cmds.length == 4) {
{ if (cmds[3].equals(cmds[1]) || cmds[0].equals("0")) {
if (cmds[3].equals(cmds[1]) || cmds[0].equals("0")) bot.send(sender, "You're kidding, right?");
{ } else {
bot.send(sender, "You're kidding, right?"); try {
} final double amt = Double.parseDouble(cmds[0].replaceAll(",", ""));
else final double from = Double.parseDouble(EXCHANGE_RATES.get(cmds[1].toUpperCase()));
{ final double to = Double.parseDouble(EXCHANGE_RATES.get(cmds[3].toUpperCase()));
try
{
final double amt = Double.parseDouble(cmds[0].replaceAll(",", ""));
final double from = Double.parseDouble(EXCHANGE_RATES.get(cmds[1].toUpperCase()));
final double to = Double.parseDouble(EXCHANGE_RATES.get(cmds[3].toUpperCase()));
bot.send(bot.getChannel(), bot.send(bot.getChannel(),
NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1) NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1)
+ ' ' + ' '
+ cmds[1].toUpperCase() + cmds[1].toUpperCase()
+ " = " + " = "
+ NumberFormat.getCurrencyInstance(Locale.US) + NumberFormat.getCurrencyInstance(Locale.US)
.format((amt * to) / from) .format((amt * to) / from)
.substring(1) .substring(1)
+ ' ' + ' '
+ cmds[3].toUpperCase()); + cmds[3].toUpperCase());
} } catch (NullPointerException ignored) {
catch (NullPointerException ignored) bot.send(sender,
{ "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
bot.send(sender, }
"The supported currencies are: " + EXCHANGE_RATES.keySet().toString()); }
} }
} } else if (query.equals(CURRENCY_RATES_KEYWORD)) {
} bot.send(sender, "Last Update: " + pubDate);
}
else if (query.equals(CURRENCY_RATES_KEYWORD))
{
bot.send(sender, "Last Update: " + pubDate);
final StringBuilder buff = new StringBuilder(0); final StringBuilder buff = new StringBuilder(0);
for (final Map.Entry<String, String> rate : EXCHANGE_RATES.entrySet()) for (final Map.Entry<String, String> rate : EXCHANGE_RATES.entrySet()) {
{ if (buff.length() > 0) {
if (buff.length() > 0) buff.append(", ");
{ }
buff.append(", "); buff.append(rate.getKey()).append(": ").append(rate.getValue());
} }
buff.append(rate.getKey()).append(": ").append(rate.getValue());
}
bot.send(sender, buff.toString()); bot.send(sender, buff.toString());
} }
} }
} } else {
else helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, true);
{ bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, true); }
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString()); }
} }
}
}
} }

View file

@ -43,73 +43,63 @@ import java.util.Random;
* @created 2014-04-28 * @created 2014-04-28
* @since 1.0 * @since 1.0
*/ */
final public class Dice extends AbstractModule final public class Dice extends AbstractModule {
{ /**
/** * The dice command.
* The dice command. */
*/ private final String DICE_CMD = "dice";
private final String DICE_CMD = "dice";
/** /**
* The default constructor. * The default constructor.
*/ */
public Dice() public Dice() {
{ commands.add(DICE_CMD);
commands.add(DICE_CMD); }
}
/** /**
* Rolls the dice. * Rolls the dice.
* *
* @param bot The bot's instance. * @param bot The bot's instance.
* @param sender The sender. * @param sender The sender.
* @param args The command arguments. * @param args The command arguments.
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. * @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
*/ */
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ final Random r = new Random();
final Random r = new Random();
int i = r.nextInt(6) + 1; int i = r.nextInt(6) + 1;
int y = r.nextInt(6) + 1; int y = r.nextInt(6) + 1;
final int playerTotal = i + y; final int playerTotal = i + y;
bot.send(bot.getChannel(), bot.send(bot.getChannel(),
sender + " rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils sender + " rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils
.bold(playerTotal)); .bold(playerTotal));
i = r.nextInt(6) + 1; i = r.nextInt(6) + 1;
y = r.nextInt(6) + 1; y = r.nextInt(6) + 1;
final int total = i + y; final int total = i + y;
bot.action( bot.action(
"rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils.bold(total)); "rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils.bold(total));
if (playerTotal < total) if (playerTotal < total) {
{ bot.action("wins.");
bot.action("wins."); } else if (playerTotal > total) {
} bot.action("lost.");
else if (playerTotal > total) } else {
{ bot.action("tied.");
bot.action("lost."); }
} }
else
{
bot.action("tied.");
}
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To roll the dice:");
bot.send(sender, "To roll the dice:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + DICE_CMD));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + DICE_CMD)); }
}
@Override @Override
public boolean isEnabled() public boolean isEnabled() {
{ return true;
return true; }
}
} }

View file

@ -49,121 +49,100 @@ import java.net.URLEncoder;
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */
final public class GoogleSearch extends AbstractModule final public class GoogleSearch extends AbstractModule {
{ /**
/** * The Google API Key property.
* The Google API Key property. */
*/ private static final String GOOGLE_API_KEY_PROP = "google-api-key";
private static final String GOOGLE_API_KEY_PROP = "google-api-key";
/** /**
* The google command. * The google command.
*/ */
private static final String GOOGLE_CMD = "google"; private static final String GOOGLE_CMD = "google";
/** /**
* The Google Custom Search Engine ID property. * The Google Custom Search Engine ID property.
*/ */
private static final String GOOGLE_CSE_KEY_PROP = "google-cse-cx"; private static final String GOOGLE_CSE_KEY_PROP = "google-cse-cx";
/** /**
* The tab indent (4 spaces). * The tab indent (4 spaces).
*/ */
private static final String TAB_INDENT = " "; private static final String TAB_INDENT = " ";
/** /**
* Creates a new {@link GoogleSearch} instance. * Creates a new {@link GoogleSearch} instance.
*/ */
public GoogleSearch() public GoogleSearch() {
{ commands.add(GOOGLE_CMD);
commands.add(GOOGLE_CMD); properties.put(GOOGLE_API_KEY_PROP, "");
properties.put(GOOGLE_API_KEY_PROP, ""); properties.put(GOOGLE_CSE_KEY_PROP, "");
properties.put(GOOGLE_CSE_KEY_PROP, ""); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ if (isEnabled() && args.length() > 0) {
if (isEnabled() && args.length() > 0) if (args.length() > 0) {
{ new Thread(() -> run(bot, sender, args)).start();
if (args.length() > 0) } else {
{ helpResponse(bot, sender, args, isPrivate);
new Thread(() -> run(bot, sender, args)).start(); }
} } else {
else helpResponse(bot, sender, args, isPrivate);
{ }
helpResponse(bot, sender, args, isPrivate); }
}
}
else
{
helpResponse(bot, sender, args, isPrivate);
}
}
/** @Override
* Searches Google. public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
*/ if (isEnabled()) {
private void run(final Mobibot bot, final String sender, final String query) bot.send(sender, "To search Google:");
{ bot.send(sender, bot.helpIndent(bot.getNick() + ": " + GOOGLE_CMD + " <query>"));
try } else {
{ bot.send(sender, "The Google searching facility is disabled.");
final String q = URLEncoder.encode(query, "UTF-8"); }
}
final URL url = @Override
new URL("https://www.googleapis.com/customsearch/v1?key=" public boolean isEnabled() {
+ properties.get(GOOGLE_API_KEY_PROP) return isValidProperties();
+ "&cx=" }
+ properties.get(GOOGLE_CSE_KEY_PROP)
+ "&q="
+ q
+ "&filter=1&num=5&alt=json");
final URLConnection conn = url.openConnection();
final StringBuilder sb = new StringBuilder(); /**
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) * Searches Google.
{ */
String line; private void run(final Mobibot bot, final String sender, final String query) {
while ((line = reader.readLine()) != null) try {
{ final String q = URLEncoder.encode(query, "UTF-8");
sb.append(line);
}
final JSONObject json = new JSONObject(sb.toString()); final URL url =
final JSONArray ja = json.getJSONArray("items"); new URL("https://www.googleapis.com/customsearch/v1?key="
+ properties.get(GOOGLE_API_KEY_PROP)
+ "&cx="
+ properties.get(GOOGLE_CSE_KEY_PROP)
+ "&q="
+ q
+ "&filter=1&num=5&alt=json");
final URLConnection conn = url.openConnection();
for (int i = 0; i < ja.length(); i++) final StringBuilder sb = new StringBuilder();
{ try (final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
final JSONObject j = ja.getJSONObject(i); String line;
bot.send(sender, Utils.unescapeXml(j.getString("title"))); while ((line = reader.readLine()) != null) {
bot.send(sender, TAB_INDENT + Utils.green(j.getString("link"))); sb.append(line);
} }
}
}
catch (Exception e)
{
bot.getLogger().warn("Unable to search in Google for: " + query, e);
bot.send(sender, "An error has occurred searching in Google: " + e.getMessage());
}
}
@Override final JSONObject json = new JSONObject(sb.toString());
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) final JSONArray ja = json.getJSONArray("items");
{
if (isEnabled())
{
bot.send(sender, "To search Google:");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + GOOGLE_CMD + " <query>"));
}
else
{
bot.send(sender, "The Google searching facility is disabled.");
}
}
@Override for (int i = 0; i < ja.length(); i++) {
public boolean isEnabled() final JSONObject j = ja.getJSONObject(i);
{ bot.send(sender, Utils.unescapeXml(j.getString("title")));
return isValidProperties(); bot.send(sender, TAB_INDENT + Utils.green(j.getString("link")));
} }
}
} catch (Exception e) {
bot.getLogger().warn("Unable to search in Google for: " + query, e);
bot.send(sender, "An error has occurred searching in Google: " + e.getMessage());
}
}
} }

View file

@ -47,73 +47,62 @@ import java.net.URLConnection;
* @created 2014-04-20 * @created 2014-04-20
* @since 1.0 * @since 1.0
*/ */
final public class Joke extends AbstractModule final public class Joke extends AbstractModule {
{ /**
* The joke command.
*/
private static final String JOKE_CMD = "joke";
/** /**
* The joke command. * The ICNDB URL.
*/ */
private static final String JOKE_CMD = "joke"; private static final String JOKE_URL =
"http://api.icndb.com/jokes/random?escape=javascript&exclude=[explicit]&limitTo=[nerdy]";
/** /**
* The ICNDB URL. * Creates a new {@link Joke} instance.
*/ */
private static final String JOKE_URL = public Joke() {
"http://api.icndb.com/jokes/random?escape=javascript&exclude=[explicit]&limitTo=[nerdy]"; commands.add(JOKE_CMD);
}
/** @Override
* Creates a new {@link Joke} instance. public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
*/ new Thread(() -> run(bot, sender)).start();
public Joke() }
{
commands.add(JOKE_CMD);
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To retrieve a random joke:");
new Thread(() -> run(bot, sender)).start(); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + JOKE_CMD));
} }
@Override /**
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) * Returns a random joke from <a href="http://www.icndb.com/">The Internet Chuck Norris Database</a>
{ */
bot.send(sender, "To retrieve a random joke:"); private void run(final Mobibot bot, final String sender) {
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + JOKE_CMD)); try {
} final URL url = new URL(JOKE_URL);
final URLConnection conn = url.openConnection();
/** final StringBuilder sb = new StringBuilder();
* Returns a random joke from <a href="http://www.icndb.com/">The Internet Chuck Norris Database</a> try (final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
*/ String line;
private void run(final Mobibot bot, final String sender) while ((line = reader.readLine()) != null) {
{ sb.append(line);
try }
{
final URL url = new URL(JOKE_URL);
final URLConnection conn = url.openConnection();
final StringBuilder sb = new StringBuilder(); final JSONObject json = new JSONObject(sb.toString());
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream())))
{
String line;
while ((line = reader.readLine()) != null)
{
sb.append(line);
}
final JSONObject json = new JSONObject(sb.toString()); bot.send(bot.getChannel(),
Colors.CYAN
bot.send(bot.getChannel(), + json.getJSONObject("value").get("joke").toString().replaceAll("\\'", "'")
Colors.CYAN .replaceAll("\\\"", "\"")
+ json.getJSONObject("value").get("joke").toString().replaceAll("\\'", "'") + Colors.NORMAL);
.replaceAll("\\\"", "\"") }
+ Colors.NORMAL); } catch (Exception e) {
} bot.getLogger().warn("Unable to retrieve random joke.", e);
} bot.send(sender, "An error has occurred retrieving a random joke: " + e.getMessage());
catch (Exception e) }
{ }
bot.getLogger().warn("Unable to retrieve random joke.", e);
bot.send(sender, "An error has occurred retrieving a random joke: " + e.getMessage());
}
}
} }

View file

@ -45,190 +45,151 @@ import java.net.UnknownHostException;
* @created 2014-04-26 * @created 2014-04-26
* @since 1.0 * @since 1.0
*/ */
final public class Lookup extends AbstractModule final public class Lookup extends AbstractModule {
{ /**
/** * THe lookup command.
* THe lookup command. */
*/ private static final String LOOKUP_CMD = "lookup";
private static final String LOOKUP_CMD = "lookup";
/** /**
* The whois host. * The whois host.
*/ */
private static final String WHOIS_HOST = "whois.arin.net"; private static final String WHOIS_HOST = "whois.arin.net";
/** /**
* The default constructor * The default constructor
*/ */
public Lookup() public Lookup() {
{ commands.add(LOOKUP_CMD);
commands.add(LOOKUP_CMD); }
}
/** /**
* Process a command. * Performs a DNS lookup on the specified query.
* *
* @param bot The bot's instance. * @param query The IP address or hostname.
* @param sender The sender. * @return The lookup query result string.
* @param args The command arguments. * @throws java.net.UnknownHostException If the host is unknown.
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. */
*/ private static String lookup(final String query)
@Override throws UnknownHostException {
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) final StringBuilder buffer = new StringBuilder("");
{
if (args.matches("(\\S.)+(\\S)+"))
{
try
{
bot.send(bot.getChannel(), Lookup.lookup(args));
}
catch (UnknownHostException ignore)
{
if (args.matches(
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"))
{
try
{
final String[] lines = Lookup.whois(args);
if ((lines != null) && (lines.length > 0)) final InetAddress[] results = InetAddress.getAllByName(query);
{ String hostInfo;
String line;
for (final String rawLine : lines) for (final InetAddress result : results) {
{ if (result.getHostAddress().equals(query)) {
line = rawLine.trim(); hostInfo = result.getHostName();
if ((line.length() > 0) && (line.charAt(0) != '#')) if (hostInfo.equals(query)) {
{ throw new UnknownHostException();
bot.send(bot.getChannel(), line); }
} } else {
} hostInfo = result.getHostAddress();
} }
else
{
bot.send(bot.getChannel(), "Unknown host.");
}
}
catch (IOException ioe)
{
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Unable to perform whois IP lookup: " + args, ioe);
}
bot.send(bot.getChannel(), "Unable to perform whois IP lookup: " + ioe.getMessage()); if (buffer.length() > 0) {
} buffer.append(", ");
} }
else
{
bot.send(bot.getChannel(), "Unknown host.");
}
}
}
else
{
helpResponse(bot, sender, args, true);
}
}
/** buffer.append(hostInfo);
* Performs a DNS lookup on the specified query. }
*
* @param query The IP address or hostname.
*
* @return The lookup query result string.
*
* @throws java.net.UnknownHostException If the host is unknown.
*/
private static String lookup(final String query)
throws UnknownHostException
{
final StringBuilder buffer = new StringBuilder("");
final InetAddress[] results = InetAddress.getAllByName(query); return buffer.toString();
String hostInfo; }
for (final InetAddress result : results) /**
{ * Performs a whois IP query.
if (result.getHostAddress().equals(query)) *
{ * @param query The IP address.
hostInfo = result.getHostName(); * @return The IP whois data, if any.
* @throws java.io.IOException If a connection error occurs.
*/
private static String[] whois(final String query)
throws IOException {
return whois(query, WHOIS_HOST);
}
if (hostInfo.equals(query)) /**
{ * Performs a whois IP query.
throw new UnknownHostException(); *
} * @param query The IP address.
} * @param host The whois host.
else * @return The IP whois data, if any.
{ * @throws java.io.IOException If a connection error occurs.
hostInfo = result.getHostAddress(); */
} @SuppressWarnings("WeakerAccess, SameParameterValue")
public static String[] whois(final String query, final String host)
throws IOException {
final WhoisClient whois = new WhoisClient();
String[] lines;
if (buffer.length() > 0) try {
{ whois.setDefaultTimeout(Mobibot.CONNECT_TIMEOUT);
buffer.append(", "); whois.connect(host);
} whois.setSoTimeout(Mobibot.CONNECT_TIMEOUT);
whois.setSoLinger(false, 0);
buffer.append(hostInfo); lines = whois.query('-' + query).split("\n");
} } finally {
whois.disconnect();
}
return buffer.toString(); return lines;
} }
/** /**
* Performs a whois IP query. * Process a command.
* *
* @param query The IP address. * @param bot The bot's instance.
* * @param sender The sender.
* @return The IP whois data, if any. * @param args The command arguments.
* * @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
* @throws java.io.IOException If a connection error occurs. */
*/ @Override
private static String[] whois(final String query) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
throws IOException if (args.matches("(\\S.)+(\\S)+")) {
{ try {
return whois(query, WHOIS_HOST); bot.send(bot.getChannel(), Lookup.lookup(args));
} } catch (UnknownHostException ignore) {
if (args.matches(
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\." +
"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)")) {
try {
final String[] lines = Lookup.whois(args);
/** if ((lines != null) && (lines.length > 0)) {
* Performs a whois IP query. String line;
*
* @param query The IP address.
* @param host The whois host.
*
* @return The IP whois data, if any.
*
* @throws java.io.IOException If a connection error occurs.
*/
@SuppressWarnings("WeakerAccess, SameParameterValue")
public static String[] whois(final String query, final String host)
throws IOException
{
final WhoisClient whois = new WhoisClient();
String[] lines;
try for (final String rawLine : lines) {
{ line = rawLine.trim();
whois.setDefaultTimeout(Mobibot.CONNECT_TIMEOUT);
whois.connect(host);
whois.setSoTimeout(Mobibot.CONNECT_TIMEOUT);
whois.setSoLinger(false, 0);
lines = whois.query('-' + query).split("\n"); if ((line.length() > 0) && (line.charAt(0) != '#')) {
} bot.send(bot.getChannel(), line);
finally }
{ }
whois.disconnect(); } else {
} bot.send(bot.getChannel(), "Unknown host.");
}
} catch (IOException ioe) {
if (bot.getLogger().isDebugEnabled()) {
bot.getLogger().debug("Unable to perform whois IP lookup: " + args, ioe);
}
return lines; bot.send(bot.getChannel(), "Unable to perform whois IP lookup: " + ioe.getMessage());
} }
} else {
bot.send(bot.getChannel(), "Unknown host.");
}
}
} else {
helpResponse(bot, sender, args, true);
}
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To perform a DNS lookup query:");
bot.send(sender, "To perform a DNS lookup query:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + LOOKUP_CMD + " <ip address or hostname>"));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + LOOKUP_CMD + " <ip address or hostname>")); }
}
} }

View file

@ -44,49 +44,47 @@ import java.util.Random;
* @created 2016-07-02 * @created 2016-07-02
* @since 1.0 * @since 1.0
*/ */
public class Ping extends AbstractModule public class Ping extends AbstractModule {
{ /**
/** * The ping responses.
* The ping responses. */
*/ private static final List<String> PINGS =
private static final List<String> PINGS = Arrays.asList("is barely alive.", Arrays.asList(
"is trying to stay awake.", "is barely alive.",
"has gone fishing.", "is trying to stay awake.",
"is somewhere over the rainbow.", "has gone fishing.",
"has fallen and can't get up.", "is somewhere over the rainbow.",
"is running. You better go chase it.", "has fallen and can't get up.",
"has just spontaneously combusted.", "is running. You better go chase it.",
"is talking to itself... don't interrupt. That's rude.", "has just spontaneously combusted.",
"is bartending at an AA meeting.", "is talking to itself... don't interrupt. That's rude.",
"is hibernating.", "is bartending at an AA meeting.",
"is saving energy: apathetic mode activated.", "is hibernating.",
"is busy. Go away!"); "is saving energy: apathetic mode activated.",
"is busy. Go away!");
/** /**
* The ping command. * The ping command.
*/ */
private static final String PING_CMD = "ping"; private static final String PING_CMD = "ping";
/** /**
* The default constructor. * The default constructor.
*/ */
public Ping() public Ping() {
{ commands.add(PING_CMD);
commands.add(PING_CMD); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ final Random r = new Random();
final Random r = new Random();
bot.action(PINGS.get(r.nextInt(PINGS.size()))); bot.action(PINGS.get(r.nextInt(PINGS.size())));
} }
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To ping the bot:");
bot.send(sender, "To ping the bot:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + PING_CMD));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + PING_CMD)); }
}
} }

View file

@ -45,120 +45,93 @@ import java.io.IOException;
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */
final public class StockQuote extends AbstractModule final public class StockQuote extends AbstractModule {
{ /**
/** * The quote command.
* The quote command. */
*/ private static final String STOCK_CMD = "stock";
private static final String STOCK_CMD = "stock";
/** /**
* The Yahoo! stock quote URL. * The Yahoo! stock quote URL.
*/ */
private static final String YAHOO_URL = "http://finance.yahoo.com/d/quotes.csv?&f=snl1d1t1c1oghv&e=.csv&s="; private static final String YAHOO_URL = "http://finance.yahoo.com/d/quotes.csv?&f=snl1d1t1c1oghv&e=.csv&s=";
/** /**
* Creates a new {@link StockQuote} instance. * Creates a new {@link StockQuote} instance.
*/ */
public StockQuote() public StockQuote() {
{ commands.add(STOCK_CMD);
commands.add(STOCK_CMD); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ if (args.length() > 0) {
if (args.length() > 0) new Thread(() -> run(bot, sender, args)).start();
{ } else {
new Thread(() -> run(bot, sender, args)).start(); helpResponse(bot, sender, args, isPrivate);
} }
else }
{
helpResponse(bot, sender, args, isPrivate);
}
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To retrieve a stock quote:");
bot.send(sender, "To retrieve a stock quote:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + STOCK_CMD + " <symbol[.country code]>"));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + STOCK_CMD + " <symbol[.country code]>")); }
}
/** /**
* Returns the specified stock quote from Yahoo! * Returns the specified stock quote from Yahoo!
*/ */
private void run(final Mobibot bot, final String sender, final String symbol) private void run(final Mobibot bot, final String sender, final String symbol) {
{ try {
try final HttpClient client = new HttpClient();
{ client.getHttpConnectionManager().getParams().setConnectionTimeout(Mobibot.CONNECT_TIMEOUT);
final HttpClient client = new HttpClient(); client.getHttpConnectionManager().getParams().setSoTimeout(Mobibot.CONNECT_TIMEOUT);
client.getHttpConnectionManager().getParams().setConnectionTimeout(Mobibot.CONNECT_TIMEOUT);
client.getHttpConnectionManager().getParams().setSoTimeout(Mobibot.CONNECT_TIMEOUT);
final GetMethod getMethod = new GetMethod(YAHOO_URL + symbol.toUpperCase()); final GetMethod getMethod = new GetMethod(YAHOO_URL + symbol.toUpperCase());
client.executeMethod(getMethod); client.executeMethod(getMethod);
final String[][] lines = CSVParser.parse(getMethod.getResponseBodyAsString()); final String[][] lines = CSVParser.parse(getMethod.getResponseBodyAsString());
if (lines.length > 0) if (lines.length > 0) {
{ final String[] quote = lines[0];
final String[] quote = lines[0];
if (quote.length > 0) if (quote.length > 0) {
{ if ((quote.length > 3) && (!"N/A".equalsIgnoreCase(quote[3]))) {
if ((quote.length > 3) && (!"N/A".equalsIgnoreCase(quote[3]))) bot.send(bot.getChannel(), "Symbol: " + quote[0] + " [" + quote[1] + ']');
{
bot.send(bot.getChannel(), "Symbol: " + quote[0] + " [" + quote[1] + ']');
if (quote.length > 5) if (quote.length > 5) {
{ bot.send(bot.getChannel(), "Last Trade: " + quote[2] + " (" + quote[5] + ')');
bot.send(bot.getChannel(), "Last Trade: " + quote[2] + " (" + quote[5] + ')'); } else {
} bot.send(bot.getChannel(), "Last Trade: " + quote[2]);
else }
{
bot.send(bot.getChannel(), "Last Trade: " + quote[2]);
}
if (quote.length > 4) if (quote.length > 4) {
{ bot.send(sender, "Time: " + quote[3] + ' ' + quote[4]);
bot.send(sender, "Time: " + quote[3] + ' ' + quote[4]); }
}
if (quote.length > 6 && !"N/A".equalsIgnoreCase(quote[6])) if (quote.length > 6 && !"N/A".equalsIgnoreCase(quote[6])) {
{ bot.send(sender, "Open: " + quote[6]);
bot.send(sender, "Open: " + quote[6]); }
}
if (quote.length > 7 && !"N/A".equalsIgnoreCase(quote[7]) && !"N/A".equalsIgnoreCase(quote[8])) if (quote.length > 7 && !"N/A".equalsIgnoreCase(quote[7]) && !"N/A".equalsIgnoreCase(quote[8])) {
{ bot.send(sender, "Day's Range: " + quote[7] + " - " + quote[8]);
bot.send(sender, "Day's Range: " + quote[7] + " - " + quote[8]); }
}
if (quote.length > 9 && !"0".equalsIgnoreCase(quote[9])) if (quote.length > 9 && !"0".equalsIgnoreCase(quote[9])) {
{ bot.send(sender, "Volume: " + quote[9]);
bot.send(sender, "Volume: " + quote[9]); }
} } else {
} bot.send(sender, "Invalid ticker symbol.");
else }
{ } else {
bot.send(sender, "Invalid ticker symbol."); bot.send(sender, "No values returned.");
} }
} } else {
else bot.send(sender, "No data returned.");
{ }
bot.send(sender, "No values returned."); } catch (IOException e) {
} bot.getLogger().debug("Unable to retrieve stock quote for: " + symbol, e);
} bot.send(sender, "An error has occurred retrieving a stock quote: " + e.getMessage());
else }
{ }
bot.send(sender, "No data returned.");
}
}
catch (IOException e)
{
bot.getLogger().debug("Unable to retrieve stock quote for: " + symbol, e);
bot.send(sender, "An error has occurred retrieving a stock quote: " + e.getMessage());
}
}
} }

View file

@ -43,92 +43,74 @@ import twitter4j.conf.ConfigurationBuilder;
* @created Sept 10, 2008 * @created Sept 10, 2008
* @since 1.0 * @since 1.0
*/ */
final public class Twitter extends AbstractModule final public class Twitter extends AbstractModule {
{ private final static String CONSUMER_KEY_PROP = "twitter-consumerKey";
private final static String CONSUMER_KEY_PROP = "twitter-consumerKey"; private final static String CONSUMER_SECRET_PROP = "twitter-consumerSecret";
private final static String TOKEN_PROP = "twitter-token";
private final static String TOKEN_SECRET_PROP = "twitter-tokenSecret";
private final static String CONSUMER_SECRET_PROP = "twitter-consumerSecret"; /**
* The twitter command.
*/
private final static String TWITTER_CMD = "twitter";
private final static String TOKEN_PROP = "twitter-token"; /**
* Creates a new {@link Twitter} instance.
*/
public Twitter() {
commands.add(TWITTER_CMD);
properties.put(CONSUMER_SECRET_PROP, "");
properties.put(CONSUMER_KEY_PROP, "");
properties.put(TOKEN_PROP, "");
properties.put(TOKEN_SECRET_PROP, "");
}
private final static String TOKEN_SECRET_PROP = "twitter-tokenSecret"; @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
if (isEnabled() && args.length() > 0) {
new Thread(() -> run(bot, sender, args)).start();
} else {
helpResponse(bot, sender, args, isPrivate);
}
}
/** @Override
* The twitter command. public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
*/ if (isEnabled()) {
private final static String TWITTER_CMD = "twitter"; bot.send(sender, "To post to Twitter:");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TWITTER_CMD + " <message>"));
} else {
bot.send(sender, "The Twitter posting facility is disabled.");
}
}
/** @Override
* Creates a new {@link Twitter} instance. public boolean isEnabled() {
*/ return isValidProperties();
public Twitter() }
{
commands.add(TWITTER_CMD);
properties.put(CONSUMER_SECRET_PROP, "");
properties.put(CONSUMER_KEY_PROP, "");
properties.put(TOKEN_PROP, "");
properties.put(TOKEN_SECRET_PROP, "");
}
@Override /**
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) * Posts to twitter.
{ */
if (isEnabled() && args.length() > 0) private void run(final Mobibot bot, final String sender, final String message) {
{ try {
new Thread(() -> run(bot, sender, args)).start(); final ConfigurationBuilder cb = new ConfigurationBuilder();
} cb.setDebugEnabled(true)
else .setOAuthConsumerKey(properties.get(CONSUMER_KEY_PROP))
{ .setOAuthConsumerSecret(properties.get(CONSUMER_SECRET_PROP))
helpResponse(bot, sender, args, isPrivate); .setOAuthAccessToken(properties.get(TOKEN_PROP))
} .setOAuthAccessTokenSecret(properties.get(TOKEN_SECRET_PROP));
} final TwitterFactory tf = new TwitterFactory(cb.build());
final twitter4j.Twitter twitter = tf.getInstance();
@Override final Status status = twitter.updateStatus(message + " (" + sender + ')');
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate)
{
if (isEnabled())
{
bot.send(sender, "To post to Twitter:");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TWITTER_CMD + " <message>"));
}
else
{
bot.send(sender, "The Twitter posting facility is disabled.");
}
}
@Override bot.send(sender,
public boolean isEnabled() "You message was posted to http://twitter.com/" + twitter.getScreenName() + "/statuses/" + status
{ .getId());
return isValidProperties(); } catch (Exception e) {
} bot.getLogger().warn("Unable to post to Twitter: " + message, e);
bot.send(sender, "An error has occurred: " + e.getMessage());
/** }
* Posts to twitter. }
*/
private void run(final Mobibot bot, final String sender, final String message)
{
try
{
final ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true)
.setOAuthConsumerKey(properties.get(CONSUMER_KEY_PROP))
.setOAuthConsumerSecret(properties.get(CONSUMER_SECRET_PROP))
.setOAuthAccessToken(properties.get(TOKEN_PROP))
.setOAuthAccessTokenSecret(properties.get(TOKEN_SECRET_PROP));
final TwitterFactory tf = new TwitterFactory(cb.build());
final twitter4j.Twitter twitter = tf.getInstance();
final Status status = twitter.updateStatus(message + " (" + sender + ')');
bot.send(sender,
"You message was posted to http://twitter.com/" + twitter.getScreenName() + "/statuses/" + status
.getId());
}
catch (Exception e)
{
bot.getLogger().warn("Unable to post to Twitter: " + message, e);
bot.send(sender, "An error has occurred: " + e.getMessage());
}
}
} }

View file

@ -43,79 +43,70 @@ import java.util.Random;
* @created 2014-04-28 * @created 2014-04-28
* @since 1.0 * @since 1.0
*/ */
final public class War extends AbstractModule final public class War extends AbstractModule {
{ /**
/** * The war command.
* The war command. */
*/ private static final String WAR_CMD = "war";
private static final String WAR_CMD = "war";
/** /**
* The deck of card. * The deck of card.
*/ */
private static final String[] WAR_DECK = private static final String[] WAR_DECK =
new String[]{"Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"}; new String[]{"Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"};
/** /**
* The suits for the deck of card. * The suits for the deck of card.
*/ */
private static final String[] WAR_SUITS = new String[]{"Hearts", "Spades", "Diamonds", "Clubs"}; private static final String[] WAR_SUITS = new String[]{"Hearts", "Spades", "Diamonds", "Clubs"};
/** /**
* The default constructor. * The default constructor.
*/ */
public War() public War() {
{ commands.add(WAR_CMD);
commands.add(WAR_CMD); }
}
/** /**
* Plays war. * Plays war.
* *
* @param bot The bot's instance. * @param bot The bot's instance.
* @param sender The sender. * @param sender The sender.
* @param args The command arguments. * @param args The command arguments.
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. * @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
*/ */
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ final Random r = new Random();
final Random r = new Random();
int i; int i;
int y; int y;
while (true) while (true) {
{ i = r.nextInt(WAR_DECK.length);
i = r.nextInt(WAR_DECK.length); y = r.nextInt(WAR_DECK.length);
y = r.nextInt(WAR_DECK.length);
bot.send(bot.getChannel(), bot.send(bot.getChannel(),
sender + " drew the " + Utils.bold(WAR_DECK[i]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]); sender + " drew the " + Utils.bold(WAR_DECK[i]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
bot.action("drew the " + Utils.bold(WAR_DECK[y]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]); bot.action("drew the " + Utils.bold(WAR_DECK[y]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
if (i != y) if (i != y) {
{ break;
break; }
}
bot.send(bot.getChannel(), "This means " + Utils.bold("WAR") + '!'); bot.send(bot.getChannel(), "This means " + Utils.bold("WAR") + '!');
} }
if (i < y) if (i < y) {
{ bot.action("lost.");
bot.action("lost."); } else if (i > y) {
} bot.action("wins.");
else if (i > y) }
{ }
bot.action("wins.");
}
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To play war:");
bot.send(sender, "To play war:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + WAR_CMD));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + WAR_CMD)); }
}
} }

View file

@ -47,145 +47,127 @@ import java.util.Date;
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */
final public class Weather extends AbstractModule final public class Weather extends AbstractModule {
{ /**
/** * The decimal number format.
* The decimal number format. */
*/ private static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("0.##");
private static final DecimalFormat NUMBER_FORMAT = new DecimalFormat("0.##");
/** /**
* The URL where the stations are listed. * The URL where the stations are listed.
*/ */
private static final String STATIONS_URL = "http://www.rap.ucar.edu/weather/surface/stations.txt"; private static final String STATIONS_URL = "http://www.rap.ucar.edu/weather/surface/stations.txt";
/** /**
* THe weather command. * THe weather command.
*/ */
private static final String WEATHER_CMD = "weather"; private static final String WEATHER_CMD = "weather";
/** /**
* Creates a new {@link Weather} instance. * Creates a new {@link Weather} instance.
*/ */
public Weather() public Weather() {
{ commands.add(WEATHER_CMD);
commands.add(WEATHER_CMD); }
}
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ new Thread(() -> run(bot, sender, args.toUpperCase(), isPrivate)).start();
new Thread(() -> run(bot, sender, args.toUpperCase(), isPrivate)).start(); }
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To display weather information:");
bot.send(sender, "To display weather information:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + WEATHER_CMD + " <station id>"));
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + WEATHER_CMD + " <station id>")); bot.send(sender, "For a listing of the ICAO station IDs, please visit: " + STATIONS_URL);
bot.send(sender, "For a listing of the ICAO station IDs, please visit: " + STATIONS_URL); }
}
@Override @Override
public boolean isPrivateMsgEnabled() public boolean isPrivateMsgEnabled() {
{ return true;
return true; }
}
/** /**
* Fetches the weather data from a specific station ID. * Fetches the weather data from a specific station ID.
*/ */
private void run(final Mobibot bot, final String sender, final String station, final boolean isPrivate) private void run(final Mobibot bot, final String sender, final String station, final boolean isPrivate) {
{ if (station.length() == 4) {
if (station.length() == 4) final Metar metar = net.sf.jweather.Weather.getMetar(station);
{
final Metar metar = net.sf.jweather.Weather.getMetar(station);
if (metar != null) if (metar != null) {
{ Float result;
Float result;
bot.send(sender, "Station ID: " + metar.getStationID(), isPrivate); bot.send(sender, "Station ID: " + metar.getStationID(), isPrivate);
bot.send(sender, bot.send(sender,
"At: " "At: "
+ Utils.UTC_SDF.format(metar.getDate()) + Utils.UTC_SDF.format(metar.getDate())
+ " UTC (" + " UTC ("
+ (((new Date()).getTime() - metar.getDate().getTime()) / 1000L / 60L) + (((new Date()).getTime() - metar.getDate().getTime()) / 1000L / 60L)
+ " minutes ago)", + " minutes ago)",
isPrivate); isPrivate);
result = metar.getWindSpeedInMPH(); result = metar.getWindSpeedInMPH();
if (result != null) if (result != null) {
{ bot.send(sender,
bot.send(sender, "Wind Speed: "
"Wind Speed: " + result
+ result + " mph, "
+ " mph, " + metar.getWindSpeedInKnots()
+ metar.getWindSpeedInKnots() + " knots, "
+ " knots, " + metar.getWindSpeedInMPS()
+ metar.getWindSpeedInMPS() + " m/s",
+ " m/s", isPrivate);
isPrivate); }
}
result = metar.getVisibility(); result = metar.getVisibility();
if (result != null) if (result != null) {
{ bot.send(sender,
bot.send(sender, "Visibility: "
"Visibility: " + (metar.getVisibilityLessThan() ? "< " : "")
+ (metar.getVisibilityLessThan() ? "< " : "") + NUMBER_FORMAT.format(result)
+ NUMBER_FORMAT.format(result) + " mi, " + metar.getVisibilityInKilometers() + " km",
+ " mi, " + metar.getVisibilityInKilometers() + " km", isPrivate);
isPrivate); }
}
result = metar.getPressure(); result = metar.getPressure();
if (result != null) if (result != null) {
{ bot.send(sender,
bot.send(sender, "Pressure: " + result + " Hg, " + metar.getPressureInHectoPascals() + " hPa",
"Pressure: " + result + " Hg, " + metar.getPressureInHectoPascals() + " hPa", isPrivate);
isPrivate); }
}
result = metar.getTemperatureInCelsius(); result = metar.getTemperatureInCelsius();
if (result != null) if (result != null) {
{ bot.send(sender,
bot.send(sender, "Temperature: " + result + " \u00B0C, " + metar.getTemperatureInFahrenheit() + " \u00B0F",
"Temperature: " + result + " \u00B0C, " + metar.getTemperatureInFahrenheit() + " \u00B0F", isPrivate);
isPrivate); }
}
if (metar.getWeatherConditions() != null) if (metar.getWeatherConditions() != null) {
{ for (final Object weatherCondition : metar.getWeatherConditions()) {
for (final Object weatherCondition : metar.getWeatherConditions()) bot.send(sender, ((WeatherCondition) weatherCondition).getNaturalLanguageString(), isPrivate);
{ }
bot.send(sender, ((WeatherCondition) weatherCondition).getNaturalLanguageString(), isPrivate); }
}
}
if (metar.getSkyConditions() != null) if (metar.getSkyConditions() != null) {
{ for (final Object skyCondition : metar.getSkyConditions()) {
for (final Object skyCondition : metar.getSkyConditions()) bot.send(sender, ((SkyCondition) skyCondition).getNaturalLanguageString(), isPrivate);
{ }
bot.send(sender, ((SkyCondition) skyCondition).getNaturalLanguageString(), isPrivate); }
}
}
return; return;
} } else {
else bot.send(sender, "Invalid Station ID. Please try again.", isPrivate);
{
bot.send(sender, "Invalid Station ID. Please try again.", isPrivate);
return; return;
} }
} }
helpResponse(bot, sender, station, isPrivate); helpResponse(bot, sender, station, isPrivate);
} }
} }

View file

@ -46,210 +46,184 @@ import java.util.TreeMap;
* @created 2014-04-27 * @created 2014-04-27
* @since 1.0 * @since 1.0
*/ */
final public class WorldTime extends AbstractModule final public class WorldTime extends AbstractModule {
{ /**
/** * The beats (Internet Time) keyword.
* The beats (Internet Time) keyword. */
*/ private static final String BEATS_KEYWORD = ".beats";
private static final String BEATS_KEYWORD = ".beats";
/** /**
* The supported countries. * The supported countries.
*/ */
private static final Map<String, String> COUNTRIES_MAP = new TreeMap<>(); private static final Map<String, String> COUNTRIES_MAP = new TreeMap<>();
/** /**
* The time command. * The time command.
*/ */
private static final String TIME_CMD = "time"; private static final String TIME_CMD = "time";
/** /**
* The date/time format. * The date/time format.
*/ */
private static final SimpleDateFormat TIME_SDF = private static final SimpleDateFormat TIME_SDF =
new SimpleDateFormat("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '"); new SimpleDateFormat("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '");
/** /**
* Creates a new {@link WorldTime} instance. * Creates a new {@link WorldTime} instance.
*/ */
public WorldTime() public WorldTime() {
{ commands.add(TIME_CMD);
commands.add(TIME_CMD);
// Initialize the countries map // Initialize the countries map
COUNTRIES_MAP.put("AU", "Australia/Sydney"); COUNTRIES_MAP.put("AU", "Australia/Sydney");
COUNTRIES_MAP.put("BE", "Europe/Brussels"); COUNTRIES_MAP.put("BE", "Europe/Brussels");
COUNTRIES_MAP.put("CA", "America/Montreal"); COUNTRIES_MAP.put("CA", "America/Montreal");
COUNTRIES_MAP.put("CDT", "America/Chicago"); COUNTRIES_MAP.put("CDT", "America/Chicago");
COUNTRIES_MAP.put("CET", "CET"); COUNTRIES_MAP.put("CET", "CET");
COUNTRIES_MAP.put("CH", "Europe/Zurich"); COUNTRIES_MAP.put("CH", "Europe/Zurich");
COUNTRIES_MAP.put("CN", "Asia/Shanghai"); COUNTRIES_MAP.put("CN", "Asia/Shanghai");
COUNTRIES_MAP.put("CST", "America/Chicago"); COUNTRIES_MAP.put("CST", "America/Chicago");
COUNTRIES_MAP.put("CU", "Cuba"); COUNTRIES_MAP.put("CU", "Cuba");
COUNTRIES_MAP.put("DE", "Europe/Berlin"); COUNTRIES_MAP.put("DE", "Europe/Berlin");
COUNTRIES_MAP.put("DK", "Europe/Copenhagen"); COUNTRIES_MAP.put("DK", "Europe/Copenhagen");
COUNTRIES_MAP.put("EDT", "America/New_York"); COUNTRIES_MAP.put("EDT", "America/New_York");
COUNTRIES_MAP.put("EG", "Africa/Cairo"); COUNTRIES_MAP.put("EG", "Africa/Cairo");
COUNTRIES_MAP.put("ER", "Africa/Asmara"); COUNTRIES_MAP.put("ER", "Africa/Asmara");
COUNTRIES_MAP.put("ES", "Europe/Madrid"); COUNTRIES_MAP.put("ES", "Europe/Madrid");
COUNTRIES_MAP.put("EST", "America/New_York"); COUNTRIES_MAP.put("EST", "America/New_York");
COUNTRIES_MAP.put("FI", "Europe/Helsinki"); COUNTRIES_MAP.put("FI", "Europe/Helsinki");
COUNTRIES_MAP.put("FR", "Europe/Paris"); COUNTRIES_MAP.put("FR", "Europe/Paris");
COUNTRIES_MAP.put("GB", "Europe/London"); COUNTRIES_MAP.put("GB", "Europe/London");
COUNTRIES_MAP.put("GMT", "GMT"); COUNTRIES_MAP.put("GMT", "GMT");
COUNTRIES_MAP.put("HK", "Asia/Hong_Kong"); COUNTRIES_MAP.put("HK", "Asia/Hong_Kong");
COUNTRIES_MAP.put("HST", "HST"); COUNTRIES_MAP.put("HST", "HST");
COUNTRIES_MAP.put("IE", "Europe/Dublin"); COUNTRIES_MAP.put("IE", "Europe/Dublin");
COUNTRIES_MAP.put("IL", "Asia/Tel_Aviv"); COUNTRIES_MAP.put("IL", "Asia/Tel_Aviv");
COUNTRIES_MAP.put("IN", "Asia/Calcutta"); COUNTRIES_MAP.put("IN", "Asia/Calcutta");
COUNTRIES_MAP.put("IR", "Asia/Tehran"); COUNTRIES_MAP.put("IR", "Asia/Tehran");
COUNTRIES_MAP.put("IS", "Atlantic/Reykjavik"); COUNTRIES_MAP.put("IS", "Atlantic/Reykjavik");
COUNTRIES_MAP.put("IT", "Europe/Rome"); COUNTRIES_MAP.put("IT", "Europe/Rome");
COUNTRIES_MAP.put("JM", "Jamaica"); COUNTRIES_MAP.put("JM", "Jamaica");
COUNTRIES_MAP.put("JP", "Asia/Tokyo"); COUNTRIES_MAP.put("JP", "Asia/Tokyo");
COUNTRIES_MAP.put("LY", "Africa/Tripoli"); COUNTRIES_MAP.put("LY", "Africa/Tripoli");
COUNTRIES_MAP.put("MDT", "America/Denver"); COUNTRIES_MAP.put("MDT", "America/Denver");
COUNTRIES_MAP.put("MH", "Kwajalein"); COUNTRIES_MAP.put("MH", "Kwajalein");
COUNTRIES_MAP.put("MST", "America/Denver"); COUNTRIES_MAP.put("MST", "America/Denver");
COUNTRIES_MAP.put("MX", "America/Mexico_City"); COUNTRIES_MAP.put("MX", "America/Mexico_City");
COUNTRIES_MAP.put("NL", "Europe/Amsterdam"); COUNTRIES_MAP.put("NL", "Europe/Amsterdam");
COUNTRIES_MAP.put("NO", "Europe/Oslo"); COUNTRIES_MAP.put("NO", "Europe/Oslo");
COUNTRIES_MAP.put("NP", "Asia/Katmandu"); COUNTRIES_MAP.put("NP", "Asia/Katmandu");
COUNTRIES_MAP.put("NZ", "Pacific/Auckland"); COUNTRIES_MAP.put("NZ", "Pacific/Auckland");
COUNTRIES_MAP.put("PDT", "America/Los_Angeles"); COUNTRIES_MAP.put("PDT", "America/Los_Angeles");
COUNTRIES_MAP.put("PK", "Asia/Karachi"); COUNTRIES_MAP.put("PK", "Asia/Karachi");
COUNTRIES_MAP.put("PL", "Europe/Warsaw"); COUNTRIES_MAP.put("PL", "Europe/Warsaw");
COUNTRIES_MAP.put("PST", "America/Los_Angeles"); COUNTRIES_MAP.put("PST", "America/Los_Angeles");
COUNTRIES_MAP.put("PT", "Europe/Lisbon"); COUNTRIES_MAP.put("PT", "Europe/Lisbon");
COUNTRIES_MAP.put("RU", "Europe/Moscow"); COUNTRIES_MAP.put("RU", "Europe/Moscow");
COUNTRIES_MAP.put("SE", "Europe/Stockholm"); COUNTRIES_MAP.put("SE", "Europe/Stockholm");
COUNTRIES_MAP.put("SG", "Asia/Singapore"); COUNTRIES_MAP.put("SG", "Asia/Singapore");
COUNTRIES_MAP.put("SU", "Europe/Moscow"); COUNTRIES_MAP.put("SU", "Europe/Moscow");
COUNTRIES_MAP.put("TH", "Asia/Bangkok"); COUNTRIES_MAP.put("TH", "Asia/Bangkok");
COUNTRIES_MAP.put("TM", "Asia/Ashgabat"); COUNTRIES_MAP.put("TM", "Asia/Ashgabat");
COUNTRIES_MAP.put("TR", "Europe/Istanbul"); COUNTRIES_MAP.put("TR", "Europe/Istanbul");
COUNTRIES_MAP.put("TW", "Asia/Taipei"); COUNTRIES_MAP.put("TW", "Asia/Taipei");
COUNTRIES_MAP.put("UK", "Europe/London"); COUNTRIES_MAP.put("UK", "Europe/London");
COUNTRIES_MAP.put("US", "America/New_York"); COUNTRIES_MAP.put("US", "America/New_York");
COUNTRIES_MAP.put("UTC", "UTC"); COUNTRIES_MAP.put("UTC", "UTC");
COUNTRIES_MAP.put("VA", "Europe/Vatican"); COUNTRIES_MAP.put("VA", "Europe/Vatican");
COUNTRIES_MAP.put("VN", "Asia/Ho_Chi_Minh"); COUNTRIES_MAP.put("VN", "Asia/Ho_Chi_Minh");
COUNTRIES_MAP.put("INTERNET", BEATS_KEYWORD); COUNTRIES_MAP.put("INTERNET", BEATS_KEYWORD);
COUNTRIES_MAP.put("BEATS", BEATS_KEYWORD); COUNTRIES_MAP.put("BEATS", BEATS_KEYWORD);
for (final String tz : TimeZone.getAvailableIDs()) for (final String tz : TimeZone.getAvailableIDs()) {
{ if (!tz.contains("/") && tz.length() == 3 & !COUNTRIES_MAP.containsKey(tz)) {
if (!tz.contains("/") && tz.length() == 3 & !COUNTRIES_MAP.containsKey(tz)) COUNTRIES_MAP.put(tz, tz);
{ }
COUNTRIES_MAP.put(tz, tz); }
} }
}
}
/** /**
* Responds with the current time in the specified timezone/country. * Responds with the current time in the specified timezone/country.
* *
* @param bot The bot's instance. * @param bot The bot's instance.
* @param sender The sender. * @param sender The sender.
* @param args The command arguments. * @param args The command arguments.
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message. * @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
*/ */
@Override @Override
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ boolean isInvalidTz = false;
boolean isInvalidTz = false; final String tz = (COUNTRIES_MAP.get((args.substring(args.indexOf(' ') + 1).trim().toUpperCase())));
final String tz = (COUNTRIES_MAP.get((args.substring(args.indexOf(' ') + 1).trim().toUpperCase()))); final String response;
final String response;
if (tz != null) if (tz != null) {
{ if (tz.equals(BEATS_KEYWORD)) {
if (tz.equals(BEATS_KEYWORD)) response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD);
{ } else {
response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD); TIME_SDF.setTimeZone(TimeZone.getTimeZone(tz));
} response = TIME_SDF.format(Calendar.getInstance().getTime()) + tz.substring(tz.indexOf('/') + 1)
else .replace('_', ' ');
{ }
TIME_SDF.setTimeZone(TimeZone.getTimeZone(tz)); } else {
response = TIME_SDF.format(Calendar.getInstance().getTime()) + tz.substring(tz.indexOf('/') + 1) isInvalidTz = true;
.replace('_', ' '); response = "The supported time zones are: " + COUNTRIES_MAP.keySet().toString();
} }
}
else
{
isInvalidTz = true;
response = "The supported time zones are: " + COUNTRIES_MAP.keySet().toString();
}
if (isPrivate) if (isPrivate) {
{ bot.send(sender, response, true);
bot.send(sender, response, true); } else {
} if (isInvalidTz) {
else bot.send(sender, response);
{ } else {
if (isInvalidTz) bot.send(bot.getChannel(), response);
{ }
bot.send(sender, response); }
} }
else
{
bot.send(bot.getChannel(), response);
}
}
}
@Override @Override
public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) public void helpResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
{ bot.send(sender, "To display a country's current date/time:");
bot.send(sender, "To display a country's current date/time:"); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TIME_CMD) + " [<country code>]");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TIME_CMD) + " [<country code>]");
bot.send(sender, "For a listing of the supported countries:"); bot.send(sender, "For a listing of the supported countries:");
bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TIME_CMD)); bot.send(sender, bot.helpIndent(bot.getNick() + ": " + TIME_CMD));
} }
/** /**
* Returns the current Internet (beat) Time. * Returns the current Internet (beat) Time.
* *
* @return The Internet Time string. * @return The Internet Time string.
*/ */
private String internetTime() private String internetTime() {
{ final Calendar gc = Calendar.getInstance();
final Calendar gc = Calendar.getInstance();
final int offset = (gc.get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000)); final int offset = (gc.get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000));
int hh = gc.get(Calendar.HOUR_OF_DAY); int hh = gc.get(Calendar.HOUR_OF_DAY);
final int mm = gc.get(Calendar.MINUTE); final int mm = gc.get(Calendar.MINUTE);
final int ss = gc.get(Calendar.SECOND); final int ss = gc.get(Calendar.SECOND);
hh -= offset; // GMT hh -= offset; // GMT
hh += 1; // BMT hh += 1; // BMT
long beats = Math.round(Math.floor((double) ((((hh * 3600) + (mm * 60) + ss) * 1000) / 86400))); long beats = Math.round(Math.floor((double) ((((hh * 3600) + (mm * 60) + ss) * 1000) / 86400)));
if (beats >= 1000) if (beats >= 1000) {
{ beats -= (long) 1000;
beats -= (long) 1000; } else if (beats < 0) {
} beats += (long) 1000;
else if (beats < 0) }
{
beats += (long) 1000;
}
if (beats < 10) if (beats < 10) {
{ return ("@00" + beats);
return ("@00" + beats); } else if (beats < 100) {
} return ("@0" + beats);
else if (beats < 100) }
{
return ("@0" + beats);
}
return ('@' + String.valueOf(beats)); return ('@' + String.valueOf(beats));
} }
@Override @Override
public boolean isPrivateMsgEnabled() public boolean isPrivateMsgEnabled() {
{ return true;
return true; }
}
} }

View file

@ -5,4 +5,4 @@ version.major=0
version.minor=7 version.minor=7
version.patch=0 version.patch=0
version.prerelease=beta version.prerelease=beta
version.buildmeta=007 version.buildmeta=008