Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(hangouts): Threading! #138

Merged
merged 2 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions anghammarad-client-node/src/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ export interface NotifyParams {
sourceSystem: string;
topicArn: string;
client?: SNS;
threadKey?: string;
}
20 changes: 15 additions & 5 deletions anghammarad-client-node/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@ export class Anghammarad {
}

messageJson(params: NotifyParams): string {
const {
message,
sourceSystem,
channel,
target,
actions,
threadKey
} = params

return JSON.stringify({
message: params.message,
sender: params.sourceSystem,
channel: params.channel,
target: params.target,
actions: params.actions,
message,
sender: sourceSystem,
channel,
target,
actions,
...(threadKey && { threadKey }), // only add "threadKey" when it is defined
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ import sttp.client3._

object HangoutsService {

def postMessage(webhook: String, message: String): Response[Either[String, String]] = {
def postMessage(webhook: String, message: HangoutMessage): Response[Either[String, String]] = {
val endpoint = message.threadKey match {
case Some(threadKey) => uri"$webhook&threadKey=$threadKey"
case _ => uri"$webhook"
}

val backend = HttpURLConnectionBackend()
basicRequest
.body(message)
.post(uri"$webhook")
.body(message.cardJson)
.post(endpoint)
.send(backend)
}

Expand All @@ -25,8 +30,8 @@ object HangoutsService {

def sendHangoutsMessage(webhook: String, message: HangoutMessage): Try[Unit] = {
for {
response <- Try {postMessage(webhook, message.cardJson)}
response <- Try {postMessage(webhook, message)}
successOrFailure <- checkResponse(response)
} yield successOrFailure
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ object Messages {
| ]
|}
|""".stripMargin
HangoutMessage(json)
HangoutMessage(json, notification.threadKey)
}

private def buttonJson(actions: List[Action]): String = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ object Serialization {
rawChannel <- hCursor.downField("channel").as[String]
rawActions <- hCursor.downField("actions").as[List[Json]]
message <- hCursor.downField("message").as[String]
threadKey <- hCursor.downField("threadKey").as[Option[String]]
channel <- parseRequestedChannel(rawChannel).toEither
targets <- parseAllTargets(rawTargets).toEither
actions <- rawActions.traverseT(parseAction).toEither
} yield Notification(subject, message, actions, targets, channel, sourceSystem)
} yield Notification(subject, message, actions, targets, channel, sourceSystem, threadKey)

parsingResult.toTry
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import scala.io.Source
class ContactsTest extends AnyFreeSpec with Matchers with TryValues {
val email = EmailMessage("subject", "text", "html")
val emailAddress = EmailAddress("test@example.com")
val hangoutMessage = HangoutMessage("json")
val hangoutMessage = HangoutMessage("json", None)
val hangoutsRoom = HangoutsRoom("webhook")

"resolveTargetContacts" - {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ class MessagesTest extends AnyFreeSpec with Matchers with EitherValues {
}

def testNotification(subject: String, message: String, actions: Action*): Notification = {
Notification(subject, message, actions.toList, Nil, All, "test")
Notification(subject, message, actions.toList, Nil, All, "test", None)
}

/**
Expand All @@ -185,7 +185,8 @@ class MessagesTest extends AnyFreeSpec with Matchers with EitherValues {
List(Action("CTA", "https://example.com/"), Action("Another CTA", "https://example.com/")),
Nil,
HangoutsChat,
"Testing"
"Testing",
None
)
val message = Messages.hangoutMessage(notification)
// println(message.cardJson)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ class SerializationTest extends AnyFreeSpec with Matchers with EitherValues with
List(Action("keep that name moving in the Overhead", "http://www.gnuterrypratchett.com/")),
List(Stack("postal-service"), App("clacks-overhead")),
Email,
"Terry Pratchett"
"Terry Pratchett",
None
)

"parseNotification" - {
Expand Down
6 changes: 4 additions & 2 deletions common/src/main/scala/com/gu/anghammarad/models/models.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ case class EmailMessage(
html: String
) extends Message
case class HangoutMessage(
cardJson: String
cardJson: String,
threadKey: Option[String]
) extends Message

case class Notification(
Expand All @@ -46,7 +47,8 @@ case class Notification(
actions: List[Action],
target: List[Target],
channel: RequestedChannel,
sourceSystem: String
sourceSystem: String,
threadKey: Option[String] = None // only used for Hangouts messages
)

case class Action(
Expand Down
12 changes: 10 additions & 2 deletions dev/src/main/scala/com/gu/anghammarad/ArgParser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ object ArgParser {
)
cmd("fields")
.action { (_, _) =>
Specified("", "", Nil, Nil, None, "", Arguments.defaultStage, None)
Specified("", "", Nil, Nil, None, "", Arguments.defaultStage, None, None)
}
.text("specify fields directly")
.children(
Expand Down Expand Up @@ -171,6 +171,13 @@ object ArgParser {
case _ => throw new RuntimeException("Arguments error")
}
text "Send message using client (will publish to SNS topic)",
opt[String]("thread-key")
.optional()
.action {
case (threadKey, fields: Specified) =>
fields.copy(threadKey = Some(threadKey))
case _ => throw new RuntimeException("Arguments error")
}
)
}

Expand All @@ -192,7 +199,8 @@ case class Specified(
channel: Option[RequestedChannel],
source: String,
configStage: String,
useTopic: Option[String]
useTopic: Option[String],
threadKey: Option[String]
) extends Arguments
object Arguments {
val defaultStage = "DEV"
Expand Down
8 changes: 4 additions & 4 deletions dev/src/main/scala/com/gu/anghammarad/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ object Main {
json <- parse(jsonStr).toTry
notification <- Serialization.generateNotification(subject, json)
} yield notification
case Specified(subject, message, actions, targets, Some(channel), source, _, _) =>
Success(Notification(subject, message, actions, targets, channel, source))
case Specified(subject, message, actions, targets, Some(channel), source, _, _, threadKey) =>
Success(Notification(subject, message, actions, targets, channel, source, threadKey))
case s: Specified =>
Fail("No channel provided")
case InitialArgs =>
Expand All @@ -93,7 +93,7 @@ object Main {
args match {
case JsonArgs(_, _, configStage) =>
Success(configStage)
case Specified(_, _, _, _, _, _, configStage, _) =>
case Specified(_, _, _, _, _, _, configStage, _, _) =>
Success(configStage)
case InitialArgs =>
argParser.showUsageOnError
Expand All @@ -105,7 +105,7 @@ object Main {
args match {
case JsonArgs(_, _, _) =>
Success(None)
case Specified(_, _, _, _, _, _, _, useClient) =>
case Specified(_, _, _, _, _, _, _, useClient, _) =>
Success(useClient)
case InitialArgs =>
argParser.showUsageOnError
Expand Down