From: lsiepel Date: Wed, 15 Nov 2023 08:12:24 +0000 (+0100) Subject: [twitter] rename binding to X (#15809) X-Git-Url: https://git.basschouten.com/?a=commitdiff_plain;h=12f02124b636cbc640509658f321428f5b57d8df;p=openhab-addons.git [twitter] rename binding to X (#15809) Signed-off-by: Leo Siepel --- diff --git a/CODEOWNERS b/CODEOWNERS index 6d8ddc9c79..4b4e4a859c 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -355,7 +355,6 @@ /bundles/org.openhab.binding.tplinksmarthome/ @Hilbrand /bundles/org.openhab.binding.tr064/ @J-N-K /bundles/org.openhab.binding.tradfri/ @cweitkamp @kaikreuzer -/bundles/org.openhab.binding.twitter/ @computergeek1507 /bundles/org.openhab.binding.unifi/ @mgbowman @Hilbrand /bundles/org.openhab.binding.unifiedremote/ @GiviMAD /bundles/org.openhab.binding.upb/ @marcusb @@ -386,6 +385,7 @@ /bundles/org.openhab.binding.wled/ @Skinah /bundles/org.openhab.binding.wolfsmartset/ @BoBiene /bundles/org.openhab.binding.wundergroundupdatereceiver/ @danieldemus +/bundles/org.openhab.binding.x/ @computergeek1507 /bundles/org.openhab.binding.xmltv/ @clinique /bundles/org.openhab.binding.xmppclient/ @pavel-gololobov /bundles/org.openhab.binding.yamahamusiccast/ @coop-git diff --git a/bom/openhab-addons/pom.xml b/bom/openhab-addons/pom.xml index 9f322e518b..bfee3215ad 100644 --- a/bom/openhab-addons/pom.xml +++ b/bom/openhab-addons/pom.xml @@ -1761,11 +1761,6 @@ org.openhab.binding.tradfri ${project.version} - - org.openhab.addons.bundles - org.openhab.binding.twitter - ${project.version} - org.openhab.addons.bundles org.openhab.binding.unifi @@ -1921,6 +1916,11 @@ org.openhab.binding.wundergroundupdatereceiver ${project.version} + + org.openhab.addons.bundles + org.openhab.binding.x + ${project.version} + org.openhab.addons.bundles org.openhab.binding.xmltv diff --git a/bundles/org.openhab.binding.twitter/NOTICE b/bundles/org.openhab.binding.twitter/NOTICE deleted file mode 100644 index 9b243a5526..0000000000 --- a/bundles/org.openhab.binding.twitter/NOTICE +++ /dev/null @@ -1,22 +0,0 @@ -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 deleted file mode 100644 index b0ed2e6aba..0000000000 --- a/bundles/org.openhab.binding.twitter/README.md +++ /dev/null @@ -1,63 +0,0 @@ -# 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 - -```text -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: - -```java -Thing twitter:account:sampleaccount [ consumerKey="11111", consumerSecret="22222", accessToken="33333", accessTokenSecret="444444" ] - -``` - -twitter.items: - -```java -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: - -```java -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 deleted file mode 100644 index 00e42c8b7f..0000000000 --- a/bundles/org.openhab.binding.twitter/pom.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - 4.0.0 - - - org.openhab.addons.bundles - org.openhab.addons.reactor.bundles - 4.1.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 deleted file mode 100644 index 86048f2829..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/feature/feature.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - 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 deleted file mode 100644 index c42baaeb2b..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterBindingConstants.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (c) 2010-2023 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 deleted file mode 100644 index 8b962d7902..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandler.java +++ /dev/null @@ -1,333 +0,0 @@ -/** - * Copyright (c) 2010-2023 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.List; -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 List.of(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.isEmpty()) { - 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 deleted file mode 100644 index d27f76f7bd..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/TwitterHandlerFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (c) 2010-2023 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 deleted file mode 100644 index 12a56c3574..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/action/TwitterActions.java +++ /dev/null @@ -1,124 +0,0 @@ -/** - * Copyright (c) 2010-2023 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 TwitterActions} 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 twitterHandler) { - this.handler = twitterHandler; - } - } - - @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 deleted file mode 100644 index 529bee31a8..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/java/org/openhab/binding/twitter/internal/config/TwitterConfig.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (c) 2010-2023 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/addon/addon.xml b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/addon/addon.xml deleted file mode 100644 index 8c90697c78..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/addon/addon.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - binding - Twitter Binding - Supports adding Thing for getting the Last Tweet. Send Tweets and Pictures with Actions. - cloud - - 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 deleted file mode 100644 index 161cccf2a8..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter.properties +++ /dev/null @@ -1,32 +0,0 @@ -# add-on - -addon.twitter.name = Twitter Binding -addon.twitter.description = Supports adding Thing for getting the Last Tweet. Send Tweets and Pictures with Actions. - -# thing types - -thing-type.twitter.account.label = Twitter Account -thing-type.twitter.account.description = Account uses for sending Tweets - -# thing types config - -thing-type.config.twitter.account.accessToken.label = Access Token -thing-type.config.twitter.account.accessTokenSecret.label = Access Token Secret -thing-type.config.twitter.account.consumerKey.label = Consumer API Key -thing-type.config.twitter.account.consumerSecret.label = Consumer API Secret -thing-type.config.twitter.account.refresh.label = Refresh Time -thing-type.config.twitter.account.refresh.description = Refresh Time for This Account in Mins - -# channel types - -channel-type.twitter.lasttweet.label = Last Tweet -channel-type.twitter.lasttweet.description = Users Last Tweet - -# actions - -sendAttachmentTweetActionLabel = send a Tweet with attachment -sendAttachmentTweetActionDescription = Sends a Tweet with an attachment. -sendDirectMessageActionLabel = send a DirectMessage -sendDirectMessageActionDescription = Sends a DirectMessage. -sendTweetActionLabel = send a Tweet -sendTweetActionDescription = Sends a Tweet. diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties deleted file mode 100644 index 06d82693ef..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_fr.properties +++ /dev/null @@ -1,32 +0,0 @@ -# add-on - -addon.twitter.name = Extension Twitter -addon.twitter.description = Cette extension permet d'obtenir le dernier Tweet ou d'envoyer des Tweets et des images depuis vos règles d'automatisation. - -# thing types - -thing-type.twitter.account.label = Compte Twitter -thing-type.twitter.account.description = Compte pour envoyer des Tweets - -# thing types config - -thing-type.config.twitter.account.accessToken.label = Jeton d'authentification -thing-type.config.twitter.account.accessTokenSecret.label = Code secret du jeton d'authentification -thing-type.config.twitter.account.consumerKey.label = Clé d'accès à l'API -thing-type.config.twitter.account.consumerSecret.label = Code secret pour l'accès à l'API -thing-type.config.twitter.account.refresh.label = Fréquence de rafraîchissement -thing-type.config.twitter.account.refresh.description = Fréquence de rafraîchissement de ce compte en minutes - -# channel types - -channel-type.twitter.lasttweet.label = Dernier Tweet -channel-type.twitter.lasttweet.description = Dernier Tweet des utilisateurs - -# actions - -sendAttachmentTweetActionLabel = envoyer un Tweet avec pièce jointe -sendAttachmentTweetActionDescription = Envoie un Tweet avec pièce jointe. -sendDirectMessageActionLabel = envoyer un message privé -sendDirectMessageActionDescription = Envoie un message privé. -sendTweetActionLabel = envoyer un Tweet -sendTweetActionDescription = Envoie un Tweet. diff --git a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties b/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties deleted file mode 100644 index 6991945830..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/i18n/twitter_ru.properties +++ /dev/null @@ -1,9 +0,0 @@ -# actions -sendTweetActionLabel = отправить твит -sendTweetActionDescription = Отправляет твит. - -sendAttachmentTweetActionLabel = отправить твит с вложением -sendAttachmentTweetActionDescription = Отправляет твит с вложением. - -sendDirectMessageActionLabel = отправить личное сообщение -sendDirectMessageActionDescription = Отправляет личное сообщение. 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 deleted file mode 100644 index 1ec1355e99..0000000000 --- a/bundles/org.openhab.binding.twitter/src/main/resources/OH-INF/thing/thing-types.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - 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/org.openhab.binding.x/NOTICE b/bundles/org.openhab.binding.x/NOTICE new file mode 100644 index 0000000000..9b243a5526 --- /dev/null +++ b/bundles/org.openhab.binding.x/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.x/README.md b/bundles/org.openhab.binding.x/README.md new file mode 100644 index 0000000000..846ee864b1 --- /dev/null +++ b/bundles/org.openhab.binding.x/README.md @@ -0,0 +1,60 @@ +# X Binding + +The X (formerly known as Twitter) binding allows your home to post 280 characters at a time. It also supports direct messages and posting with media. + +## Supported Things + +```text +account - X Account. +``` + +## Thing Configuration + +The X Account Thing requires you to create a X App in the X 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 | Post refresh interval in minutes | + +## Channels + +| channel | type | description | +|----------|--------|-----------------------------------------------| +| lastpost | String | This channel provides the Latest post message | + +## Full Example + +x.things: + +```java +Thing x:account:sampleaccount [ consumerKey="11111", consumerSecret="22222", accessToken="33333", accessTokenSecret="444444" ] +``` + +x.items: + +```java +String sample_post "Latest post: [%s]" { channel="x:account:sampleaccount:lastpost" } +``` + +## Rule Action + +This binding includes rule actions for sending posts and direct messages. + +- `boolean success = sendPost(String text)` +- `boolean success = sendPostWithAttachment(String text, String URL)` +- `boolean success = sendDirectMessage(String recipientID, String text)` + +Examples: + +```java +val postActions = getActions("x","x:account:sampleaccount") +val success = postActions.sendPost("This is A Post") +val success2 = postActions.sendPostWithAttachment("This is A Post with a Pic", file:///tmp/201601011031.jpg) +val success3 = postActions.sendPostWithAttachment("Windows Picture", "D:\\Test.png" ) +val success4 = postActions.sendPostWithAttachment("HTTP Picture", "http://www.mywebsite.com/Test.png" ) +val success5 = postActions.sendDirectMessage("1234567", "Wake Up" ) +``` diff --git a/bundles/org.openhab.binding.x/pom.xml b/bundles/org.openhab.binding.x/pom.xml new file mode 100644 index 0000000000..f7020d2f91 --- /dev/null +++ b/bundles/org.openhab.binding.x/pom.xml @@ -0,0 +1,29 @@ + + + + 4.0.0 + + + org.openhab.addons.bundles + org.openhab.addons.reactor.bundles + 4.1.0-SNAPSHOT + + + org.openhab.binding.x + + openHAB Add-ons :: Bundles :: X Binding + + + !org.slf4j.impl.*,!android.*,!com.android.org.*,!dalvik.*,!javax.annotation.meta.*,!org.apache.harmony.*,!org.conscrypt.*,!sun.*,!com.google.appengine.api.* + + + + + org.twitter4j + twitter4j-core + 4.1.2 + compile + + + diff --git a/bundles/org.openhab.binding.x/src/main/feature/feature.xml b/bundles/org.openhab.binding.x/src/main/feature/feature.xml new file mode 100644 index 0000000000..ffb954879f --- /dev/null +++ b/bundles/org.openhab.binding.x/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.x/${project.version} + + diff --git a/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java new file mode 100644 index 0000000000..d35f5246b6 --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XBindingConstants.java @@ -0,0 +1,34 @@ +/** + * Copyright (c) 2010-2023 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.x.internal; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.openhab.core.thing.ThingTypeUID; + +/** + * The {@link XBindingConstants} class defines common constants, which are + * used across the whole binding. + * + * @author Scott Hanson - Initial contribution + */ +@NonNullByDefault +public class XBindingConstants { + + private static final String BINDING_ID = "x"; + + // 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_LASTPOST = "lastpost"; +} diff --git a/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java new file mode 100644 index 0000000000..b262840e2e --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandler.java @@ -0,0 +1,332 @@ +/** + * Copyright (c) 2010-2023 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.x.internal; + +import static org.openhab.binding.x.internal.XBindingConstants.CHANNEL_LASTPOST; + +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.List; +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.x.internal.action.XActions; +import org.openhab.binding.x.internal.config.XConfig; +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.Twitter; +import twitter4j.TwitterException; +import twitter4j.v1.DirectMessage; +import twitter4j.v1.ResponseList; +import twitter4j.v1.Status; +import twitter4j.v1.StatusUpdate; + +/** + * The {@link XHandler} is responsible for handling commands, which are + * sent to one of the channels. + * + * @author Scott Hanson - Initial contribution + */ + +@NonNullByDefault +public class XHandler extends BaseThingHandler { + + private final Logger logger = LoggerFactory.getLogger(XHandler.class); + + private XConfig config = new XConfig(); + + private @Nullable ScheduledFuture refreshTask; + + private static final int CHARACTER_LIMIT = 280; + + private static @Nullable Twitter client = null; + boolean isProperlyConfigured = false; + + public XHandler(Thing thing) { + super(thing); + } + + @Override + public void handleCommand(ChannelUID channelUID, Command command) { + } + + // creates list of available Actions + @Override + public Collection> getServices() { + return List.of(XActions.class); + } + + @Override + public void initialize() { + config = getConfigAs(XConfig.class); + + // create a New X/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 X Status + * + */ + private void refresh() { + try { + if (!checkPrerequisites()) { + return; + } + Twitter localClient = client; + if (localClient != null) { + ResponseList statuses = localClient.v1().timelines().getUserTimeline(); + if (!statuses.isEmpty()) { + updateState(CHANNEL_LASTPOST, StringType.valueOf(statuses.get(0).getText())); + } else { + logger.debug("No Statuses Found"); + } + } + } catch (TwitterException e) { + logger.debug("Error when trying to refresh X Account: {}", e.getMessage()); + } + } + + /** + * Internal method for sending a post, with or without image + * + * @param postTxt + * text string to be sent as a Post + * @param fileToAttach + * the file to attach. May be null if no attached file. + * + * @return true, if sending the post has been successful and + * false in all other cases. + */ + private boolean sendPost(final String postTxt, final @Nullable File fileToAttach) { + if (!checkPrerequisites()) { + return false; + } + // abbreviate the Post to meet the 280 character limit ... + String abbreviatedPostTxt = abbreviateString(postTxt, CHARACTER_LIMIT); + try { + Twitter localClient = client; + if (localClient != null) { + // send the Post + StatusUpdate status = StatusUpdate.of(abbreviatedPostTxt); + if (fileToAttach != null && fileToAttach.isFile()) { + status = status.media(fileToAttach); + } + Status updatedStatus = localClient.v1().tweets().updateStatus(status); + logger.debug("Successfully sent Post '{}'", updatedStatus.getText()); + updateState(CHANNEL_LASTPOST, StringType.valueOf(updatedStatus.getText())); + return true; + } + } catch (TwitterException e) { + logger.warn("Failed to send Post '{}' because of : {}", abbreviatedPostTxt, e.getLocalizedMessage()); + } + return false; + } + + /** + * Sends a standard Post. + * + * @param postTxt + * text string to be sent as a Post + * + * @return true, if sending the post has been successful and + * false in all other cases. + */ + public boolean sendPost(String postTxt) { + if (!checkPrerequisites()) { + return false; + } + return sendPost(postTxt, (File) null); + } + + /** + * Sends a Post with an image + * + * @param postTxt + * text string to be sent as a Post + * @param postPicture + * 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 post has been successful and + * false in all other cases. + */ + public boolean sendPost(String postTxt, String postPicture) { + if (!checkPrerequisites()) { + return false; + } + + // prepare the image attachment + File fileToAttach = null; + boolean deleteTemporaryFile = false; + if (postPicture.startsWith("http://") || postPicture.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-x-remote_attached_file" + "." + + getExtension(postPicture); + + // URL url = new URL(postPicture); + fileToAttach = new File(path); + deleteTemporaryFile = true; + + RawType rawPicture = HttpUtil.downloadImage(postPicture); + 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 post file from {}", postPicture); + } + } catch (IOException ex) { + logger.debug("Could not write {} to temp dir. {}", postPicture, ex.getMessage()); + } + } else { + // we have a local file and can just use it directly + fileToAttach = new File(postPicture); + } + + if (fileToAttach != null && fileToAttach.isFile()) { + logger.debug("Image '{}' correctly found, will be included in post", postPicture); + } else { + logger.warn("Image '{}' not found, will only post text", postPicture); + } + + // send the Post + boolean result = sendPost(postTxt, 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 Post to meet the allowed character limit ... + String abbreviatedMessageTxt = abbreviateString(messageTxt, CHARACTER_LIMIT); + // send the direct message + DirectMessage message = localClient.v1().directMessages().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 X account was created with prerequisites + * + * @return true, if X account was initialized + * false in all other cases. + */ + private boolean checkPrerequisites() { + if (client == null) { + logger.debug("X client is not yet configured > execution aborted!"); + return false; + } + if (!isProperlyConfigured) { + logger.debug("X 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() { + Twitter client = Twitter.newBuilder().oAuthConsumer(config.consumerKey, config.consumerSecret) + .oAuthAccessToken(config.accessToken, config.accessTokenSecret).build(); + + 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.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java new file mode 100644 index 0000000000..50a9341d25 --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/XHandlerFactory.java @@ -0,0 +1,55 @@ +/** + * Copyright (c) 2010-2023 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.x.internal; + +import static org.openhab.binding.x.internal.XBindingConstants.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 XHandlerFactory} is responsible for creating things and thing + * handlers. + * + * @author Scott Hanson - Initial contribution + */ +@NonNullByDefault +@Component(configurationPid = "binding.x", service = ThingHandlerFactory.class) +public class XHandlerFactory 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 XHandler(thing); + } + + return null; + } +} diff --git a/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java new file mode 100644 index 0000000000..8133645ddf --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/action/XActions.java @@ -0,0 +1,124 @@ +/** + * Copyright (c) 2010-2023 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.x.internal.action; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.openhab.binding.x.internal.XHandler; +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 XActions} class defines rule actions for sending post + * + * @author Scott Hanson - Initial contribution + */ +@ThingActionsScope(name = "x") +@NonNullByDefault +public class XActions implements ThingActions { + + private final Logger logger = LoggerFactory.getLogger(XActions.class); + + private @Nullable XHandler handler; + + @RuleAction(label = "@text/sendPostActionLabel", description = "@text/sendPostActionDescription") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPost( + @ActionInput(name = "text") @Nullable String text) { + if (text == null) { + logger.warn("Cannot send Post as text is missing."); + return false; + } + + final XHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot post."); + return false; + } else { + return handler.sendPost(text); + } + } + + @RuleAction(label = "@text/sendAttachmentPostActionLabel", description = "@text/sendAttachmentPostActionDescription") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPostWithAttachment( + @ActionInput(name = "text") @Nullable String text, @ActionInput(name = "url") @Nullable String urlString) { + if (text == null) { + logger.warn("Cannot send Post as text is missing."); + return false; + } + if (urlString == null) { + logger.warn("Cannot send Post as urlString is missing."); + return false; + } + + final XHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot post."); + return false; + } else { + return handler.sendPost(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 XHandler handler = this.handler; + if (handler == null) { + logger.debug("Handler is null, cannot post."); + return false; + } else { + return handler.sendDirectMessage(recipient, text); + } + } + + public static boolean sendPost(ThingActions actions, @Nullable String text) { + return ((XActions) actions).sendPost(text); + } + + public static boolean sendPostWithAttachment(ThingActions actions, @Nullable String text, + @Nullable String urlString) { + return ((XActions) actions).sendPostWithAttachment(text, urlString); + } + + public static boolean sendDirectMessage(ThingActions actions, @Nullable String recipient, @Nullable String text) { + return ((XActions) actions).sendDirectMessage(recipient, text); + } + + @Override + public void setThingHandler(@Nullable ThingHandler handler) { + if (handler instanceof XHandler xHandler) { + this.handler = xHandler; + } + } + + @Override + public @Nullable ThingHandler getThingHandler() { + return handler; + } +} diff --git a/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java new file mode 100644 index 0000000000..73e11d9dd7 --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/java/org/openhab/binding/x/internal/config/XConfig.java @@ -0,0 +1,30 @@ +/** + * Copyright (c) 2010-2023 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.x.internal.config; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link XConfig} class contains fields mapping thing configuration parameters. + * + * @author Scott Hanson - Initial contribution + */ + +@NonNullByDefault +public class XConfig { + public String consumerKey = ""; + public String consumerSecret = ""; + public String accessToken = ""; + public String accessTokenSecret = ""; + public int refresh = 30; +} diff --git a/bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml new file mode 100644 index 0000000000..acb2764808 --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/addon/addon.xml @@ -0,0 +1,11 @@ + + + + binding + X Binding + Supports adding Thing for getting the Last Post. Send Posts and Pictures with Actions. + cloud + + diff --git a/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties new file mode 100644 index 0000000000..66bc6924ed --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/i18n/x.properties @@ -0,0 +1,32 @@ +# add-on + +addon.x.name = X Binding +addon.x.description = Supports adding Thing for getting the Last Post. Send Posts and Pictures with Actions. + +# thing types + +thing-type.x.account.label = X Account +thing-type.x.account.description = Account uses for sending posts + +# thing types config + +thing-type.config.x.account.accessToken.label = Access Token +thing-type.config.x.account.accessTokenSecret.label = Access Token Secret +thing-type.config.x.account.consumerKey.label = Consumer API Key +thing-type.config.x.account.consumerSecret.label = Consumer API Secret +thing-type.config.x.account.refresh.label = Refresh Time +thing-type.config.x.account.refresh.description = Refresh Time for This Account in Mins + +# channel types + +channel-type.x.lastpost.label = Last Post +channel-type.x.lastpost.description = Users Last Post + +# actions + +sendAttachmentPostActionLabel = send a Post with attachment +sendAttachmentPostActionDescription = Sends a Post with an attachment. +sendDirectMessageActionLabel = send a DirectMessage +sendDirectMessageActionDescription = Sends a DirectMessage. +sendPostActionLabel = send a Post +sendPostActionDescription = Sends a Post. diff --git a/bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml new file mode 100644 index 0000000000..d18df8f5e1 --- /dev/null +++ b/bundles/org.openhab.binding.x/src/main/resources/OH-INF/thing/thing-types.xml @@ -0,0 +1,46 @@ + + + + + + Account uses for sending posts + + + + + + + + + password + + + + password + + + + password + + + + password + + + + Refresh Time for This Account in Mins + 30 + + + + + + + String + + Users Last Post + + + diff --git a/bundles/pom.xml b/bundles/pom.xml index e992b98ac4..24ba021ef0 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -387,7 +387,6 @@ 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 @@ -419,6 +418,7 @@ org.openhab.binding.wled org.openhab.binding.wolfsmartset org.openhab.binding.wundergroundupdatereceiver + org.openhab.binding.x org.openhab.binding.xmltv org.openhab.binding.xmppclient org.openhab.binding.yamahamusiccast