10 changed files with 347 additions and 15 deletions
@ -0,0 +1,143 @@ |
|||
package org.thingsboard.server.service.notification.channels; |
|||
|
|||
import com.fasterxml.jackson.annotation.JsonInclude; |
|||
import com.fasterxml.jackson.annotation.JsonProperty; |
|||
import com.google.common.base.Strings; |
|||
import lombok.Data; |
|||
import lombok.RequiredArgsConstructor; |
|||
import lombok.Setter; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.springframework.boot.web.client.RestTemplateBuilder; |
|||
import org.springframework.stereotype.Component; |
|||
import org.springframework.web.client.RestTemplate; |
|||
import org.thingsboard.server.common.data.id.TenantId; |
|||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; |
|||
import org.thingsboard.server.common.data.notification.targets.MicrosoftTeamsNotificationTargetConfig; |
|||
import org.thingsboard.server.common.data.notification.template.MicrosoftTeamsDeliveryMethodNotificationTemplate; |
|||
import org.thingsboard.server.service.notification.NotificationProcessingContext; |
|||
|
|||
import java.time.Duration; |
|||
import java.time.temporal.ChronoUnit; |
|||
import java.util.List; |
|||
|
|||
@Component |
|||
@RequiredArgsConstructor |
|||
public class MicrosoftTeamsNotificationChannel implements NotificationChannel<MicrosoftTeamsNotificationTargetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate> { |
|||
|
|||
@Setter |
|||
private RestTemplate restTemplate = new RestTemplateBuilder() |
|||
.setConnectTimeout(Duration.of(15, ChronoUnit.SECONDS)) |
|||
.setReadTimeout(Duration.of(15, ChronoUnit.SECONDS)) |
|||
.build(); |
|||
|
|||
@Override |
|||
public void sendNotification(MicrosoftTeamsNotificationTargetConfig targetConfig, MicrosoftTeamsDeliveryMethodNotificationTemplate processedTemplate, NotificationProcessingContext ctx) throws Exception { |
|||
if (StringUtils.isNotEmpty(processedTemplate.getCustomMessageCardJson())) { |
|||
restTemplate.postForEntity(targetConfig.getWebhookUrl(), processedTemplate.getCustomMessageCardJson(), String.class); |
|||
return; |
|||
} |
|||
|
|||
Message message = new Message(); |
|||
message.setThemeColor(Strings.emptyToNull(processedTemplate.getThemeColor())); |
|||
if (StringUtils.isEmpty(processedTemplate.getSubject())) { |
|||
message.setText(processedTemplate.getBody()); |
|||
} else { |
|||
message.setSummary(processedTemplate.getSubject()); |
|||
Message.Section section = new Message.Section(); |
|||
section.setActivityTitle(processedTemplate.getSubject()); |
|||
section.setActivitySubtitle(processedTemplate.getBody()); |
|||
message.setSections(List.of(section)); |
|||
} |
|||
if (processedTemplate.getButton() != null) { |
|||
var button = processedTemplate.getButton(); |
|||
Message.ActionCard actionCard = new Message.ActionCard(); |
|||
actionCard.setType("OpenUri"); |
|||
actionCard.setName(button.getName()); |
|||
var target = new Message.ActionCard.Target("default", button.getUri()); |
|||
actionCard.setTargets(List.of(target)); |
|||
message.setPotentialAction(List.of(actionCard)); |
|||
} |
|||
|
|||
restTemplate.postForEntity(targetConfig.getWebhookUrl(), message, String.class); |
|||
} |
|||
|
|||
@Override |
|||
public void check(TenantId tenantId) throws Exception { |
|||
} |
|||
|
|||
@Override |
|||
public NotificationDeliveryMethod getDeliveryMethod() { |
|||
return NotificationDeliveryMethod.MICROSOFT_TEAMS; |
|||
} |
|||
|
|||
@Data |
|||
public static class Message { |
|||
@JsonProperty("@type") |
|||
private final String type = "MessageCard"; |
|||
@JsonProperty("@context") |
|||
private final String context = "http://schema.org/extensions"; |
|||
private String themeColor; |
|||
private String summary; |
|||
private String text; |
|||
private List<Section> sections; |
|||
private List<ActionCard> potentialAction; |
|||
|
|||
@Data |
|||
public static class Section { |
|||
private String activityTitle; |
|||
private String activitySubtitle; |
|||
private String activityImage; |
|||
private List<Fact> facts; |
|||
private boolean markdown; |
|||
|
|||
@Data |
|||
public static class Fact { |
|||
private final String name; |
|||
private final String value; |
|||
} |
|||
} |
|||
|
|||
@Data |
|||
@JsonInclude(JsonInclude.Include.NON_NULL) |
|||
public static class ActionCard { |
|||
@JsonProperty("@type") |
|||
private String type; // ActionCard, OpenUri
|
|||
private String name; |
|||
private List<Input> inputs; // for ActionCard
|
|||
private List<Action> actions; // for ActionCard
|
|||
private List<Target> targets; |
|||
|
|||
@Data |
|||
public static class Input { |
|||
@JsonProperty("@type") |
|||
private String type; // TextInput, DateInput, MultichoiceInput
|
|||
private String id; |
|||
private boolean isMultiple; |
|||
private String title; |
|||
private boolean isMultiSelect; |
|||
|
|||
@Data |
|||
public static class Choice { |
|||
private final String display; |
|||
private final String value; |
|||
} |
|||
} |
|||
|
|||
@Data |
|||
public static class Action { |
|||
@JsonProperty("@type") |
|||
private final String type; // HttpPOST
|
|||
private final String name; |
|||
private final String target; // url
|
|||
} |
|||
|
|||
@Data |
|||
public static class Target { |
|||
private final String os; |
|||
private final String uri; |
|||
} |
|||
} |
|||
|
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
package org.thingsboard.server.common.data.notification.targets; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
|
|||
import javax.validation.constraints.NotBlank; |
|||
import javax.validation.constraints.NotEmpty; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
public class MicrosoftTeamsNotificationTargetConfig extends NotificationTargetConfig implements NotificationRecipient { |
|||
|
|||
@NotBlank |
|||
private String webhookUrl; |
|||
@NotEmpty |
|||
private String channelName; |
|||
|
|||
@Override |
|||
public NotificationTargetType getType() { |
|||
return NotificationTargetType.MICROSOFT_TEAMS; |
|||
} |
|||
|
|||
@Override |
|||
public Object getId() { |
|||
return webhookUrl; |
|||
} |
|||
|
|||
@Override |
|||
public String getTitle() { |
|||
return channelName; |
|||
} |
|||
|
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
package org.thingsboard.server.common.data.notification.template; |
|||
|
|||
import lombok.Data; |
|||
import lombok.EqualsAndHashCode; |
|||
import lombok.NoArgsConstructor; |
|||
import lombok.ToString; |
|||
import org.apache.commons.lang3.StringUtils; |
|||
import org.apache.commons.lang3.tuple.Pair; |
|||
import org.thingsboard.server.common.data.notification.NotificationDeliveryMethod; |
|||
|
|||
import java.util.List; |
|||
import java.util.function.Consumer; |
|||
|
|||
@Data |
|||
@EqualsAndHashCode(callSuper = true) |
|||
@NoArgsConstructor |
|||
@ToString(callSuper = true) |
|||
public class MicrosoftTeamsDeliveryMethodNotificationTemplate extends DeliveryMethodNotificationTemplate implements HasSubject { |
|||
|
|||
private String subject; |
|||
private String themeColor; |
|||
private Button button; |
|||
|
|||
private String customMessageCardJson; |
|||
|
|||
public MicrosoftTeamsDeliveryMethodNotificationTemplate(DeliveryMethodNotificationTemplate other) { |
|||
super(other); |
|||
} |
|||
|
|||
@Override |
|||
public NotificationDeliveryMethod getMethod() { |
|||
return NotificationDeliveryMethod.MICROSOFT_TEAMS; |
|||
} |
|||
|
|||
@Override |
|||
public MicrosoftTeamsDeliveryMethodNotificationTemplate copy() { |
|||
return new MicrosoftTeamsDeliveryMethodNotificationTemplate(this); |
|||
} |
|||
|
|||
@Override |
|||
public List<TemplatableValue> getTemplatableValues() { |
|||
return List.of( |
|||
TemplatableValue.of(body, this::setBody), |
|||
TemplatableValue.of(subject, this::setSubject), |
|||
TemplatableValue.of(button, Button::getName, Button::setName), |
|||
TemplatableValue.of(button, Button::getUri, Button::setUri), |
|||
TemplatableValue.of(customMessageCardJson, this::setCustomMessageCardJson) |
|||
); |
|||
} |
|||
|
|||
@Data |
|||
public static class Button { |
|||
private String name; |
|||
private String uri; |
|||
} |
|||
|
|||
} |
|||
Loading…
Reference in new issue