Implemented Entries manager.

Implemented Messages manager.
Enabled caching of the currency exchange rates.
Moved commands, utils, etc. to separate classes.
Added more weather data.
This commit is contained in:
Erik C. Thauvin 2014-04-28 19:41:31 -07:00
parent 153363a320
commit e31a22af11
28 changed files with 3778 additions and 2198 deletions

View file

@ -61,13 +61,12 @@ compileJava {
} }
} }
//options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation" options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
} }
jar { jar {
manifest.attributes( manifest.attributes('Main-Class': mainClassName,
'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
} }
@ -106,5 +105,4 @@ task deploy(dependsOn: ['build', 'copyToDeploy', 'copyToDeployLib']) {
task release(dependsOn: ['deploy', 'wrapper']) { task release(dependsOn: ['deploy', 'wrapper']) {
group = "Publishing" group = "Publishing"
description = "Releases new version." description = "Releases new version."
isRelease = true
} }

View file

@ -1,3 +1,3 @@
#ANT Task: ch.oscg.jreleaseinfo.BuildNumberHandler #ANT Task: ch.oscg.jreleaseinfo.BuildNumberHandler
#Sun Apr 20 23:26:28 PDT 2014 #Fri Apr 25 18:08:16 PDT 2014
build.num.last=0 build.num.last=0

View file

@ -70,7 +70,18 @@
</profile> </profile>
</annotationProcessing> </annotationProcessing>
</component> </component>
<component name="CopyrightManager" default="" /> <component name="CopyrightManager" default="Mobibot">
<copyright>
<option name="notice" value="@(#)&amp;#36;file.fileName&#10;&#10;Copyright (c) 2004-&amp;#36;today.year, Erik C. Thauvin (erik@thauvin.net)&#10;All rights reserved.&#10;&#10;Redistribution and use in source and binary forms, with or without&#10;modification, are permitted provided that the following conditions are&#10;met:&#10;&#10;Redistributions of source code must retain the above copyright notice,&#10;this list of conditions and the following disclaimer.&#10;&#10;Redistributions in binary form must reproduce the above copyright notice,&#10;this list of conditions and the following disclaimer in the documentation&#10;and/or other materials provided with the distribution.&#10;&#10;Neither the name of the author nor the names of its contributors may be&#10;used to endorse or promote products derived from this software without&#10;specific prior written permission.&#10;&#10;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS&#10;IS&quot; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,&#10;THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR&#10;PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR&#10;CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,&#10;EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,&#10;PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR&#10;PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF&#10;LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING&#10;NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS&#10;SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." />
<option name="keyword" value="Copyright" />
<option name="allowReplaceKeyword" value="Erik C. Thauvin" />
<option name="myName" value="Mobibot" />
<option name="myLocal" value="true" />
</copyright>
<module2copyright>
<element module="All" copyright="Mobibot" />
</module2copyright>
</component>
<component name="DependenciesAnalyzeManager"> <component name="DependenciesAnalyzeManager">
<option name="myForwardDirection" value="false" /> <option name="myForwardDirection" value="false" />
</component> </component>

File diff suppressed because it is too large Load diff

View file

@ -15,6 +15,9 @@ weblog=http://www.mobitopia.org/
feed=http://www.mobitopia.org/rss.xml feed=http://www.mobitopia.org/rss.xml
backlogs=http://www.mobitopia.org/mobibot/logs backlogs=http://www.mobitopia.org/mobibot/logs
tell-max-days=5
tell-max-size=50
#delicious-user= #delicious-user=
#delicious-pwd= #delicious-pwd=

View file

@ -0,0 +1,256 @@
/*
* @(#)Commands.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
/**
* The <code>commands</code>, <code>keywords</code> and <code>arguments</code>.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-26
* @since 1.0
*/
public class Commands
{
/**
* The currency command.
*/
public static final String CURRENCY_CMD = "currency";
/**
* The rates keyword.
*/
public static final String CURRENCY_RATES_KEYWORD = "rates";
/**
* The weather command.
*/
public static final String WEATHER_CMD = "weather";
/**
* Debug command line argument.
*/
public static final String DEBUG_ARG = "debug";
/**
* Help command line argument.
*/
public static final String HELP_ARG = "help";
/**
* Properties command line argument.
*/
public static final String PROPS_ARG = "properties";
/**
* Properties version line argument.
*/
public static final String VERSION_ARG = "version";
/**
* The add (back)log command.
*/
public static final String ADDLOG_CMD = "addlog";
/**
* The debug command.
*/
public static final String DEBUG_CMD = "debug";
/**
* The dices command.
*/
public static final String DICE_CMD = "dice";
/**
* The say command.
*/
public static final String SAY_CMD = "say";
/**
* The die command.
*/
public static final String DIE_CMD = "die";
/**
* The cycle command.
*/
public static final String CYCLE_CMD = "cycle";
/**
* The msg command.
*/
public static final String MSG_CMD = "msg";
/**
* The ignore command.
*/
public static final String IGNORE_CMD = "ignore";
/**
* The ignore <code>me</code> keyword.
*/
public static final String IGNORE_ME_KEYWORD = "me";
/**
* The help command.
*/
public static final String HELP_CMD = "help";
/**
* The help on posting keyword.
*/
public static final String HELP_POSTING_KEYWORD = "posting";
/**
* The help on tags keyword.
*/
public static final String HELP_TAGS_KEYWORD = "tags";
/**
* The Google command.
*/
public static final String GOOGLE_CMD = "google";
/**
* The Twitter command.
*/
public static final String TWITTER_CMD = "twitter";
/**
* The math command.
*/
public static final String CALC_CMD = "calc";
/**
* The me command.
*/
public static final String ME_CMD = "me";
/**
* The nick command.
*/
public static final String NICK_CMD = "nick";
/**
* The link command.
*/
public static final String LINK_CMD = "L";
/**
* The lookup command.
*/
public static final String LOOKUP_CMD = "lookup";
/**
* The ping command.
*/
public static final String PING_CMD = "ping";
/**
* The pong command.
*/
public static final String PONG_CMD = "pong";
/**
* The quote command.
*/
public static final String QUOTE_CMD = "quote";
/**
* The recap command.
*/
public static final String RECAP_CMD = "recap";
/**
* The stock command.
*/
public static final String STOCK_CMD = "stock";
/**
* The time command.
*/
public static final String TIME_CMD = "time";
/**
* The tell command.
*/
public static final String TELL_CMD = "tell";
/**
* The {@link #TELL_CMD} delete command.
*/
public static final String TELL_DEL_CMD = "del";
/**
* The {@link #TELL_CMD} all command.
*/
public static final String TELL_ALL_CMD = "all";
/**
* The war command.
*/
public static final String WAR_CMD = "war";
/**
* The users command.
*/
public static final String USERS_CMD = "users";
/**
* The info command.
*/
public static final String INFO_CMD = "info";
/**
* The version command.
*/
public static final String VERSION_CMD = "version";
/**
* The view command.
*/
public static final String VIEW_CMD = "view";
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private Commands()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
}

View file

@ -1,7 +1,7 @@
/* /*
* @(#)CurrencyConverter.java * @(#)CurrencyConverter.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import org.jdom.Document; import org.jdom.Document;
@ -51,7 +49,6 @@ import java.util.*;
* Converts various currencies. * Converts various currencies.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Feb 11, 2004 * @created Feb 11, 2004
* @since 1.0 * @since 1.0
*/ */
@ -67,11 +64,6 @@ public class CurrencyConverter implements Runnable
*/ */
private static final Map<String, String> EXCHANGE_RATES = new TreeMap<String, String>(); private static final Map<String, String> EXCHANGE_RATES = new TreeMap<String, String>();
/**
* The rates keyword.
*/
private static final String RATES_KEYWORD = "rates";
/** /**
* The bot. * The bot.
*/ */
@ -80,12 +72,12 @@ public class CurrencyConverter implements Runnable
/** /**
* The actual currency query. * The actual currency query.
*/ */
private final String query; private String query;
/** /**
* The nick of the person who sent the message. * The nick of the person who sent the message.
*/ */
private final String sender; private String sender;
/** /**
* The last exchange rates table publication date. * The last exchange rates table publication date.
@ -96,17 +88,24 @@ public class CurrencyConverter implements Runnable
* Creates a new CurrencyConverter object. * Creates a new CurrencyConverter object.
* *
* @param bot The bot. * @param bot The bot.
* @param sender The nick of the person who sent the message.
* @param query The currency query.
* @param date The current date.
*/ */
public CurrencyConverter(Mobibot bot, String sender, String query, String date) public CurrencyConverter(Mobibot bot)
{ {
this.bot = bot; this.bot = bot;
this.sender = sender; }
this.query = query.toLowerCase();
if (!pubDate.equals(date)) /**
* Sets the query.
*
* @param sender The nick of the person who sent the message.
* @param query The currency query.
*/
public void setQuery(String sender, String query)
{
this.query = query;
this.sender = sender;
if (!pubDate.equals(Utils.today()))
{ {
EXCHANGE_RATES.clear(); EXCHANGE_RATES.clear();
} }
@ -115,110 +114,115 @@ public class CurrencyConverter implements Runnable
// Converts specified currencies. // Converts specified currencies.
public final void run() public final void run()
{ {
if (EXCHANGE_RATES.isEmpty()) if (Utils.isValidString(sender) && Utils.isValidString(query))
{ {
try if (EXCHANGE_RATES.isEmpty())
{ {
final SAXBuilder builder = new SAXBuilder(); try
builder.setIgnoringElementContentWhitespace(true);
final Document doc = builder.build(new URL(EXCHANGE_TABLE_URL));
final Element root = doc.getRootElement();
final Namespace ns = root.getNamespace("");
final Element cubeRoot = root.getChild("Cube", ns);
final Element cubeTime = cubeRoot.getChild("Cube", ns);
pubDate = cubeTime.getAttribute("time").getValue();
final List cubes = cubeTime.getChildren();
Element cube;
for (final Object rawCube : cubes)
{ {
cube = (Element) rawCube; final SAXBuilder builder = new SAXBuilder();
EXCHANGE_RATES.put(cube.getAttribute("currency").getValue(), cube.getAttribute("rate").getValue()); builder.setIgnoringElementContentWhitespace(true);
}
EXCHANGE_RATES.put("EUR", "1"); final Document doc = builder.build(new URL(EXCHANGE_TABLE_URL));
} final Element root = doc.getRootElement();
catch (JDOMException e) final Namespace ns = root.getNamespace("");
{ final Element cubeRoot = root.getChild("Cube", ns);
bot.getLogger().debug("Unable to parse the exchange rates table.", e); final Element cubeTime = cubeRoot.getChild("Cube", ns);
bot.send(sender, "An error has occurred while parsing the exchange rates table.");
}
catch (IOException e)
{
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()) pubDate = cubeTime.getAttribute("time").getValue();
{
if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-z]{3}+ to [a-z]{3}+"))
{
final String[] cmds = query.split(" ");
if (cmds.length == 4) final List cubes = cubeTime.getChildren();
{ Element cube;
if (cmds[3].equals(cmds[1]))
for (final Object rawCube : cubes)
{ {
bot.send(sender, "You're kidding, right?"); cube = (Element) rawCube;
EXCHANGE_RATES
.put(cube.getAttribute("currency").getValue(), cube.getAttribute("rate").getValue());
} }
else
{
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(), EXCHANGE_RATES.put("EUR", "1");
NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1) + ' ' + }
cmds[1].toUpperCase() + " = " + catch (JDOMException e)
NumberFormat.getCurrencyInstance(Locale.US).format((amt * to) / from).substring(1) {
+ ' ' + cmds[3].toUpperCase() bot.getLogger().debug("Unable to parse the exchange rates table.", e);
); bot.send(sender, "An error has occurred while parsing the exchange rates table.");
} }
catch (NullPointerException ignored) catch (IOException e)
{
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 (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[3].equals(cmds[1]) || cmds[0].equals("0"))
{ {
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString()); bot.send(sender, "You're kidding, right?");
}
else
{
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(),
NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1) + ' ' +
cmds[1].toUpperCase() + " = " +
NumberFormat.getCurrencyInstance(Locale.US).format((amt * to) / from)
.substring(1) + ' ' + cmds[3].toUpperCase()
);
}
catch (NullPointerException ignored)
{
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
}
} }
} }
} }
} else if (query.equals(Commands.CURRENCY_RATES_KEYWORD))
else if (query.equals(RATES_KEYWORD))
{
bot.send(sender, "Last Update: " + pubDate);
final Iterator<String> it = EXCHANGE_RATES.keySet().iterator();
String rate;
final StringBuilder buff = new StringBuilder(0);
while (it.hasNext())
{ {
rate = it.next(); bot.send(sender, "Last Update: " + pubDate);
if (buff.length() > 0)
final Iterator<String> it = EXCHANGE_RATES.keySet().iterator();
String rate;
final StringBuilder buff = new StringBuilder(0);
while (it.hasNext())
{ {
buff.append(", "); rate = it.next();
if (buff.length() > 0)
{
buff.append(", ");
}
buff.append(rate).append(": ").append(EXCHANGE_RATES.get(rate));
} }
buff.append(rate).append(": ").append(EXCHANGE_RATES.get(rate));
bot.send(sender, buff.toString());
}
else
{
bot.helpResponse(sender, Commands.CURRENCY_CMD + ' ' + query);
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
} }
bot.send(sender, buff.toString());
} }
else else
{ {
bot.helpResponse(sender, Mobibot.CURRENCY_CMD + ' ' + query); bot.getLogger().debug("The exchange rate table is empty.");
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString()); bot.send(sender, "Sorry, but the exchange rate table is empty.");
} }
} }
else
{
bot.getLogger().debug("The exchange rate table is empty.");
bot.send(sender, "Sorry, but the exchange rate table is empty.");
}
} }
} }

View file

@ -1,7 +1,7 @@
/* /*
* @(#)DeliciousPoster.java * @(#)DeliciousPoster.java
* *
* Copyright (c) 2005, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import del.icio.us.Delicious; import del.icio.us.Delicious;
@ -42,11 +40,10 @@ import del.icio.us.Delicious;
* The class to handle posts to del.icio.us. * The class to handle posts to del.icio.us.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Mar 5, 2005 * @created Mar 5, 2005
* @noinspection UnnecessaryBoxing
* @since 1.0 * @since 1.0
*/ */
@SuppressWarnings("UnnecessaryBoxing")
public class DeliciousPoster public class DeliciousPoster
{ {
private final Delicious delicious; private final Delicious delicious;
@ -78,16 +75,28 @@ public class DeliciousPoster
public Object construct() public Object construct()
{ {
return Boolean.valueOf(delicious.addPost(entry.getLink(), return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(), entry.getTitle(),
postedBy(entry), postedBy(entry),
entry.getDeliciousTags(), entry.getDeliciousTags(),
entry.getDate())); entry.getDate()));
} }
}; };
worker.start(); worker.start();
} }
/**
* Returns he del.icio.us extended attribution line.
*
* @param entry The entry.
*
* @return The extended attribution line.
*/
private String postedBy(EntryLink entry)
{
return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + ircServer + ')';
}
/** /**
* Deletes a post to del.icio.us. * Deletes a post to del.icio.us.
* *
@ -125,36 +134,24 @@ public class DeliciousPoster
delicious.deletePost(oldUrl); delicious.deletePost(oldUrl);
return Boolean.valueOf(delicious.addPost(entry.getLink(), return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(), entry.getTitle(),
postedBy(entry), postedBy(entry),
entry.getDeliciousTags(), entry.getDeliciousTags(),
entry.getDate())); entry.getDate()));
} }
else else
{ {
return Boolean.valueOf(delicious.addPost(entry.getLink(), return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(), entry.getTitle(),
postedBy(entry), postedBy(entry),
entry.getDeliciousTags(), entry.getDeliciousTags(),
entry.getDate(), entry.getDate(),
true, true,
true)); true));
} }
} }
}; };
worker.start(); worker.start();
} }
/**
* Returns he del.icio.us extended attribution line.
*
* @param entry The entry.
*
* @return The extended attribution line.
*/
private String postedBy(EntryLink entry)
{
return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + ircServer + ')';
}
} }

View file

@ -0,0 +1,97 @@
/*
* @(#)Dice.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import java.util.Random;
/**
* The {@link net.thauvin.erik.mobibot.Commands#DICE_CMD} command
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-28
* @since 1.0
*/
public class Dice
{
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private Dice()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Rolls the dice
*
* @param bot The bot.
* @param sender The sender's nickname.
*/
public static void roll(Mobibot bot, String sender)
{
final Random r = new Random();
int i = r.nextInt(6) + 1;
int y = r.nextInt(6) + 1;
final int playerTotal = i + y;
bot.send(bot.getChannel(),
sender + " rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils
.bold(playerTotal)
);
i = r.nextInt(6) + 1;
y = r.nextInt(6) + 1;
final int total = i + y;
bot.action(
"rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils.bold(total));
if (playerTotal < total)
{
bot.action("wins.");
}
else if (playerTotal > total)
{
bot.action("lost.");
}
else
{
bot.action("tied.");
}
}
}

View file

@ -0,0 +1,384 @@
/*
* @(#)EntriesMgr.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import com.sun.syndication.feed.synd.*;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.SyndFeedOutput;
import java.io.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
/**
* Manages the feed entries.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-28
* @since 1.0
*/
public class EntriesMgr
{
/**
* The name of the file containing the current entries.
*/
public static final String CURRENT_XML = "current.xml";
/**
* The name of the file containing the backlog entries.
*/
public static final String NAV_XML = "nav.xml";
/**
* The maximum number of backlogs to keep.
*/
private static final int MAX_BACKLOGS = 10;
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private EntriesMgr()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Loads the current entries.
*
* @param file The file containing the current entries.
* @param channel The channel
* @param entries The entries.
*
* @return The feed's last published date.
*
* @throws java.io.FileNotFoundException If the file was not found.
* @throws com.sun.syndication.io.FeedException If an error occurred while reading the feed.
*/
@SuppressWarnings("unchecked")
public static String loadEntries(String file, String channel, List<EntryLink> entries)
throws FileNotFoundException, FeedException
{
entries.clear();
final SyndFeedInput input = new SyndFeedInput();
String today;
InputStreamReader reader = null;
try
{
reader = new InputStreamReader(new FileInputStream(new File(file)));
final SyndFeed feed = input.build(reader);
today = Utils.ISO_SDF.format(feed.getPublishedDate());
final List items = feed.getEntries();
SyndEntry item;
SyndContent description;
String[] comments;
String author;
EntryLink entry;
for (int i = items.size() - 1; i >= 0; i--)
{
item = (SyndEntryImpl) items.get(i);
author = item.getAuthor()
.substring(item.getAuthor().lastIndexOf('(') + 1, item.getAuthor().length() - 1);
entry = new EntryLink(item.getLink(),
item.getTitle(),
author,
channel,
item.getPublishedDate(),
item.getCategories());
description = item.getDescription();
comments = description.getValue().split("<br/>");
int split;
for (final String comment : comments)
{
split = comment.indexOf(": ");
if (split != -1)
{
entry.addComment(comment.substring(split + 2).trim(), comment.substring(0, split).trim());
}
}
entries.add(entry);
}
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException ignore)
{
; // Do nothing
}
}
}
return today;
}
/**
* Loads the backlogs.
*
* @param file The file containing the backlogs.
* @param history The history list.
*
* @throws FileNotFoundException If the file was not found.
* @throws FeedException If an error occurred while reading the feed.
*/
public static void loadBacklogs(String file, List<String> history)
throws FileNotFoundException, FeedException
{
history.clear();
final SyndFeedInput input = new SyndFeedInput();
InputStreamReader reader = null;
try
{
reader = new InputStreamReader(new FileInputStream(new File(file)));
final SyndFeed feed = input.build(reader);
final List items = feed.getEntries();
SyndEntry item;
for (int i = items.size() - 1; i >= 0; i--)
{
item = (SyndEntryImpl) items.get(i);
history.add(item.getTitle());
}
}
finally
{
if (reader != null)
{
try
{
reader.close();
}
catch (IOException ignore)
{
; // Do nothing
}
}
}
}
/**
* Saves the entries.
*
* @param isDayBackup Set the true if the daily backup file should also be created.
*/
public static void saveEntries(Mobibot bot, List<EntryLink> entries, List<String> history, boolean isDayBackup)
{
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Saving...");
}
if (Utils.isValidString(bot.getLogsDir()) && Utils.isValidString(bot.getWeblogUrl()))
{
FileWriter fw = null;
try
{
fw = new FileWriter(new File(bot.getLogsDir() + CURRENT_XML));
SyndFeed rss = new SyndFeedImpl();
rss.setFeedType("rss_2.0");
rss.setTitle(bot.getChannel() + " IRC Links");
rss.setDescription("Links from " + bot.getIrcServer() + " on " + bot.getChannel());
rss.setLink(bot.getWeblogUrl());
rss.setPublishedDate(Calendar.getInstance().getTime());
rss.setLanguage("en");
EntryLink entry;
StringBuffer buff;
EntryComment comment;
final List<SyndEntry> items = new ArrayList<SyndEntry>(0);
SyndEntry item;
SyndContent description;
for (int i = (entries.size() - 1); i >= 0; --i)
{
entry = entries.get(i);
buff = new StringBuffer(
"Posted by <b>" + entry.getNick() + "</b> on <a href=\"irc://" + bot.getIrcServer() + '/'
+ entry.getChannel() + "\"><b>" + entry.getChannel() + "</b></a>"
);
if (entry.getCommentsCount() > 0)
{
buff.append(" <br/><br/>");
final EntryComment[] comments = entry.getComments();
for (int j = 0; j < comments.length; j++)
{
comment = comments[j];
if (j > 0)
{
buff.append(" <br/>");
}
buff.append(comment.getNick()).append(": ").append(comment.getComment());
}
}
item = new SyndEntryImpl();
item.setLink(entry.getLink());
description = new SyndContentImpl();
description.setValue(buff.toString());
item.setDescription(description);
item.setTitle(entry.getTitle());
item.setPublishedDate(entry.getDate());
item.setAuthor(
bot.getChannel().substring(1) + '@' + bot.getIrcServer() + " (" + entry.getNick() + ')');
item.setCategories(entry.getTags());
items.add(item);
}
rss.setEntries(items);
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Writing the entries feed.");
}
final SyndFeedOutput output = new SyndFeedOutput();
output.output(rss, fw);
fw.close();
fw = new FileWriter(new File(bot.getLogsDir() + bot.getToday() + ".xml"));
output.output(rss, fw);
if (isDayBackup)
{
if (Utils.isValidString(bot.getBacklogsUrl()))
{
if (history.indexOf(bot.getToday()) == -1)
{
history.add(bot.getToday());
while (history.size() > MAX_BACKLOGS)
{
history.remove(0);
}
}
fw.close();
fw = new FileWriter(new File(bot.getLogsDir() + NAV_XML));
rss = new SyndFeedImpl();
rss.setFeedType("rss_2.0");
rss.setTitle(bot.getChannel() + " IRC Links Backlogs");
rss.setDescription("Backlogs of Links from " + bot.getIrcServer() + " on " + bot.getChannel());
rss.setLink(bot.getBacklogsUrl());
rss.setPublishedDate(Calendar.getInstance().getTime());
String date;
items.clear();
for (int i = (history.size() - 1); i >= 0; --i)
{
date = history.get(i);
item = new SyndEntryImpl();
item.setLink(bot.getBacklogsUrl() + date + ".xml");
item.setTitle(date);
description = new SyndContentImpl();
description.setValue("Links for " + date);
item.setDescription(description);
items.add(item);
}
rss.setEntries(items);
if (bot.getLogger().isDebugEnabled())
{
bot.getLogger().debug("Writing the backlog feed.");
}
output.output(rss, fw);
}
else
{
bot.getLogger().warn("Unable to generate the backlogs feed. No property configured.");
}
}
}
catch (Exception e)
{
bot.getLogger().warn("Unable to generate the feed.", e);
}
finally
{
try
{
if (fw != null)
{
fw.close();
}
}
catch (Exception ignore)
{
; // Do nothing
}
}
}
else
{
bot.getLogger().warn("Unable to generate the feed. At least one of the required property is missing.");
}
}
}

View file

@ -1,7 +1,7 @@
/* /*
* @(#)EntryComment.java * @(#)EntryComment.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import java.io.Serializable; import java.io.Serializable;
@ -44,7 +42,6 @@ import java.util.Date;
* The class used to store comments associated to a specific entry. * The class used to store comments associated to a specific entry.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Jan 31, 2004 * @created Jan 31, 2004
* @since 1.0 * @since 1.0
*/ */
@ -80,6 +77,7 @@ public class EntryComment implements Serializable
/** /**
* Creates a new comment. * Creates a new comment.
*
* @noinspection UnusedDeclaration * @noinspection UnusedDeclaration
*/ */
protected EntryComment() protected EntryComment()
@ -101,6 +99,7 @@ public class EntryComment implements Serializable
* Sets the comment. * Sets the comment.
* *
* @param comment The actual comment. * @param comment The actual comment.
*
* @noinspection UnusedDeclaration * @noinspection UnusedDeclaration
*/ */
public final void setComment(String comment) public final void setComment(String comment)

View file

@ -1,7 +1,7 @@
/* /*
* @(#)EntryLink.java * @(#)EntryLink.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import com.sun.syndication.feed.synd.SyndCategoryImpl; import com.sun.syndication.feed.synd.SyndCategoryImpl;
@ -48,7 +46,6 @@ import java.util.List;
* The class used to store link entries. * The class used to store link entries.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Jan 31, 2004 * @created Jan 31, 2004
* @since 1.0 * @since 1.0
*/ */
@ -106,6 +103,61 @@ public class EntryLink implements Serializable
setTags(tags); setTags(tags);
} }
/**
* Sets the tags.
*
* @param tags The space-delimited tags.
*/
public final synchronized void setTags(String tags)
{
if (tags != null)
{
final String[] parts = tags.replaceAll(", ", " ").replaceAll(",", " ").split(" ");
SyndCategoryImpl tag;
String part;
char mod;
for (final String rawPart : parts)
{
part = rawPart.trim();
if (part.length() >= 2)
{
tag = new SyndCategoryImpl();
tag.setName(part.substring(1).toLowerCase());
mod = part.charAt(0);
if (mod == '-')
{
// Don't remove the channel tag, if any.
if (!tag.getName().equals(channel.substring(1)))
{
this.tags.remove(tag);
}
}
else if (mod == '+')
{
if (!this.tags.contains(tag))
{
this.tags.add(tag);
}
}
else
{
tag.setName(part.trim().toLowerCase());
if (!this.tags.contains(tag))
{
this.tags.add(tag);
}
}
}
}
}
}
/** /**
* Creates a new entry. * Creates a new entry.
* *
@ -129,6 +181,7 @@ public class EntryLink implements Serializable
/** /**
* Creates a new EntryLink object. * Creates a new EntryLink object.
*
* @noinspection UnusedDeclaration * @noinspection UnusedDeclaration
*/ */
protected EntryLink() protected EntryLink()
@ -178,6 +231,7 @@ public class EntryLink implements Serializable
* Sets the channel. * Sets the channel.
* *
* @param channel The channel. * @param channel The channel.
*
* @noinspection UnusedDeclaration * @noinspection UnusedDeclaration
*/ */
public final synchronized void setChannel(String channel) public final synchronized void setChannel(String channel)
@ -279,6 +333,7 @@ public class EntryLink implements Serializable
* Set the comment's author login. * Set the comment's author login.
* *
* @param login The new login. * @param login The new login.
*
* @noinspection UnusedDeclaration * @noinspection UnusedDeclaration
*/ */
public final synchronized void setLogin(String login) public final synchronized void setLogin(String login)
@ -319,56 +374,11 @@ public class EntryLink implements Serializable
/** /**
* Sets the tags. * Sets the tags.
* *
* @param tags The space-delimited tags. * @param tags The tags.
*/ */
public final synchronized void setTags(String tags) final synchronized void setTags(List<SyndCategoryImpl> tags)
{ {
if (tags != null) this.tags.addAll(tags);
{
final String[] parts = tags.replaceAll(", ", " ").replaceAll(",", " ").split(" ");
SyndCategoryImpl tag;
String part;
char mod;
for (final String rawPart : parts)
{
part = rawPart.trim();
if (part.length() >= 2)
{
tag = new SyndCategoryImpl();
tag.setName(part.substring(1).toLowerCase());
mod = part.charAt(0);
if (mod == '-')
{
// Don't remove the channel tag, if any.
if (!tag.getName().equals(channel.substring(1)))
{
this.tags.remove(tag);
}
}
else if (mod == '+')
{
if (!this.tags.contains(tag))
{
this.tags.add(tag);
}
}
else
{
tag.setName(part.trim().toLowerCase());
if (!this.tags.contains(tag))
{
this.tags.add(tag);
}
}
}
}
}
} }
/** /**
@ -426,16 +436,6 @@ public class EntryLink implements Serializable
} }
} }
/**
* Sets the tags.
*
* @param tags The tags.
*/
public final synchronized void setTags(List<SyndCategoryImpl> tags)
{
this.tags.addAll(tags);
}
/** /**
* Returns a string representation of the object. * Returns a string representation of the object.
* *
@ -444,8 +444,8 @@ public class EntryLink implements Serializable
public final String toString() public final String toString()
{ {
return super.toString() + "[ channel -> '" + channel + '\'' + ", comments -> " + comments + ", date -> " return super.toString() + "[ channel -> '" + channel + '\'' + ", comments -> " + comments + ", date -> " + date
+ date + ", link -> '" + link + '\'' + ", login -> '" + login + '\'' + ", nick -> '" + nick + '\'' + ", link -> '" + link + '\'' + ", login -> '" + login + '\'' + ", nick -> '" + nick + '\''
+ ", tags -> " + tags + ", title -> '" + title + '\'' + " ]"; + ", tags -> " + tags + ", title -> '" + title + '\'' + " ]";
} }
} }

View file

@ -1,7 +1,7 @@
/* /*
* @(#)FeedReader.java * @(#)FeedReader.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndEntry;
@ -50,7 +48,6 @@ import java.util.List;
* Reads a RSS feed. * Reads a RSS feed.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Feb 1, 2004 * @created Feb 1, 2004
* @since 1.0 * @since 1.0
*/ */

View file

@ -1,7 +1,7 @@
/* /*
* @(#)GoogleSearch.java * @(#)GoogleSearch.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,12 +30,9 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot;
package net.thauvin.erik.mobibot;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONObject; import org.json.JSONObject;
@ -50,7 +47,6 @@ import java.net.URLEncoder;
* Performs a Google search or spell checking query. * Performs a Google search or spell checking query.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */
@ -95,7 +91,6 @@ public class GoogleSearch implements Runnable
*/ */
public final void run() public final void run()
{ {
try try
{ {
final String query = URLEncoder.encode(this.query, "UTF-8"); final String query = URLEncoder.encode(this.query, "UTF-8");
@ -119,12 +114,11 @@ public class GoogleSearch implements Runnable
for (int i = 0; i < ja.length(); i++) for (int i = 0; i < ja.length(); i++)
{ {
final JSONObject j = ja.getJSONObject(i); final JSONObject j = ja.getJSONObject(i);
bot.send(sender, Mobibot.unescapeXml(j.getString("titleNoFormatting"))); bot.send(sender, Utils.unescapeXml(j.getString("titleNoFormatting")));
bot.send(sender, TAB_INDENT + j.getString("url")); bot.send(sender, TAB_INDENT + j.getString("url"));
} }
reader.close(); reader.close();
} }
catch (Exception e) catch (Exception e)
{ {

View file

@ -0,0 +1,162 @@
/*
* @(#)Lookup.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import org.apache.commons.net.WhoisClient;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* Performs a DNS lookup query.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-26
* @since 1.0
*/
public class Lookup
{
/**
* The whois host.
*/
@SuppressWarnings("WeakerAccess")
public static final String WHOIS_HOST = "whois.arin.net";
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private Lookup()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* 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.
*/
public static String lookup(String query)
throws UnknownHostException
{
final StringBuilder buffer = new StringBuilder("");
final InetAddress[] results = InetAddress.getAllByName(query);
String hostInfo;
for (final InetAddress result : results)
{
if (result.getHostAddress().equals(query))
{
hostInfo = result.getHostName();
if (hostInfo.equals(query))
{
throw new UnknownHostException();
}
}
else
{
hostInfo = result.getHostAddress();
}
if (buffer.length() > 0)
{
buffer.append(", ");
}
buffer.append(hostInfo);
}
return buffer.toString();
}
/**
* Performs a whois IP query.
*
* @param query The IP address.
*
* @return The IP whois data, if any.
*
* @throws java.io.IOException If a connection error occurs.
*/
public static String[] whois(String query)
throws IOException
{
return whois(query, WHOIS_HOST);
}
/**
* Performs a whois IP query.
*
* @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(String query, String host)
throws IOException
{
final WhoisClient whois = new WhoisClient();
String[] lines;
try
{
whois.setDefaultTimeout(Mobibot.CONNECT_TIMEOUT);
whois.connect(host);
whois.setSoTimeout(Mobibot.CONNECT_TIMEOUT);
whois.setSoLinger(false, 0);
lines = whois.query('-' + query).split("\n");
}
finally
{
whois.disconnect();
}
return lines;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
/* /*
* @(#)Quote.java * @(#)Quote.java
* *
* Copyright (c) 2014, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import org.jibble.pircbot.Colors; import org.jibble.pircbot.Colors;
@ -53,6 +51,13 @@ import java.net.URLConnection;
*/ */
public class Quote implements Runnable public class Quote implements Runnable
{ {
/**
* The I Heart Quotes URL.
*/
private static final String QUOTE_URL =
"http://www.iheartquotes.com/api/v1/random?format=json&max_lines=1&source=esr+humorix_misc+humorix_stories+joel_on_software+macintosh+math+mav_flame+osp_rules+paul_graham+prog_style+subversion";
/** /**
* The bot. * The bot.
*/ */
@ -82,7 +87,7 @@ public class Quote implements Runnable
{ {
try try
{ {
final URL url = new URL("http://www.iheartquotes.com/api/v1/random?format=json&max_lines=1"); final URL url = new URL(QUOTE_URL);
final URLConnection conn = url.openConnection(); final URLConnection conn = url.openConnection();
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
@ -96,7 +101,7 @@ public class Quote implements Runnable
final JSONObject json = new JSONObject(sb.toString()); final JSONObject json = new JSONObject(sb.toString());
bot.send(bot.getChannel(), Colors.BLUE + json.getString("quote") + Colors.BLUE); bot.send(bot.getChannel(), Colors.CYAN + json.getString("quote") + Colors.CYAN);
reader.close(); reader.close();
} }

View file

@ -1,5 +1,39 @@
/*
* @(#)ReleaseInfo.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* Created by JReleaseInfo AntTask from Open Source Competence Group */ /* Created by JReleaseInfo AntTask from Open Source Competence Group */
/* Creation date Sun Apr 20 23:26:28 PDT 2014 */ /* Creation date Fri Apr 25 18:08:16 PDT 2014 */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import java.util.Date; import java.util.Date;
@ -9,51 +43,73 @@ import java.util.Date;
* *
* @author JReleaseInfo AntTask * @author JReleaseInfo AntTask
*/ */
public class ReleaseInfo { public class ReleaseInfo
{
/** /**
* Disables the default constructor. * buildDate (set during build process to 1398474496363L).
* @throws UnsupportedOperationException if the constructor is called. */
*/ private static final Date buildDate = new Date(1398474496363L);
private ReleaseInfo() throws UnsupportedOperationException {
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* project (set during build process to "mobibot").
*/
private static final String project = "mobibot";
/** buildDate (set during build process to 1398061588708L). */ /**
private static final Date buildDate = new Date(1398061588708L); * version (set during build process to "0.6").
*/
private static final String version = "0.6";
/** /**
* Get buildDate (set during build process to Sun Apr 20 23:26:28 PDT 2014). * Disables the default constructor.
* @return Date buildDate *
*/ * @throws UnsupportedOperationException if the constructor is called.
public static Date getBuildDate() { return buildDate; } */
private ReleaseInfo()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Get buildDate (set during build process to Fri Apr 25 18:08:16 PDT 2014).
*
* @return Date buildDate
*/
public static Date getBuildDate()
{
return buildDate;
}
/** project (set during build process to "mobibot"). */ /**
private static final String project = "mobibot"; * Get project (set during build process to "mobibot").
*
* @return String project
*/
public static String getProject()
{
return project;
}
/** /**
* Get project (set during build process to "mobibot"). * Get version (set during build process to "0.6").
* @return String project *
*/ * @return String version
public static String getProject() { return project; } */
public static String getVersion()
{
return version;
}
/**
/** version (set during build process to "0.6"). */ * Get buildNumber (set during build process to 0).
private static final String version = "0.6"; *
* @return int buildNumber
/** */
* Get version (set during build process to "0.6"). public static int getBuildNumber()
* @return String version {
*/ return 0;
public static String getVersion() { return version; } }
/**
* Get buildNumber (set during build process to 0).
* @return int buildNumber
*/
public static int getBuildNumber() { return 0; }
} }

View file

@ -1,7 +1,7 @@
/* /*
* @(#)StockQuote.java * @(#)StockQuote.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import com.Ostermiller.util.CSVParser; import com.Ostermiller.util.CSVParser;
@ -46,7 +44,6 @@ import java.io.IOException;
* Retrieves a stock quote from Yahoo!. * Retrieves a stock quote from Yahoo!.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */

View file

@ -1,133 +1,159 @@
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import javax.swing.SwingUtilities; import javax.swing.*;
/** /**
* This is the 3rd version of SwingWorker (also known as * This is the 3rd version of SwingWorker (also known as SwingWorker 3), an abstract class that you subclass to perform
* SwingWorker 3), an abstract class that you subclass to * GUI-related work in a dedicated thread. For instructions on and examples of using this class, see:
* perform GUI-related work in a dedicated thread. For * <p/>
* instructions on and examples of using this class, see:
*
* http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html * http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
* * <p/>
* Note that the API changed slightly in the 3rd version: * Note that the API changed slightly in the 3rd version: You must now invoke start() on the SwingWorker after creating
* You must now invoke start() on the SwingWorker after * it.
* creating it.
* *
* @noinspection ALL * @noinspection ALL
*/ */
public abstract class SwingWorker { public abstract class SwingWorker
private Object value; // see getValue(), setValue() {
private Object value; // see getValue(), setValue()
/** private ThreadVar threadVar;
* Class to maintain reference to current worker thread
* under separate synchronization control.
*/
private static class ThreadVar {
private Thread thread;
ThreadVar(Thread t) { thread = t; }
synchronized Thread get() { return thread; }
synchronized void clear() { thread = null; }
}
private ThreadVar threadVar; /**
* Start a thread that will call the <code>construct</code> method and then exit.
*/
public SwingWorker()
{
final Runnable doFinished = new Runnable()
{
public void run()
{
finished();
}
};
/** Runnable doConstruct = new Runnable()
* Get the value produced by the worker thread, or null if it {
* hasn't been constructed yet. public void run()
*/ {
protected synchronized Object getValue() { try
return value; {
} setValue(construct());
}
finally
{
threadVar.clear();
}
/** SwingUtilities.invokeLater(doFinished);
* Set the value produced by worker thread }
*/ };
private synchronized void setValue(Object x) {
value = x;
}
/** Thread t = new Thread(doConstruct);
* Compute the value to be returned by the <code>get</code> method. threadVar = new ThreadVar(t);
*/ }
public abstract Object construct();
/** /**
* Called on the event dispatching thread (not on the worker thread) * Called on the event dispatching thread (not on the worker thread) after the <code>construct</code> method has
* after the <code>construct</code> method has returned. * returned.
*/ */
public void finished() { public void finished()
} {
}
/** /**
* A new method that interrupts the worker thread. Call this method * Compute the value to be returned by the <code>get</code> method.
* to force the worker to stop what it's doing. */
*/ public abstract Object construct();
public void interrupt() {
Thread t = threadVar.get();
if (t != null) {
t.interrupt();
}
threadVar.clear();
}
/** /**
* Return the value created by the <code>construct</code> method. * A new method that interrupts the worker thread. Call this method to force the worker to stop what it's doing.
* Returns null if either the constructing thread or the current */
* thread was interrupted before a value was produced. public void interrupt()
* {
* @return the value created by the <code>construct</code> method Thread t = threadVar.get();
*/ if (t != null)
public Object get() { {
while (true) { t.interrupt();
Thread t = threadVar.get(); }
if (t == null) { threadVar.clear();
return getValue(); }
}
try {
t.join();
}
catch (InterruptedException e) {
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/**
* Return the value created by the <code>construct</code> method. Returns null if either the constructing thread or
* the current thread was interrupted before a value was produced.
*
* @return the value created by the <code>construct</code> method
*/
public Object get()
{
while (true)
{
Thread t = threadVar.get();
if (t == null)
{
return getValue();
}
try
{
t.join();
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt(); // propagate
return null;
}
}
}
/** /**
* Start a thread that will call the <code>construct</code> method * Get the value produced by the worker thread, or null if it hasn't been constructed yet.
* and then exit. */
*/ protected synchronized Object getValue()
public SwingWorker() { {
final Runnable doFinished = new Runnable() { return value;
public void run() { finished(); } }
};
Runnable doConstruct = new Runnable() { /**
public void run() { * Set the value produced by worker thread
try { */
setValue(construct()); private synchronized void setValue(Object x)
} {
finally { value = x;
threadVar.clear(); }
}
SwingUtilities.invokeLater(doFinished); /**
} * Start the worker thread.
}; */
public void start()
{
Thread t = threadVar.get();
if (t != null)
{
t.start();
}
}
Thread t = new Thread(doConstruct); /**
threadVar = new ThreadVar(t); * Class to maintain reference to current worker thread under separate synchronization control.
} */
private static class ThreadVar
{
private Thread thread;
/** ThreadVar(Thread t)
* Start the worker thread. {
*/ thread = t;
public void start() { }
Thread t = threadVar.get();
if (t != null) { synchronized Thread get()
t.start(); {
} return thread;
} }
synchronized void clear()
{
thread = null;
}
}
} }

View file

@ -0,0 +1,146 @@
/*
* @(#)TellMessage.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import java.io.Serializable;
import java.util.Calendar;
import java.util.Date;
/**
* The <code>TellMessage</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-24
* @since 1.0
*/
public class TellMessage implements Serializable
{
private static final long serialVersionUID = 1L;
private final String sender;
private final String recipient;
private final String message;
private final String id;
final private Date queued;
private Date received;
private boolean isReceived;
private boolean isNotified;
/**
* Create a new message.
*
* @param sender The sender's nick.
* @param recipient The recipient's nick.
* @param message The message.
*/
public TellMessage(String sender, String recipient, String message)
{
this.sender = sender;
this.recipient = recipient;
this.message = message;
this.queued = Calendar.getInstance().getTime();
this.id = Utils.TIMESTAMP_SDF.format(this.queued);
}
public String getSender()
{
return sender;
}
public String getRecipient()
{
return recipient;
}
public String getMessage()
{
return message;
}
public Date getQueued()
{
return queued;
}
public Date getReceived()
{
return received;
}
public void setReceived()
{
this.received = Calendar.getInstance().getTime();
this.isReceived = true;
}
public boolean isNotified()
{
return this.isNotified;
}
public void setNotified()
{
this.isNotified = true;
}
public String getId()
{
return this.id;
}
public boolean isReceived()
{
return this.isReceived;
}
public boolean isMatchId(String id)
{
return this.id.equals(id);
}
public boolean isMatch(String nick)
{
return (sender.equalsIgnoreCase(nick) || recipient.equalsIgnoreCase(nick));
}
}

View file

@ -0,0 +1,156 @@
/*
* @(#)TellMessagesMgr.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import org.apache.commons.logging.impl.Log4JLogger;
import java.io.*;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* Managers the {@link Commands#TELL_CMD} messages.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-26
* @since 1.0
*/
public class TellMessagesMgr
{
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private TellMessagesMgr()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Loads the messages.
*
* @param file The serialized objects file.
* @param logger The logger.
*
* @return The {@link net.thauvin.erik.mobibot.TellMessage} array.
*/
@SuppressWarnings("unchecked")
public static List<TellMessage> load(String file, Log4JLogger logger)
{
try
{
final ObjectInput input = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)));
try
{
return ((List<TellMessage>) input.readObject());
}
finally
{
input.close();
}
}
catch (FileNotFoundException ignore)
{
; // Do nothing.
}
catch (IOException 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 (List<TellMessage>) new ArrayList();
}
/**
* Saves the messages.
*
* @param file The serialized objects file.
* @param messages The {@link net.thauvin.erik.mobibot.TellMessage} array.
* @param logger The logger.
*/
public static void save(String file, List<TellMessage> messages, Log4JLogger logger)
{
try
{
final ObjectOutput output = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
try
{
output.writeObject(messages);
}
finally
{
output.close();
}
}
catch (IOException e)
{
logger.error("Unable to save messages queue.", e);
}
}
/**
* Cleans the messages queue.
*/
public static void cleanTellMessages(List<TellMessage> tellMessages, int tellMaxDays)
{
final Calendar maxDate = Calendar.getInstance();
final Date today = new Date();
synchronized (tellMessages)
{
for (final TellMessage message : tellMessages)
{
maxDate.setTime(message.getQueued());
maxDate.add(Calendar.DATE, tellMaxDays);
if (maxDate.getTime().before(today))
{
tellMessages.remove(message);
}
}
}
}
}

View file

@ -1,7 +1,7 @@
/* /*
* @(#)Twitter.java * @(#)Twitter.java
* *
* Copyright (C) 2007 Erik C. Thauvin * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import twitter4j.Status; import twitter4j.Status;
@ -44,7 +42,6 @@ import twitter4j.conf.ConfigurationBuilder;
* Inserts presence information into Twitter. * Inserts presence information into Twitter.
* *
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a> * @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @version $Revision$, $Date$
* @created Sept 10, 2008 * @created Sept 10, 2008
* @since 1.0 * @since 1.0
*/ */
@ -121,8 +118,8 @@ public class Twitter implements Runnable
final Status status = twitter.updateStatus(message + " (" + sender + ')'); final Status status = twitter.updateStatus(message + " (" + sender + ')');
bot.send(sender, bot.send(sender,
"You message was posted to http://twitter.com/" + twitter.getScreenName() + "/statuses/" + status "You message was posted to http://twitter.com/" + twitter.getScreenName() + "/statuses/" + status
.getId() .getId()
); );
} }
catch (Exception e) catch (Exception e)

View file

@ -20,7 +20,6 @@ import java.io.InputStreamReader;
* *
* @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>
* @version $Revision$, $Date$
* @created Sep 13, 2010 * @created Sep 13, 2010
* @since 1.0 * @since 1.0
*/ */

View file

@ -0,0 +1,309 @@
/*
* @(#)Utils.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import org.jibble.pircbot.Colors;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Calendar;
/**
* Miscellaneous utilities class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-26
* @since 1.0
*/
public class Utils
{
/**
* The timestamp simple date format.
*/
public static final SimpleDateFormat TIMESTAMP_SDF = new SimpleDateFormat("yyyyMMddHHmmss");
/**
* The UTC (yyyy-MM-dd HH:mm) simple date format.
*/
static final SimpleDateFormat UTC_SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm");
/**
* The ISO (YYYY-MM-DD) simple date format.
*/
static final SimpleDateFormat ISO_SDF = new SimpleDateFormat("yyyy-MM-dd");
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private Utils()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Converts XML/XHTML entities to plain text.
*
* @param str The string to unescape.
*
* @return The unescaped string.
*/
public static String unescapeXml(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;
}
/**
* Copies a file.
*
* @param in The source file.
* @param out The destination file.
*
* @throws java.io.IOException If the file could not be copied.
* @noinspection UnusedDeclaration
*/
public static void copyFile(File in, File out)
throws IOException
{
FileChannel inChannel = null;
FileChannel outChannel = null;
FileInputStream input = null;
FileOutputStream output = null;
try
{
input = new FileInputStream(in);
output = new FileOutputStream(out);
inChannel = input.getChannel();
outChannel = output.getChannel();
inChannel.transferTo(0L, inChannel.size(), outChannel);
}
finally
{
try
{
if (inChannel != null)
{
inChannel.close();
}
if (input != null)
{
input.close();
}
}
catch (Exception ignore)
{
; // Do nothing
}
try
{
if (outChannel != null)
{
outChannel.close();
}
if (output != null)
{
output.close();
}
}
catch (Exception ignore)
{
; // Do nothing
}
}
}
/**
* Returns the current Internet (beat) Time.
*
* @return The Internet Time string.
*/
public static String internetTime()
{
final Calendar gc = Calendar.getInstance();
final int offset = (gc.get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000));
int hh = gc.get(Calendar.HOUR_OF_DAY);
final int mm = gc.get(Calendar.MINUTE);
final int ss = gc.get(Calendar.SECOND);
hh -= offset; // GMT
hh += 1; // BMT
long beats = Math.round(Math.floor((double) ((((hh * 3600) + (mm * 60) + ss) * 1000) / 86400)));
if (beats >= 1000)
{
beats -= (long) 1000;
}
else if (beats < 0)
{
beats += (long) 1000;
}
if (beats < 10)
{
return ("@00" + String.valueOf(beats));
}
else if (beats < 100)
{
return ("@0" + String.valueOf(beats));
}
return ('@' + String.valueOf(beats));
}
/**
* Returns a property as an int.
*
* @param property The port property value.
* @param def The default property value.
*
* @return The port or default value if invalid.
*/
public static int getIntProperty(String property, int def)
{
int prop;
try
{
prop = Integer.parseInt(property);
}
catch (NumberFormatException ignore)
{
prop = def;
}
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.
*/
public static String ensureDir(String location, 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 true if the given string is valid.
*
* @param s The string to validate.
*
* @return true if the string is non-empty and not null, false otherwise.
*/
public static boolean isValidString(String s)
{
return (s != null) && (s.trim().length() > 0);
}
/**
* Makes the given int bold.
*
* @param i The int.
*
* @return The bold string.
*/
public static String bold(int i)
{
return Colors.BOLD + i + Colors.BOLD;
}
/**
* 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());
}
/**
* Makes the given string bold.
*
* @param s The string.
*
* @return The bold string.
*/
public static String bold(String s)
{
return Colors.BOLD + s + Colors.BOLD;
}
}

View file

@ -0,0 +1,110 @@
/*
* @(#)War.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import java.util.Random;
/**
* The <code>War</code> class.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-28
* @since 1.0
*/
public class War
{
/**
* The deck of card for the {@link net.thauvin.erik.mobibot.Commands#WAR_CMD war} command.
*/
private static final String[] WAR_DECK =
new String[]{"Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"};
/**
* The suits for the deck of card for the {@link Commands#WAR_CMD war} command.
*/
private static final String[] WAR_SUITS = new String[]{"Hearts", "Spades", "Diamonds", "Clubs"};
/**
* Disables the default constructor.
*
* @throws UnsupportedOperationException if an error occurred. if the constructor is called.
*/
private War()
throws UnsupportedOperationException
{
throw new UnsupportedOperationException("Illegal constructor call.");
}
/**
* Plays war.
*
* @param bot The bot.
* @param sender The sender's nickname.
*/
public static void play(Mobibot bot, String sender)
{
final Random r = new Random();
int i;
int y;
while (true)
{
i = r.nextInt(WAR_DECK.length);
y = r.nextInt(WAR_DECK.length);
bot.send(bot.getChannel(),
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)]);
if (i != y)
{
break;
}
}
if (i < y)
{
bot.action("lost.");
}
else if (i > y)
{
bot.action("wins.");
}
else
{
bot.action("tied.");
}
}
}

View file

@ -1,7 +1,7 @@
/* /*
* @(#)Weather.java * @(#)Weather.java
* *
* Copyright (c) 2004, Erik C. Thauvin (erik@thauvin.net) * Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@ -30,10 +30,8 @@
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id$
*
*/ */
package net.thauvin.erik.mobibot; package net.thauvin.erik.mobibot;
import net.sf.jweather.metar.Metar; import net.sf.jweather.metar.Metar;
@ -48,7 +46,6 @@ import java.util.Iterator;
* Fetches the weather data from a specific station ID. * Fetches the weather data from a specific station ID.
* *
* @author Erik C. Thauvin * @author Erik C. Thauvin
* @version $Revision$, $Date$
* @created Feb 7, 2004 * @created Feb 7, 2004
* @since 1.0 * @since 1.0
*/ */
@ -116,9 +113,9 @@ public class Weather implements Runnable
bot.send(sender, "Station ID: " + metar.getStationID(), isPrivate); bot.send(sender, "Station ID: " + metar.getStationID(), isPrivate);
bot.send(sender, bot.send(sender,
"At: " + metar.getDateString() + " UTC (" + ( "At: " + Utils.UTC_SDF.format(metar.getDate()) + " UTC (" + (
((new Date()).getTime() - metar.getDate().getTime()) / 1000L / 60L) + " minutes ago)", ((new Date()).getTime() - metar.getDate().getTime()) / 1000L / 60L) + " minutes ago)",
isPrivate isPrivate
); );
result = metar.getWindSpeedInMPH(); result = metar.getWindSpeedInMPH();
@ -126,28 +123,30 @@ public class Weather implements Runnable
if (result != null) if (result != null)
{ {
bot.send(sender, bot.send(sender,
"Wind Speed: " + result + " mph, " + metar.getWindSpeedInKnots() + " knots", isPrivate); "Wind Speed: " + result + " mph, " + metar.getWindSpeedInKnots() + " knots, " + metar
.getWindSpeedInMPS() + " m/s",
isPrivate
);
} }
result = metar.getVisibility(); result = metar.getVisibility();
if (result != null) if (result != null)
{ {
if (!metar.getVisibilityLessThan()) bot.send(sender,
{ "Visibility: " + (metar.getVisibilityLessThan() ? "< " : "") + NUMBER_FORMAT.format(result)
bot.send(sender, "Visibility: " + NUMBER_FORMAT.format(result) + " mile(s)", isPrivate); + " mi, " + metar.getVisibilityInKilometers() + " km",
} isPrivate
else );
{
bot.send(sender, "Visibility: < " + NUMBER_FORMAT.format(result) + " mile(s)", isPrivate);
}
} }
result = metar.getPressure(); result = metar.getPressure();
if (result != null) if (result != null)
{ {
bot.send(sender, "Pressure: " + result + " in Hg", isPrivate); bot.send(sender,
"Pressure: " + result + " Hg, " + metar.getPressureInHectoPascals() + " hPa",
isPrivate);
} }
result = metar.getTemperatureInCelsius(); result = metar.getTemperatureInCelsius();
@ -155,7 +154,8 @@ public class Weather implements Runnable
if (result != null) if (result != null)
{ {
bot.send(sender, bot.send(sender,
"Temperature: " + result + " C, " + metar.getTemperatureInFahrenheit() + " F", isPrivate); "Temperature: " + result + " \u00B0C, " + metar.getTemperatureInFahrenheit() + " \u00B0F",
isPrivate);
} }
if (metar.getWeatherConditions() != null) if (metar.getWeatherConditions() != null)
@ -192,6 +192,6 @@ public class Weather implements Runnable
} }
} }
bot.helpResponse(sender, Mobibot.WEATHER_CMD); bot.helpResponse(sender, Commands.WEATHER_CMD);
} }
} }

View file

@ -0,0 +1,190 @@
/*
* @(#)Time.java
*
* Copyright (c) 2004-2014, Erik C. Thauvin (erik@thauvin.net)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the author nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package net.thauvin.erik.mobibot;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;
/**
* Processes the {@link net.thauvin.erik.mobibot.Commands#TIME_CMD} command.
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-27
* @since 1.0
*/
public class WorldTime
{
/**
* The countries supported by the {@link net.thauvin.erik.mobibot.Commands#TIME_CMD time} command.
*/
private static final Map<String, String> COUNTRIES_MAP = new TreeMap<String, String>();
/**
* The beats (Internet Time) keyword.
*/
private static final String BEATS_KEYWORD = ".beats";
/**
* The date/time format for the {@link net.thauvin.erik.mobibot.Commands#TIME_CMD time} command.
*/
private static final SimpleDateFormat TIME_SDF =
new SimpleDateFormat("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '");
/**
* Creates a new time object.
*/
public WorldTime()
{
// Initialize the countries map
COUNTRIES_MAP.put("AU", "Australia/Sydney");
COUNTRIES_MAP.put("BE", "Europe/Brussels");
COUNTRIES_MAP.put("CA", "America/Montreal");
COUNTRIES_MAP.put("CDT", "America/Chicago");
COUNTRIES_MAP.put("CET", "CET");
COUNTRIES_MAP.put("CH", "Europe/Zurich");
COUNTRIES_MAP.put("CN", "Asia/Shanghai");
COUNTRIES_MAP.put("CST", "America/Chicago");
COUNTRIES_MAP.put("CU", "Cuba");
COUNTRIES_MAP.put("DE", "Europe/Berlin");
COUNTRIES_MAP.put("DK", "Europe/Copenhagen");
COUNTRIES_MAP.put("EDT", "America/New_York");
COUNTRIES_MAP.put("EG", "Africa/Cairo");
COUNTRIES_MAP.put("ER", "Africa/Asmara");
COUNTRIES_MAP.put("ES", "Europe/Madrid");
COUNTRIES_MAP.put("EST", "America/New_York");
COUNTRIES_MAP.put("FI", "Europe/Helsinki");
COUNTRIES_MAP.put("FR", "Europe/Paris");
COUNTRIES_MAP.put("GB", "Europe/London");
COUNTRIES_MAP.put("GMT", "GMT");
COUNTRIES_MAP.put("HK", "Asia/Hong_Kong");
COUNTRIES_MAP.put("HST", "HST");
COUNTRIES_MAP.put("IE", "Europe/Dublin");
COUNTRIES_MAP.put("IL", "Asia/Tel_Aviv");
COUNTRIES_MAP.put("IN", "Asia/Calcutta");
COUNTRIES_MAP.put("IR", "Asia/Tehran");
COUNTRIES_MAP.put("IS", "Atlantic/Reykjavik");
COUNTRIES_MAP.put("IT", "Europe/Rome");
COUNTRIES_MAP.put("JM", "Jamaica");
COUNTRIES_MAP.put("JP", "Asia/Tokyo");
COUNTRIES_MAP.put("LY", "Africa/Tripoli");
COUNTRIES_MAP.put("MDT", "America/Denver");
COUNTRIES_MAP.put("MH", "Kwajalein");
COUNTRIES_MAP.put("MST", "America/Denver");
COUNTRIES_MAP.put("MX", "America/Mexico_City");
COUNTRIES_MAP.put("NL", "Europe/Amsterdam");
COUNTRIES_MAP.put("NO", "Europe/Oslo");
COUNTRIES_MAP.put("NP", "Asia/Katmandu");
COUNTRIES_MAP.put("NZ", "Pacific/Auckland");
COUNTRIES_MAP.put("PDT", "America/Los_Angeles");
COUNTRIES_MAP.put("PK", "Asia/Karachi");
COUNTRIES_MAP.put("PL", "Europe/Warsaw");
COUNTRIES_MAP.put("PST", "America/Los_Angeles");
COUNTRIES_MAP.put("PT", "Europe/Lisbon");
COUNTRIES_MAP.put("RU", "Europe/Moscow");
COUNTRIES_MAP.put("SE", "Europe/Stockholm");
COUNTRIES_MAP.put("SG", "Asia/Singapore");
COUNTRIES_MAP.put("SU", "Europe/Moscow");
COUNTRIES_MAP.put("TH", "Asia/Bangkok");
COUNTRIES_MAP.put("TM", "Asia/Ashgabat");
COUNTRIES_MAP.put("TR", "Europe/Istanbul");
COUNTRIES_MAP.put("TW", "Asia/Taipei");
COUNTRIES_MAP.put("UK", "Europe/London");
COUNTRIES_MAP.put("US", "America/New_York");
COUNTRIES_MAP.put("UTC", "UTC");
COUNTRIES_MAP.put("VA", "Europe/Vatican");
COUNTRIES_MAP.put("VN", "Asia/Ho_Chi_Minh");
COUNTRIES_MAP.put("INTERNET", BEATS_KEYWORD);
COUNTRIES_MAP.put("BEATS", BEATS_KEYWORD);
for (final String tz : TimeZone.getAvailableIDs())
{
if (!tz.contains("/") && tz.length() == 3 & !COUNTRIES_MAP.containsKey(tz))
{
COUNTRIES_MAP.put(tz, tz);
}
}
}
/**
* Responds with the current time.
*
* @param sender The nick of the person who sent the message.
* @param args The time command arguments.
* @param isPrivate Set to true is the response should be send as a private message.
*/
public final void timeResponse(Mobibot bot, String sender, String args, boolean isPrivate)
{
boolean isInvalidTz = false;
final String tz = (COUNTRIES_MAP.get((args.substring(args.indexOf(' ') + 1).trim().toUpperCase())));
final String response;
if (tz != null)
{
if (tz.equals(BEATS_KEYWORD))
{
response = ("The current Internet Time is: " + Utils.internetTime() + ' ' + BEATS_KEYWORD);
}
else
{
TIME_SDF.setTimeZone(TimeZone.getTimeZone(tz));
response = TIME_SDF.format(Calendar.getInstance().getTime()) + tz.substring(tz.indexOf('/') + 1)
.replace('_', ' ');
}
}
else
{
isInvalidTz = true;
response = "The supported time zones/countries are: " + COUNTRIES_MAP.keySet().toString();
}
if (isPrivate)
{
bot.send(sender, response, true);
}
else
{
if (isInvalidTz)
{
bot.send(sender, response);
}
else
{
bot.send(bot.getChannel(), response);
}
}
}
}