Skip to content

Commit b3cd11c

Browse files
authored
Merging pull request #18760
1 parent 53adaf1 commit b3cd11c

File tree

5 files changed

+181
-6
lines changed

5 files changed

+181
-6
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import app from "../../inmobile.app.mjs";
2+
import utils from "../../common/utils.mjs";
3+
4+
export default {
5+
key: "inmobile-send-sms-messages",
6+
name: "Send SMS Messages",
7+
description: "Send one or more SMS messages using the InMobile API. [See the documentation](https://www.inmobile.com/docs/rest-api)",
8+
version: "0.0.1",
9+
type: "action",
10+
annotations: {
11+
readOnlyHint: false,
12+
destructiveHint: true,
13+
openWorldHint: true,
14+
},
15+
props: {
16+
app,
17+
messages: {
18+
type: "string[]",
19+
label: "Messages",
20+
description: `An array of message objects (1-250 messages). Each message object supports the following properties:
21+
22+
**Required Fields:**
23+
- \`to\` (string): The msisdn (country code and number) to send to. Remember to include country code, e.g. \`4512345678\`
24+
- \`text\` (string): The text message (1-10000 characters)
25+
- \`from\` (string): The sender. Can be a 3-11 character text sender or up to 14 digit sender number
26+
27+
**Optional Fields:**
28+
- \`countryHint\` (string): Country code for optimal phone number validation, e.g. \`44\` or \`GB\`
29+
- \`messageId\` (string): Optional message ID to identify the message (1-50 characters, must be unique)
30+
- \`respectBlacklist\` (boolean): Block message if target number is blacklisted. Default: \`true\`
31+
- \`validityPeriodInSeconds\` (integer): Validity period (60-172800 seconds). Default: \`172800\` (48 hours)
32+
- \`statusCallbackUrl\` (string): URL for delivery status callbacks
33+
- \`sendTime\` (string): Schedule message for future sending, e.g. \`2024-12-31T14:50:23Z\` (UTC time)
34+
- \`msisdnCooldownInMinutes\` (integer): Prevent sending to same number within period (60-43200 minutes)
35+
- \`flash\` (boolean): Send as flash message (class0). Default: \`false\`
36+
- \`encoding\` (string): Message encoding - \`gsm7\` (default, 160 chars), \`ucs2\` (70 chars), or \`auto\`
37+
38+
**Example:**
39+
\`\`\`json
40+
[
41+
{
42+
"to": "4512345678",
43+
"text": "Hello World",
44+
"from": "YourSender",
45+
"encoding": "gsm7"
46+
},
47+
{
48+
"to": "4587654321",
49+
"text": "Another message",
50+
"from": "YourSender",
51+
"flash": true
52+
}
53+
]
54+
\`\`\``,
55+
},
56+
},
57+
async run({ $ }) {
58+
const {
59+
app,
60+
messages,
61+
} = this;
62+
63+
const response = await app.sendSms({
64+
$,
65+
data: {
66+
messages: utils.parseArray(messages),
67+
},
68+
});
69+
70+
$.export("$summary", "Successfully sent SMS messages");
71+
return response;
72+
},
73+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
const parseJson = (input, maxDepth = 100) => {
2+
const seen = new WeakSet();
3+
const parse = (value) => {
4+
if (maxDepth <= 0) {
5+
return value;
6+
}
7+
if (typeof(value) === "string") {
8+
// Only parse if the string looks like a JSON object or array
9+
const trimmed = value.trim();
10+
if (
11+
(trimmed.startsWith("{") && trimmed.endsWith("}")) ||
12+
(trimmed.startsWith("[") && trimmed.endsWith("]"))
13+
) {
14+
try {
15+
return parseJson(JSON.parse(value), maxDepth - 1);
16+
} catch (e) {
17+
return value;
18+
}
19+
}
20+
return value;
21+
} else if (typeof(value) === "object" && value !== null && !Array.isArray(value)) {
22+
if (seen.has(value)) {
23+
return value;
24+
}
25+
seen.add(value);
26+
return Object.entries(value)
27+
.reduce((acc, [
28+
key,
29+
val,
30+
]) => Object.assign(acc, {
31+
[key]: parse(val),
32+
}), {});
33+
} else if (Array.isArray(value)) {
34+
return value.map((item) => parse(item));
35+
}
36+
return value;
37+
};
38+
39+
return parse(input);
40+
};
41+
42+
function parseArray(input, maxDepth = 100) {
43+
if (typeof input === "string") {
44+
const trimmed = input.trim();
45+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
46+
try {
47+
const parsed = JSON.parse(trimmed);
48+
if (Array.isArray(parsed)) {
49+
return parsed.map((item) => parseArray(item, maxDepth - 1));
50+
}
51+
} catch (e) {
52+
throw new Error(`Invalid JSON array format: ${e.message}`);
53+
}
54+
}
55+
return parseJson(input, maxDepth);
56+
}
57+
58+
if (Array.isArray(input)) {
59+
return input.map((item) => parseArray(item, maxDepth));
60+
}
61+
62+
return input;
63+
}
64+
65+
export default {
66+
parseJson,
67+
parseArray,
68+
};
Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,38 @@
1+
import { axios } from "@pipedream/platform";
2+
13
export default {
24
type: "app",
35
app: "inmobile",
4-
propDefinitions: {},
56
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
7+
getUrl(path) {
8+
return `https://api.inmobile.com/v4${path}`;
9+
},
10+
getAuth() {
11+
return {
12+
username: "x",
13+
password: this.$auth.api_key,
14+
};
15+
},
16+
makeRequest({
17+
$ = this, path, ...args
18+
}) {
19+
return axios($, {
20+
url: this.getUrl(path),
21+
auth: this.getAuth(),
22+
...args,
23+
});
24+
},
25+
post(args = {}) {
26+
return this.makeRequest({
27+
method: "POST",
28+
...args,
29+
});
30+
},
31+
sendSms(args = {}) {
32+
return this.post({
33+
path: "/sms/outgoing",
34+
...args,
35+
});
936
},
1037
},
1138
};

components/inmobile/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/inmobile",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream InMobile Components",
55
"main": "inmobile.app.mjs",
66
"keywords": [
@@ -11,5 +11,8 @@
1111
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
1212
"publishConfig": {
1313
"access": "public"
14+
},
15+
"dependencies": {
16+
"@pipedream/platform": "^3.1.0"
1417
}
1518
}

pnpm-lock.yaml

Lines changed: 5 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)