Skip to content
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
4 changes: 3 additions & 1 deletion components/loopmessage/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Overview

The LoopMessage API offers you the ability to send, receive, and manage messages within your applications. Through Pipedream's integration, you can harness this API to automate communication processes, organize message flows, and even connect to various data sources or other APIs to create complex messaging workflows. With Pipedream, you can trigger actions based on events, schedule messages, and interact with users in real-time without managing servers or infrastructure.
LoopMessage is an omnichannel messaging solution that allows you to receive and send messages across multiple channels: iMessage/SMS/RCS/WhatsApp. Through Pipedream's integration, you can harness this platform to automate communication processes, organize message flows, and even connect to various data sources or other APIs to create complex messaging workflows. With Pipedream, you can trigger actions based on events, schedule messages, and interact with users in real-time without managing servers or infrastructure.

# Example Use Cases

- **Building AI Assistants**: Create AI-powered chatbots that can respond to user queries, integrate with natural language processing (NLP) services, and provide personalized assistance.

- **Automated Customer Support Tickets**: Automatically create customer support tickets in your helpdesk software when a message is received via LoopMessage. Use this to streamline support queries and ensure no customer message is overlooked.

- **Scheduled Notifications**: Send out scheduled notifications to users or groups based on certain triggers or timeframes. This could be used for reminders, promotional campaigns, or important updates, integrating with services like Google Calendar for event-driven alerts.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import app from "../../loopmessage.app.mjs";

export default {
key: "loopmessage-check-message-status",
name: "Check Message Status",
description: "Action to get the current outbound message status. Possible values: processing, failed, delivered.",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I missed this earlier. All actions should have doc links to the relevant documentation. Applies to all actions.

Suggested change
description: "Action to get the current outbound message status. Possible values: processing, failed, delivered.",
description: "Action to get the current outbound message status. Possible values: processing, failed, delivered. [See the documentation](<url here>)",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michelle0927 The problem is that the documentation URLs may change over time. If we provide a link there and the page is moved, it could confuse users.

type: "action",
version: "0.0.4",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: true,
},
props: {
app,
messageId: {
type: "string",
label: "Message ID",
description: "Outbound message ID.",
},
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Props should display a list of async options if possible. Could the message history endpoint be used to retrieve message IDs?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We plan to add it in a future update.

},
methods: {
getSummary(response) {
return `Message status: ${response.status ?? "unknown"}`;
},
},
async run({ $: step }) {
try {
const response = await this.app.getMessageStatus(this.messageId, {
step,
});
step.export("$summary", this.getSummary(response));

return response;
} catch (error) {
if (error.response?.status === 400) {
const message =
error.response.data?.message ??
error.response.data?.error_code ??
JSON.stringify(error.response.data);

throw new Error(message);
}
throw error;
}
},
};
61 changes: 0 additions & 61 deletions components/loopmessage/actions/common/send-message.mjs

This file was deleted.

47 changes: 39 additions & 8 deletions components/loopmessage/actions/send-reaction/send-reaction.mjs
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
import common from "../common/send-message.mjs";
import constants from "../../common/constants.mjs";
import app from "../../loopmessage.app.mjs";
import utils from "../../common/utils.mjs";

export default {
...common,
key: "loopmessage-send-reaction",
name: "Send Reaction",
description: "Action to submit your request to the sending queue. When a request in the queue will be ready to send a reaction in iMessage, an attempt will be made to deliver it to the recipient. [See the documentation](https://docs.loopmessage.com/imessage-conversation-api/messaging/send-message#send-reaction)",
description: "Action to send a reaction in iMessage or RCS.",
type: "action",
version: "0.0.3",
version: "0.0.4",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
props: {
...common.props,
app,
contact: {
propDefinition: [
app,
"contact",
],
},
messageId: {
type: "string",
label: "Message ID",
Expand All @@ -23,14 +29,39 @@ export default {
reaction: {
type: "string",
label: "Reaction",
description: "Reactions that starts with `-` mean *remove* it from the message. You can check the [Apple guide](https://support.apple.com/HT206894) about reactions and tapbacks.",
description: "Reactions that starts with `-` mean remove it from the message.",
options: constants.REACTIONS,
},
},
methods: {
...common.methods,
getSummary(response) {
return `Successfully sent a reaction to with ID \`${response.message_id}\``;
return `Request accepted. Message ID: \`${response.message_id}\``;
},
Comment thread
coderabbitai[bot] marked this conversation as resolved.
},
async run({ $: step }) {
const {
app,
...data
} = this;

try {
const response = await app.sendReaction({
step,
data: utils.keysToSnakeCase(data),
});
step.export("$summary", this.getSummary(response));

return response;
} catch (error) {
if (error.response?.status === 400) {
const message =
error.response.data?.message ??
error.response.data?.error_code ??
JSON.stringify(error.response.data);

throw new Error(message);
}
throw error;
}
},
};
Original file line number Diff line number Diff line change
@@ -1,42 +1,107 @@
import common from "../common/send-message.mjs";
import app from "../../loopmessage.app.mjs";
import utils from "../../common/utils.mjs";

export default {
...common,
key: "loopmessage-send-text-message",
name: "Send Text Message",
description: "Action to send a text in iMessage to an individual recipient. [See the documentation](https://docs.loopmessage.com/imessage-conversation-api/messaging/send-message#send-single-message)",
name: "Send Outbound Message",
description: "Action to send a message to an individual recipient.",
type: "action",
version: "0.0.3",
version: "0.0.4",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
props: {
...common.props,
service: {
app,
contact: {
propDefinition: [
common.props.app,
"service",
app,
"contact",
],
},
text: {
propDefinition: [
app,
"text",
],
},
subject: {
propDefinition: [
common.props.app,
app,
"subject",
],
},
effect: {
propDefinition: [
common.props.app,
app,
"effect",
],
},
sender: {
optional: true,
propDefinition: [
app,
"sender",
],
},
attachments: {
type: "string[]",
label: "Attachments",
description: "Optional. An array of strings. The string must be a full URL of your image. URL should start with https://. HTTP links (without SSL) are not supported. This must be a publicly accessible file URL: we will not be able to reach any URLs that are hidden or that require authentication.",
optional: true,
},
Comment thread
michelle0927 marked this conversation as resolved.
replyToId: {
optional: true,
propDefinition: [
app,
"replyToId",
],
},
channel: {
optional: true,
propDefinition: [
app,
"channel",
],
},
passthrough: {
optional: true,
propDefinition: [
app,
"passthrough",
],
},
},
methods: {
...common.methods,
getSummary(response) {
return `Successfully sent a text message with ID \`${response.message_id}\``;
return `Request accepted. Message ID: \`${response.message_id}\``;
},
},
async run({ $: step }) {
const {
app,
...data
} = this;

try {
const response = await app.sendMessage({
step,
data: utils.keysToSnakeCase(data),
});
step.export("$summary", this.getSummary(response));

return response;
} catch (error) {
if (error.response?.status === 400) {
const message =
error.response.data?.message ??
error.response.data?.error_code ??
JSON.stringify(error.response.data);

throw new Error(message);
}
throw error;
}
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import app from "../../loopmessage.app.mjs";
import utils from "../../common/utils.mjs";

export default {
key: "loopmessage-send-voice-message",
name: "Send Outbound Voice Message",
description: "Send a voice memo. Supports only in: iMessage, RCS, WhatsApp.",
type: "action",
version: "0.0.1",
annotations: {
destructiveHint: false,
openWorldHint: true,
readOnlyHint: false,
},
props: {
app,
contact: {
propDefinition: [
app,
"contact",
],
},
sender: {
optional: true,
propDefinition: [
app,
"sender",
],
},
mediaUrl: {
propDefinition: [
app,
"mediaUrl",
],
},
passthrough: {
optional: true,
propDefinition: [
app,
"passthrough",
],
},
},
methods: {
getSummary(response) {
return `Request accepted. Message ID: \`${response.message_id}\``;
},
},
async run({ $: step }) {
const {
app,
...data
} = this;

try {
const response = await app.sendMessage({
step,
data: utils.keysToSnakeCase(data),
});
step.export("$summary", this.getSummary(response));

return response;
} catch (error) {
if (error.response?.status === 400) {
const message =
error.response.data?.message ??
error.response.data?.error_code ??
JSON.stringify(error.response.data);

throw new Error(message);
}
throw error;
}
},
};
Loading
Loading