Implemented Rock Paper Scissors module in Kotlin.
This commit is contained in:
parent
d8da21b0ef
commit
92576f9496
26 changed files with 501 additions and 248 deletions
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
Copyright (c) 2004-2020, 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
|
||||||
|
|
|
@ -14,13 +14,13 @@ import java.time.*;
|
||||||
public final class ReleaseInfo {
|
public final class ReleaseInfo {
|
||||||
public static final String PROJECT = "mobibot";
|
public static final String PROJECT = "mobibot";
|
||||||
public static final LocalDateTime BUILDDATE =
|
public static final LocalDateTime BUILDDATE =
|
||||||
LocalDateTime.ofInstant(Instant.ofEpochMilli(1584572412391L), ZoneId.systemDefault());
|
LocalDateTime.ofInstant(Instant.ofEpochMilli(1584966079848L), ZoneId.systemDefault());
|
||||||
public static final int MAJOR = 0;
|
public static final int MAJOR = 0;
|
||||||
public static final int MINOR = 7;
|
public static final int MINOR = 7;
|
||||||
public static final int PATCH = 3;
|
public static final int PATCH = 3;
|
||||||
public static final String PRERELEASE = "beta";
|
public static final String PRERELEASE = "beta";
|
||||||
public static final String BUILDMETA = "581";
|
public static final String BUILDMETA = "682";
|
||||||
public static final String VERSION = "0.7.3-beta+581";
|
public static final String VERSION = "0.7.3-beta+682";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables the default constructor.
|
* Disables the default constructor.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* FeedReader.java
|
* FeedReader.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -88,11 +88,14 @@ class FeedReader implements Runnable {
|
||||||
|
|
||||||
SyndEntry item;
|
SyndEntry item;
|
||||||
final List<SyndEntry> items = feed.getEntries();
|
final List<SyndEntry> items = feed.getEntries();
|
||||||
|
if (items.isEmpty()) {
|
||||||
for (int i = 0; (i < items.size()) && (i < MAX_ITEMS); i++) {
|
bot.send(sender, "There is currently nothing to view. Why don't you post something?");
|
||||||
item = items.get(i);
|
} else {
|
||||||
bot.send(sender, item.getTitle());
|
for (int i = 0; (i < items.size()) && (i < MAX_ITEMS); i++) {
|
||||||
bot.send(sender, TAB_INDENT + Utils.green(item.getLink()));
|
item = items.get(i);
|
||||||
|
bot.send(sender, item.getTitle());
|
||||||
|
bot.send(sender, TAB_INDENT + Utils.green(item.getLink()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (MalformedURLException e) {
|
} catch (MalformedURLException e) {
|
||||||
bot.getLogger().debug("Invalid feed URL.", e);
|
bot.getLogger().debug("Invalid feed URL.", e);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Mobibot.java
|
* Mobibot.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -47,6 +47,7 @@ import net.thauvin.erik.mobibot.modules.Joke;
|
||||||
import net.thauvin.erik.mobibot.modules.Lookup;
|
import net.thauvin.erik.mobibot.modules.Lookup;
|
||||||
import net.thauvin.erik.mobibot.modules.ModuleException;
|
import net.thauvin.erik.mobibot.modules.ModuleException;
|
||||||
import net.thauvin.erik.mobibot.modules.Ping;
|
import net.thauvin.erik.mobibot.modules.Ping;
|
||||||
|
import net.thauvin.erik.mobibot.modules.RockPaperScissors;
|
||||||
import net.thauvin.erik.mobibot.modules.StockQuote;
|
import net.thauvin.erik.mobibot.modules.StockQuote;
|
||||||
import net.thauvin.erik.mobibot.modules.Twitter;
|
import net.thauvin.erik.mobibot.modules.Twitter;
|
||||||
import net.thauvin.erik.mobibot.modules.War;
|
import net.thauvin.erik.mobibot.modules.War;
|
||||||
|
@ -62,7 +63,6 @@ import org.apache.commons.cli.HelpFormatter;
|
||||||
import org.apache.commons.cli.Option;
|
import org.apache.commons.cli.Option;
|
||||||
import org.apache.commons.cli.Options;
|
import org.apache.commons.cli.Options;
|
||||||
import org.apache.commons.cli.ParseException;
|
import org.apache.commons.cli.ParseException;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
import org.apache.logging.log4j.Level;
|
import org.apache.logging.log4j.Level;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
@ -93,6 +93,9 @@ import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
import static net.thauvin.erik.mobibot.Utils.bold;
|
||||||
|
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements the #mobitopia bot.
|
* Implements the #mobitopia bot.
|
||||||
*
|
*
|
||||||
|
@ -101,7 +104,8 @@ import java.util.StringTokenizer;
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("WeakerAccess")
|
@SuppressWarnings("WeakerAccess")
|
||||||
@Version(properties = "version.properties", className = "ReleaseInfo")
|
@Version(properties = "version.properties",
|
||||||
|
className = "ReleaseInfo")
|
||||||
public class Mobibot extends PircBot {
|
public class Mobibot extends PircBot {
|
||||||
|
|
||||||
// The default port.
|
// The default port.
|
||||||
|
@ -111,9 +115,10 @@ public class Mobibot extends PircBot {
|
||||||
private static final String DEFAULT_SERVER = "irc.freenode.net";
|
private static final String DEFAULT_SERVER = "irc.freenode.net";
|
||||||
|
|
||||||
// The info strings.
|
// The info strings.
|
||||||
private static final String[] INFO_STRS =
|
@SuppressWarnings("indentation")
|
||||||
{ReleaseInfo.PROJECT + " v" + ReleaseInfo.VERSION + " by Erik C. Thauvin (erik@thauvin.net)",
|
private static final String[] INFO_STRS = {
|
||||||
"https://www.mobitopia.org/mobibot/"};
|
ReleaseInfo.PROJECT + " v" + ReleaseInfo.VERSION + " by Erik C. Thauvin (erik@thauvin.net)",
|
||||||
|
"https://www.mobitopia.org/mobibot/" };
|
||||||
|
|
||||||
// The link match string.
|
// The link match string.
|
||||||
private static final String LINK_MATCH = "^[hH][tT][tT][pP](|[sS])://.*";
|
private static final String LINK_MATCH = "^[hH][tT][tT][pP](|[sS])://.*";
|
||||||
|
@ -137,14 +142,15 @@ public class Mobibot extends PircBot {
|
||||||
private static final String TAGS_MARKER = "tags:";
|
private static final String TAGS_MARKER = "tags:";
|
||||||
|
|
||||||
/* The version strings.*/
|
/* The version strings.*/
|
||||||
|
@SuppressWarnings("indentation")
|
||||||
private static final String[] VERSION_STRS =
|
private static final String[] VERSION_STRS =
|
||||||
{"Version: " + ReleaseInfo.VERSION + " (" + Utils.isoLocalDate(ReleaseInfo.BUILDDATE) + ')',
|
{ "Version: " + ReleaseInfo.VERSION + " (" + Utils.isoLocalDate(ReleaseInfo.BUILDDATE) + ')',
|
||||||
"Platform: " + System.getProperty("os.name") + " (" + System.getProperty("os.version") + ", " + System
|
"Platform: " + System.getProperty("os.name") + " (" + System.getProperty("os.version") + ", "
|
||||||
.getProperty("os.arch") + ", " + System.getProperty("user.country") + ')',
|
+ System.getProperty("os.arch") + ", " + System.getProperty("user.country") + ')',
|
||||||
"Runtime: " + System.getProperty("java.runtime.name") + " (build " + System
|
"Runtime: " + System.getProperty("java.runtime.name") + " (build " + System.getProperty(
|
||||||
.getProperty("java.runtime.version") + ')',
|
"java.runtime.version") + ')',
|
||||||
"VM: " + System.getProperty("java.vm.name") + " (build " + System.getProperty("java.vm.version") + ", "
|
"VM: " + System.getProperty("java.vm.name") + " (build " + System.getProperty("java.vm.version") + ", "
|
||||||
+ System.getProperty("java.vm.info") + ')'};
|
+ System.getProperty("java.vm.info") + ')' };
|
||||||
// The logger.
|
// The logger.
|
||||||
private static final Logger logger = LogManager.getLogger(Mobibot.class);
|
private static final Logger logger = LogManager.getLogger(Mobibot.class);
|
||||||
// The commands list.
|
// The commands list.
|
||||||
|
@ -272,6 +278,7 @@ public class Mobibot extends PircBot {
|
||||||
MODULES.add(new Joke());
|
MODULES.add(new Joke());
|
||||||
MODULES.add(new Lookup());
|
MODULES.add(new Lookup());
|
||||||
MODULES.add(new Ping());
|
MODULES.add(new Ping());
|
||||||
|
MODULES.add(new RockPaperScissors());
|
||||||
MODULES.add(new StockQuote());
|
MODULES.add(new StockQuote());
|
||||||
|
|
||||||
twitterModule = new Twitter();
|
twitterModule = new Twitter();
|
||||||
|
@ -308,21 +315,29 @@ public class Mobibot extends PircBot {
|
||||||
* @param args The command line arguments.
|
* @param args The command line arguments.
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(
|
@SuppressFBWarnings(
|
||||||
{
|
{
|
||||||
"INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
|
"INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE",
|
||||||
"DM_DEFAULT_ENCODING",
|
"DM_DEFAULT_ENCODING",
|
||||||
"IOI_USE_OF_FILE_STREAM_CONSTRUCTORS"
|
"IOI_USE_OF_FILE_STREAM_CONSTRUCTORS"
|
||||||
})
|
})
|
||||||
@SuppressWarnings({"PMD.SystemPrintln", "PMD.AvoidFileStream", "PMD.CloseResource"})
|
@SuppressWarnings({ "PMD.SystemPrintln", "PMD.AvoidFileStream", "PMD.CloseResource" })
|
||||||
public static void main(final String[] args) {
|
public static void main(final String[] args) {
|
||||||
// Setup the command line options
|
// Setup the command line options
|
||||||
final Options options = new Options()
|
final Options options = new Options()
|
||||||
.addOption(Commands.HELP_ARG.substring(0, 1), Commands.HELP_ARG, false, "print this help message")
|
.addOption(Commands.HELP_ARG.substring(0, 1),
|
||||||
.addOption(Commands.DEBUG_ARG.substring(0, 1), Commands.DEBUG_ARG, false,
|
Commands.HELP_ARG,
|
||||||
"print debug & logging data directly to the console")
|
false,
|
||||||
.addOption(Option.builder(Commands.PROPS_ARG.substring(0, 1)).hasArg().argName("file")
|
"print this help message")
|
||||||
.desc("use " + "alternate properties file").longOpt(Commands.PROPS_ARG).build())
|
.addOption(Commands.DEBUG_ARG.substring(0, 1), Commands.DEBUG_ARG, false,
|
||||||
.addOption(Commands.VERSION_ARG.substring(0, 1), Commands.VERSION_ARG, false, "print version info");
|
"print debug & logging data directly to the console")
|
||||||
|
.addOption(Option.builder(Commands.PROPS_ARG.substring(0, 1)).hasArg()
|
||||||
|
.argName("file")
|
||||||
|
.desc("use " + "alternate properties file")
|
||||||
|
.longOpt(Commands.PROPS_ARG).build())
|
||||||
|
.addOption(Commands.VERSION_ARG.substring(0, 1),
|
||||||
|
Commands.VERSION_ARG,
|
||||||
|
false,
|
||||||
|
"print version info");
|
||||||
|
|
||||||
// Parse the command line
|
// Parse the command line
|
||||||
final CommandLineParser parser = new DefaultParser();
|
final CommandLineParser parser = new DefaultParser();
|
||||||
|
@ -347,7 +362,7 @@ public class Mobibot extends PircBot {
|
||||||
final Properties p = new Properties();
|
final Properties p = new Properties();
|
||||||
|
|
||||||
try (final InputStream fis = Files.newInputStream(
|
try (final InputStream fis = Files.newInputStream(
|
||||||
Paths.get(line.getOptionValue(Commands.PROPS_ARG.charAt(0), "./mobibot.properties")))) {
|
Paths.get(line.getOptionValue(Commands.PROPS_ARG.charAt(0), "./mobibot.properties")))) {
|
||||||
// Load the properties files
|
// Load the properties files
|
||||||
p.load(fis);
|
p.load(fis);
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
|
@ -368,7 +383,7 @@ public class Mobibot extends PircBot {
|
||||||
if (!line.hasOption(Commands.DEBUG_ARG.charAt(0))) {
|
if (!line.hasOption(Commands.DEBUG_ARG.charAt(0))) {
|
||||||
try {
|
try {
|
||||||
final PrintStream stdout = new PrintStream(
|
final PrintStream stdout = new PrintStream(
|
||||||
new FileOutputStream(logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true));
|
new FileOutputStream(logsDir + channel.substring(1) + '.' + Utils.today() + ".log", true));
|
||||||
System.setOut(stdout);
|
System.setOut(stdout);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
System.err.println("Unable to open output (stdout) log file.");
|
System.err.println("Unable to open output (stdout) log file.");
|
||||||
|
@ -423,7 +438,7 @@ public class Mobibot extends PircBot {
|
||||||
* @param action The action.
|
* @param action The action.
|
||||||
*/
|
*/
|
||||||
private void action(final String channel, final String action) {
|
private void action(final String channel, final String action) {
|
||||||
if (StringUtils.isNotBlank(channel) && StringUtils.isNotBlank(action)) {
|
if (isNotBlank(channel) && isNotBlank(action)) {
|
||||||
sendAction(channel, action);
|
sendAction(channel, action);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -431,7 +446,7 @@ public class Mobibot extends PircBot {
|
||||||
/**
|
/**
|
||||||
* Connects to the server and joins the channel.
|
* Connects to the server and joins the channel.
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings({"DM_EXIT", "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE"})
|
@SuppressFBWarnings({ "DM_EXIT", "INFORMATION_EXPOSURE_THROUGH_AN_ERROR_MESSAGE" })
|
||||||
public final void connect() {
|
public final void connect() {
|
||||||
try {
|
try {
|
||||||
connect(ircServer, ircPort);
|
connect(ircServer, ircPort);
|
||||||
|
@ -447,7 +462,7 @@ public class Mobibot extends PircBot {
|
||||||
if (retries == MAX_RECONNECT) {
|
if (retries == MAX_RECONNECT) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(
|
logger.debug(
|
||||||
"Unable to reconnect to {} after {} retries.", ircServer, MAX_RECONNECT, ex);
|
"Unable to reconnect to {} after {} retries.", ircServer, MAX_RECONNECT, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
e.printStackTrace(System.err);
|
e.printStackTrace(System.err);
|
||||||
|
@ -470,7 +485,7 @@ public class Mobibot extends PircBot {
|
||||||
* @param sender The nick of the person who sent the private message.
|
* @param sender The nick of the person who sent the private message.
|
||||||
*/
|
*/
|
||||||
private void feedResponse(final String sender) {
|
private void feedResponse(final String sender) {
|
||||||
if (StringUtils.isNotBlank(feedUrl)) {
|
if (isNotBlank(feedUrl)) {
|
||||||
new Thread(new FeedReader(this, sender, feedUrl)).start();
|
new Thread(new FeedReader(this, sender, feedUrl)).start();
|
||||||
} else {
|
} else {
|
||||||
send(sender, "There is no weblog setup for this channel.");
|
send(sender, "There is no weblog setup for this channel.");
|
||||||
|
@ -561,7 +576,7 @@ public class Mobibot extends PircBot {
|
||||||
for (final char c : getNick().toCharArray()) {
|
for (final char c : getNick().toCharArray()) {
|
||||||
if (Character.isLetter(c)) {
|
if (Character.isLetter(c)) {
|
||||||
buff.append('[').append(String.valueOf(c).toLowerCase(Constants.LOCALE)).append(
|
buff.append('[').append(String.valueOf(c).toLowerCase(Constants.LOCALE)).append(
|
||||||
String.valueOf(c).toUpperCase(Constants.LOCALE)).append(']');
|
String.valueOf(c).toUpperCase(Constants.LOCALE)).append(']');
|
||||||
} else {
|
} else {
|
||||||
buff.append(c);
|
buff.append(c);
|
||||||
}
|
}
|
||||||
|
@ -606,7 +621,7 @@ public class Mobibot extends PircBot {
|
||||||
* @return The indented help string.
|
* @return The indented help string.
|
||||||
*/
|
*/
|
||||||
public String helpIndent(final String help, final boolean isBold) {
|
public String helpIndent(final String help, final boolean isBold) {
|
||||||
return " " + (isBold ? Utils.bold(help) : help);
|
return " " + (isBold ? bold(help) : help);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -619,21 +634,21 @@ public class Mobibot extends PircBot {
|
||||||
final String lcTopic = topic.toLowerCase(Constants.LOCALE).trim();
|
final String lcTopic = topic.toLowerCase(Constants.LOCALE).trim();
|
||||||
|
|
||||||
if (Commands.HELP_POSTING_KEYWORD.equals(lcTopic)) {
|
if (Commands.HELP_POSTING_KEYWORD.equals(lcTopic)) {
|
||||||
send(sender, Utils.bold("Post a URL, by saying it on a line on its own:"));
|
send(sender, bold("Post a URL, by saying it on a line on its own:"));
|
||||||
send(sender, helpIndent("<url> [<title>] [" + TAGS_MARKER + "<+tag> [...]]"));
|
send(sender, helpIndent("<url> [<title>] [" + TAGS_MARKER + "<+tag> [...]]"));
|
||||||
send(sender, "I will reply with a label, for example: " + Utils.bold(Commands.LINK_CMD + '1'));
|
send(sender, "I will reply with a label, for example: " + bold(Commands.LINK_CMD + '1'));
|
||||||
send(sender, "To add a title, use a its label and a pipe:");
|
send(sender, "To add a title, use a its label and a pipe:");
|
||||||
send(sender, helpIndent(Commands.LINK_CMD + "1:|This is the title"));
|
send(sender, helpIndent(Commands.LINK_CMD + "1:|This is the title"));
|
||||||
send(sender, "To add a comment: ");
|
send(sender, "To add a comment: ");
|
||||||
send(sender, helpIndent(Commands.LINK_CMD + "1:This is a comment"));
|
send(sender, helpIndent(Commands.LINK_CMD + "1:This is a comment"));
|
||||||
send(sender, "I will reply with a label, for example: " + Utils.bold(Commands.LINK_CMD + "1.1"));
|
send(sender, "I will reply with a label, for example: " + bold(Commands.LINK_CMD + "1.1"));
|
||||||
send(sender, "To edit a comment, use its label: ");
|
send(sender, "To edit a comment, use its label: ");
|
||||||
send(sender, helpIndent(Commands.LINK_CMD + "1.1:This is an edited comment"));
|
send(sender, helpIndent(Commands.LINK_CMD + "1.1:This is an edited comment"));
|
||||||
send(sender, "To delete a comment, use its label and a minus sign: ");
|
send(sender, "To delete a comment, use its label and a minus sign: ");
|
||||||
send(sender, helpIndent(Commands.LINK_CMD + "1.1:-"));
|
send(sender, helpIndent(Commands.LINK_CMD + "1.1:-"));
|
||||||
send(sender, "You can also view a posting by saying its label.");
|
send(sender, "You can also view a posting by saying its label.");
|
||||||
} else if (Commands.HELP_TAGS_KEYWORD.equals(lcTopic)) {
|
} else if (Commands.HELP_TAGS_KEYWORD.equals(lcTopic)) {
|
||||||
send(sender, Utils.bold("To categorize or tag a URL, use its label and a T:"));
|
send(sender, bold("To categorize or tag a URL, use its label and a T:"));
|
||||||
send(sender, helpIndent(Commands.LINK_CMD + "1T:<+tag|-tag> [...]"));
|
send(sender, helpIndent(Commands.LINK_CMD + "1T:<+tag|-tag> [...]"));
|
||||||
} else if (Commands.VIEW_CMD.equals(lcTopic)) {
|
} else if (Commands.VIEW_CMD.equals(lcTopic)) {
|
||||||
send(sender, "To list or search the current URL posts:");
|
send(sender, "To list or search the current URL posts:");
|
||||||
|
@ -685,7 +700,7 @@ public class Mobibot extends PircBot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send(sender, Utils.bold("Type a URL on " + ircChannel + " to post it."));
|
send(sender, bold("Type a URL on " + ircChannel + " to post it."));
|
||||||
send(sender, "For more information on a specific command, type:");
|
send(sender, "For more information on a specific command, type:");
|
||||||
send(sender, helpIndent(getNick() + ": " + Commands.HELP_CMD + " <command>"));
|
send(sender, helpIndent(getNick() + ": " + Commands.HELP_CMD + " <command>"));
|
||||||
send(sender, "The commands are:");
|
send(sender, "The commands are:");
|
||||||
|
@ -743,12 +758,12 @@ public class Mobibot extends PircBot {
|
||||||
*/
|
*/
|
||||||
private void identify() {
|
private void identify() {
|
||||||
// Identify with NickServ
|
// Identify with NickServ
|
||||||
if (StringUtils.isNotBlank(identPwd)) {
|
if (isNotBlank(identPwd)) {
|
||||||
identify(identPwd);
|
identify(identPwd);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Identify with a specified nick
|
// Identify with a specified nick
|
||||||
if (StringUtils.isNotBlank(identNick) && StringUtils.isNotBlank(identMsg)) {
|
if (isNotBlank(identNick) && isNotBlank(identMsg)) {
|
||||||
sendMessage(identNick, identMsg);
|
sendMessage(identNick, identMsg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -818,7 +833,7 @@ public class Mobibot extends PircBot {
|
||||||
final StringBuilder info = new StringBuilder(29);
|
final StringBuilder info = new StringBuilder(29);
|
||||||
|
|
||||||
info.append("Uptime: ").append(Utils.uptime(ManagementFactory.getRuntimeMXBean().getUptime())).append(
|
info.append("Uptime: ").append(Utils.uptime(ManagementFactory.getRuntimeMXBean().getUptime())).append(
|
||||||
" [Entries: ").append(entries.size());
|
" [Entries: ").append(entries.size());
|
||||||
|
|
||||||
if (tell.isEnabled() && isOp(sender)) {
|
if (tell.isEnabled() && isOp(sender)) {
|
||||||
info.append(", Messages: ").append(tell.size());
|
info.append(", Messages: ").append(tell.size());
|
||||||
|
@ -836,7 +851,7 @@ public class Mobibot extends PircBot {
|
||||||
* @return <code>true</code> if the nick should be ignored, <code>false</code> otherwise.
|
* @return <code>true</code> if the nick should be ignored, <code>false</code> otherwise.
|
||||||
*/
|
*/
|
||||||
private boolean isIgnoredNick(final String nick) {
|
private boolean isIgnoredNick(final String nick) {
|
||||||
return StringUtils.isNotBlank(nick) && ignoredNicks.contains(nick.toLowerCase(Constants.LOCALE));
|
return isNotBlank(nick) && ignoredNicks.contains(nick.toLowerCase(Constants.LOCALE));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -871,7 +886,7 @@ public class Mobibot extends PircBot {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected final void onDisconnect() {
|
protected final void onDisconnect() {
|
||||||
if (StringUtils.isNotBlank(weblogUrl)) {
|
if (isNotBlank(weblogUrl)) {
|
||||||
setVersion(weblogUrl);
|
setVersion(weblogUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,7 +898,8 @@ public class Mobibot extends PircBot {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(value = "CC_CYCLOMATIC_COMPLEXITY", justification = "Working on it.")
|
@SuppressFBWarnings(value = "CC_CYCLOMATIC_COMPLEXITY",
|
||||||
|
justification = "Working on it.")
|
||||||
@Override
|
@Override
|
||||||
protected final void onMessage(final String channel, final String sender, final String login, final String hostname,
|
protected final void onMessage(final String channel, final String sender, final String login, final String hostname,
|
||||||
final String message) {
|
final String message) {
|
||||||
|
@ -923,7 +939,7 @@ public class Mobibot extends PircBot {
|
||||||
if (data.length == 1) {
|
if (data.length == 1) {
|
||||||
title = data[0].trim();
|
title = data[0].trim();
|
||||||
} else {
|
} else {
|
||||||
if (StringUtils.isNotBlank(data[0])) {
|
if (isNotBlank(data[0])) {
|
||||||
title = data[0].trim();
|
title = data[0].trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -936,7 +952,7 @@ public class Mobibot extends PircBot {
|
||||||
final Document html = Jsoup.connect(link).userAgent("Mozilla").get();
|
final Document html = Jsoup.connect(link).userAgent("Mozilla").get();
|
||||||
final String htmlTitle = html.title();
|
final String htmlTitle = html.title();
|
||||||
|
|
||||||
if (StringUtils.isNotBlank(htmlTitle)) {
|
if (isNotBlank(htmlTitle)) {
|
||||||
title = htmlTitle;
|
title = htmlTitle;
|
||||||
}
|
}
|
||||||
} catch (IOException ignore) {
|
} catch (IOException ignore) {
|
||||||
|
@ -962,7 +978,7 @@ public class Mobibot extends PircBot {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
final EntryLink entry = entries.get(dupIndex);
|
final EntryLink entry = entries.get(dupIndex);
|
||||||
send(sender, Utils.bold("Duplicate") + " >> " + EntriesUtils.buildLink(dupIndex, entry));
|
send(sender, bold("Duplicate") + " >> " + EntriesUtils.buildLink(dupIndex, entry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (message.matches(getNickPattern() + ":.*")) { // mobibot: <command>
|
} else if (message.matches(getNickPattern() + ":.*")) { // mobibot: <command>
|
||||||
|
@ -1000,7 +1016,7 @@ public class Mobibot extends PircBot {
|
||||||
for (final AbstractModule module : MODULES) { // modules
|
for (final AbstractModule module : MODULES) { // modules
|
||||||
for (final String c : module.getCommands()) {
|
for (final String c : module.getCommands()) {
|
||||||
if (cmd.startsWith(c)) {
|
if (cmd.startsWith(c)) {
|
||||||
module.commandResponse(this, sender, args, false);
|
module.commandResponse(this, sender, cmd, args, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1185,7 +1201,8 @@ public class Mobibot extends PircBot {
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@SuppressFBWarnings(value = {"DM_EXIT", "CC_CYCLOMATIC_COMPLEXITY"}, justification = "Yes, we want to bail out.")
|
@SuppressFBWarnings(value = { "DM_EXIT", "CC_CYCLOMATIC_COMPLEXITY" },
|
||||||
|
justification = "Yes, we want to bail out.")
|
||||||
@Override
|
@Override
|
||||||
protected final void onPrivateMessage(final String sender, final String login, final String hostname,
|
protected final void onPrivateMessage(final String sender, final String login, final String hostname,
|
||||||
final String message) {
|
final String message) {
|
||||||
|
@ -1280,7 +1297,7 @@ public class Mobibot extends PircBot {
|
||||||
if (module.isPrivateMsgEnabled()) {
|
if (module.isPrivateMsgEnabled()) {
|
||||||
for (final String c : module.getCommands()) {
|
for (final String c : module.getCommands()) {
|
||||||
if (cmd.equals(c)) {
|
if (cmd.equals(c)) {
|
||||||
module.commandResponse(this, sender, args, true);
|
module.commandResponse(this, sender, cmd, args, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1352,7 +1369,7 @@ public class Mobibot extends PircBot {
|
||||||
* sent.
|
* sent.
|
||||||
*/
|
*/
|
||||||
public final void send(final String sender, final String message, final boolean isPrivate) {
|
public final void send(final String sender, final String message, final boolean isPrivate) {
|
||||||
if (StringUtils.isNotBlank(message) && StringUtils.isNotBlank(sender)) {
|
if (isNotBlank(message) && isNotBlank(sender)) {
|
||||||
if (isPrivate) {
|
if (isPrivate) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Sending message to {} : {}", sender, message);
|
logger.debug("Sending message to {} : {}", sender, message);
|
||||||
|
@ -1460,7 +1477,7 @@ public class Mobibot extends PircBot {
|
||||||
* @param nicks The nicks to ignore
|
* @param nicks The nicks to ignore
|
||||||
*/
|
*/
|
||||||
final void setIgnoredNicks(final String nicks) {
|
final void setIgnoredNicks(final String nicks) {
|
||||||
if (StringUtils.isNotBlank(nicks)) {
|
if (isNotBlank(nicks)) {
|
||||||
final StringTokenizer st = new StringTokenizer(nicks, ",");
|
final StringTokenizer st = new StringTokenizer(nicks, ",");
|
||||||
|
|
||||||
while (st.hasMoreTokens()) {
|
while (st.hasMoreTokens()) {
|
||||||
|
@ -1475,7 +1492,7 @@ public class Mobibot extends PircBot {
|
||||||
* @param apiToken The API token
|
* @param apiToken The API token
|
||||||
*/
|
*/
|
||||||
final void setPinboardAuth(final String apiToken) {
|
final void setPinboardAuth(final String apiToken) {
|
||||||
if (StringUtils.isNotBlank(apiToken)) {
|
if (isNotBlank(apiToken)) {
|
||||||
pinboard = new Pinboard(this, apiToken, ircServer);
|
pinboard = new Pinboard(this, apiToken, ircServer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1520,7 +1537,7 @@ public class Mobibot extends PircBot {
|
||||||
* @param msg The twitter message.
|
* @param msg The twitter message.
|
||||||
*/
|
*/
|
||||||
final void twitterNotification(final String msg) {
|
final void twitterNotification(final String msg) {
|
||||||
if (twitterModule.isEnabled() && StringUtils.isNotBlank(twitterHandle)) {
|
if (twitterModule.isEnabled() && isNotBlank(twitterHandle)) {
|
||||||
new Thread(() -> {
|
new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
twitterModule.post(twitterHandle, getName() + ' ' + ReleaseInfo.VERSION + " " + msg, true);
|
twitterModule.post(twitterHandle, getName() + ' ' + ReleaseInfo.VERSION + " " + msg, true);
|
||||||
|
@ -1629,8 +1646,8 @@ public class Mobibot extends PircBot {
|
||||||
|| (entry.getNick().toLowerCase(Constants.LOCALE).contains(lcArgs))) {
|
|| (entry.getNick().toLowerCase(Constants.LOCALE).contains(lcArgs))) {
|
||||||
if (sent > MAX_ENTRIES) {
|
if (sent > MAX_ENTRIES) {
|
||||||
send(sender,
|
send(sender,
|
||||||
"To view more, try: " + Utils
|
"To view more, try: "
|
||||||
.bold(getNick() + ": " + Commands.VIEW_CMD + ' ' + (i + 1) + ' ' + lcArgs),
|
+ bold(getNick() + ": " + Commands.VIEW_CMD + ' ' + (i + 1) + ' ' + lcArgs),
|
||||||
isPrivate);
|
isPrivate);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1642,7 +1659,7 @@ public class Mobibot extends PircBot {
|
||||||
} else {
|
} else {
|
||||||
if (sent > MAX_ENTRIES) {
|
if (sent > MAX_ENTRIES) {
|
||||||
send(sender,
|
send(sender,
|
||||||
"To view more, try: " + Utils.bold(getNick() + ": " + Commands.VIEW_CMD + ' ' + (i + 1)),
|
"To view more, try: " + bold(getNick() + ": " + Commands.VIEW_CMD + ' ' + (i + 1)),
|
||||||
isPrivate);
|
isPrivate);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1,3 +1,35 @@
|
||||||
|
/*
|
||||||
|
* TwitterOAuth.java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2020, 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 this project 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 HOLDER 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;
|
package net.thauvin.erik.mobibot;
|
||||||
|
|
||||||
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Utils.java
|
* Utils.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -34,6 +34,7 @@ package net.thauvin.erik.mobibot;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jibble.pircbot.Colors;
|
import org.jibble.pircbot.Colors;
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
@ -233,8 +234,7 @@ public final class Utils {
|
||||||
* @return The unescaped string.
|
* @return The unescaped string.
|
||||||
*/
|
*/
|
||||||
public static String unescapeXml(final String str) {
|
public static String unescapeXml(final String str) {
|
||||||
return str.replace("&", "&").replace("<", "<").replace(">", ">").replace(""", "\"").replace(
|
return Jsoup.parse(str).text();
|
||||||
"'", "'").replace("'", "'");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -254,9 +254,9 @@ public final class Utils {
|
||||||
final long weeks = days / 7;
|
final long weeks = days / 7;
|
||||||
days %= 7;
|
days %= 7;
|
||||||
final long hours = TimeUnit.MILLISECONDS.toHours(uptime) - TimeUnit.DAYS.toHours(
|
final long hours = TimeUnit.MILLISECONDS.toHours(uptime) - TimeUnit.DAYS.toHours(
|
||||||
TimeUnit.MILLISECONDS.toDays(uptime));
|
TimeUnit.MILLISECONDS.toDays(uptime));
|
||||||
final long minutes = TimeUnit.MILLISECONDS.toMinutes(uptime) - TimeUnit.HOURS.toMinutes(
|
final long minutes = TimeUnit.MILLISECONDS.toMinutes(uptime) - TimeUnit.HOURS.toMinutes(
|
||||||
TimeUnit.MILLISECONDS.toHours(uptime));
|
TimeUnit.MILLISECONDS.toHours(uptime));
|
||||||
|
|
||||||
if (years > 0) {
|
if (years > 0) {
|
||||||
info.append(years).append(plural(years, " year ", " years "));
|
info.append(years).append(plural(years, " year ", " years "));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* AbstractModule.java
|
* AbstractModule.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -57,11 +57,13 @@ public abstract class AbstractModule {
|
||||||
*
|
*
|
||||||
* @param bot The bot's instance.
|
* @param bot The bot's instance.
|
||||||
* @param sender The sender.
|
* @param sender The sender.
|
||||||
|
* @param cmd The command.
|
||||||
* @param args The command arguments.
|
* @param args The command arguments.
|
||||||
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
||||||
*/
|
*/
|
||||||
public abstract void commandResponse(final Mobibot bot,
|
public abstract void commandResponse(final Mobibot bot,
|
||||||
final String sender,
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
final String args,
|
final String args,
|
||||||
final boolean isPrivate);
|
final boolean isPrivate);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Calc.java
|
* Calc.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -81,7 +81,11 @@ public class Calc extends AbstractModule {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
if (StringUtils.isNotBlank(args)) {
|
if (StringUtils.isNotBlank(args)) {
|
||||||
bot.send(calc(args));
|
bot.send(calc(args));
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* CurrencyConverter.java
|
* CurrencyConverter.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -87,44 +87,6 @@ public final class CurrencyConverter extends ThreadedModule {
|
||||||
commands.add(CURRENCY_CMD);
|
commands.add(CURRENCY_CMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
|
||||||
synchronized (this) {
|
|
||||||
if (!pubDate.equals(Utils.today())) {
|
|
||||||
EXCHANGE_RATES.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
super.commandResponse(bot, sender, args, isPrivate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts the specified currencies.
|
|
||||||
*/
|
|
||||||
@SuppressFBWarnings("REDOS")
|
|
||||||
@Override
|
|
||||||
void run(final Mobibot bot, final String sender, final String query) {
|
|
||||||
if (StringUtils.isNotBlank(sender) && StringUtils.isNotBlank(query)) {
|
|
||||||
if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+")) {
|
|
||||||
try {
|
|
||||||
final Message msg = convertCurrency(query);
|
|
||||||
if (msg.isError()) {
|
|
||||||
helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, false);
|
|
||||||
}
|
|
||||||
bot.send(sender, msg);
|
|
||||||
} catch (ModuleException e) {
|
|
||||||
bot.getLogger().warn(e.getDebugMessage(), e);
|
|
||||||
bot.send(sender, e.getMessage());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts from a currency to another.
|
* Converts from a currency to another.
|
||||||
*
|
*
|
||||||
|
@ -157,8 +119,8 @@ public final class CurrencyConverter extends ThreadedModule {
|
||||||
for (final Element rawCube : cubes) {
|
for (final Element rawCube : cubes) {
|
||||||
cube = rawCube;
|
cube = rawCube;
|
||||||
EXCHANGE_RATES.put(
|
EXCHANGE_RATES.put(
|
||||||
cube.getAttribute("currency").getValue(),
|
cube.getAttribute("currency").getValue(),
|
||||||
cube.getAttribute("rate").getValue());
|
cube.getAttribute("rate").getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
EXCHANGE_RATES.put("EUR", "1");
|
EXCHANGE_RATES.put("EUR", "1");
|
||||||
|
@ -166,7 +128,7 @@ public final class CurrencyConverter extends ThreadedModule {
|
||||||
throw new ModuleException(query, "An error has occurred while parsing the exchange rates table.", e);
|
throw new ModuleException(query, "An error has occurred while parsing the exchange rates table.", e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new ModuleException(
|
throw new ModuleException(
|
||||||
query, "An error has occurred while fetching the exchange rates table.", e);
|
query, "An error has occurred while fetching the exchange rates table.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,23 +143,23 @@ public final class CurrencyConverter extends ThreadedModule {
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
final double amt = Double.parseDouble(cmds[0].replace(",", ""));
|
final double amt = Double.parseDouble(cmds[0].replace(",", ""));
|
||||||
final double from = Double.parseDouble(EXCHANGE_RATES.get(cmds[1]
|
final double from =
|
||||||
.toUpperCase(Constants.LOCALE)));
|
Double.parseDouble(EXCHANGE_RATES.get(cmds[1].toUpperCase(Constants.LOCALE)));
|
||||||
final double to = Double.parseDouble(EXCHANGE_RATES.get(cmds[3].toUpperCase(Constants.LOCALE)));
|
final double to = Double.parseDouble(EXCHANGE_RATES.get(cmds[3].toUpperCase(Constants.LOCALE)));
|
||||||
|
|
||||||
return new PublicMessage(
|
return new PublicMessage(
|
||||||
NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1)
|
NumberFormat.getCurrencyInstance(Locale.US).format(amt).substring(1)
|
||||||
+ ' '
|
+ ' '
|
||||||
+ cmds[1].toUpperCase(Constants.LOCALE)
|
+ cmds[1].toUpperCase(Constants.LOCALE)
|
||||||
+ " = "
|
+ " = "
|
||||||
+ NumberFormat.getCurrencyInstance(Locale.US)
|
+ NumberFormat.getCurrencyInstance(Locale.US)
|
||||||
.format((amt * to) / from)
|
.format((amt * to) / from)
|
||||||
.substring(1)
|
.substring(1)
|
||||||
+ ' '
|
+ ' '
|
||||||
+ cmds[3].toUpperCase(Constants.LOCALE));
|
+ cmds[3].toUpperCase(Constants.LOCALE));
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ModuleException("convertCurrency(" + query + ')',
|
throw new ModuleException("convertCurrency(" + query + ')',
|
||||||
"The supported currencies are: " + EXCHANGE_RATES.keySet(), e);
|
"The supported currencies are: " + EXCHANGE_RATES.keySet(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (CURRENCY_RATES_KEYWORD.equals(query)) {
|
} else if (CURRENCY_RATES_KEYWORD.equals(query)) {
|
||||||
|
@ -219,6 +181,48 @@ public final class CurrencyConverter extends ThreadedModule {
|
||||||
return new ErrorMessage("The supported currencies are: " + EXCHANGE_RATES.keySet());
|
return new ErrorMessage("The supported currencies are: " + EXCHANGE_RATES.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (!pubDate.equals(Utils.today())) {
|
||||||
|
EXCHANGE_RATES.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
super.commandResponse(bot, sender, cmd, args, isPrivate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the specified currencies.
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings("REDOS")
|
||||||
|
@Override
|
||||||
|
void run(final Mobibot bot, final String sender, final String cmd, final String query) {
|
||||||
|
if (StringUtils.isNotBlank(sender) && StringUtils.isNotBlank(query)) {
|
||||||
|
if (query.matches("\\d+([,\\d]+)?(\\.\\d+)? [a-zA-Z]{3}+ to [a-zA-Z]{3}+")) {
|
||||||
|
try {
|
||||||
|
final Message msg = convertCurrency(query);
|
||||||
|
if (msg.isError()) {
|
||||||
|
helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, false);
|
||||||
|
}
|
||||||
|
bot.send(sender, msg);
|
||||||
|
} catch (ModuleException e) {
|
||||||
|
bot.getLogger().warn(e.getDebugMessage(), e);
|
||||||
|
bot.send(sender, e.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
helpResponse(bot, sender, CURRENCY_CMD + ' ' + query, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Dice.java
|
* Dice.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -57,15 +57,14 @@ public final class Dice extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rolls the dice.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param bot The bot's instance.
|
|
||||||
* @param sender The sender.
|
|
||||||
* @param args The command arguments.
|
|
||||||
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
final SecureRandom r = new SecureRandom();
|
final SecureRandom r = new SecureRandom();
|
||||||
|
|
||||||
int i = r.nextInt(6) + 1;
|
int i = r.nextInt(6) + 1;
|
||||||
|
@ -73,15 +72,15 @@ public final class Dice extends AbstractModule {
|
||||||
final int playerTotal = i + y;
|
final int playerTotal = i + y;
|
||||||
|
|
||||||
bot.send(bot.getChannel(),
|
bot.send(bot.getChannel(),
|
||||||
sender + " rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of "
|
sender + " rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of "
|
||||||
+ Utils.bold(playerTotal));
|
+ Utils.bold(playerTotal));
|
||||||
|
|
||||||
i = r.nextInt(6) + 1;
|
i = r.nextInt(6) + 1;
|
||||||
y = r.nextInt(6) + 1;
|
y = r.nextInt(6) + 1;
|
||||||
final int total = i + y;
|
final int total = i + y;
|
||||||
|
|
||||||
bot.action(
|
bot.action(
|
||||||
"rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils.bold(total));
|
"rolled two dice: " + Utils.bold(i) + " and " + Utils.bold(y) + " for a total of " + Utils.bold(total));
|
||||||
|
|
||||||
if (playerTotal < total) {
|
if (playerTotal < total) {
|
||||||
bot.action("wins.");
|
bot.action("wins.");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* GoogleSearch.java
|
* GoogleSearch.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -96,7 +96,7 @@ public final class GoogleSearch extends ThreadedModule {
|
||||||
* Searches Google.
|
* Searches Google.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void run(final Mobibot bot, final String sender, final String query) {
|
void run(final Mobibot bot, final String sender, final String cmd, final String query) {
|
||||||
if (StringUtils.isNotBlank(query)) {
|
if (StringUtils.isNotBlank(query)) {
|
||||||
try {
|
try {
|
||||||
final List<Message> results = searchGoogle(query, properties.get(GOOGLE_API_KEY_PROP),
|
final List<Message> results = searchGoogle(query, properties.get(GOOGLE_API_KEY_PROP),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Joke.java
|
* Joke.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -56,7 +56,7 @@ public final class Joke extends ThreadedModule {
|
||||||
private static final String JOKE_CMD = "joke";
|
private static final String JOKE_CMD = "joke";
|
||||||
// The ICNDB URL.
|
// The ICNDB URL.
|
||||||
private static final String JOKE_URL =
|
private static final String JOKE_URL =
|
||||||
"http://api.icndb.com/jokes/random?escape=javascript&exclude=[explicit]&limitTo=[nerdy]";
|
"http://api.icndb.com/jokes/random?escape=javascript&exclude=[explicit]&limitTo=[nerdy]";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new {@link Joke} instance.
|
* Creates a new {@link Joke} instance.
|
||||||
|
@ -79,7 +79,7 @@ public final class Joke extends ThreadedModule {
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
try (final BufferedReader reader =
|
try (final BufferedReader reader =
|
||||||
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8))) {
|
||||||
String line;
|
String line;
|
||||||
while ((line = reader.readLine()) != null) {
|
while ((line = reader.readLine()) != null) {
|
||||||
sb.append(line);
|
sb.append(line);
|
||||||
|
@ -88,8 +88,8 @@ public final class Joke extends ThreadedModule {
|
||||||
final JSONObject json = new JSONObject(sb.toString());
|
final JSONObject json = new JSONObject(sb.toString());
|
||||||
|
|
||||||
return new PublicMessage(
|
return new PublicMessage(
|
||||||
json.getJSONObject("value").get("joke").toString().replace("\\'", "'")
|
json.getJSONObject("value").get("joke").toString().replace("\\'", "'")
|
||||||
.replace("\\\"", "\""));
|
.replace("\\\"", "\""));
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new ModuleException("randomJoke()", "An error has occurred retrieving a random joke.", e);
|
throw new ModuleException("randomJoke()", "An error has occurred retrieving a random joke.", e);
|
||||||
|
@ -100,15 +100,19 @@ public final class Joke extends ThreadedModule {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
new Thread(() -> run(bot, sender, args)).start();
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
|
new Thread(() -> run(bot, sender, cmd, args)).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a random joke from <a href="http://www.icndb.com/">The Internet Chuck Norris Database</a>.
|
* Returns a random joke from <a href="http://www.icndb.com/">The Internet Chuck Norris Database</a>.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void run(final Mobibot bot, final String sender, final String arg) {
|
void run(final Mobibot bot, final String sender, final String cmd, final String arg) {
|
||||||
try {
|
try {
|
||||||
bot.send(Utils.cyan(randomJoke().getMessage()));
|
bot.send(Utils.cyan(randomJoke().getMessage()));
|
||||||
} catch (ModuleException e) {
|
} catch (ModuleException e) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Lookup.java
|
* Lookup.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -143,15 +143,14 @@ public final class Lookup extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process a command.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param bot The bot's instance.
|
|
||||||
* @param sender The sender.
|
|
||||||
* @param args The command arguments.
|
|
||||||
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
if (args.matches("(\\S.)+(\\S)+")) {
|
if (args.matches("(\\S.)+(\\S)+")) {
|
||||||
try {
|
try {
|
||||||
bot.send(Lookup.lookup(args));
|
bot.send(Lookup.lookup(args));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Ping.java
|
* Ping.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -50,19 +50,19 @@ public class Ping extends AbstractModule {
|
||||||
* The ping responses.
|
* The ping responses.
|
||||||
*/
|
*/
|
||||||
static final List<String> PINGS =
|
static final List<String> PINGS =
|
||||||
Arrays.asList(
|
Arrays.asList(
|
||||||
"is barely alive.",
|
"is barely alive.",
|
||||||
"is trying to stay awake.",
|
"is trying to stay awake.",
|
||||||
"has gone fishing.",
|
"has gone fishing.",
|
||||||
"is somewhere over the rainbow.",
|
"is somewhere over the rainbow.",
|
||||||
"has fallen and can't get up.",
|
"has fallen and can't get up.",
|
||||||
"is running. You better go chase it.",
|
"is running. You better go chase it.",
|
||||||
"has just spontaneously combusted.",
|
"has just spontaneously combusted.",
|
||||||
"is talking to itself... don't interrupt. That's rude.",
|
"is talking to itself... don't interrupt. That's rude.",
|
||||||
"is bartending at an AA meeting.",
|
"is bartending at an AA meeting.",
|
||||||
"is hibernating.",
|
"is hibernating.",
|
||||||
"is saving energy: apathetic mode activated.",
|
"is saving energy: apathetic mode activated.",
|
||||||
"is busy. Go away!");
|
"is busy. Go away!");
|
||||||
/**
|
/**
|
||||||
* The ping command.
|
* The ping command.
|
||||||
*/
|
*/
|
||||||
|
@ -80,7 +80,11 @@ public class Ping extends AbstractModule {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
final SecureRandom r = new SecureRandom();
|
final SecureRandom r = new SecureRandom();
|
||||||
bot.action(PINGS.get(r.nextInt(PINGS.size())));
|
bot.action(PINGS.get(r.nextInt(PINGS.size())));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,116 @@
|
||||||
|
/*
|
||||||
|
* RockPaperScissors.kt
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2020, 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 this project 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 HOLDER 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.modules
|
||||||
|
|
||||||
|
import net.thauvin.erik.mobibot.Mobibot
|
||||||
|
import net.thauvin.erik.mobibot.Utils
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple module example in Kotlin.
|
||||||
|
*/
|
||||||
|
class RockPaperScissors : AbstractModule() {
|
||||||
|
init {
|
||||||
|
with(commands) {
|
||||||
|
add(Shapes.ROCK.value)
|
||||||
|
add(Shapes.SCISSORS.value)
|
||||||
|
add(Shapes.PAPER.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Shapes(val value: String) {
|
||||||
|
ROCK("rock"), PAPER("paper"), SCISSORS("scissors")
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class Results {
|
||||||
|
WIN, LOSE, DRAW
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* Returns the the randomly picked shape and result.
|
||||||
|
*/
|
||||||
|
fun winLoseOrDraw(hand: Shapes): Pair<Shapes, Results> {
|
||||||
|
val botHand = Shapes.values()[Random.nextInt(0, Shapes.values().size)]
|
||||||
|
val result: Results
|
||||||
|
if (botHand == hand) {
|
||||||
|
result = Results.DRAW
|
||||||
|
} else {
|
||||||
|
when (botHand) {
|
||||||
|
Shapes.ROCK -> {
|
||||||
|
result = if (hand == Shapes.PAPER) {
|
||||||
|
Results.WIN
|
||||||
|
} else {
|
||||||
|
Results.LOSE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Shapes.PAPER -> {
|
||||||
|
result = if (hand == Shapes.ROCK) {
|
||||||
|
Results.LOSE
|
||||||
|
} else {
|
||||||
|
Results.WIN
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Shapes.SCISSORS -> {
|
||||||
|
result = if (hand == Shapes.ROCK) {
|
||||||
|
Results.WIN
|
||||||
|
} else {
|
||||||
|
Results.LOSE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Pair(botHand, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun commandResponse(bot: Mobibot?, sender: String?, cmd: String?, args: String?, isPrivate: Boolean) {
|
||||||
|
val result = winLoseOrDraw(Shapes.valueOf(cmd!!.toUpperCase()))
|
||||||
|
val picked = "picked ${Utils.bold(result.first.value)}."
|
||||||
|
when (result.second) {
|
||||||
|
Results.WIN -> bot!!.action("$picked You win.")
|
||||||
|
Results.LOSE -> bot!!.action("$picked You lose.")
|
||||||
|
else -> bot!!.action("$picked We have a draw.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun helpResponse(bot: Mobibot?, sender: String?, args: String?, isPrivate: Boolean) {
|
||||||
|
bot!!.send(sender, "To play Rock Paper Scissors:")
|
||||||
|
bot.send(
|
||||||
|
sender,
|
||||||
|
bot.helpIndent("${bot.nick}: ${Shapes.ROCK.value} or ${Shapes.PAPER.value} or ${Shapes.SCISSORS.value}")
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* StockQuote.java
|
* StockQuote.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -211,7 +211,7 @@ public final class StockQuote extends ThreadedModule {
|
||||||
* Returns the specified stock quote from Alpha Advantage.
|
* Returns the specified stock quote from Alpha Advantage.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void run(final Mobibot bot, final String sender, final String symbol) {
|
void run(final Mobibot bot, final String sender, final String cmd, final String symbol) {
|
||||||
if (StringUtils.isNotBlank(symbol)) {
|
if (StringUtils.isNotBlank(symbol)) {
|
||||||
try {
|
try {
|
||||||
final List<Message> messages = getQuote(symbol, properties.get(ALPHAVANTAGE_API_KEY_PROP));
|
final List<Message> messages = getQuote(symbol, properties.get(ALPHAVANTAGE_API_KEY_PROP));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* ThreadedModule.java
|
* ThreadedModule.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -46,9 +46,13 @@ public abstract class ThreadedModule extends AbstractModule {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
if (isEnabled() && args.length() > 0) {
|
if (isEnabled() && args.length() > 0) {
|
||||||
new Thread(() -> run(bot, sender, args)).start();
|
new Thread(() -> run(bot, sender, cmd, args)).start();
|
||||||
} else {
|
} else {
|
||||||
helpResponse(bot, sender, args, isPrivate);
|
helpResponse(bot, sender, args, isPrivate);
|
||||||
}
|
}
|
||||||
|
@ -57,5 +61,5 @@ public abstract class ThreadedModule extends AbstractModule {
|
||||||
/**
|
/**
|
||||||
* Runs the thread.
|
* Runs the thread.
|
||||||
*/
|
*/
|
||||||
abstract void run(Mobibot bot, String sender, String args);
|
abstract void run(Mobibot bot, String sender, @SuppressWarnings("unused") String cmd, String args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Twitter.java
|
* Twitter.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -148,7 +148,7 @@ public final class Twitter extends ThreadedModule {
|
||||||
* Posts to twitter.
|
* Posts to twitter.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void run(final Mobibot bot, final String sender, final String message) {
|
void run(final Mobibot bot, final String sender, final String cmd, final String message) {
|
||||||
try {
|
try {
|
||||||
bot.send(sender, post(sender, message, false).getMessage());
|
bot.send(sender, post(sender, message, false).getMessage());
|
||||||
} catch (ModuleException e) {
|
} catch (ModuleException e) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* War.java
|
* War.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -49,9 +49,9 @@ public final class War extends AbstractModule {
|
||||||
private static final String WAR_CMD = "war";
|
private static final String WAR_CMD = "war";
|
||||||
// The deck of card.
|
// The deck of card.
|
||||||
private static final String[] WAR_DECK =
|
private static final String[] WAR_DECK =
|
||||||
new String[]{"Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2"};
|
new String[]{ "Ace", "King", "Queen", "Jack", "10", "9", "8", "7", "6", "5", "4", "3", "2" };
|
||||||
// The suits for the deck of card.
|
// The suits for the deck of card.
|
||||||
private static final String[] WAR_SUITS = new String[]{"Hearts", "Spades", "Diamonds", "Clubs"};
|
private static final String[] WAR_SUITS = new String[]{ "Hearts", "Spades", "Diamonds", "Clubs" };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default constructor.
|
* The default constructor.
|
||||||
|
@ -62,15 +62,14 @@ public final class War extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Plays war.
|
* {@inheritDoc}
|
||||||
*
|
|
||||||
* @param bot The bot's instance.
|
|
||||||
* @param sender The sender.
|
|
||||||
* @param args The command arguments.
|
|
||||||
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
final SecureRandom r = new SecureRandom();
|
final SecureRandom r = new SecureRandom();
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -81,7 +80,7 @@ public final class War extends AbstractModule {
|
||||||
y = r.nextInt(WAR_DECK.length);
|
y = r.nextInt(WAR_DECK.length);
|
||||||
|
|
||||||
bot.send(bot.getChannel(),
|
bot.send(bot.getChannel(),
|
||||||
sender + " drew the " + Utils.bold(WAR_DECK[i]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
|
sender + " drew the " + Utils.bold(WAR_DECK[i]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
|
||||||
bot.action("drew the " + Utils.bold(WAR_DECK[y]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
|
bot.action("drew the " + Utils.bold(WAR_DECK[y]) + " of " + WAR_SUITS[r.nextInt(WAR_SUITS.length)]);
|
||||||
|
|
||||||
if (i != y) {
|
if (i != y) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Weather2.java
|
* Weather2.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -217,7 +217,7 @@ public class Weather2 extends ThreadedModule {
|
||||||
* Fetches the weather data from a specific city.
|
* Fetches the weather data from a specific city.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
void run(final Mobibot bot, final String sender, final String args) {
|
void run(final Mobibot bot, final String sender, final String cmd, final String args) {
|
||||||
if (StringUtils.isNotBlank(args)) {
|
if (StringUtils.isNotBlank(args)) {
|
||||||
try {
|
try {
|
||||||
final List<Message> messages = getWeather(args, properties.get(OWM_API_KEY_PROP));
|
final List<Message> messages = getWeather(args, properties.get(OWM_API_KEY_PROP));
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* WorldTime.java
|
* WorldTime.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
@ -146,9 +146,9 @@ public final class WorldTime extends AbstractModule {
|
||||||
countries.put("INTERNET", BEATS_KEYWORD);
|
countries.put("INTERNET", BEATS_KEYWORD);
|
||||||
countries.put("BEATS", BEATS_KEYWORD);
|
countries.put("BEATS", BEATS_KEYWORD);
|
||||||
|
|
||||||
ZoneId.getAvailableZoneIds().stream().filter(tz ->
|
ZoneId.getAvailableZoneIds().stream()
|
||||||
!tz.contains("/") && tz.length() == 3 && !countries.containsKey(tz)).forEach(tz ->
|
.filter(tz -> !tz.contains("/") && tz.length() == 3 && !countries.containsKey(tz))
|
||||||
countries.put(tz, tz));
|
.forEach(tz -> countries.put(tz, tz));
|
||||||
|
|
||||||
COUNTRIES_MAP = Collections.unmodifiableMap(countries);
|
COUNTRIES_MAP = Collections.unmodifiableMap(countries);
|
||||||
}
|
}
|
||||||
|
@ -162,15 +162,58 @@ public final class WorldTime extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Responds with the current time in the specified timezone/country.
|
* Returns the current Internet (beat) Time.
|
||||||
*
|
*
|
||||||
* @param bot The bot's instance.
|
* @return The Internet Time string.
|
||||||
* @param sender The sender.
|
*/
|
||||||
* @param args The command arguments.
|
private static String internetTime() {
|
||||||
* @param isPrivate Set to <code>true</code> if the response should be sent as a private message.
|
final ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC+01:00"));
|
||||||
|
final int beats = (int) ((zdt.get(ChronoField.SECOND_OF_MINUTE) + (zdt.get(ChronoField.MINUTE_OF_HOUR) * 60)
|
||||||
|
+ (zdt.get(ChronoField.HOUR_OF_DAY) * 3600)) / 86.4);
|
||||||
|
return String.format("%c%03d", '@', beats);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the world time.
|
||||||
|
*
|
||||||
|
* <ul>
|
||||||
|
* <li>PST</li>
|
||||||
|
* <li>BEATS</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param query The query.
|
||||||
|
* @return The {@link Message} containing the world time.
|
||||||
|
*/
|
||||||
|
@SuppressFBWarnings("STT_STRING_PARSING_A_FIELD")
|
||||||
|
static Message worldTime(final String query) {
|
||||||
|
final String tz = (COUNTRIES_MAP.get((query.substring(query.indexOf(' ') + 1).trim()
|
||||||
|
.toUpperCase(Constants.LOCALE))));
|
||||||
|
final String response;
|
||||||
|
|
||||||
|
if (tz != null) {
|
||||||
|
if (BEATS_KEYWORD.equals(tz)) {
|
||||||
|
response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD);
|
||||||
|
} else {
|
||||||
|
response = ZonedDateTime.now().withZoneSameInstant(ZoneId.of(tz)).format(
|
||||||
|
DateTimeFormatter.ofPattern("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '"))
|
||||||
|
+ tz.substring(tz.indexOf('/') + 1).replace('_', ' ');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new ErrorMessage("The supported countries/zones are: " + COUNTRIES_MAP.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PublicMessage(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void commandResponse(final Mobibot bot, final String sender, final String args, final boolean isPrivate) {
|
public void commandResponse(final Mobibot bot,
|
||||||
|
final String sender,
|
||||||
|
final String cmd,
|
||||||
|
final String args,
|
||||||
|
final boolean isPrivate) {
|
||||||
final Message msg = worldTime(args);
|
final Message msg = worldTime(args);
|
||||||
|
|
||||||
if (isPrivate) {
|
if (isPrivate) {
|
||||||
|
@ -203,48 +246,4 @@ public final class WorldTime extends AbstractModule {
|
||||||
public boolean isPrivateMsgEnabled() {
|
public boolean isPrivateMsgEnabled() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current Internet (beat) Time.
|
|
||||||
*
|
|
||||||
* @return The Internet Time string.
|
|
||||||
*/
|
|
||||||
private static String internetTime() {
|
|
||||||
final ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("UTC+01:00"));
|
|
||||||
final int beats = (int) ((zdt.get(ChronoField.SECOND_OF_MINUTE) + (zdt.get(ChronoField.MINUTE_OF_HOUR) * 60)
|
|
||||||
+ (zdt.get(ChronoField.HOUR_OF_DAY) * 3600)) / 86.4);
|
|
||||||
return String.format("%c%03d", '@', beats);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the world time.
|
|
||||||
*
|
|
||||||
* <ul>
|
|
||||||
* <li>PST</li>
|
|
||||||
* <li>BEATS</li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param query The query.
|
|
||||||
* @return The {@link Message} containing the world time.
|
|
||||||
*/
|
|
||||||
@SuppressFBWarnings("STT_STRING_PARSING_A_FIELD")
|
|
||||||
static Message worldTime(final String query) {
|
|
||||||
final String tz = (COUNTRIES_MAP.get((query.substring(query.indexOf(' ') + 1).trim()
|
|
||||||
.toUpperCase(Constants.LOCALE))));
|
|
||||||
final String response;
|
|
||||||
|
|
||||||
if (tz != null) {
|
|
||||||
if (BEATS_KEYWORD.equals(tz)) {
|
|
||||||
response = ("The current Internet Time is: " + internetTime() + ' ' + BEATS_KEYWORD);
|
|
||||||
} else {
|
|
||||||
response = ZonedDateTime.now().withZoneSameInstant(ZoneId.of(tz)).format(
|
|
||||||
DateTimeFormatter.ofPattern("'The time is 'HH:mm' on 'EEEE, d MMMM yyyy' in '"))
|
|
||||||
+ tz.substring(tz.indexOf('/') + 1).replace('_', ' ');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return new ErrorMessage("The supported countries/zones are: " + COUNTRIES_MAP.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PublicMessage(response);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* EntryLinkTest.java
|
* EntryLinkTest.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* AbstractModuleTest.java
|
* AbstractModuleTest.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/*
|
||||||
|
* RockPaperScissorsTest.kt
|
||||||
|
*
|
||||||
|
* Copyright (c) 2004-2020, 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 this project 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 HOLDER 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.modules
|
||||||
|
|
||||||
|
import net.thauvin.erik.mobibot.modules.RockPaperScissors.Results
|
||||||
|
import net.thauvin.erik.mobibot.modules.RockPaperScissors.Shapes
|
||||||
|
import org.assertj.core.api.Assertions.assertThat
|
||||||
|
import org.testng.annotations.Test
|
||||||
|
|
||||||
|
class RockPaperScissorsTest {
|
||||||
|
@Test(invocationCount = 5)
|
||||||
|
fun testWinLoseOrDraw() {
|
||||||
|
var play = RockPaperScissors.winLoseOrDraw(Shapes.SCISSORS)
|
||||||
|
// println("SCISSORS vs ${play.first}: ${play.second}")
|
||||||
|
when (play.first) {
|
||||||
|
Shapes.SCISSORS -> assertThat(play.second).`as`("SCISSORS vs ${play.first}").isEqualTo(Results.DRAW)
|
||||||
|
Shapes.ROCK -> assertThat(play.second).`as`("SCISSORS vs ${play.first}").isEqualTo(Results.LOSE)
|
||||||
|
else -> assertThat(play.second).`as`("SCISSORS vs ${play.first}").isEqualTo(Results.WIN)
|
||||||
|
}
|
||||||
|
|
||||||
|
play = RockPaperScissors.winLoseOrDraw(Shapes.ROCK)
|
||||||
|
// println("ROCK vs ${play.first}: ${play.second}")
|
||||||
|
when (play.first) {
|
||||||
|
Shapes.SCISSORS -> assertThat(play.second).`as`("ROCK vs ${play.first}").isEqualTo(Results.WIN)
|
||||||
|
Shapes.ROCK -> assertThat(play.second).`as`("ROCK vs ${play.first}").isEqualTo(Results.DRAW)
|
||||||
|
else -> assertThat(play.second).`as`("ROCK vs ${play.first}").isEqualTo(Results.LOSE)
|
||||||
|
}
|
||||||
|
|
||||||
|
play = RockPaperScissors.winLoseOrDraw(Shapes.PAPER)
|
||||||
|
// println("PAPER vs ${play.first}: ${play.second}")
|
||||||
|
when (play.first) {
|
||||||
|
Shapes.SCISSORS -> assertThat(play.second).`as`("PAPER vs ${play.first}").isEqualTo(Results.LOSE)
|
||||||
|
Shapes.ROCK -> assertThat(play.second).`as`("PAPER vs ${play.first}").isEqualTo(Results.WIN)
|
||||||
|
else -> assertThat(play.second).`as`("PAPER vs ${play.first}").isEqualTo(Results.DRAW)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* TellMessageTest.java
|
* TellMessageTest.java
|
||||||
*
|
*
|
||||||
* Copyright (c) 2004-2019, Erik C. Thauvin (erik@thauvin.net)
|
* Copyright (c) 2004-2020, 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
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
#Generated by the Semver Plugin for Gradle
|
#Generated by the Semver Plugin for Gradle
|
||||||
#Wed Mar 18 16:00:11 PDT 2020
|
#Mon Mar 23 05:21:18 PDT 2020
|
||||||
version.buildmeta=581
|
version.buildmeta=682
|
||||||
version.major=0
|
version.major=0
|
||||||
version.minor=7
|
version.minor=7
|
||||||
version.patch=3
|
version.patch=3
|
||||||
version.prerelease=beta
|
version.prerelease=beta
|
||||||
version.project=mobibot
|
version.project=mobibot
|
||||||
version.semver=0.7.3-beta+581
|
version.semver=0.7.3-beta+682
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue