Code cleanup.

More gradle integration.
Implemented random quote via iheartquotes.com
Implemented war game.
This commit is contained in:
Erik C. Thauvin 2014-04-24 06:07:45 -07:00
parent 5858e12b1a
commit 153363a320
23 changed files with 1408 additions and 1004 deletions

1
.gitignore vendored
View file

@ -17,4 +17,5 @@
/proguard-project.txt
/project.properties
/test-output
/weather.log
CVS

View file

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

View file

@ -1,10 +1,14 @@
apply plugin: 'java'
apply plugin: 'idea'
version = '0.5'
ext.packageName = 'net.thauvin.erik.mobibot'
ext.mainClassName = packageName + '.Mobibot'
ext.deployDir = 'deploy'
defaultTasks 'deploy'
version = '0.6'
def packageName = 'net.thauvin.erik.mobibot'
def mainClassName = packageName + '.Mobibot'
def deployDir = 'deploy'
def isRelease = 'release' in gradle.startParameter.taskNames
repositories {
mavenCentral()
@ -40,13 +44,10 @@ dependencies {
//compile files('../path/to/example.jar')
}
task wrapper(type: Wrapper) {
gradleVersion = gradle.gradleVersion
}
compileJava {
dependsOn wrapper
doFirst {
if (isRelease)
{
ant.taskdef(name: 'jreleaseinfo',
classname: 'ch.oscg.jreleaseinfo.anttask.JReleaseInfoAntTask',
classpath: 'ant/jreleaseinfo-1.3.0.jar')
@ -56,35 +57,54 @@ compileJava {
project: rootProject.name,
version: version,
buildnumfile: file('buildnum.properties'))
}
}
//options.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
}
jar {
doFirst {
manifest {
attributes("Manifest-Version": "1.0",
"Main-Class": mainClassName,
"Class-Path": '. ./lib/' + configurations.compile.collect { it.getName() }.join(' ./lib/'))
}
}
manifest.attributes(
'Main-Class': mainClassName,
'Class-Path': '. ./lib/' + configurations.compile.collect { it.getName() }.join(' ./lib/'))
version = null
}
task deploy(dependsOn: build) {
description = "Copies all needed files to the ${deployDir} directory."
copy {
into deployDir + '/lib'
from configurations.runtime
clean {
delete deployDir
}
task wrapper(type: Wrapper) {
gradleVersion = gradle.gradleVersion
}
task copyToDeploy(type: Copy) {
from('properties') {
include '*.properties'
}
copy {
from 'properties'
into deployDir
include('*.properties')
}
copy {
from jar
into deployDir
}
file(deployDir + '/logs').mkdirs();
}
task copyToDeployLib(type: Copy) {
configurations.runtime
into deployDir + '/lib'
}
task deploy(dependsOn: ['build', 'copyToDeploy', 'copyToDeployLib']) {
description = "Copies all needed files to the ${deployDir} directory."
group = "Publishing"
outputs.dir deployDir
inputs.files copyToDeploy
inputs.files copyToDeployLib
mustRunAfter clean
file(deployDir + '/logs').mkdir()
}
task release(dependsOn: ['deploy', 'wrapper']) {
group = "Publishing"
description = "Releases new version."
isRelease = true
}

View file

@ -1,12 +0,0 @@
# Project
proj.name=mobibot
proj.version=0.5
proj.package=net.thauvin.erik.mobibot
proj.run=${proj.package}.Mobibot
# Locations
path.classes=build
path.src=src
path.dist=dist
path.lib=lib
path.ant=ant

View file

@ -1,3 +1,3 @@
#ANT Task: ch.oscg.jreleaseinfo.BuildNumberHandler
#Sat Apr 19 21:14:33 PDT 2014
build.num.last=40
#Sun Apr 20 23:26:28 PDT 2014
build.num.last=0

View file

@ -1,6 +1,6 @@
Mobibot License
Copyright (c) 2004-2010, Erik C. Thauvin (erik@thauvin.net)
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,

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<module external.linked.project.path="$MODULE_DIR$" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.5" relativePaths="false" type="JAVA_MODULE" version="4">
<module external.linked.project.path="K:\java\mobibot" external.root.project.path="$MODULE_DIR$" external.system.id="GRADLE" external.system.module.group="" external.system.module.version="0.6" relativePaths="false" type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
@ -24,12 +24,12 @@
<orderEntry type="library" exported="" name="Gradle: jsoup-1.7.3" level="project" />
<orderEntry type="library" exported="" name="Gradle: rome-1.0" level="project" />
<orderEntry type="library" exported="" name="Gradle: json-20140107" level="project" />
<orderEntry type="library" exported="" name="Gradle: utils-1.07.00" level="project" />
<orderEntry type="library" exported="" name="Gradle: jweather-0.3.0" level="project" />
<orderEntry type="library" exported="" name="Gradle: twitter4j-core-4.0.1" level="project" />
<orderEntry type="library" exported="" name="Gradle: delicious-1.14" level="project" />
<orderEntry type="library" exported="" name="Gradle: rome-fetcher-1.0" level="project" />
<orderEntry type="library" exported="" name="Gradle: exp4j-0.3.11" level="project" />
<orderEntry type="library" exported="" name="Gradle: utils-1.07.00" level="project" />
</component>
</module>

View file

@ -109,10 +109,9 @@
<option name="gradleHome" value="C:/gradle" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="K:\java\mobibot" />
</set>
</option>
<option name="useAutoImport" value="true" />
</GradleProjectSettings>
</option>
</component>
@ -641,7 +640,7 @@
<module fileurl="file://$PROJECT_DIR$/mobibot.iml" filepath="$PROJECT_DIR$/mobibot.iml" />
</modules>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_3" assert-keyword="false" jdk-15="false" project-jdk-name="1.7.x" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.7.x" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="ResourceManagerContainer">
@ -775,13 +774,6 @@
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/log4j/log4j/1.2.17/677abe279b68c5e7490d6d50c6951376238d7d3e/log4j-1.2.17-sources.jar!/" />
</SOURCES>
</library>
<library name="Gradle: MathEvaluator">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/MathEvaluator.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
<library name="Gradle: oro-2.0.8">
<CLASSES>
<root url="jar://$USER_HOME$/.gradle/caches/modules-2/files-2.1/oro/oro/2.0.8/5592374f834645c4ae250f4c9fbb314c9369d698/oro-2.0.8.jar!/" />

File diff suppressed because it is too large Load diff

View file

@ -65,7 +65,7 @@ public class CurrencyConverter implements Runnable
/**
* The exchange rates.
*/
private static final Map EXCHANGE_RATES = new TreeMap();
private static final Map<String, String> EXCHANGE_RATES = new TreeMap<String, String>();
/**
* The rates keyword.
@ -75,22 +75,22 @@ public class CurrencyConverter implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The actual currency _query.
* The actual currency query.
*/
private final String _query;
private final String query;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* The last exchange rates table publication date.
*/
private String s_date = "";
private String pubDate = "";
/**
* Creates a new CurrencyConverter object.
@ -102,11 +102,11 @@ public class CurrencyConverter implements Runnable
*/
public CurrencyConverter(Mobibot bot, String sender, String query, String date)
{
_bot = bot;
_sender = sender;
_query = query.toLowerCase();
this.bot = bot;
this.sender = sender;
this.query = query.toLowerCase();
if (!s_date.equals(date))
if (!pubDate.equals(date))
{
EXCHANGE_RATES.clear();
}
@ -128,14 +128,14 @@ public class CurrencyConverter implements Runnable
final Element cubeRoot = root.getChild("Cube", ns);
final Element cubeTime = cubeRoot.getChild("Cube", ns);
s_date = cubeTime.getAttribute("time").getValue();
pubDate = cubeTime.getAttribute("time").getValue();
final List cubes = cubeTime.getChildren();
Element cube;
for (int i = 0; i < cubes.size(); i++)
for (final Object rawCube : cubes)
{
cube = (Element) cubes.get(i);
cube = (Element) rawCube;
EXCHANGE_RATES.put(cube.getAttribute("currency").getValue(), cube.getAttribute("rate").getValue());
}
@ -143,37 +143,37 @@ public class CurrencyConverter implements Runnable
}
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);
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());
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-z]{3}+ to [a-z]{3}+"))
if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-z]{3}+ to [a-z]{3}+"))
{
final String[] cmds = _query.split(" ");
final String[] cmds = query.split(" ");
if (cmds.length == 4)
{
if (cmds[3].equals(cmds[1]))
{
_bot.send(_sender, "You're kidding, right?");
bot.send(sender, "You're kidding, right?");
}
else
{
try
{
final double amt = Double.parseDouble(cmds[0].replaceAll(",", ""));
final double from = Double.parseDouble((String) EXCHANGE_RATES.get(cmds[1].toUpperCase()));
final double to = Double.parseDouble((String) EXCHANGE_RATES.get(cmds[3].toUpperCase()));
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) + ' ' +
cmds[1].toUpperCase() + " = " +
NumberFormat.getCurrencyInstance(Locale.US).format((amt * to) / from).substring(1)
@ -182,23 +182,23 @@ public class CurrencyConverter implements Runnable
}
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(RATES_KEYWORD))
else if (query.equals(RATES_KEYWORD))
{
_bot.send(_sender, "Last Update: " + s_date);
bot.send(sender, "Last Update: " + pubDate);
final Iterator it = EXCHANGE_RATES.keySet().iterator();
final Iterator<String> it = EXCHANGE_RATES.keySet().iterator();
String rate;
final StringBuffer buff = new StringBuffer(0);
final StringBuilder buff = new StringBuilder(0);
while (it.hasNext())
{
rate = (String) it.next();
rate = it.next();
if (buff.length() > 0)
{
buff.append(", ");
@ -206,19 +206,19 @@ public class CurrencyConverter implements Runnable
buff.append(rate).append(": ").append(EXCHANGE_RATES.get(rate));
}
_bot.send(_sender, buff.toString());
bot.send(sender, buff.toString());
}
else
{
_bot.helpResponse(_sender, Mobibot.CURRENCY_CMD + ' ' + _query);
_bot.send(_sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
bot.helpResponse(sender, Mobibot.CURRENCY_CMD + ' ' + query);
bot.send(sender, "The supported currencies are: " + EXCHANGE_RATES.keySet().toString());
}
}
else
{
_bot.getLogger().debug("The exchange rate table is empty.");
_bot.send(_sender, "Sorry, but 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.");
}
}
}

View file

@ -49,9 +49,9 @@ import del.icio.us.Delicious;
*/
public class DeliciousPoster
{
private final Delicious _delicious;
private final Delicious delicious;
private final String _ircServer;
private final String ircServer;
/**
* Creates a new DeliciousPoster instance.
@ -62,8 +62,8 @@ public class DeliciousPoster
*/
public DeliciousPoster(String username, String password, String ircServer)
{
_delicious = new Delicious(username, password);
_ircServer = ircServer;
delicious = new Delicious(username, password);
this.ircServer = ircServer;
}
/**
@ -77,7 +77,7 @@ public class DeliciousPoster
{
public Object construct()
{
return Boolean.valueOf(_delicious.addPost(entry.getLink(),
return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
@ -101,7 +101,7 @@ public class DeliciousPoster
{
public Object construct()
{
return Boolean.valueOf(_delicious.deletePost(link));
return Boolean.valueOf(delicious.deletePost(link));
}
};
@ -122,9 +122,9 @@ public class DeliciousPoster
{
if (!oldUrl.equals(entry.getLink()))
{
_delicious.deletePost(oldUrl);
delicious.deletePost(oldUrl);
return Boolean.valueOf(_delicious.addPost(entry.getLink(),
return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
@ -132,7 +132,7 @@ public class DeliciousPoster
}
else
{
return Boolean.valueOf(_delicious.addPost(entry.getLink(),
return Boolean.valueOf(delicious.addPost(entry.getLink(),
entry.getTitle(),
postedBy(entry),
entry.getDeliciousTags(),
@ -155,6 +155,6 @@ public class DeliciousPoster
*/
private String postedBy(EntryLink entry)
{
return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + _ircServer + ')';
return "Posted by " + entry.getNick() + " on " + entry.getChannel() + " (" + ircServer + ')';
}
}

View file

@ -52,17 +52,19 @@ public class EntryComment implements Serializable
{
/**
* The serial version UID.
*
* @noinspection UnusedDeclaration
*/
static final long serialVersionUID = 6957415292233553224L;
/**
* 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.
@ -72,8 +74,8 @@ public class EntryComment implements Serializable
*/
public EntryComment(String comment, String nick)
{
_comment = comment;
_nick = nick;
this.comment = comment;
this.nick = nick;
}
/**
@ -92,7 +94,7 @@ public class EntryComment implements Serializable
*/
public final String getComment()
{
return _comment;
return comment;
}
/**
@ -103,17 +105,19 @@ public class EntryComment implements Serializable
*/
public final void setComment(String comment)
{
_comment = comment;
this.comment = comment;
}
/**
* Returns the comment's creation date.
*
* @return The date.
*
* @noinspection UnusedDeclaration
*/
public final Date getDate()
{
return _date;
return date;
}
/**
@ -123,7 +127,7 @@ public class EntryComment implements Serializable
*/
public final String getNick()
{
return _nick;
return nick;
}
/**
@ -133,6 +137,6 @@ public class EntryComment implements Serializable
*/
public final void setNick(String nick)
{
_nick = nick;
this.nick = nick;
}
}

View file

@ -56,32 +56,34 @@ public class EntryLink implements Serializable
{
/**
* The serial version UID.
*
* @noinspection UnusedDeclaration
*/
static final long serialVersionUID = 3676245542270899086L;
// The link's comments
private final List _comments = new ArrayList(0);
private final List<EntryComment> comments = new ArrayList<EntryComment>(0);
// The tags/categories
private final List _tags = new ArrayList(0);
private final List<SyndCategoryImpl> tags = new ArrayList<SyndCategoryImpl>(0);
// The channel
private String _channel = "";
private String channel = "";
// The creation date
private Date _date = Calendar.getInstance().getTime();
private Date date = Calendar.getInstance().getTime();
// The link's URL
private String _link = "";
private String link = "";
// The author's login
private String _login = "";
private String login = "";
// The author's nickname
private String _nick = "";
private String nick = "";
// The link's title
private String _title = "";
private String title = "";
/**
* Creates a new entry.
@ -95,11 +97,11 @@ public class EntryLink implements Serializable
*/
public EntryLink(String link, String title, String nick, String login, String channel, String tags)
{
_link = link;
_title = title;
_nick = nick;
_login = login;
_channel = channel;
this.link = link;
this.title = title;
this.nick = nick;
this.login = login;
this.channel = channel;
setTags(tags);
}
@ -114,13 +116,13 @@ public class EntryLink implements Serializable
* @param date The entry date.
* @param tags The entry's tags/categories.
*/
public EntryLink(String link, String title, String nick, String channel, Date date, List tags)
public EntryLink(String link, String title, String nick, String channel, Date date, List<SyndCategoryImpl> tags)
{
_link = link;
_title = title;
_nick = nick;
_channel = channel;
_date = date;
this.link = link;
this.title = title;
this.nick = nick;
this.channel = channel;
this.date = date;
setTags(tags);
}
@ -144,9 +146,9 @@ public class EntryLink implements Serializable
*/
public final synchronized int addComment(String comment, String nick)
{
_comments.add(new EntryComment(comment, nick));
comments.add(new EntryComment(comment, nick));
return (_comments.size() - 1);
return (comments.size() - 1);
}
/**
@ -156,9 +158,9 @@ public class EntryLink implements Serializable
*/
public final synchronized void deleteComment(int index)
{
if (index < _comments.size())
if (index < comments.size())
{
_comments.remove(index);
comments.remove(index);
}
}
@ -169,7 +171,7 @@ public class EntryLink implements Serializable
*/
public final synchronized String getChannel()
{
return _channel;
return channel;
}
/**
@ -180,7 +182,7 @@ public class EntryLink implements Serializable
*/
public final synchronized void setChannel(String channel)
{
_channel = channel;
this.channel = channel;
}
/**
@ -192,7 +194,7 @@ public class EntryLink implements Serializable
*/
public final synchronized EntryComment getComment(int index)
{
return ((EntryComment) _comments.get(index));
return (comments.get(index));
}
/**
@ -202,7 +204,7 @@ public class EntryLink implements Serializable
*/
public final synchronized EntryComment[] getComments()
{
return ((EntryComment[]) _comments.toArray(new EntryComment[_comments.size()]));
return (comments.toArray(new EntryComment[comments.size()]));
}
/**
@ -212,7 +214,7 @@ public class EntryLink implements Serializable
*/
public final synchronized int getCommentsCount()
{
return _comments.size();
return comments.size();
}
/**
@ -222,7 +224,7 @@ public class EntryLink implements Serializable
*/
public final synchronized Date getDate()
{
return _date;
return date;
}
/**
@ -232,12 +234,12 @@ public class EntryLink implements Serializable
*/
public final synchronized String getDeliciousTags()
{
final StringBuffer tags = new StringBuffer(_nick);
final StringBuilder tags = new StringBuilder(nick);
for (int i = 0; i < _tags.size(); i++)
for (final Object tag : this.tags)
{
tags.append(',');
tags.append(((SyndCategoryImpl) _tags.get(i)).getName());
tags.append(((SyndCategoryImpl) tag).getName());
}
return tags.toString();
@ -250,7 +252,7 @@ public class EntryLink implements Serializable
*/
public final synchronized String getLink()
{
return _link;
return link;
}
/**
@ -260,7 +262,7 @@ public class EntryLink implements Serializable
*/
public final synchronized void setLink(String link)
{
_link = link;
this.link = link;
}
/**
@ -270,7 +272,7 @@ public class EntryLink implements Serializable
*/
public final synchronized String getLogin()
{
return _login;
return login;
}
/**
@ -281,7 +283,7 @@ public class EntryLink implements Serializable
*/
public final synchronized void setLogin(String login)
{
_login = login;
this.login = login;
}
/**
@ -291,7 +293,7 @@ public class EntryLink implements Serializable
*/
public final synchronized String getNick()
{
return _nick;
return nick;
}
/**
@ -301,7 +303,7 @@ public class EntryLink implements Serializable
*/
public final synchronized void setNick(String nick)
{
_nick = nick;
this.nick = nick;
}
/**
@ -311,7 +313,7 @@ public class EntryLink implements Serializable
*/
public final synchronized List getTags()
{
return _tags;
return tags;
}
/**
@ -329,9 +331,9 @@ public class EntryLink implements Serializable
String part;
char mod;
for (int i = 0; i < parts.length; i++)
for (final String rawPart : parts)
{
part = parts[i].trim();
part = rawPart.trim();
if (part.length() >= 2)
{
@ -343,25 +345,25 @@ public class EntryLink implements Serializable
if (mod == '-')
{
// Don't remove the channel tag, if any.
if (!tag.getName().equals(_channel.substring(1)))
if (!tag.getName().equals(channel.substring(1)))
{
_tags.remove(tag);
this.tags.remove(tag);
}
}
else if (mod == '+')
{
if (!_tags.contains(tag))
if (!this.tags.contains(tag))
{
_tags.add(tag);
this.tags.add(tag);
}
}
else
{
tag.setName(part.trim().toLowerCase());
if (!_tags.contains(tag))
if (!this.tags.contains(tag))
{
_tags.add(tag);
this.tags.add(tag);
}
}
}
@ -376,7 +378,7 @@ public class EntryLink implements Serializable
*/
public final synchronized String getTitle()
{
return _title;
return title;
}
/**
@ -386,7 +388,7 @@ public class EntryLink implements Serializable
*/
public final synchronized void setTitle(String title)
{
_title = title;
this.title = title;
}
/**
@ -396,7 +398,7 @@ public class EntryLink implements Serializable
*/
public final synchronized boolean hasComments()
{
return (!_comments.isEmpty());
return (!comments.isEmpty());
}
/**
@ -406,7 +408,7 @@ public class EntryLink implements Serializable
*/
public final synchronized boolean hasTags()
{
return (!_tags.isEmpty());
return (!tags.isEmpty());
}
/**
@ -418,9 +420,9 @@ public class EntryLink implements Serializable
*/
public final synchronized void setComment(int index, String comment, String nick)
{
if (index < _comments.size())
if (index < comments.size())
{
_comments.set(index, new EntryComment(comment, nick));
comments.set(index, new EntryComment(comment, nick));
}
}
@ -429,9 +431,9 @@ public class EntryLink implements Serializable
*
* @param tags The tags.
*/
public final synchronized void setTags(List tags)
public final synchronized void setTags(List<SyndCategoryImpl> tags)
{
_tags.addAll(tags);
this.tags.addAll(tags);
}
/**
@ -442,8 +444,8 @@ public class EntryLink implements Serializable
public final String toString()
{
return super.toString() + "[ channel -> '" + _channel + '\'' + ", comments -> " + _comments + ", date -> "
+ _date + ", link -> '" + _link + '\'' + ", login -> '" + _login + '\'' + ", nick -> '" + _nick + '\''
+ ", tags -> " + _tags + ", title -> '" + _title + '\'' + " ]";
return super.toString() + "[ channel -> '" + channel + '\'' + ", comments -> " + comments + ", date -> "
+ date + ", link -> '" + link + '\'' + ", login -> '" + login + '\'' + ", nick -> '" + nick + '\''
+ ", tags -> " + tags + ", title -> '" + title + '\'' + " ]";
}
}

View file

@ -69,17 +69,17 @@ public class FeedReader implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* The URL to fetch.
*/
private final String _url;
private final String url;
/**
* Creates a new FeedReader object.
@ -90,9 +90,9 @@ public class FeedReader implements Runnable
*/
public FeedReader(Mobibot bot, String sender, String url)
{
_bot = bot;
_sender = sender;
_url = url;
this.bot = bot;
this.sender = sender;
this.url = url;
}
/**
@ -100,30 +100,30 @@ public class FeedReader implements Runnable
*/
public final void run()
{
final FeedFetcher fetcher = new HttpURLFeedFetcher(_bot.getFeedInfoCache());
final FeedFetcher fetcher = new HttpURLFeedFetcher(bot.getFeedInfoCache());
try
{
final SyndFeed feed = fetcher.retrieveFeed(new URL(_url));
final SyndFeed feed = fetcher.retrieveFeed(new URL(url));
SyndEntry item;
final List items = feed.getEntries();
for (int i = 0; (i < items.size()) && (i < MAX_ITEMS); i++)
{
item = (SyndEntryImpl) items.get(i);
_bot.send(_sender, item.getTitle());
_bot.send(_sender, TAB_INDENT + item.getLink());
bot.send(sender, item.getTitle());
bot.send(sender, TAB_INDENT + item.getLink());
}
}
catch (MalformedURLException e)
{
_bot.getLogger().debug("Invalid feed URL.", e);
_bot.send(_sender, "The feed URL is invalid.");
bot.getLogger().debug("Invalid feed URL.", e);
bot.send(sender, "The feed URL is invalid.");
}
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());
bot.getLogger().debug("Unable to fetch the feed.", e);
bot.send(sender, "An error has occurred while fetching the feed: " + e.getMessage());
}
}
}

View file

@ -64,17 +64,17 @@ public class GoogleSearch implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The search query.
*/
private final String _query;
private final String query;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* Creates a new GoogleSearch object.
@ -85,9 +85,9 @@ public class GoogleSearch implements Runnable
*/
public GoogleSearch(Mobibot bot, String sender, String query)
{
_bot = bot;
_sender = sender;
_query = query;
this.bot = bot;
this.sender = sender;
this.query = query;
}
/**
@ -98,13 +98,13 @@ public class GoogleSearch implements Runnable
try
{
final String query = URLEncoder.encode(_query, "UTF-8");
final String query = URLEncoder.encode(this.query, "UTF-8");
final URL url =
new URL("http://ajax.googleapis.com/ajax/services/search/web?start=0&rsz=small&v=1.0&q=" + query);
final URLConnection conn = url.openConnection();
final StringBuffer sb = new StringBuffer();
final StringBuilder sb = new StringBuilder();
final BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
@ -119,8 +119,8 @@ public class GoogleSearch implements Runnable
for (int i = 0; i < ja.length(); i++)
{
final JSONObject j = ja.getJSONObject(i);
_bot.send(_sender, Mobibot.unescapeXml(j.getString("titleNoFormatting")));
_bot.send(_sender, TAB_INDENT + j.getString("url"));
bot.send(sender, Mobibot.unescapeXml(j.getString("titleNoFormatting")));
bot.send(sender, TAB_INDENT + j.getString("url"));
}
reader.close();
@ -128,8 +128,8 @@ public class GoogleSearch implements Runnable
}
catch (Exception e)
{
_bot.getLogger().warn("Unable to search in Google for: " + _query, e);
_bot.send(_sender, "An error has occurred: " + e.getMessage());
bot.getLogger().warn("Unable to search in Google for: " + query, e);
bot.send(sender, "An error has occurred: " + e.getMessage());
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,109 @@
/*
* @(#)Quote.java
*
* Copyright (c) 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.
*
* $Id$
*
*/
package net.thauvin.erik.mobibot;
import org.jibble.pircbot.Colors;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
/**
* Retrieve quote from <a href="iheartquotes.com">I Heart Quotes</a>
*
* @author <a href="mailto:erik@thauvin.net">Erik C. Thauvin</a>
* @created 2014-04-20
* @since 1.0
*/
public class Quote implements Runnable
{
/**
* The bot.
*/
private final Mobibot bot;
/**
* The nick of the person who sent the message.
*/
private final String sender;
/**
* Creates a new StockQuote object.
*
* @param bot The bot.
* @param sender The nick of the person who sent the message.
*/
public Quote(Mobibot bot, String sender)
{
this.bot = bot;
this.sender = sender;
}
/**
* Returns a random quote.
*/
public final void run()
{
try
{
final URL url = new URL("http://www.iheartquotes.com/api/v1/random?format=json&max_lines=1");
final URLConnection conn = url.openConnection();
final StringBuilder sb = new StringBuilder();
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.BLUE + json.getString("quote") + Colors.BLUE);
reader.close();
}
catch (Exception e)
{
bot.getLogger().warn("Unable to retrieve random quote.", e);
bot.send(sender, "An error has occurred: " + e.getMessage());
}
}
}

View file

@ -1,5 +1,5 @@
/* Created by JReleaseInfo AntTask from Open Source Competence Group */
/* Creation date Sat Apr 19 21:14:33 PDT 2014 */
/* Creation date Sun Apr 20 23:26:28 PDT 2014 */
package net.thauvin.erik.mobibot;
import java.util.Date;
@ -20,11 +20,11 @@ public class ReleaseInfo {
}
/** buildDate (set during build process to 1397967273141L). */
private static final Date buildDate = new Date(1397967273141L);
/** buildDate (set during build process to 1398061588708L). */
private static final Date buildDate = new Date(1398061588708L);
/**
* Get buildDate (set during build process to Sat Apr 19 21:14:33 PDT 2014).
* Get buildDate (set during build process to Sun Apr 20 23:26:28 PDT 2014).
* @return Date buildDate
*/
public static Date getBuildDate() { return buildDate; }
@ -40,20 +40,20 @@ public class ReleaseInfo {
public static String getProject() { return project; }
/** version (set during build process to "0.5"). */
private static final String version = "0.5";
/** version (set during build process to "0.6"). */
private static final String version = "0.6";
/**
* Get version (set during build process to "0.5").
* Get version (set during build process to "0.6").
* @return String version
*/
public static String getVersion() { return version; }
/**
* Get buildNumber (set during build process to 40).
* Get buildNumber (set during build process to 0).
* @return int buildNumber
*/
public static int getBuildNumber() { return 40; }
public static int getBuildNumber() { return 0; }
}

View file

@ -60,17 +60,17 @@ public class StockQuote implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* The stock symbol.
*/
private final String _symbol;
private final String symbol;
/**
* Creates a new StockQuote object.
@ -81,9 +81,9 @@ public class StockQuote implements Runnable
*/
public StockQuote(Mobibot bot, String sender, String symbol)
{
_bot = bot;
_sender = sender;
_symbol = symbol;
this.bot = bot;
this.sender = sender;
this.symbol = symbol;
}
/**
@ -97,7 +97,7 @@ public class StockQuote implements Runnable
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);
final String[][] lines = CSVParser.parse(getMethod.getResponseBodyAsString());
@ -110,56 +110,56 @@ public class StockQuote implements Runnable
{
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)
{
_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]);
bot.send(bot.getChannel(), "Last Trade: " + quote[2]);
}
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]))
{
_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]))
{
_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]))
{
_bot.send(_sender, "Volume: " + quote[9]);
bot.send(sender, "Volume: " + quote[9]);
}
}
else
{
_bot.send(_sender, "Invalid ticker symbol.");
bot.send(sender, "Invalid ticker symbol.");
}
}
else
{
_bot.send(_sender, "No values returned.");
bot.send(sender, "No values returned.");
}
}
else
{
_bot.send(_sender, "No data returned.");
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: " + e.getMessage());
bot.getLogger().debug("Unable to retrieve stock quote for: " + symbol, e);
bot.send(sender, "An error has occurred: " + e.getMessage());
}
}
}

View file

@ -53,37 +53,37 @@ public class Twitter implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The Twitter consumer secret.
*/
private final String _consumerSecret;
private final String consumerSecret;
/**
* The Twitter consumer key.
*/
private final String _consumerKey;
private final String consumerKey;
/**
* The Twitter message.
*/
private final String _message;
private final String message;
/**
* The Twitter access token.
*/
private final String _accessToken;
private final String accessToken;
/**
* The Twitter access token secret.
*/
private final String _accessTokenSecret;
private final String accessTokenSecret;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* Creates a new Twitter object.
@ -99,13 +99,13 @@ public class Twitter implements Runnable
public Twitter(Mobibot bot, String sender, String consumerKey, String consumerSecret, String accessToken,
String accessTokenSecret, String message)
{
_bot = bot;
_consumerKey = consumerKey;
_consumerSecret = consumerSecret;
_accessToken = accessToken;
_accessTokenSecret = accessTokenSecret;
_message = message;
_sender = sender;
this.bot = bot;
this.consumerKey = consumerKey;
this.consumerSecret = consumerSecret;
this.accessToken = accessToken;
this.accessTokenSecret = accessTokenSecret;
this.message = message;
this.sender = sender;
}
public final void run()
@ -113,22 +113,22 @@ public class Twitter implements Runnable
try
{
final ConfigurationBuilder cb = new ConfigurationBuilder();
cb.setDebugEnabled(true).setOAuthConsumerKey(_consumerKey).setOAuthConsumerSecret(_consumerSecret)
.setOAuthAccessToken(_accessToken).setOAuthAccessTokenSecret(_accessTokenSecret);
cb.setDebugEnabled(true).setOAuthConsumerKey(consumerKey).setOAuthConsumerSecret(consumerSecret)
.setOAuthAccessToken(accessToken).setOAuthAccessTokenSecret(accessTokenSecret);
final TwitterFactory tf = new TwitterFactory(cb.build());
final twitter4j.Twitter twitter = tf.getInstance();
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
.getId()
);
}
catch (Exception e)
{
_bot.getLogger().warn("Unable to post to Twitter: " + _message, e);
_bot.send(_sender, "An error has occurred: " + e.getMessage());
bot.getLogger().warn("Unable to post to Twitter: " + message, e);
bot.send(sender, "An error has occurred: " + e.getMessage());
}
}
}

View file

@ -67,22 +67,22 @@ public class Weather implements Runnable
/**
* The bot.
*/
private final Mobibot _bot;
private final Mobibot bot;
/**
* The nick of the person who sent the message.
*/
private final String _sender;
private final String sender;
/**
* The station ID.
*/
private final String _station;
private final String station;
/**
* The private message flag.
*/
private final boolean _isPrivate;
private final boolean isPrivate;
/**
* Creates a new Weather object.
@ -94,10 +94,10 @@ public class Weather implements Runnable
*/
public Weather(Mobibot bot, String sender, String station, boolean isPrivate)
{
_bot = bot;
_sender = sender;
_station = station.toUpperCase();
_isPrivate = isPrivate;
this.bot = bot;
this.sender = sender;
this.station = station.toUpperCase();
this.isPrivate = isPrivate;
}
/**
@ -105,29 +105,28 @@ public class Weather implements Runnable
*/
public final void run()
{
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)
{
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: " + metar.getDateString() + " UTC (" + (
((new Date()).getTime() - metar.getDate().getTime()) / 1000L / 60L) + " minutes ago)",
_isPrivate
isPrivate
);
result = metar.getWindSpeedInMPH();
if (result != null)
{
_bot.send(_sender,
"Wind Speed: " + result + " mph, " + metar.getWindSpeedInKnots() + " knots",
_isPrivate);
bot.send(sender,
"Wind Speed: " + result + " mph, " + metar.getWindSpeedInKnots() + " knots", isPrivate);
}
result = metar.getVisibility();
@ -136,11 +135,11 @@ public class Weather implements Runnable
{
if (!metar.getVisibilityLessThan())
{
_bot.send(_sender, "Visibility: " + NUMBER_FORMAT.format(result) + " mile(s)", _isPrivate);
bot.send(sender, "Visibility: " + NUMBER_FORMAT.format(result) + " mile(s)", isPrivate);
}
else
{
_bot.send(_sender, "Visibility: < " + NUMBER_FORMAT.format(result) + " mile(s)", _isPrivate);
bot.send(sender, "Visibility: < " + NUMBER_FORMAT.format(result) + " mile(s)", isPrivate);
}
}
@ -148,26 +147,26 @@ public class Weather implements Runnable
if (result != null)
{
_bot.send(_sender, "Pressure: " + result + " in Hg", _isPrivate);
bot.send(sender, "Pressure: " + result + " in Hg", isPrivate);
}
result = metar.getTemperatureInCelsius();
if (result != null)
{
_bot.send(_sender,
"Temperature: " + result + " C, " + metar.getTemperatureInFahrenheit() + " F",
_isPrivate);
bot.send(sender,
"Temperature: " + result + " C, " + metar.getTemperatureInFahrenheit() + " F", isPrivate);
}
if (metar.getWeatherConditions() != null)
{
final Iterator it = metar.getWeatherConditions().iterator();
//noinspection WhileLoopReplaceableByForEach
while (it.hasNext())
{
final WeatherCondition weatherCondition = (WeatherCondition) it.next();
_bot.send(_sender, weatherCondition.getNaturalLanguageString(), _isPrivate);
bot.send(sender, weatherCondition.getNaturalLanguageString(), isPrivate);
}
}
@ -175,10 +174,11 @@ public class Weather implements Runnable
{
final Iterator it = metar.getSkyConditions().iterator();
//noinspection WhileLoopReplaceableByForEach
while (it.hasNext())
{
final SkyCondition skyCondition = (SkyCondition) it.next();
_bot.send(_sender, skyCondition.getNaturalLanguageString(), _isPrivate);
bot.send(sender, skyCondition.getNaturalLanguageString(), isPrivate);
}
}
@ -186,12 +186,12 @@ public class Weather implements Runnable
}
else
{
_bot.send(_sender, "Invalid Station ID. Please try again.", _isPrivate);
bot.send(sender, "Invalid Station ID. Please try again.", isPrivate);
return;
}
}
_bot.helpResponse(_sender, Mobibot.WEATHER_CMD);
bot.helpResponse(sender, Mobibot.WEATHER_CMD);
}
}

View file

@ -1,17 +1,41 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>mobibot</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<link rel="stylesheet" type="text/css" href="simple.css" />
<title>mobibot</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<link rel="stylesheet" type="text/css" href="simple.css"/>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-20827507-3']);
_gaq.push(['_trackPageview']);
(function ()
{
var ga = document.createElement('script');
ga.type = 'text/javascript';
ga.async = true;
ga.src =
('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="content">
<h1>mobibot</h1>
<h2>The #mobitopia bot</h2>
<p class="note"> The latest version of mobibot is always available via <a href="http://cvs.thauvin.net/java/mobibot/"><strong>CVS</strong></a>. </p>
<p class="note"> The latest version of mobibot is always available via
<a href="https://github.com/ethauvin/mobibot/"><strong>GitHub</strong></a>. </p>
<h3>About mobibot</h3>
<p><strong>mobibot</strong> is the <a href="http://www.mobitopia.org/"><strong>#mobitopia</strong></a> IRC channel bot. It is built on Paul Mutton's <a href="http://www.jibble.org/pircbot.php"><strong>PircBot Java-based Framework</strong></a>.</p>
<p><strong>mobibot</strong> is the
<a href="http://www.mobitopia.org/"><strong>#mobitopia</strong></a> IRC channel bot. It is built on Paul Mutton's
<a href="http://www.jibble.org/pircbot.php"><strong>PircBot Java-based Framework</strong></a>.</p>
<p>mobibot is making extensive use of various <strong>open source libraries</strong>, including:</p>
<ul>
<li><a href="http://commons.apache.org/proper/commons-cli/">Commons CLI</a></li>
@ -24,33 +48,67 @@
<li><a href="http://ostermiller.org/utils/">OstermillerUtils</a></li>
<li><a href="http://rometools.github.io/rome/">Rome</a></li>
<li><a href="http://twitter4j.org/en/index.html">Twitter4J</a></li>
<li><a href="http://jsoup.org/">jsoup</a></li>
</ul>
<p>mobibot was written by <a href="http://erik.thauvin.net/"><strong>Erik C. Thauvin</strong></a> as a replacement for the channel's original <a href="http://usefulinc.com/chump/">ChumpBot</a>. </p>
<p>mobibot was written by
<a href="http://erik.thauvin.net/"><strong>Erik C. Thauvin</strong></a> as a replacement for the channel's original
<a href="https://github.com/edumbill/chump">ChumpBot</a>. </p>
<h3>Features</h3>
<p>mobibot's main functionality is to <strong>capture URLs</strong> posted on the channel. The URLs are automatically gathered into a publishable <a href="http://www.mobitopia.org/rss.xml"><strong>RSS feed</strong></a>. </p>
<p>mobibot's main functionality is to
<strong>capture URLs</strong> posted on the channel. The URLs are automatically gathered into a publishable
<a href="http://www.mobitopia.org/rss.xml"><strong>RSS feed</strong></a>. </p>
<p>Other features include:</p>
<ul>
<li>Performing calculations</li>
<li>Converting between currencies</li>
<li>Rolling dice</li>
<li>Performing Google searches</li>
<li>Displaying the latest entries on Mobitopia</li>
<li>Performing DNS lookups</li>
<li>Performing calculations
<div><code>mobibot: calc (floor(sqrt(3))+3.14)*3^2</code></div>
</li>
<li>Converting between currencies
<div><code>mobibot: currency 17.54 USD to EUR</code></div>
</li>
<li>Performing Google searches
<div><code>mobibot: google mobitopia on irc</code></div>
</li>
<li>Displaying weather information
<div><code>mobibot: weather KSFO</code></div>
</li>
<li>Performing DNS lookups
<div><code>mobibot: lookup www.apple.com</code></div>
</li>
<li>Retrieving stock quotes
<div><code>mobibot: stock GOOG</code></div>
</li>
<li>Displaying the time in various time zones
<div><code>mobibot: time UK</code></div>
</li>
<li>Recapping public channel messages</li>
<li>Retrieving stock quotes</li>
<li>Displaying the time in various time zones</li>
<li>Listing the users on the channel</li>
<li>Displaying weather information</li>
<li>Random quotes from <a href="http://iheartquotes.com">I Heart Quotes</a></li>
<li>Rolling dice and playing war</li>
<li>Posting to <a href="http://twitter.com/mobitopia">Twitter</a></li>
</ul>
<p>Some of the internal features include RSS feed backlogs, rolling logs, debugging toggle and much more.</p>
<p>If you have any feature suggestions, please post them to the <a href="http://erik.thauvin.net/wiki/mobibot"><strong>mobibot wiki</strong></a>. </p>
<p>If you have any feature suggestions, please post them to the
<a href="http://erik.thauvin.net/wiki/mobibot"><strong>mobibot wiki</strong></a>. </p>
<h3>Using mobibot</h3>
<p>To use mobibot, simply <strong>join <a href="irc://irc.freenode.net/#mobitopia">#mobitopia</a></strong> on <strong>irc.freenode.net</strong> and type:</p>
<p>To use mobibot, simply <strong>join <a href="irc://irc.freenode.net/#mobitopia">#mobitopia</a></strong> on
<strong>irc.freenode.net</strong> and type:</p>
<p><code>mobibot: help</code></p>
<p>mobibot will reply with a listing of the commands currently supported.</p>
<h3>Licenses</h3>
<p>There are various open source licenses attached to mobibot. Please refer to the <strong><a href="http://cvs.thauvin.net/java/mobibot/licenses/">licenses</a></strong> directory in the CVS tree for more details.</p>
<p>There are various open source licenses attached to mobibot. Please refer to the
<strong><a href="https://github.com/ethauvin/mobibot/tree/master/licenses">licenses</a></strong> directory in the source tree for more details.
</p>
</div>
</body>
</html>

View file

@ -3,7 +3,7 @@ body {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 13px;
color: #000000;
margin: 0px;
margin: 0;
}
h1 {
@ -24,6 +24,7 @@ code {
font-size: 12px;
color: #000066;
background-color: #ffeedd;
margin-left: 20px
}
a:hover {
@ -34,8 +35,8 @@ a:hover {
#content {
float: none;
position: relative;
margin: 0px 10px 10px 10px;
padding: 0px 10px 10px 10px;
margin: 0 10px 10px 10px;
padding: 0 10px 10px 10px;
}
#content p {