From c88974525cc8534672859291c01eede62789e76d Mon Sep 17 00:00:00 2001 From: Jeremy Date: Sat, 28 Sep 2024 16:58:23 -0400 Subject: [PATCH] [pushbullet] Add link and file push type support (#17472) * [pushbullet] Add link and file push type support Signed-off-by: jsetton --- .../org.openhab.binding.pushbullet/README.md | 21 +- .../internal/PushbulletBindingConstants.java | 15 +- .../internal/PushbulletConfiguration.java | 19 +- .../internal/PushbulletHandlerFactory.java | 14 +- .../internal/PushbulletHttpClient.java | 203 ++++++++++++ .../internal/action/PushbulletActions.java | 125 ++++++- .../exception/PushbulletApiException.java | 33 ++ .../PushbulletAuthenticationException.java | 29 ++ .../internal/handler/PushbulletHandler.java | 313 +++++++++++++----- .../internal/model/InstantDeserializer.java | 42 +++ .../pushbullet/internal/model/Push.java | 85 ----- .../pushbullet/internal/model/PushError.java | 74 ----- .../internal/model/PushRequest.java | 128 +++++++ .../internal/model/PushResponse.java | 222 ++++++++----- .../pushbullet/internal/model/PushType.java | 32 ++ .../internal/model/UploadRequest.java | 46 +++ .../internal/model/UploadResponse.java | 61 ++++ .../pushbullet/internal/model/User.java | 114 +++++++ .../src/main/resources/OH-INF/addon/addon.xml | 4 +- .../OH-INF/i18n/pushbullet.properties | 32 +- .../resources/OH-INF/thing/thing-types.xml | 4 +- 21 files changed, 1240 insertions(+), 376 deletions(-) create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHttpClient.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletApiException.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletAuthenticationException.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/InstantDeserializer.java delete mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/Push.java delete mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushError.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushRequest.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushType.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadRequest.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadResponse.java create mode 100644 bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/User.java diff --git a/bundles/org.openhab.binding.pushbullet/README.md b/bundles/org.openhab.binding.pushbullet/README.md index 99472b6f07..54e70a6558 100644 --- a/bundles/org.openhab.binding.pushbullet/README.md +++ b/bundles/org.openhab.binding.pushbullet/README.md @@ -48,6 +48,11 @@ Two different actions available: - `sendPushbulletNote(String recipient, String messsage)` - `sendPushbulletNote(String recipient, String title, String messsage)` +- `sendPushbulletLink(String recipient, String url)` +- `sendPushbulletLink(String recipient, String title, String messsage, String url)` +- `sendPushbulletFile(String recipient, String content)` +- `sendPushbulletFile(String recipient, String title, String messsage, String content)` +- `sendPushbulletFile(String recipient, String title, String messsage, String content, String fileName)` Since there is a separate rule action instance for each `bot` thing, this needs to be retrieved through `getActions(scope, thingUID)`. The first parameter always has to be `pushbullet` and the second is the full Thing UID of the bot that should be used. @@ -56,11 +61,25 @@ Once this action instance is retrieved, you can invoke the action method on it. The recipient can either be an email address, a channel tag or `null`. If it is not specified or properly formatted, the note will be broadcast to all of the user account's devices. +The file content can be an image URL, a local file path or an Image item state. + +The file name is used in the upload link and how it appears in the push message for non-image content. +If it is not specified, it is automatically determined from the image URL or file path. +For Image item state content, it defaults to `image.jpg`. + +For the `sendPushbulletNote` action, parameter `message` is required. +Likewise, for `sendPushbulletLink`, `url` and for `sendPushbulletFile`, `content` parameters are required. +Any other parameters for these actions are optional and can be set to `null`. + Examples: ```java val actions = getActions("pushbullet", "pushbullet:bot:r2d2") -val result = actions.sendPushbulletNote("someone@example.com", "R2D2 talks here...", "This is the pushed note.") +actions.sendPushbulletNote("someone@example.com", "Note Example", "This is the pushed note.") +actions.sendPushbulletLink("someone@example.com", "Link Example", "This is the pushed link", "https://example.com") +actions.sendPushbulletFile("someone@example.com", "File Example", "This is the pushed file", "https://example.com/image.png") +actions.sendPushbulletFile("someone@example.com", null, null, "/path/to/somefile.pdf", "document.pdf") +actions.sendPushbulletFile("someone@example.com", ImageItem.state.toFullString) ``` ## Full Example diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletBindingConstants.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletBindingConstants.java index 8f8f143827..6f55cd9c11 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletBindingConstants.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletBindingConstants.java @@ -22,11 +22,12 @@ import org.openhab.core.thing.ThingTypeUID; * used across the whole binding. * * @author Hakan Tandogan - Initial contribution + * @author Jeremy Setton - Add link and file push type support */ @NonNullByDefault public class PushbulletBindingConstants { - private static final String BINDING_ID = "pushbullet"; + public static final String BINDING_ID = "pushbullet"; // List of all Thing Type UIDs public static final ThingTypeUID THING_TYPE_BOT = new ThingTypeUID(BINDING_ID, "bot"); @@ -38,8 +39,16 @@ public class PushbulletBindingConstants { public static final String TITLE = "title"; public static final String MESSAGE = "message"; + // Thing properties + public static final String PROPERTY_EMAIL = "email"; + public static final String PROPERTY_NAME = "name"; + // Binding logic constants - public static final String API_METHOD_PUSHES = "pushes"; + public static final String API_ENDPOINT_PUSHES = "/pushes"; + public static final String API_ENDPOINT_UPLOAD_REQUEST = "/upload-request"; + public static final String API_ENDPOINT_USERS_ME = "/users/me"; + + public static final String IMAGE_FILE_NAME = "image.jpg"; - public static final int TIMEOUT = 30 * 1000; // 30 seconds + public static final int MAX_UPLOAD_SIZE = 26214400; } diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletConfiguration.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletConfiguration.java index 125b3cf791..8884d07f4a 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletConfiguration.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletConfiguration.java @@ -19,37 +19,26 @@ import org.eclipse.jdt.annotation.Nullable; * The {@link PushbulletConfiguration} class contains fields mapping thing configuration parameters. * * @author Hakan Tandogan - Initial contribution + * @author Jeremy Setton - Add link and file push type support */ @NonNullByDefault public class PushbulletConfiguration { private @Nullable String name; - private String token = "invalid"; + private String token = ""; - private String apiUrlBase = "invalid"; + private String apiUrlBase = "https://api.pushbullet.com/v2"; public @Nullable String getName() { return name; } - public void setName(String name) { - this.name = name; - } - - public String getToken() { + public String getAccessToken() { return token; } - public void setToken(String token) { - this.token = token; - } - public String getApiUrlBase() { return apiUrlBase; } - - public void setApiUrlBase(String apiUrlBase) { - this.apiUrlBase = apiUrlBase; - } } diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHandlerFactory.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHandlerFactory.java index 96867dd6b6..a3b1e48898 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHandlerFactory.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHandlerFactory.java @@ -16,24 +16,36 @@ import static org.openhab.binding.pushbullet.internal.PushbulletBindingConstants import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.pushbullet.internal.handler.PushbulletHandler; +import org.openhab.core.io.net.http.HttpClientFactory; 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.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Reference; /** * The {@link PushbulletHandlerFactory} is responsible for creating things and thing * handlers. * * @author Hakan Tandogan - Initial contribution + * @author Jeremy Setton - Add link and file push type support */ @NonNullByDefault @Component(configurationPid = "binding.pushbullet", service = ThingHandlerFactory.class) public class PushbulletHandlerFactory extends BaseThingHandlerFactory { + private final HttpClient httpClient; + + @Activate + public PushbulletHandlerFactory(final @Reference HttpClientFactory httpClientFactory) { + this.httpClient = httpClientFactory.getCommonHttpClient(); + } + @Override public boolean supportsThingType(ThingTypeUID thingTypeUID) { return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID); @@ -44,7 +56,7 @@ public class PushbulletHandlerFactory extends BaseThingHandlerFactory { ThingTypeUID thingTypeUID = thing.getThingTypeUID(); if (THING_TYPE_BOT.equals(thingTypeUID)) { - return new PushbulletHandler(thing); + return new PushbulletHandler(thing, httpClient); } return null; diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHttpClient.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHttpClient.java new file mode 100644 index 0000000000..eebd311576 --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/PushbulletHttpClient.java @@ -0,0 +1,203 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal; + +import java.time.Instant; +import java.util.Objects; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.BytesContentProvider; +import org.eclipse.jetty.client.util.MultiPartContentProvider; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpFields; +import org.eclipse.jetty.http.HttpMethod; +import org.eclipse.jetty.http.HttpStatus; +import org.eclipse.jetty.http.MimeTypes; +import org.openhab.binding.pushbullet.internal.exception.PushbulletApiException; +import org.openhab.binding.pushbullet.internal.exception.PushbulletAuthenticationException; +import org.openhab.binding.pushbullet.internal.model.InstantDeserializer; +import org.openhab.core.OpenHAB; +import org.openhab.core.library.types.RawType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonSyntaxException; + +/** + * The {@link PushbulletHttpClient} handles requests to Pushbullet API + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class PushbulletHttpClient { + private static final String AGENT = "openHAB/" + OpenHAB.getVersion(); + + private static final int TIMEOUT = 30; // in seconds + + private static final String HEADER_RATELIMIT_RESET = "X-Ratelimit-Reset"; + + private final Logger logger = LoggerFactory.getLogger(PushbulletHttpClient.class); + + private final Gson gson = new GsonBuilder().registerTypeHierarchyAdapter(Instant.class, new InstantDeserializer()) + .create(); + + private PushbulletConfiguration config = new PushbulletConfiguration(); + + private final HttpClient httpClient; + + public PushbulletHttpClient(HttpClient httpClient) { + this.httpClient = httpClient; + } + + public void setConfiguration(PushbulletConfiguration config) { + this.config = config; + } + + /** + * Executes an api request + * + * @param apiEndpoint the request api endpoint + * @param responseType the response type + * @return the unpacked response + * @throws PushbulletApiException + */ + public T executeRequest(String apiEndpoint, Class responseType) throws PushbulletApiException { + return executeRequest(apiEndpoint, null, responseType); + } + + /** + * Executes an api request + * + * @param apiEndpoint the request api endpoint + * @param body the request body object + * @param responseType the response type + * @return the unpacked response + * @throws PushbulletApiException + */ + public T executeRequest(String apiEndpoint, @Nullable Object body, Class responseType) + throws PushbulletApiException { + String url = config.getApiUrlBase() + apiEndpoint; + String accessToken = config.getAccessToken(); + + Request request = newRequest(url).header("Access-Token", accessToken); + + if (body != null) { + StringContentProvider content = new StringContentProvider(gson.toJson(body)); + String contentType = MimeTypes.Type.APPLICATION_JSON.asString(); + + request.method(HttpMethod.POST).content(content, contentType); + } + + String responseBody = sendRequest(request); + + try { + T response = Objects.requireNonNull(gson.fromJson(responseBody, responseType)); + logger.debug("Unpacked Response: {}", response); + return response; + } catch (JsonSyntaxException e) { + logger.debug("Failed to unpack response as '{}': {}", responseType.getSimpleName(), e.getMessage()); + throw new PushbulletApiException(e); + } + } + + /** + * Uploads a file + * + * @param url the upload url + * @param data the file data + * @throws PushbulletApiException + */ + public void uploadFile(String url, RawType data) throws PushbulletApiException { + MultiPartContentProvider content = new MultiPartContentProvider(); + content.addFieldPart("file", new BytesContentProvider(data.getMimeType(), data.getBytes()), null); + + Request request = newRequest(url).method(HttpMethod.POST).content(content); + + sendRequest(request); + } + + /** + * Creates a new http request + * + * @param url the request url + * @return the new Request object with default parameters + */ + private Request newRequest(String url) { + return httpClient.newRequest(url).agent(AGENT).timeout(TIMEOUT, TimeUnit.SECONDS); + } + + /** + * Sends a http request + * + * @param request the request to send + * @return the response body + * @throws PushbulletApiException + */ + private String sendRequest(Request request) throws PushbulletApiException { + try { + logger.debug("Request {} {}", request.getMethod(), request.getURI()); + logger.debug("Request Headers: {}", request.getHeaders()); + + ContentResponse response = request.send(); + + int statusCode = response.getStatus(); + String statusReason = response.getReason(); + String responseBody = response.getContentAsString(); + + logger.debug("Got HTTP {} Response: '{}'", statusCode, responseBody); + + switch (statusCode) { + case HttpStatus.OK_200: + case HttpStatus.NO_CONTENT_204: + return responseBody; + case HttpStatus.UNAUTHORIZED_401: + case HttpStatus.FORBIDDEN_403: + throw new PushbulletAuthenticationException(statusReason); + case HttpStatus.TOO_MANY_REQUESTS_429: + logger.warn("Rate limited for making too many requests until {}", + getRateLimitResetTime(response.getHeaders())); + default: + throw new PushbulletApiException(statusReason); + } + } catch (InterruptedException | TimeoutException | ExecutionException e) { + logger.debug("Failed to send request: {}", e.getMessage()); + throw new PushbulletApiException(e); + } + } + + /** + * Returns the rate limit reset time included in response headers + * + * @param headers the response headers + * @return the rate limit reset time if found in headers, otherwise null + */ + private @Nullable Instant getRateLimitResetTime(HttpFields headers) { + try { + long resetTime = headers.getLongField(HEADER_RATELIMIT_RESET); + if (resetTime != -1) { + return Instant.ofEpochSecond(resetTime); + } + } catch (NumberFormatException ignored) { + } + return null; + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java index 79f5afd071..c8fa95dade 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/action/PushbulletActions.java @@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory; * The {@link PushbulletActions} class defines rule actions for sending notifications * * @author Hakan Tandogan - Initial contribution + * @author Jeremy Setton - Add link and file push type support */ @Component(scope = ServiceScope.PROTOTYPE, service = PushbulletActions.class) @ThingActionsScope(name = "pushbullet") @@ -52,9 +53,9 @@ public class PushbulletActions implements ThingActions { @RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc") public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote( - @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient, - @ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc") @Nullable String title, - @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc") @Nullable String message) { + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title, + @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String", required = true) String message) { logger.trace("sendPushbulletNote '{}', '{}', '{}'", recipient, title, message); PushbulletHandler localHandler = handler; @@ -63,18 +64,18 @@ public class PushbulletActions implements ThingActions { return false; } - return localHandler.sendPush(recipient, title, message, "note"); + return localHandler.sendPushNote(recipient, title, message); } public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient, @Nullable String title, - @Nullable String message) { + String message) { return ((PushbulletActions) actions).sendPushbulletNote(recipient, title, message); } @RuleAction(label = "@text/actionSendPushbulletNoteLabel", description = "@text/actionSendPushbulletNoteDesc") public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletNote( - @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc") @Nullable String recipient, - @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc") @Nullable String message) { + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String", required = true) String message) { logger.trace("sendPushbulletNote '{}', '{}'", recipient, message); PushbulletHandler localHandler = handler; @@ -83,11 +84,115 @@ public class PushbulletActions implements ThingActions { return false; } - return localHandler.sendPush(recipient, message, "note"); + return localHandler.sendPushNote(recipient, null, message); } - public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient, - @Nullable String message) { + public static boolean sendPushbulletNote(ThingActions actions, @Nullable String recipient, String message) { return ((PushbulletActions) actions).sendPushbulletNote(recipient, message); } + + @RuleAction(label = "@text/actionSendPushbulletLinkLabel", description = "@text/actionSendPushbulletLinkDesc") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletLink( + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title, + @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message, + @ActionInput(name = "url", label = "@text/actionSendPushbulletLinkInputUrlLabel", description = "@text/actionSendPushbulletLinkInputUrlDesc", type = "java.lang.String", required = true) String url) { + logger.trace("sendPushbulletLink '{}', '{}', '{}', '{}'", recipient, title, message, url); + + PushbulletHandler localHandler = handler; + if (localHandler == null) { + logger.warn("Pushbullet service Handler is null!"); + return false; + } + + return localHandler.sendPushLink(recipient, title, message, url); + } + + public static boolean sendPushbulletLink(ThingActions actions, @Nullable String recipient, @Nullable String title, + @Nullable String message, String url) { + return ((PushbulletActions) actions).sendPushbulletLink(recipient, title, message, url); + } + + @RuleAction(label = "@text/actionSendPushbulletLinkLabel", description = "@text/actionSendPushbulletLinkDesc") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletLink( + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "url", label = "@text/actionSendPushbulletLinkInputUrlLabel", description = "@text/actionSendPushbulletLinkInputUrlDesc", type = "java.lang.String", required = true) String url) { + logger.trace("sendPushbulletLink '{}', '{}'", recipient, url); + + PushbulletHandler localHandler = handler; + if (localHandler == null) { + logger.warn("Pushbullet service Handler is null!"); + return false; + } + + return localHandler.sendPushLink(recipient, null, null, url); + } + + public static boolean sendPushbulletLink(ThingActions actions, @Nullable String recipient, String url) { + return ((PushbulletActions) actions).sendPushbulletLink(recipient, url); + } + + @RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile( + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title, + @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message, + @ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content, + @ActionInput(name = "filename", label = "@text/actionSendPushbulletFileInputName", description = "@text/actionSendPushbulletFileInputNameDesc", type = "java.lang.String") @Nullable String fileName) { + logger.trace("sendPushbulletFile '{}', '{}', '{}', '{}', '{}'", recipient, title, message, content, fileName); + + PushbulletHandler localHandler = handler; + if (localHandler == null) { + logger.warn("Pushbullet service Handler is null!"); + return false; + } + + return localHandler.sendPushFile(recipient, title, message, content, fileName); + } + + public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, @Nullable String title, + @Nullable String message, String content, @Nullable String filename) { + return ((PushbulletActions) actions).sendPushbulletFile(recipient, title, message, content, filename); + } + + @RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile( + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "title", label = "@text/actionSendPushbulletNoteInputTitleLabel", description = "@text/actionSendPushbulletNoteInputTitleDesc", type = "java.lang.String") @Nullable String title, + @ActionInput(name = "message", label = "@text/actionSendPushbulletNoteInputMessageLabel", description = "@text/actionSendPushbulletNoteInputMessageDesc", type = "java.lang.String") @Nullable String message, + @ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content) { + logger.trace("sendPushbulletFile '{}', '{}', '{}', '{}'", recipient, title, message, content); + + PushbulletHandler localHandler = handler; + if (localHandler == null) { + logger.warn("Pushbullet service Handler is null!"); + return false; + } + + return localHandler.sendPushFile(recipient, title, message, content, null); + } + + public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, @Nullable String title, + @Nullable String message, String content) { + return ((PushbulletActions) actions).sendPushbulletFile(recipient, title, message, content); + } + + @RuleAction(label = "@text/actionSendPushbulletFileLabel", description = "@text/actionSendPushbulletFileDesc") + public @ActionOutput(name = "success", type = "java.lang.Boolean") Boolean sendPushbulletFile( + @ActionInput(name = "recipient", label = "@text/actionSendPushbulletNoteInputRecipientLabel", description = "@text/actionSendPushbulletNoteInputRecipientDesc", type = "java.lang.String") @Nullable String recipient, + @ActionInput(name = "content", label = "@text/actionSendPushbulletFileInputContent", description = "@text/actionSendPushbulletFileInputContentDesc", type = "java.lang.String", required = true) String content) { + logger.trace("sendPushbulletFile '{}', '{}'", recipient, content); + + PushbulletHandler localHandler = handler; + if (localHandler == null) { + logger.warn("Pushbullet service Handler is null!"); + return false; + } + + return localHandler.sendPushFile(recipient, null, null, content, null); + } + + public static boolean sendPushbulletFile(ThingActions actions, @Nullable String recipient, String content) { + return ((PushbulletActions) actions).sendPushbulletFile(recipient, content); + } } diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletApiException.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletApiException.java new file mode 100644 index 0000000000..60ef7e19ec --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletApiException.java @@ -0,0 +1,33 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.exception; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link PushbulletApiException} represents a Pushbullet API exception + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class PushbulletApiException extends Exception { + private static final long serialVersionUID = 1L; + + public PushbulletApiException(String message) { + super(message); + } + + public PushbulletApiException(Exception exception) { + super(exception); + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletAuthenticationException.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletAuthenticationException.java new file mode 100644 index 0000000000..56ec0284e4 --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/exception/PushbulletAuthenticationException.java @@ -0,0 +1,29 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.exception; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +/** + * The {@link PushbulletAuthenticationException} represents a Pushbullet authentication exception + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class PushbulletAuthenticationException extends PushbulletApiException { + private static final long serialVersionUID = 1L; + + public PushbulletAuthenticationException(String message) { + super(message); + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/handler/PushbulletHandler.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/handler/PushbulletHandler.java index f1ceaaefd2..3055ea3f80 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/handler/PushbulletHandler.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/handler/PushbulletHandler.java @@ -14,14 +14,14 @@ package org.openhab.binding.pushbullet.internal.handler; import static org.openhab.binding.pushbullet.internal.PushbulletBindingConstants.*; -import java.io.ByteArrayInputStream; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; -import java.util.Properties; +import java.util.Objects; import java.util.Set; -import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.mail.internet.AddressException; @@ -29,49 +29,51 @@ import javax.mail.internet.InternetAddress; import org.eclipse.jdt.annotation.NonNullByDefault; import org.eclipse.jdt.annotation.Nullable; -import org.eclipse.jetty.http.HttpHeader; -import org.eclipse.jetty.http.HttpMethod; -import org.eclipse.jetty.http.MimeTypes; +import org.eclipse.jetty.client.HttpClient; import org.openhab.binding.pushbullet.internal.PushbulletConfiguration; +import org.openhab.binding.pushbullet.internal.PushbulletHttpClient; import org.openhab.binding.pushbullet.internal.action.PushbulletActions; -import org.openhab.binding.pushbullet.internal.model.Push; +import org.openhab.binding.pushbullet.internal.exception.PushbulletApiException; +import org.openhab.binding.pushbullet.internal.exception.PushbulletAuthenticationException; +import org.openhab.binding.pushbullet.internal.model.PushRequest; import org.openhab.binding.pushbullet.internal.model.PushResponse; +import org.openhab.binding.pushbullet.internal.model.PushType; +import org.openhab.binding.pushbullet.internal.model.UploadRequest; +import org.openhab.binding.pushbullet.internal.model.UploadResponse; +import org.openhab.binding.pushbullet.internal.model.User; import org.openhab.core.io.net.http.HttpUtil; +import org.openhab.core.library.types.RawType; import org.openhab.core.thing.ChannelUID; import org.openhab.core.thing.Thing; import org.openhab.core.thing.ThingStatus; +import org.openhab.core.thing.ThingStatusDetail; import org.openhab.core.thing.binding.BaseThingHandler; import org.openhab.core.thing.binding.ThingHandlerService; import org.openhab.core.types.Command; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.Version; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; - /** * The {@link PushbulletHandler} is responsible for handling commands, which are * sent to one of the channels. * * @author Hakan Tandogan - Initial contribution + * @author Jeremy Setton - Add link and file push type support */ @NonNullByDefault public class PushbulletHandler extends BaseThingHandler { - private final Logger logger = LoggerFactory.getLogger(PushbulletHandler.class); + private static final Pattern CHANNEL_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]+$"); - private final Gson gson = new GsonBuilder().create(); + private final Logger logger = LoggerFactory.getLogger(PushbulletHandler.class); - private static final Version VERSION = FrameworkUtil.getBundle(PushbulletHandler.class).getVersion(); + private final PushbulletHttpClient httpClient; - private static final Pattern CHANNEL_PATTERN = Pattern.compile("^[a-zA-Z0-9_-]+$"); + private int maxUploadSize; - private @Nullable PushbulletConfiguration config; - - public PushbulletHandler(Thing thing) { + public PushbulletHandler(Thing thing, HttpClient httpClient) { super(thing); + this.httpClient = new PushbulletHttpClient(httpClient); } @Override @@ -86,13 +88,42 @@ public class PushbulletHandler extends BaseThingHandler { @Override public void initialize() { - logger.debug("Start initializing!"); - config = getConfigAs(PushbulletConfiguration.class); + logger.debug("Starting {}", thing.getUID()); + + PushbulletConfiguration config = getConfigAs(PushbulletConfiguration.class); + + if (config.getAccessToken().isEmpty()) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Undefined access token."); + return; + } - // Name and Token are both "required", so set the Thing immediately ONLINE. - updateStatus(ThingStatus.ONLINE); + httpClient.setConfiguration(config); - logger.debug("Finished initializing!"); + scheduler.execute(() -> retrieveAccountInfo()); + + updateStatus(ThingStatus.UNKNOWN); + } + + private void retrieveAccountInfo() { + try { + User user = httpClient.executeRequest(API_ENDPOINT_USERS_ME, User.class); + + maxUploadSize = Objects.requireNonNullElse(user.getMaxUploadSize(), MAX_UPLOAD_SIZE); + + logger.debug("Set maximum upload size for {} to {} bytes", thing.getUID(), maxUploadSize); + + updateProperty(PROPERTY_NAME, user.getName()); + updateProperty(PROPERTY_EMAIL, user.getEmail()); + + logger.debug("Updated properties for {} to {}", thing.getUID(), thing.getProperties()); + + updateStatus(ThingStatus.ONLINE); + } catch (PushbulletAuthenticationException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.CONFIGURATION_ERROR, "Invalid access token."); + } catch (PushbulletApiException e) { + updateStatus(ThingStatus.OFFLINE, ThingStatusDetail.COMMUNICATION_ERROR, + "Unable to retrieve account info."); + } } @Override @@ -100,125 +131,227 @@ public class PushbulletHandler extends BaseThingHandler { return Set.of(PushbulletActions.class); } - public boolean sendPush(@Nullable String recipient, @Nullable String message, String type) { - return sendPush(recipient, "", message, type); + /** + * Sends a push note + * + * @param recipient the recipient + * @param title the title + * @param message the message + * @return true if successful + */ + public boolean sendPushNote(@Nullable String recipient, @Nullable String title, String message) { + PushRequest request = newPushRequest(recipient, title, message, PushType.NOTE); + + return sendPush(request); } - public boolean sendPush(@Nullable String recipient, @Nullable String title, @Nullable String message, String type) { - boolean result = false; + /** + * Sends a push link + * + * @param recipient the recipient + * @param title the title + * @param message the message + * @param url the message url + * @return true if successful + */ + public boolean sendPushLink(@Nullable String recipient, @Nullable String title, @Nullable String message, + String url) { + PushRequest request = newPushRequest(recipient, title, message, PushType.LINK); + request.setUrl(url); - logger.debug("sendPush is called for "); - logger.debug("Thing {}", thing); - logger.debug("Thing Label: '{}'", thing.getLabel()); + return sendPush(request); + } - PushbulletConfiguration configuration = getConfigAs(PushbulletConfiguration.class); - logger.debug("CFG {}", configuration); + /** + * Sends a push file + * + * @param recipient the recipient + * @param title the title + * @param message the message + * @param content the file content + * @param fileName the file name + * @return true if successful + */ + public boolean sendPushFile(@Nullable String recipient, @Nullable String title, @Nullable String message, + String content, @Nullable String fileName) { + UploadResponse upload = uploadFile(content, fileName); + if (upload == null) { + return false; + } - Properties headers = prepareRequestHeaders(configuration); + PushRequest request = newPushRequest(recipient, title, message, PushType.FILE); + request.setFileName(upload.getFileName()); + request.setFileType(upload.getFileType()); + request.setFileUrl(upload.getFileUrl()); - String request = prepareMessageBody(recipient, title, message, type); + return sendPush(request); + } - try (InputStream stream = new ByteArrayInputStream(request.getBytes(StandardCharsets.UTF_8))) { - String pushAPI = configuration.getApiUrlBase() + "/" + API_METHOD_PUSHES; + /** + * Helper method to send a push request + * + * @param request the push request + * @return true if successful + */ + private boolean sendPush(PushRequest request) { + logger.debug("Sending push notification for {}", thing.getUID()); + logger.debug("Push Request: {}", request); - String responseString = HttpUtil.executeUrl(HttpMethod.POST.asString(), pushAPI, headers, stream, - MimeTypes.Type.APPLICATION_JSON.asString(), TIMEOUT); + try { + httpClient.executeRequest(API_ENDPOINT_PUSHES, request, PushResponse.class); + return true; + } catch (PushbulletApiException e) { + return false; + } + } - logger.debug("Got Response: {}", responseString); - PushResponse response = gson.fromJson(responseString, PushResponse.class); + /** + * Helper method to upload a file to use in push message + * + * @param content the file content + * @param fileName the file name + * @return the upload response if successful, otherwise null + */ + private @Nullable UploadResponse uploadFile(String content, @Nullable String fileName) { + RawType data = getContentData(content); + if (data == null) { + logger.warn("Failed to get content data from '{}'", content); + return null; + } - logger.debug("Unpacked Response: {}", response); + logger.debug("Content Data: {}", data); - if ((null != response) && (null == response.getPushError())) { - result = true; - } - } catch (IOException e) { - logger.warn("IO problems pushing note: {}", e.getMessage()); + int size = data.getBytes().length; + if (size > maxUploadSize) { + logger.warn("Content data size {} is greater than maximum upload size {}", size, maxUploadSize); + return null; } - return result; + try { + UploadRequest request = new UploadRequest(); + request.setFileName(fileName != null ? fileName : getContentFileName(content)); + request.setFileType(data.getMimeType()); + + logger.debug("Upload Request: {}", request); + + UploadResponse response = httpClient.executeRequest(API_ENDPOINT_UPLOAD_REQUEST, request, + UploadResponse.class); + + String uploadUrl = response.getUploadUrl(); + if (uploadUrl == null) { + throw new PushbulletApiException("Undefined upload url"); + } + + httpClient.uploadFile(uploadUrl, data); + + return response; + } catch (PushbulletApiException e) { + return null; + } } /** - * helper method to populate the request headers + * Helper method to get the data for a given content * - * @param configuration - * @return + * @param content the file content + * @return the data raw type if available, otherwise null */ - private Properties prepareRequestHeaders(PushbulletConfiguration configuration) { - Properties headers = new Properties(); - headers.put(HttpHeader.USER_AGENT, "openHAB / Pushbullet binding " + VERSION); - headers.put(HttpHeader.CONTENT_TYPE, MimeTypes.Type.APPLICATION_JSON.asString()); - headers.put("Access-Token", configuration.getToken()); - - logger.debug("Headers: {}", headers); + private @Nullable RawType getContentData(String content) { + try { + if (content.startsWith("data:")) { + return RawType.valueOf(content); + } else if (content.startsWith("http")) { + return HttpUtil.downloadImage(content); + } else { + Path path = Path.of(content); + byte[] bytes = Files.readAllBytes(path); + String mimeType = Files.probeContentType(path); + return new RawType(bytes, mimeType); + } + } catch (IllegalArgumentException | IOException e) { + logger.debug("Failed to get content data: {}", e.getMessage()); + return null; + } + } - return headers; + /** + * Helper method to get the file name for a given content + * + * @param content the file content + * @return the file name if available, otherwise null + */ + private @Nullable String getContentFileName(String content) { + if (content.startsWith("data:")) { + return IMAGE_FILE_NAME; + } + try { + Path fileName = Path.of(content.startsWith("http") ? new URL(content).getPath() : content).getFileName(); + if (fileName != null) { + return fileName.toString(); + } + } catch (MalformedURLException e) { + logger.debug("Malformed url content: {}", e.getMessage()); + } + return null; } /** - * helper method to create a message body from data to be transferred. + * Helper method to create a push request * - * @param recipient - * @param title - * @param message - * @param type + * @param recipient the recipient + * @param title the title + * @param message the message + * @param type the push type * - * @return the message as a String to be posted + * @return the push request object */ - private String prepareMessageBody(@Nullable String recipient, @Nullable String title, @Nullable String message, - String type) { + private PushRequest newPushRequest(@Nullable String recipient, @Nullable String title, @Nullable String message, + PushType type) { logger.debug("Recipient is '{}'", recipient); logger.debug("Title is '{}'", title); logger.debug("Message is '{}'", message); + logger.debug("Type is '{}'", type); - Push push = new Push(); - push.setTitle(title); - push.setBody(message); - push.setType(type); + PushRequest request = new PushRequest(); + request.setTitle(title); + request.setBody(message); + request.setType(type); if (recipient != null) { if (isValidEmail(recipient)) { logger.debug("Recipient is an email address"); - push.setEmail(recipient); + request.setEmail(recipient); } else if (isValidChannel(recipient)) { logger.debug("Recipient is a channel tag"); - push.setChannel(recipient); + request.setChannel(recipient); } else { logger.warn("Invalid recipient: {}", recipient); logger.warn("Message will be broadcast to all user's devices."); } } - logger.debug("Push: {}", push); - - String request = gson.toJson(push); - logger.debug("Packed Request: {}", request); - return request; } /** - * helper method checking if channel tag is valid. + * Helper method checking if channel tag is valid * - * @param channel - * @return + * @param channel the channel tag + * @return true if matches pattern */ private static boolean isValidChannel(String channel) { - Matcher m = CHANNEL_PATTERN.matcher(channel); - return m.matches(); + return CHANNEL_PATTERN.matcher(channel).matches(); } /** - * helper method checking if email address is valid. + * Helper method checking if email address is valid * - * @param email - * @return + * @param email the email address + * @return true if parsed successfully */ private static boolean isValidEmail(String email) { try { - InternetAddress emailAddr = new InternetAddress(email); - emailAddr.validate(); + new InternetAddress(email, true); return true; } catch (AddressException e) { return false; diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/InstantDeserializer.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/InstantDeserializer.java new file mode 100644 index 0000000000..28d5ea0c6f --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/InstantDeserializer.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.time.Instant; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; + +/** + * The {@link InstantDeserializer} deserializes a timestamp returned by the API. + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class InstantDeserializer implements JsonDeserializer { + + @Override + public @Nullable Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { + BigDecimal timestamp = json.getAsBigDecimal(); + BigDecimal[] parts = timestamp.divideAndRemainder(BigDecimal.ONE); + long seconds = parts[0].longValueExact(); + long nanos = parts[1].movePointRight(9).longValue(); + return Instant.ofEpochSecond(seconds, nanos); + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/Push.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/Push.java deleted file mode 100644 index e65bf82aac..0000000000 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/Push.java +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2010-2024 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.pushbullet.internal.model; - -import com.google.gson.annotations.SerializedName; - -/** - * This class represents the push request sent to the API. - * - * @author Hakan Tandogan - Initial contribution - * @author Hakan Tandogan - Migrated from openHAB 1 action with the same name - */ -public class Push { - - @SerializedName("title") - private String title; - - @SerializedName("body") - private String body; - - @SerializedName("type") - private String type; - - @SerializedName("email") - private String email; - - @SerializedName("channel_tag") - private String channelTag; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public String getBody() { - return body; - } - - public void setBody(String body) { - this.body = body; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getEmail() { - return email; - } - - public void setEmail(String email) { - this.email = email; - } - - public String getChannel() { - return channelTag; - } - - public void setChannel(String channelTag) { - this.channelTag = channelTag; - } - - @Override - public String toString() { - return "Push {" + "title='" + title + '\'' + ", body='" + body + '\'' + ", type='" + type + '\'' + ", email='" - + email + '\'' + ", channelTag='" + channelTag + '\'' + '}'; - } -} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushError.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushError.java deleted file mode 100644 index a8c1504e7f..0000000000 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushError.java +++ /dev/null @@ -1,74 +0,0 @@ -/** - * Copyright (c) 2010-2024 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.pushbullet.internal.model; - -import com.google.gson.annotations.SerializedName; - -/** - * This class represents errors in the response fetched from the API. - * - * @author Hakan Tandogan - Initial contribution - * @author Hakan Tandogan - Migrated from openHAB 1 action with the same name - */ -public class PushError { - - @SerializedName("type") - private String type; - - @SerializedName("message") - private String message; - - @SerializedName("param") - private String param; - - @SerializedName("cat") - private String cat; - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getMessage() { - return message; - } - - public void setMessage(String message) { - this.message = message; - } - - public String getParam() { - return param; - } - - public void setParam(String param) { - this.param = param; - } - - public String getCat() { - return cat; - } - - public void setCat(String cat) { - this.cat = cat; - } - - @Override - public String toString() { - return "PushError {" + "type='" + type + '\'' + ", message='" + message + '\'' + ", param='" + param + '\'' - + ", cat='" + cat + '\'' + '}'; - } -} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushRequest.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushRequest.java new file mode 100644 index 0000000000..8c9df023fa --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushRequest.java @@ -0,0 +1,128 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.annotations.SerializedName; + +/** + * This class represents the push request sent to the API. + * + * @author Hakan Tandogan - Initial contribution + * @author Hakan Tandogan - Migrated from openHAB 1 action with the same name + * @author Jeremy Setton - Add link and file push type support + */ +@NonNullByDefault +public class PushRequest { + + @SerializedName("type") + private @Nullable PushType type; + + @SerializedName("title") + private @Nullable String title; + + @SerializedName("body") + private @Nullable String body; + + @SerializedName("url") + private @Nullable String url; + + @SerializedName("file_name") + private @Nullable String fileName; + + @SerializedName("file_type") + private @Nullable String fileType; + + @SerializedName("file_url") + private @Nullable String fileUrl; + + @SerializedName("source_device_iden") + private @Nullable String sourceDeviceIden; + + @SerializedName("device_iden") + private @Nullable String deviceIden; + + @SerializedName("client_iden") + private @Nullable String clientIden; + + @SerializedName("channel_tag") + private @Nullable String channelTag; + + @SerializedName("email") + private @Nullable String email; + + @SerializedName("guid") + private @Nullable String guid; + + public void setTitle(@Nullable String title) { + this.title = title; + } + + public void setType(@Nullable PushType type) { + this.type = type; + } + + public void setBody(@Nullable String body) { + this.body = body; + } + + public void setUrl(@Nullable String url) { + this.url = url; + } + + public void setFileName(@Nullable String fileName) { + this.fileName = fileName; + } + + public void setFileType(@Nullable String fileType) { + this.fileType = fileType; + } + + public void setFileUrl(@Nullable String fileUrl) { + this.fileUrl = fileUrl; + } + + public void setSourceDeviceIden(@Nullable String sourceDeviceIden) { + this.sourceDeviceIden = sourceDeviceIden; + } + + public void setDeviceIden(@Nullable String deviceIden) { + this.deviceIden = deviceIden; + } + + public void setClientIden(@Nullable String clientIden) { + this.clientIden = clientIden; + } + + public void setChannel(@Nullable String channelTag) { + this.channelTag = channelTag; + } + + public void setEmail(@Nullable String email) { + this.email = email; + } + + public void setGuid(@Nullable String guid) { + this.guid = guid; + } + + @Override + public String toString() { + return "Push {type='" + type + "', title='" + title + "', body='" + body + "', url='" + url + "', fileName='" + + fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl + "', sourceDeviceIden='" + + sourceDeviceIden + "', deviceIden='" + deviceIden + "', clientIden='" + clientIden + "', channelTag='" + + channelTag + "', email='" + email + "', guid='" + guid + "'}"; + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushResponse.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushResponse.java index 246980d575..89e1279ccb 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushResponse.java +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushResponse.java @@ -12,200 +12,238 @@ */ package org.openhab.binding.pushbullet.internal.model; +import java.time.Instant; +import java.util.List; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + import com.google.gson.annotations.SerializedName; /** - * This class represents the answer to pushes provided by the API. + * This class represents the push response received from the API. * * @author Hakan Tandogan - Initial contribution * @author Hakan Tandogan - Migrated from openHAB 1 action with the same name + * @author Jeremy Setton - Add link and file push type support */ +@NonNullByDefault public class PushResponse { + @SerializedName("iden") + private @Nullable String iden; + @SerializedName("active") - private String active; + private @Nullable Boolean active; - @SerializedName("iden") - private String iden; + @SerializedName("created") + private @Nullable Instant created; + + @SerializedName("modified") + private @Nullable Instant modified; @SerializedName("type") - private String type; + private @Nullable PushType type; @SerializedName("dismissed") - private Boolean dismissed; + private @Nullable Boolean dismissed; + + @SerializedName("guid") + private @Nullable String guid; @SerializedName("direction") - private String direction; + private @Nullable String direction; @SerializedName("sender_iden") - private String senderIdentifier; + private @Nullable String senderIdentifier; @SerializedName("sender_email") - private String senderEmail; + private @Nullable String senderEmail; @SerializedName("sender_email_normalized") - private String senderEmailNormalized; + private @Nullable String senderEmailNormalized; @SerializedName("sender_name") - private String senderName; + private @Nullable String senderName; @SerializedName("receiver_iden") - private String receiverIdentifier; + private @Nullable String receiverIdentifier; @SerializedName("receiver_email") - private String receiverEmail; + private @Nullable String receiverEmail; @SerializedName("receiver_email_normalized") - private String receiverEmailNormalized; + private @Nullable String receiverEmailNormalized; + + @SerializedName("target_device_iden") + private @Nullable String targetDeviceIden; + + @SerializedName("source_device_iden") + private @Nullable String sourceDeviceIden; + + @SerializedName("client_iden") + private @Nullable String clientIden; + + @SerializedName("channel_iden") + private @Nullable String channelIden; + + @SerializedName("awake_app_guids") + private @Nullable List awakeAppGuids; @SerializedName("title") - private String title; + private @Nullable String title; @SerializedName("body") - private String body; + private @Nullable String body; - @SerializedName("error_code") - private String errorCode; + @SerializedName("url") + private @Nullable String url; - @SerializedName("error") - private PushError pushError; + @SerializedName("file_name") + private @Nullable String fileName; - public String getActive() { - return active; - } + @SerializedName("file_type") + private @Nullable String fileType; - public void setActive(String active) { - this.active = active; - } + @SerializedName("file_url") + private @Nullable String fileUrl; + + @SerializedName("image_url") + private @Nullable String imageUrl; - public String getIden() { + @SerializedName("image_width") + private @Nullable Integer imageWidth; + + @SerializedName("image_height") + private @Nullable Integer imageHeight; + + public @Nullable String getIden() { return iden; } - public void setIden(String iden) { - this.iden = iden; + public @Nullable Boolean getActive() { + return active; } - public String getType() { - return type; + public @Nullable Instant getCreated() { + return created; } - public void setType(String type) { - this.type = type; + public @Nullable Instant getModified() { + return modified; } - public Boolean getDismissed() { - return dismissed; + public @Nullable PushType getType() { + return type; } - public void setDismissed(Boolean dismissed) { - this.dismissed = dismissed; + public @Nullable Boolean getDismissed() { + return dismissed; } - public String getDirection() { - return direction; + public @Nullable String getGuid() { + return guid; } - public void setDirection(String direction) { - this.direction = direction; + public @Nullable String getDirection() { + return direction; } - public String getSenderIdentifier() { + public @Nullable String getSenderIdentifier() { return senderIdentifier; } - public void setSenderIdentifier(String senderIdentifier) { - this.senderIdentifier = senderIdentifier; - } - - public String getSenderEmail() { + public @Nullable String getSenderEmail() { return senderEmail; } - public void setSenderEmail(String senderEmail) { - this.senderEmail = senderEmail; - } - - public String getSenderEmailNormalized() { + public @Nullable String getSenderEmailNormalized() { return senderEmailNormalized; } - public void setSenderEmailNormalized(String senderEmailNormalized) { - this.senderEmailNormalized = senderEmailNormalized; + public @Nullable String getSenderName() { + return senderName; } - public String getSenderName() { - return senderName; + public @Nullable String getReceiverIdentifier() { + return receiverIdentifier; } - public void setSenderName(String senderName) { - this.senderName = senderName; + public @Nullable String getReceiverEmail() { + return receiverEmail; } - public String getReceiverIdentifier() { - return receiverIdentifier; + public @Nullable String getReceiverEmailNormalized() { + return receiverEmailNormalized; } - public void setReceiverIdentifier(String receiverIdentifier) { - this.receiverIdentifier = receiverIdentifier; + public @Nullable String getTargetDeviceIden() { + return targetDeviceIden; } - public String getReceiverEmail() { - return receiverEmail; + public @Nullable String getSourceDeviceIden() { + return sourceDeviceIden; } - public void setReceiverEmail(String receiverEmail) { - this.receiverEmail = receiverEmail; + public @Nullable String getClientIden() { + return clientIden; } - public String getReceiverEmailNormalized() { - return receiverEmailNormalized; + public @Nullable String getChannelIden() { + return channelIden; } - public void setReceiverEmailNormalized(String receiverEmailNormalized) { - this.receiverEmailNormalized = receiverEmailNormalized; + public @Nullable List getAwakeAppGuids() { + return awakeAppGuids; } - public String getTitle() { + public @Nullable String getTitle() { return title; } - public void setTitle(String title) { - this.title = title; + public @Nullable String getBody() { + return body; } - public String getBody() { - return body; + public @Nullable String getUrl() { + return url; + } + + public @Nullable String getFileName() { + return fileName; } - public void setBody(String body) { - this.body = body; + public @Nullable String getFileType() { + return fileType; } - public String getErrorCode() { - return errorCode; + public @Nullable String getFileUrl() { + return fileUrl; } - public void setErrorCode(String errorCode) { - this.errorCode = errorCode; + public @Nullable String getImageUrl() { + return imageUrl; } - public PushError getPushError() { - return pushError; + public @Nullable Integer getImageWidth() { + return imageWidth; } - public void setPushError(PushError pushError) { - this.pushError = pushError; + public @Nullable Integer getImageHeight() { + return imageHeight; } @Override public String toString() { - return "PushResponse {" + "active='" + active + '\'' + ", iden='" + iden + '\'' + ", type='" + type + '\'' - + ", dismissed=" + dismissed + ", direction='" + direction + '\'' + ", senderIdentifier='" - + senderIdentifier + '\'' + ", senderEmail='" + senderEmail + '\'' + ", senderEmailNormalized='" - + senderEmailNormalized + '\'' + ", senderName='" + senderName + '\'' + ", receiverIdentifier='" - + receiverIdentifier + '\'' + ", receiverEmail='" + receiverEmail + '\'' + ", receiverEmailNormalized='" - + receiverEmailNormalized + '\'' + ", title='" + title + '\'' + ", body='" + body + '\'' - + ", errorCode='" + errorCode + '\'' + ", pushError=" + pushError + '}'; + return "PushResponse {iden='" + iden + ", active='" + active + "', created='" + created + "', modified='" + + modified + "', type='" + type + "', dismissed='" + dismissed + "', guid='" + guid + "', direction='" + + direction + "', senderIdentifier='" + senderIdentifier + "', senderEmail='" + senderEmail + + "', senderEmailNormalized='" + senderEmailNormalized + "', senderName='" + senderName + + "', receiverIdentifier='" + receiverIdentifier + "', receiverEmail='" + receiverEmail + + "', receiverEmailNormalized='" + receiverEmailNormalized + "', targetDeviceIden='" + targetDeviceIden + + "', sourceDeviceIden='" + sourceDeviceIden + "', clientIden='" + clientIden + "', channelIden='" + + channelIden + "', awakeAppGuids='" + awakeAppGuids + "', title='" + title + "', body='" + body + + "', url='" + url + "', fileName='" + fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl + + "', imageUrl='" + imageUrl + "', imageWidth='" + imageWidth + "', imageHeight='" + imageHeight + "'}"; } } diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushType.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushType.java new file mode 100644 index 0000000000..cc1f19494f --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/PushType.java @@ -0,0 +1,32 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; + +import com.google.gson.annotations.SerializedName; + +/** + * This class represents the push type. + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public enum PushType { + @SerializedName("note") + NOTE, + @SerializedName("link") + LINK, + @SerializedName("file") + FILE +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadRequest.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadRequest.java new file mode 100644 index 0000000000..937ced4ea5 --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadRequest.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.annotations.SerializedName; + +/** + * This class represents the upload request sent to the API. + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class UploadRequest { + + @SerializedName("file_name") + private @Nullable String fileName; + + @SerializedName("file_type") + private @Nullable String fileType; + + public void setFileName(@Nullable String fileName) { + this.fileName = fileName; + } + + public void setFileType(@Nullable String fileType) { + this.fileType = fileType; + } + + @Override + public String toString() { + return "UploadRequest {fileName='" + fileName + "', fileType='" + fileType + "'}"; + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadResponse.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadResponse.java new file mode 100644 index 0000000000..392222f2f6 --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/UploadResponse.java @@ -0,0 +1,61 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.annotations.SerializedName; + +/** + * This class represents the upload response received from the API. + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class UploadResponse { + + @SerializedName("file_name") + private @Nullable String fileName; + + @SerializedName("file_type") + private @Nullable String fileType; + + @SerializedName("file_url") + private @Nullable String fileUrl; + + @SerializedName("upload_url") + private @Nullable String uploadUrl; + + public @Nullable String getFileName() { + return fileName; + } + + public @Nullable String getFileType() { + return fileType; + } + + public @Nullable String getFileUrl() { + return fileUrl; + } + + public @Nullable String getUploadUrl() { + return uploadUrl; + } + + @Override + public String toString() { + return "UploadResponse {fileName='" + fileName + "', fileType='" + fileType + "', fileUrl='" + fileUrl + + "', uploadUrl='" + uploadUrl + "'}"; + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/User.java b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/User.java new file mode 100644 index 0000000000..5657c4dbcc --- /dev/null +++ b/bundles/org.openhab.binding.pushbullet/src/main/java/org/openhab/binding/pushbullet/internal/model/User.java @@ -0,0 +1,114 @@ +/** + * Copyright (c) 2010-2024 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.pushbullet.internal.model; + +import java.time.Instant; + +import org.eclipse.jdt.annotation.NonNullByDefault; +import org.eclipse.jdt.annotation.Nullable; + +import com.google.gson.annotations.SerializedName; + +/** + * This class represents the user object received from the API. + * + * @author Jeremy Setton - Initial contribution + */ +@NonNullByDefault +public class User { + + @SerializedName("iden") + private @Nullable String iden; + + @SerializedName("active") + private @Nullable Boolean active; + + @SerializedName("created") + private @Nullable Instant created; + + @SerializedName("modified") + private @Nullable Instant modified; + + @SerializedName("email") + private @Nullable String email; + + @SerializedName("email_normalized") + private @Nullable String emailNormalized; + + @SerializedName("name") + private @Nullable String name; + + @SerializedName("image_url") + private @Nullable String imageUrl; + + @SerializedName("max_upload_size") + private @Nullable Integer maxUploadSize; + + @SerializedName("referred_count") + private @Nullable Integer referredCount; + + @SerializedName("referrer_iden") + private @Nullable String referrerIden; + + public @Nullable String getIden() { + return iden; + } + + public @Nullable Boolean getActive() { + return active; + } + + public @Nullable Instant getCreated() { + return created; + } + + public @Nullable Instant getModified() { + return modified; + } + + public @Nullable String getEmail() { + return email; + } + + public @Nullable String getEmailNormalized() { + return emailNormalized; + } + + public @Nullable String getName() { + return name; + } + + public @Nullable String getImageUrl() { + return imageUrl; + } + + public @Nullable Integer getMaxUploadSize() { + return maxUploadSize; + } + + public @Nullable Integer getReferredCount() { + return referredCount; + } + + public @Nullable String getReferrerIden() { + return referrerIden; + } + + @Override + public String toString() { + return "User {iden='" + iden + ", active='" + active + "', created='" + created + "', modified='" + modified + + "', email='" + email + "', emailNormalized='" + emailNormalized + "', name='" + name + "', imageUrl='" + + imageUrl + "', maxUploadSize='" + maxUploadSize + "', referredCount='" + referredCount + + "', referrerIden='" + referrerIden + "'}"; + } +} diff --git a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/addon/addon.xml b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/addon/addon.xml index 5271608761..0781854439 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/addon/addon.xml +++ b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/addon/addon.xml @@ -4,8 +4,8 @@ xsi:schemaLocation="https://openhab.org/schemas/addon/v1.0.0 https://openhab.org/schemas/addon-1.0.0.xsd"> binding - @text/addon.pushbullet.name - @text/addon.pushbullet.description + Pushbullet Binding + The Pushbullet binding allows you to send messages to other users of the Pushbullet service. cloud diff --git a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/i18n/pushbullet.properties b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/i18n/pushbullet.properties index 4b0ddc0593..beb771ae5f 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/i18n/pushbullet.properties +++ b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/i18n/pushbullet.properties @@ -2,9 +2,33 @@ addon.pushbullet.name = Pushbullet Binding addon.pushbullet.description = The Pushbullet binding allows you to send messages to other users of the Pushbullet service. +# thing types +thing-type.pushbullet.bot.label = Pushbullet Bot +thing-type.pushbullet.bot.description = Bot to send messages with. + +# thing types config +thing-type.config.pushbullet.bot.name.label = Name +thing-type.config.pushbullet.bot.name.description = Explicit Name of Bot, if wanted +thing-type.config.pushbullet.bot.token.label = Access Token +thing-type.config.pushbullet.bot.token.description = Access token obtained from the account settings page +thing-type.config.pushbullet.bot.apiUrlBase.label = API Server +thing-type.config.pushbullet.bot.apiUrlBase.description = The Pushbullet API Server to use, for local testing + +# channel types +channel-type.pushbullet.recipient-channel.label = Recipient +channel-type.pushbullet.recipient-channel.description = Mail address or Channel Name +channel-type.pushbullet.title-channel.label = Title +channel-type.pushbullet.title-channel.description = Title of the message +channel-type.pushbullet.message-channel.label = Message +channel-type.pushbullet.message-channel.description = The text that is to be sent + # action actionSendPushbulletNoteLabel = publish a Pushbullet message -actionSendPushbulletNoteDesc = Publishes a Title to the given Pushbullet Recipient. +actionSendPushbulletNoteDesc = Publishes a note to the given Pushbullet Recipient. +actionSendPushbulletLinkLabel = publish a Pushbullet message with link +actionSendPushbulletLinkDesc = Publishes a link to the given Pushbullet Recipient. +actionSendPushbulletFileLabel = publish a Pushbullet message with file +actionSendPushbulletFileDesc = Publishes a file to the given Pushbullet Recipient. actionSendPushbulletNoteInputRecipientLabel = Pushbullet Recipient actionSendPushbulletNoteInputRecipientDesc = The Recipient to publish a Title to. @@ -12,6 +36,12 @@ actionSendPushbulletNoteInputTitleLabel = Title actionSendPushbulletNoteInputTitleDesc = The Title to publish actionSendPushbulletNoteInputMessageLabel = Message actionSendPushbulletNoteInputMessageDesc = The Message to publish +actionSendPushbulletLinkInputUrlLabel = Link URL +actionSendPushbulletLinkInputUrlDesc = The Link URL to publish +actionSendPushbulletFileInputContent = File Content +actionSendPushbulletFileInputContentDesc = The File Content to publish +actionSendPushbulletFileInputName = File Name +actionSendPushbulletFileInputNameDesc = The File Name to publish # error texts offline.conf-error-httpresponseexception = The pushbullet server reported an error, possibly an expired token. Check on web site diff --git a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/thing/thing-types.xml b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/thing/thing-types.xml index 1dfc83e70a..9e5e31ef0d 100644 --- a/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/thing/thing-types.xml +++ b/bundles/org.openhab.binding.pushbullet/src/main/resources/OH-INF/thing/thing-types.xml @@ -22,8 +22,8 @@ - - Token as obtained from the server + + Access token obtained from the account settings page -- 2.47.3