From b37022c5d78dddd54f133bb6bdbdff7ec7298b7e Mon Sep 17 00:00:00 2001 From: Scott H Date: Sun, 5 Sep 2021 03:33:00 -0400 Subject: [PATCH] [Twitter] 3.0 Twitter Binding (#10241) * [twitter][WIP] Initial contribution using the 1.x binding as a template, I created a new Twitter Binding. Signed-off-by: Scott Hanson (github: computergeek1507) Signed-off-by: Scott Hanson * trying to fix twitter4j dependency stuff Signed-off-by: Scott Hanson * add to bundle POM Signed-off-by: Scott Hanson * trying to fix build Signed-off-by: Scott Hanson * Fixed dependency issues, Got Actions working Signed-off-by: Scott Hanson * updating readme Signed-off-by: Scott Hanson * fix class name Signed-off-by: Scott Hanson * Fixes based on review Signed-off-by: Scott Hanson * Cleanup based on review and mvn checks Signed-off-by: Scott Hanson * grammar fix Signed-off-by: Scott Hanson * remove Apache dependencies Signed-off-by: Scott Hanson * added Null Checks based on review Signed-off-by: Scott Hanson * change null check around Signed-off-by: Scott Hanson --- CODEOWNERS | 1 + bundles/org.openhab.binding.twitter/NOTICE | 22 ++ bundles/org.openhab.binding.twitter/README.md | 66 ++++ bundles/org.openhab.binding.twitter/pom.xml | 29 ++ .../src/main/feature/feature.xml | 9 + .../internal/TwitterBindingConstants.java | 34 ++ .../twitter/internal/TwitterHandler.java | 333 ++++++++++++++++++ .../internal/TwitterHandlerFactory.java | 55 +++ .../internal/action/TwitterActions.java | 124 +++++++ .../internal/config/TwitterConfig.java | 30 ++ .../main/resources/OH-INF/binding/binding.xml | 9 + .../resources/OH-INF/i18n/twitter.properties | 9 + .../resources/OH-INF/thing/thing-types.xml | 47 +++ bundles/pom.xml | 1 + 14 files changed, 769 insertions(+) create mode 100644 bundles/org.openhab.binding.twitter/NOTICE create mode 100644 bundles/org.openhab.binding.twitter/README.md create mode 100644 bundles/org.openhab.binding.twitter/pom.xml create mode 100644 bundles/org.openhab.binding.twitter/src/main/feature/feature.xml create mode 100644 bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java create mode 100644 bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java create mode 100644 bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java create mode 100644 bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java create mode 100644 bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java create mode 100644 bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/binding/binding.xml create mode 100644 bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties create mode 100644 bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml diff --git a/CODEOWNERS b/CODEOWNERS index 6589d06de..08597b6e9 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -299,6 +299,7 @@ /bundles/org.openhab.binding.tplinksmarthome/ @Hilbrand /bundles/org.openhab.binding.tr064/ @openhab/add-ons-maintainers /bundles/org.openhab.binding.tradfri/ @cweitkamp @kaikreuzer +/bundles/org.openhab.binding.twitter/ @computergeek1507 /bundles/org.openhab.binding.unifi/ @mgbowman /bundles/org.openhab.binding.unifiedremote/ @GiviMAD /bundles/org.openhab.binding.upb/ @marcusb diff --git a/bundles/org.openhab.binding.twitter/NOTICE b/bundles/org.openhab.binding.twitter/NOTICE new file mode 100644 index 000000000..9b243a552 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/NOTICE @@ -0,0 +1,22 @@ +This content is produced and maintained by the openHAB project. + +* Project home: https://www.openhab.org + +== Declared Project Licenses + +This program and the accompanying materials are made available under the terms +of the Eclipse Public License 2.0 which is available at +https://www.eclipse.org/legal/epl-2.0/. + +== Source Code + +https://github.com/openhab/openhab-addons + +== Third-party Content + +twitter4j +* License: Apache License 2.0 +* Project: https://twitter4j.org/ +* Source: https://github.com/Twitter4J/Twitter4J + + diff --git a/bundles/org.openhab.binding.twitter/README.md b/bundles/org.openhab.binding.twitter/README.md new file mode 100644 index 000000000..6c120b6d8 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/README.md @@ -0,0 +1,66 @@ +# Twitter Binding + +The Twitter binding allows your home to Tweet 280 characters at a time. It also supports direct messages and tweeting with media. + +## Supported Things + +``` +account - Twitter Account. + +``` + +## Thing Configuration + +The Twitter Account Thing requires you to create a Twitter App in the Twitter Developer Page. + +| Property | Default | Required | Description | +|-------------------|---------|:--------:|-----------------------------------| +| consumerKey | | Yes | Consumer API Key | +| consumerSecret | | Yes | Consumer API Secret | +| accessToken | | Yes | Access Token | +| accessTokenSecret | | Yes | Access Token Secret | +| refresh | 30 | No | Tweet refresh interval in minutes | + + +## Channels + +| channel | type | description | +|------------|--------|------------------------------------------------| +| lasttweet | String | This channel provides the Latest Tweet message | + + +## Full Example + +twitter.things: + +``` +Thing twitter:account:sampleaccount [ consumerKey="11111", consumerSecret="22222", accessToken="33333", accessTokenSecret="444444" ] + +``` + +twitter.items: + +``` +String sample_tweet "Latest Tweet: [%s]" { channel="twitter:account:sampleaccount:lasttweet" } + +``` + +## Rule Action + +This binding includes rule actions for sending tweets and direct messages. + +* `boolean success = sendTweet(String text)` +* `boolean success = sendTweetWithAttachment(String text, String URL)` +* `boolean success = sendDirectMessage(String recipientID, String text)` + +Examples: + +``` +val tweetActions = getActions("twitter","twitter:account:sampleaccount") +val success = tweetActions.sendTweet("This is A Tweet") +val success2 = tweetActions.sendTweetWithAttachment("This is A Tweet with a Pic", file:///tmp/201601011031.jpg) +val success3 = tweetActions.sendTweetWithAttachment("Windows Picture", "D:\\Test.png" ) +val success4 = tweetActions.sendTweetWithAttachment("HTTP Picture", "http://www.mywebsite.com/Test.png" ) +val success5 = tweetActions.sendDirectMessage("1234567", "Wake Up" ) + +``` diff --git a/bundles/org.openhab.binding.twitter/pom.xml b/bundles/org.openhab.binding.twitter/pom.xml new file mode 100644 index 000000000..03450d9a7 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 3.2.0-SNAPSHOT + + + org.openhab.binding.twitter + + openHAB Add-ons :: Bundles :: Twitter Binding + + + !android.*,!com.android.org.*,!dalvik.*,!javax.annotation.meta.*,!org.apache.harmony.*,!org.conscrypt.*,!sun.*,!com.google.appengine.api.* + + + + + org.twitter4j + twitter4j-core + 4.0.7 + compile + + + diff --git a/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml b/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml new file mode 100644 index 000000000..86048f282 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml @@ -0,0 +1,9 @@ + + + mvn:org.openhab.core.features.karaf/org.openhab.core.features.karaf.openhab-core/${ohc.version}/xml/features + + + openhab-runtime-base + mvn:org.openhab.addons.bundles/org.openhab.binding.twitter/${project.version} + + diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java new file mode 100644 index 000000000..5b05b1b77 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.twitter.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link TwitterBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Scott Hanson - Initial contribution + */ +@NonNullByDefault +public class TwitterBindingConstants { + + private static final String BINDING_ID = "twitter"; + + // List of all Thing Type UIDs + public static final ThingTypeUID THING_TYPE_ACCOUNT = new ThingTypeUID(BINDING_ID, "account"); + + // List of all Channel ids + public static final String CHANNEL_LASTTWEET = "lasttweet"; +} diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java new file mode 100644 index 000000000..b0e206848 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java @@ -0,0 +1,333 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.twitter.internal; + +import static org.openhab.binding.twitter.internal.TwitterBindingConstants.CHANNEL_LASTTWEET; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.twitter.internal.action.TwitterActions; +import org.openhab.binding.twitter.internal.config.TwitterConfig; +import org.openhab.core.io.net.http.HttpUtil; +import org.openhab.core.library.types.RawType; +import org.openhab.core.library.types.StringType; +import org.openhab.core.thing.ChannelUID; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.binding.BaseThingHandler; +import org.openhab.core.thing.binding.ThingHandlerService; +import org.openhab.core.types.Command; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import twitter4j.DirectMessage; +import twitter4j.ResponseList; +import twitter4j.Status; +import twitter4j.StatusUpdate; +import twitter4j.Twitter; +import twitter4j.TwitterException; +import twitter4j.TwitterFactory; +import twitter4j.auth.AccessToken; + +/** + * The {@link TwitterHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Scott Hanson - Initial contribution + */ + +@NonNullByDefault +public class TwitterHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(TwitterHandler.class); + + private TwitterConfig config = new TwitterConfig(); + + private @Nullable ScheduledFuture refreshTask; + + private static final int CHARACTER_LIMIT = 280; + + private static @Nullable Twitter client = null; + boolean isProperlyConfigured = false; + + public TwitterHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + // creates list of available Actions + @Override + public Collection> getServices() { + return Collections.singletonList(TwitterActions.class); + } + + @Override + public void initialize() { + config = getConfigAs(TwitterConfig.class); + + // create a New Twitter Client + Twitter localClient = createClient(); + client = localClient; + refresh();// Get latest status + isProperlyConfigured = true; + refreshTask = scheduler.scheduleWithFixedDelay(this::refresh, 0, config.refresh, TimeUnit.MINUTES); + updateStatus(ThingStatus.ONLINE); + } + + @Override + public void dispose() { + ScheduledFuture localRefreshTask = refreshTask; + if (localRefreshTask != null) { + localRefreshTask.cancel(true); + } + } + + /** + * Internal method for Getting Twitter Status + * + */ + private void refresh() { + try { + if (!checkPrerequisites()) { + return; + } + Twitter localClient = client; + if (localClient != null) { + ResponseList statuses = localClient.getUserTimeline(); + if (statuses.size() > 0) { + updateState(CHANNEL_LASTTWEET, StringType.valueOf(statuses.get(0).getText())); + } else { + logger.debug("No Statuses Found"); + } + } + } catch (TwitterException e) { + logger.debug("Error when trying to refresh Twitter Account: {}", e.getMessage()); + } + } + + /** + * Internal method for sending a tweet, with or without image + * + * @param tweetTxt + * text string to be sent as a Tweet + * @param fileToAttach + * the file to attach. May be null if no attached file. + * + * @return true, if sending the tweet has been successful and + * false in all other cases. + */ + private boolean sendTweet(final String tweetTxt, final @Nullable File fileToAttach) { + if (!checkPrerequisites()) { + return false; + } + // abbreviate the Tweet to meet the 280 character limit ... + String abbreviatedTweetTxt = abbreviateString(tweetTxt, CHARACTER_LIMIT); + try { + Twitter localClient = client; + if (localClient != null) { + // send the Tweet + StatusUpdate status = new StatusUpdate(abbreviatedTweetTxt); + if (fileToAttach != null && fileToAttach.isFile()) { + status.setMedia(fileToAttach); + } + Status updatedStatus = localClient.updateStatus(status); + logger.debug("Successfully sent Tweet '{}'", updatedStatus.getText()); + updateState(CHANNEL_LASTTWEET, StringType.valueOf(updatedStatus.getText())); + return true; + } + } catch (TwitterException e) { + logger.warn("Failed to send Tweet '{}' because of : {}", abbreviatedTweetTxt, e.getLocalizedMessage()); + } + return false; + } + + /** + * Sends a standard Tweet. + * + * @param tweetTxt + * text string to be sent as a Tweet + * + * @return true, if sending the tweet has been successful and + * false in all other cases. + */ + public boolean sendTweet(String tweetTxt) { + if (!checkPrerequisites()) { + return false; + } + return sendTweet(tweetTxt, (File) null); + } + + /** + * Sends a Tweet with an image + * + * @param tweetTxt + * text string to be sent as a Tweet + * @param tweetPicture + * the path of the picture that needs to be attached (either an url, + * either a path pointing to a local file) + * + * @return true, if sending the tweet has been successful and + * false in all other cases. + */ + public boolean sendTweet(String tweetTxt, String tweetPicture) { + if (!checkPrerequisites()) { + return false; + } + + // prepare the image attachment + File fileToAttach = null; + boolean deleteTemporaryFile = false; + if (tweetPicture.startsWith("http://") || tweetPicture.startsWith("https://")) { + try { + // we have a remote url and need to download the remote file to a temporary location + Path tDir = Files.createTempDirectory("TempDirectory"); + String path = tDir + File.separator + "openhab-twitter-remote_attached_file" + "." + + getExtension(tweetPicture); + + // URL url = new URL(tweetPicture); + fileToAttach = new File(path); + deleteTemporaryFile = true; + + RawType rawPicture = HttpUtil.downloadImage(tweetPicture); + if (rawPicture != null) { + try (FileOutputStream fos = new FileOutputStream(path)) { + fos.write(rawPicture.getBytes(), 0, rawPicture.getBytes().length); + } catch (FileNotFoundException ex) { + logger.debug("Could not create {} in temp dir. {}", path, ex.getMessage()); + } catch (IOException ex) { + logger.debug("Could not write {} to temp dir. {}", path, ex.getMessage()); + } + } else { + logger.debug("Could not download tweet file from {}", tweetPicture); + } + } catch (IOException ex) { + logger.debug("Could not write {} to temp dir. {}", tweetPicture, ex.getMessage()); + } + } else { + // we have a local file and can just use it directly + fileToAttach = new File(tweetPicture); + } + + if (fileToAttach != null && fileToAttach.isFile()) { + logger.debug("Image '{}' correctly found, will be included in tweet", tweetPicture); + } else { + logger.warn("Image '{}' not found, will only tweet text", tweetPicture); + } + + // send the Tweet + boolean result = sendTweet(tweetTxt, fileToAttach); + // delete temp file (if needed) + if (deleteTemporaryFile) { + if (fileToAttach != null) { + try { + fileToAttach.delete(); + } catch (final Exception ignored) { + return false; + } + } + } + return result; + } + + /** + * Sends a DirectMessage + * + * @param recipientId + * recipient ID of the twitter user + * @param messageTxt + * text string to be sent as a Direct Message + * + * @return true, if sending the direct message has been successful and + * false in all other cases. + */ + public boolean sendDirectMessage(String recipientId, String messageTxt) { + if (!checkPrerequisites()) { + return false; + } + + try { + Twitter localClient = client; + if (localClient != null) { + // abbreviate the Tweet to meet the allowed character limit ... + String abbreviatedMessageTxt = abbreviateString(messageTxt, CHARACTER_LIMIT); + // send the direct message + DirectMessage message = localClient.sendDirectMessage(recipientId, abbreviatedMessageTxt); + logger.debug("Successfully sent direct message '{}' to @'{}'", message.getText(), + message.getRecipientId()); + return true; + } + } catch (TwitterException e) { + logger.warn("Failed to send Direct Message '{}' because of :'{}'", messageTxt, e.getLocalizedMessage()); + } + return false; + } + + /** + * check if twitter account was created with prerequisites + * + * @return true, if twitter account was initialized + * false in all other cases. + */ + private boolean checkPrerequisites() { + if (client == null) { + logger.debug("Twitter client is not yet configured > execution aborted!"); + return false; + } + if (!isProperlyConfigured) { + logger.debug("Twitter client is not yet configured > execution aborted!"); + return false; + } + return true; + } + + /** + * Creates and returns a Twitter4J Twitter client. + * + * @return a new instance of a Twitter4J Twitter client. + */ + private twitter4j.Twitter createClient() { + twitter4j.Twitter client = TwitterFactory.getSingleton(); + client.setOAuthConsumer(config.consumerKey, config.consumerSecret); + client.setOAuthAccessToken(new AccessToken(config.accessToken, config.accessTokenSecret)); + return client; + } + + public static String abbreviateString(String input, int maxLength) { + if (input.length() <= maxLength) { + return input; + } else { + return input.substring(0, maxLength); + } + } + + public static String getExtension(String filename) { + if (filename.contains(".")) { + return filename.substring(filename.lastIndexOf(".") + 1); + } + return new String(); + } +} diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java new file mode 100644 index 000000000..356e79f08 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.twitter.internal; + +import static org.openhab.binding.twitter.internal.TwitterBindingConstants.THING_TYPE_ACCOUNT; + +import java.util.Set; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.core.thing.Thing; +import org.openhab.core.thing.ThingTypeUID; +import org.openhab.core.thing.binding.BaseThingHandlerFactory; +import org.openhab.core.thing.binding.ThingHandler; +import org.openhab.core.thing.binding.ThingHandlerFactory; +import org.osgi.service.component.annotations.Component; + +/** + * The {@link TwitterHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Scott Hanson - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.twitter", service = ThingHandlerFactory.class) +public class TwitterHandlerFactory extends BaseThingHandlerFactory { + + private static final Set SUPPORTED_THING_TYPES_UIDS = Set.of(THING_TYPE_ACCOUNT); + + @Override + public boolean supportsThingType(ThingTypeUID thingTypeUID) { + return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); + } + + @Override + protected @Nullable ThingHandler createHandler(Thing thing) { + ThingTypeUID thingTypeUID = thing.getThingTypeUID(); + + if (THING_TYPE_ACCOUNT.equals(thingTypeUID)) { + return new TwitterHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java new file mode 100644 index 000000000..ee11b5b41 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.twitter.internal.action; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.twitter.internal.TwitterHandler; +import org.openhab.core.automation.annotation.ActionInput; +import org.openhab.core.automation.annotation.ActionOutput; +import org.openhab.core.automation.annotation.RuleAction; +import org.openhab.core.thing.binding.ThingActions; +import org.openhab.core.thing.binding.ThingActionsScope; +import org.openhab.core.thing.binding.ThingHandler; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@link TweetActions} class defines rule actions for sending tweet + * + * @author Scott Hanson - Initial contribution + */ +@ThingActionsScope(name = "twitter") +@NonNullByDefault +public class TwitterActions implements ThingActions { + + private final Logger logger = LoggerFactory.getLogger(TwitterActions.class); + + private @Nullable TwitterHandler handler; + + @RuleAction(label = "@text/sendTweetActionLabel", description = "@text/sendTweetActionDescription") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendTweet( + @ActionInput(name = "text") @Nullable String text) { + if (text == null) { + logger.warn("Cannot send Tweet as text is missing."); + return false; + } + + final TwitterHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot tweet."); + return false; + } else { + return handler.sendTweet(text); + } + } + + @RuleAction(label = "@text/sendAttachmentTweetActionLabel", description = "@text/sendAttachmentTweetActionDescription") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendTweetWithAttachment( + @ActionInput(name = "text") @Nullable String text, @ActionInput(name = "url") @Nullable String urlString) { + if (text == null) { + logger.warn("Cannot send Tweet as text is missing."); + return false; + } + if (urlString == null) { + logger.warn("Cannot send Tweet as urlString is missing."); + return false; + } + + final TwitterHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot tweet."); + return false; + } else { + return handler.sendTweet(text, urlString); + } + } + + @RuleAction(label = "@text/sendDirectMessageActionLabel", description = "@text/sendDirectMessageActionDescription") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendDirectMessage( + @ActionInput(name = "recipient") @Nullable String recipient, + @ActionInput(name = "text") @Nullable String text) { + if (recipient == null) { + logger.warn("Cannot send Direct Message as recipient is missing."); + return false; + } + if (text == null) { + logger.warn("Cannot send Direct Message as text is missing."); + return false; + } + + final TwitterHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot tweet."); + return false; + } else { + return handler.sendDirectMessage(recipient, text); + } + } + + public static boolean sendTweet(ThingActions actions, @Nullable String text) { + return ((TwitterActions) actions).sendTweet(text); + } + + public static boolean sendTweetWithAttachment(ThingActions actions, @Nullable String text, + @Nullable String urlString) { + return ((TwitterActions) actions).sendTweetWithAttachment(text, urlString); + } + + public static boolean sendDirectMessage(ThingActions actions, @Nullable String recipient, @Nullable String text) { + return ((TwitterActions) actions).sendDirectMessage(recipient, text); + } + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof TwitterHandler) { + this.handler = (TwitterHandler) handler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return handler; + } +} diff --git a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java new file mode 100644 index 000000000..1f4432e79 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2021 Contributors to the openHAB project + * + * See the NOTICE file(s) distributed with this work for additional + * information. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0 + * + * SPDX-License-Identifier: EPL-2.0 + */ +package org.openhab.binding.twitter.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link TwitterConfig} class contains fields mapping thing configuration parameters. + * + * @author Scott Hanson - Initial contribution + */ + +@NonNullByDefault +public class TwitterConfig { + public String consumerKey = ""; + public String consumerSecret = ""; + public String accessToken = ""; + public String accessTokenSecret = ""; + public int refresh = 30; +} diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/binding/binding.xml b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/binding/binding.xml new file mode 100644 index 000000000..20e7da402 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/binding/binding.xml @@ -0,0 +1,9 @@ + + + + Twitter Binding + Supports adding Thing for getting the Last Tweet. Send Tweets and Pictures with Actions. + + diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties new file mode 100644 index 000000000..3de984bd6 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties @@ -0,0 +1,9 @@ +# actions +sendTweetActionLabel = send a Tweet +sendTweetActionDescription = Sends a Tweet. + +sendAttachmentTweetActionLabel = send a Tweet with attachment +sendAttachmentTweetActionDescription = Sends a Tweet with an attachment. + +sendDirectMessageActionLabel = send a DirectMessage +sendDirectMessageActionDescription = Sends a DirectMessage. diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 000000000..1ec1355e9 --- /dev/null +++ b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,47 @@ + + + + + + Account uses for sending Tweets + + + + + + + + + password + + + + password + + + + password + + + + password + + + + Refresh Time for This Account in Mins + 30 + + + + + + + String + + Users Last Tweet + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index 24e1feb55..0e568d188 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -331,6 +331,7 @@ org.openhab.binding.tplinksmarthome org.openhab.binding.tr064 org.openhab.binding.tradfri + org.openhab.binding.twitter org.openhab.binding.unifi org.openhab.binding.unifiedremote org.openhab.binding.upnpcontrol