Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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 common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const LIMIT = 100;
3 changes: 0 additions & 3 deletions components/ortto/.gitignore

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { parseObject } from "../../common/utils.mjs";
import ortto from "../../ortto.app.mjs";

export default {
key: "ortto-create-custom-activity",
name: "Create Custom Activity",
description: "Creates a unique activity for a person. Can optionally initialize a new record beforehand. [See the documentation](https://help.ortto.com/developer/latest/api-reference/activity/index.html)",
version: "0.0.1",
type: "action",
props: {
ortto,
activityId: {
propDefinition: [
ortto,
"activityId",
],
},
attributes: {
propDefinition: [
ortto,
"attributes",
],
},
fields: {
propDefinition: [
ortto,
"fields",
],
},
},
async run({ $ }) {
const response = await this.ortto.createCustomActivity({
$,
data: {
"activities": [
{
activity_id: this.activityId,
attributes: parseObject(this.attributes),
fields: parseObject(this.fields),
},
],
"merge_by": [
"str::email",
],
},
});

$.export("$summary", "Successfully created activity");
return response;
},
};
109 changes: 109 additions & 0 deletions components/ortto/actions/create-person/create-person.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { clearObj } from "../../common/utils.mjs";
import ortto from "../../ortto.app.mjs";

export default {
key: "ortto-create-person",
name: "Create or Update a Person",
description: "Create or update a preexisting person in the Ortto account. [See the documentation](https://help.ortto.com/a-250-api-reference)",
version: "0.0.1",
type: "action",
props: {
ortto,
firstName: {
type: "string",
label: "First Name",
description: "The person's first name.",
optional: true,
},
lastName: {
type: "string",
label: "Last Name",
description: "The person's last name.",
optional: true,
},
phone: {
type: "string",
label: "Phone",
description: "The person's phone number.",
},
email: {
type: "string",
label: "Email",
description: "The person's email address.",
},
city: {
type: "string",
label: "City",
description: "The person's address city.",
optional: true,
},
country: {
type: "string",
label: "Country",
description: "The person's address country.",
optional: true,
},
region: {
type: "string",
label: "Region",
description: "The person's address region.",
optional: true,
},
birthday: {
type: "string",
label: "Birthday",
description: "The person's birth date.",
optional: true,
},
},
async run({ $ }) {
const {
ortto,
...props
} = this;

const birthday = {};
if (props.birthday) {
const date = new Date(props.birthday);
birthday.day = date.getDate();
birthday.month = date.getMonth() + 1;
birthday.year = date.getFullYear();
}

const response = await ortto.createPerson({
data: {
people: [
{
fields: clearObj({
"str::first": props.firstName,
"str::last": props.lastName,
"phn::phone": {
"phone": props.phone,
"parse_with_country_code": true,
},
"str::email": props.email,
"geo::city": {
name: props.city,
},
"geo::country": {
name: props.country,
},
"geo::region": {
name: props.region,
},
"dtz::b": birthday,
}),
},
],
async: false,
merge_by: [
"str::email",
],
merge_strategy: 3,
find_strategy: 0,
},
});
$.export("$summary", "Person successfully initialized or updated!");
return response;
},
};
39 changes: 39 additions & 0 deletions components/ortto/actions/opt-out-sms/opt-out-sms.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import ortto from "../../ortto.app.mjs";

export default {
key: "ortto-opt-out-sms",
name: "Opt Out of SMS",
description: "Allows a user to opt-out from all SMS communications. [See the documentation](https://help.ortto.com/a-250-api-reference)",
version: "0.0.1",
type: "action",
props: {
ortto,
userEmail: {
propDefinition: [
ortto,
"userEmail",
],
},
},
async run({ $ }) {
const response = await this.ortto.updatePerson({
data: {
people: [
{
fields: {
"str::email": this.userEmail,
"bol::sp": false,
},
},
],
async: false,
merge_by: [
"str::email",
],
},
});

$.export("$summary", `Successfully opted out SMS for User ID: ${this.userEmail}`);
return response;
},
};
13 changes: 0 additions & 13 deletions components/ortto/app/ortto.app.ts

This file was deleted.

41 changes: 41 additions & 0 deletions components/ortto/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
export const clearObj = (obj) => {
return Object.entries(obj)
.filter(([
,
v,
]) => (v != null && v != "" && JSON.stringify(v) != "{}"))
.reduce((acc, [
k,
v,
]) => ({
...acc,
[k]: (!Array.isArray(v) && v === Object(v))
? clearObj(v)
: v,
}), {});
};

export const parseObject = (obj) => {
if (!obj) return undefined;

if (Array.isArray(obj)) {
return obj.map((item) => {
if (typeof item === "string") {
try {
return JSON.parse(item);
} catch (e) {
return item;
}
}
return item;
});
}
if (typeof obj === "string") {
try {
return JSON.parse(obj);
} catch (e) {
return obj;
}
}
return obj;
};
115 changes: 115 additions & 0 deletions components/ortto/ortto.app.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { axios } from "@pipedream/platform";
import { LIMIT } from "../../common/constants.mjs";

export default {
type: "app",
app: "ortto",
propDefinitions: {
userEmail: {
type: "string",
label: "User Email",
description: "Specify the user email to opt out from all SMS communications.",
async options({ page }) {
const { contacts } = await this.listPeople({
data: {
limit: LIMIT,
offset: LIMIT * page,
fields: [
"str::first",
"str::last",
"str::email",
],
},
});

return contacts.map(({ fields }) => ({
label: `${fields["str::first"]} ${fields["str::last"]} (${fields["str::email"]})`,
value: fields["str::email"],
}));
},
},
activityId: {
type: "string",
label: "Activity Id",
description: "The Id of the activity definition. You can find the id by clicking on the activity, the id will be in the url \"/activities/{ACTIVITY_ID}/overview\"",
},
fields: {
type: "object",
label: "Fields",
description: "An object with the fields of the activity. You can find the fields by clicking on the activity and on the Developer button.",
},
attributes: {
type: "object",
label: "Attributes",
description: "An object with the attributes. You can find the attributes by clicking on the activity and on the Developer button.",
},
},
methods: {
_baseUrl() {
return `https://${this.$auth.region}/v1`;
},
_headers() {
return {
"X-Api-Key": `${this.$auth.api_key}`,
"Content-Type": "application/json",
};
},
_makeRequest({
$ = this, path, ...opts
}) {
return axios($, {
method: "POST",
url: this._baseUrl() + path,
headers: this._headers(),
...opts,
});
},
listPeople(opts = {}) {
return this._makeRequest({
path: "/person/get",
...opts,
});
},
updatePerson(opts = {}) {
return this._makeRequest({
path: "/person/merge",
...opts,
});
},
createPerson(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/person/merge",
...opts,
});
},
createCustomActivity(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/activities/create",
...opts,
});
},
async *paginate({
fn, data = {}, fieldName, ...opts
}) {
let hasMore = false;
let page = 0;

do {
data.limit = LIMIT;
data.offset = LIMIT * page++;
const response = await fn({
data,
...opts,
});
for (const d of response[fieldName]) {
yield d;
}

hasMore = response.has_more;

} while (hasMore);
},
},
};
Loading