From 8f408d1f4646ea4cc672ebff006e58e61d77dd22 Mon Sep 17 00:00:00 2001 From: "Erik C. Thauvin" Date: Fri, 19 Apr 2019 21:02:01 -0700 Subject: [PATCH] Added twitter notification on join. --- properties/mobibot.properties | 3 + .../net/thauvin/erik/mobibot/Mobibot.java | 29 +++--- .../thauvin/erik/mobibot/modules/Twitter.java | 95 +++++++++++++++---- .../erik/mobibot/modules/TwitterTest.java | 77 +++++++++++++++ 4 files changed, 170 insertions(+), 34 deletions(-) create mode 100644 src/test/java/net/thauvin/erik/mobibot/modules/TwitterTest.java diff --git a/properties/mobibot.properties b/properties/mobibot.properties index 545107d..1932bd0 100644 --- a/properties/mobibot.properties +++ b/properties/mobibot.properties @@ -34,6 +34,9 @@ tell-max-size=50 #twitter-token= #twitter-tokenSecret= +# Twitter handle to receive channel join notifications +#twitter-handle= + # # Create custom search engine at: https://cse.google.com/ # and get API key from: https://console.developers.google.com/ diff --git a/src/main/java/net/thauvin/erik/mobibot/Mobibot.java b/src/main/java/net/thauvin/erik/mobibot/Mobibot.java index 4f34376..1beb0fa 100644 --- a/src/main/java/net/thauvin/erik/mobibot/Mobibot.java +++ b/src/main/java/net/thauvin/erik/mobibot/Mobibot.java @@ -287,7 +287,11 @@ public class Mobibot extends PircBot { MODULES.add(new Lookup()); MODULES.add(new Ping()); MODULES.add(new StockQuote()); - MODULES.add(new Twitter()); + + twitterModule = new Twitter(); + MODULES.add(twitterModule); + twitterHandle = p.getProperty(Constants.TWITTER_HANDLE_PROP, ""); + MODULES.add(new War()); MODULES.add(new Weather2()); MODULES.add(new WorldTime()); @@ -919,19 +923,18 @@ public class Mobibot extends PircBot { */ public final void joinChannel() { joinChannel(ircChannel); - } - /** - * {@inheritDoc} - */ - @Override - protected final void onAction(final String sender, - final String login, - final String hostname, - final String target, - final String action) { - if (target.equals(ircChannel)) { - storeRecap(sender, action, true); + if (twitterModule.isEnabled() && Utils.isValidString(twitterHandle)) { + new Thread(() -> { + try { + twitterModule.post( + twitterHandle, + getName() + ReleaseInfo.VERSION + " has joined " + ircChannel, + true); + } catch (ModuleException e) { + logger.warn(e.getMessage(), e); + } + }).start(); } } diff --git a/src/main/java/net/thauvin/erik/mobibot/modules/Twitter.java b/src/main/java/net/thauvin/erik/mobibot/modules/Twitter.java index ef067a6..465424b 100644 --- a/src/main/java/net/thauvin/erik/mobibot/modules/Twitter.java +++ b/src/main/java/net/thauvin/erik/mobibot/modules/Twitter.java @@ -33,6 +33,9 @@ package net.thauvin.erik.mobibot.modules; import net.thauvin.erik.mobibot.Mobibot; +import net.thauvin.erik.mobibot.msg.Message; +import net.thauvin.erik.mobibot.msg.NoticeMessage; +import twitter4j.DirectMessage; import twitter4j.Status; import twitter4j.TwitterFactory; import twitter4j.conf.ConfigurationBuilder; @@ -46,10 +49,10 @@ import twitter4j.conf.ConfigurationBuilder; */ public final class Twitter extends ThreadedModule { // The property keys. - private static final String CONSUMER_KEY_PROP = "twitter-consumerKey"; - private static final String CONSUMER_SECRET_PROP = "twitter-consumerSecret"; - private static final String TOKEN_PROP = "twitter-token"; - private static final String TOKEN_SECRET_PROP = "twitter-tokenSecret"; + static final String CONSUMER_KEY_PROP = "twitter-consumerKey"; + static final String CONSUMER_SECRET_PROP = "twitter-consumerSecret"; + static final String TOKEN_PROP = "twitter-token"; + static final String TOKEN_SECRET_PROP = "twitter-tokenSecret"; // The twitter command. private static final String TWITTER_CMD = "twitter"; @@ -64,6 +67,50 @@ public final class Twitter extends ThreadedModule { properties.put(TOKEN_SECRET_PROP, ""); } + /** + * Post on Twitter. + * + * @param consumerKey The consumer key. + * @param consumerSecret The consumer secret. + * @param token The token. + * @param tokenSecret The token secret. + * @param handle The Twitter handle (dm) or nickname. + * @param message The message to post. + * @param isDm The direct message flag. + * @return The {@link Message} to send back. + * @throws ModuleException If an error occurs while posting. + */ + static Message twitterPost(final String consumerKey, + final String consumerSecret, + final String token, + final String tokenSecret, + final String handle, + final String message, + final boolean isDm) throws ModuleException { + try { + final ConfigurationBuilder cb = new ConfigurationBuilder(); + cb.setDebugEnabled(true) + .setOAuthConsumerKey(consumerKey) + .setOAuthConsumerSecret(consumerSecret) + .setOAuthAccessToken(token) + .setOAuthAccessTokenSecret(tokenSecret); + + final TwitterFactory tf = new TwitterFactory(cb.build()); + final twitter4j.Twitter twitter = tf.getInstance(); + + if (!isDm) { + final Status status = twitter.updateStatus(message + " (" + handle + ')'); + return new NoticeMessage("You message was posted to http://twitter.com/" + twitter.getScreenName() + + "/statuses/" + status.getId()); + } else { + final DirectMessage dm = twitter.sendDirectMessage(handle, message); + return new NoticeMessage(dm.getText()); + } + } catch (Exception e) { + throw new ModuleException("twitterPost(" + message + ")", "An error has occurred: " + e.getMessage(), e); + } + } + /** * {@inheritDoc} */ @@ -77,29 +124,35 @@ public final class Twitter extends ThreadedModule { } } + /** + * Post on Twitter. + * + * @param handle The Twitter handle (dm) or nickname. + * @param message The message to post. + * @param isDm The direct message flag. + * @return The {@link Message} to send back. + * @throws ModuleException If an error occurs while posting. + */ + public Message post(final String handle, final String message, final boolean isDm) throws ModuleException { + return twitterPost(properties.get(CONSUMER_KEY_PROP), + properties.get(CONSUMER_SECRET_PROP), + properties.get(TOKEN_PROP), + properties.get(TOKEN_SECRET_PROP), + handle, + message, + isDm); + } + /** * Posts to twitter. */ @Override void run(final Mobibot bot, final String sender, final String message) { try { - final ConfigurationBuilder cb = new ConfigurationBuilder(); - cb.setDebugEnabled(true) - .setOAuthConsumerKey(properties.get(CONSUMER_KEY_PROP)) - .setOAuthConsumerSecret(properties.get(CONSUMER_SECRET_PROP)) - .setOAuthAccessToken(properties.get(TOKEN_PROP)) - .setOAuthAccessTokenSecret(properties.get(TOKEN_SECRET_PROP)); - final TwitterFactory tf = new TwitterFactory(cb.build()); - final twitter4j.Twitter twitter = tf.getInstance(); - - final Status status = twitter.updateStatus(message + " (" + sender + ')'); - - bot.send(sender, - "You message was posted to http://twitter.com/" + twitter.getScreenName() + "/statuses/" + status - .getId()); - } catch (Exception e) { - bot.getLogger().warn("Unable to post to Twitter: " + message, e); - bot.send(sender, "An error has occurred: " + e.getMessage()); + bot.send(sender, post(sender, message, false).getMessage()); + } catch (ModuleException e) { + bot.getLogger().warn(e.getDebugMessage(), e); + bot.send(sender, e.getMessage()); } } } diff --git a/src/test/java/net/thauvin/erik/mobibot/modules/TwitterTest.java b/src/test/java/net/thauvin/erik/mobibot/modules/TwitterTest.java new file mode 100644 index 0000000..3293956 --- /dev/null +++ b/src/test/java/net/thauvin/erik/mobibot/modules/TwitterTest.java @@ -0,0 +1,77 @@ +/* + * TwitterTest.java + * + * Copyright (c) 2004-2019, 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.Constants; +import org.testng.annotations.Test; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * The TwitterTest class. + * + * @author Erik C. Thauvin + * @created 2019-04-19 + * @since 1.0 + */ +public class TwitterTest { + private String getCi() { + if ("true".equals(System.getenv("CIRCLECI"))) { + return "CircleCI"; + } else if ("true".equals(System.getenv("TRAVIS"))) { + return "Travis CI"; + } else { + try { + return InetAddress.getLocalHost().getHostName(); + } catch (UnknownHostException e) { + return "Unknown Host"; + } + } + } + + @Test + public void testPostTwitter() throws ModuleException { + final String msg = "Testing Twitter API from " + getCi(); + assertThat(Twitter.twitterPost( + LocalProperties.getProperty(Twitter.CONSUMER_KEY_PROP), + LocalProperties.getProperty(Twitter.CONSUMER_SECRET_PROP), + LocalProperties.getProperty(Twitter.TOKEN_PROP), + LocalProperties.getProperty(Twitter.TOKEN_SECRET_PROP), + LocalProperties.getProperty(Constants.TWITTER_HANDLE_PROP), + msg, + true).getMessage()).as("twitterPost(" + msg + ')').isEqualTo(msg); + } +}