Skip to content

Commit afad520

Browse files
committed
ortto init
1 parent c200237 commit afad520

File tree

9 files changed

+593
-1
lines changed

9 files changed

+593
-1
lines changed
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import ortto from "../../ortto.app.mjs";
2+
3+
export default {
4+
key: "ortto-create-custom-activity",
5+
name: "Create Custom Activity",
6+
description: "Creates a unique activity for a user. Can optionally initialize a new record beforehand. [See the documentation](https://help.ortto.com/developer/latest/api-reference/activity/index.html)",
7+
version: "0.0.{{ts}}",
8+
type: "action",
9+
props: {
10+
ortto,
11+
activityName: {
12+
propDefinition: [
13+
ortto,
14+
"activityName",
15+
],
16+
},
17+
recordId: {
18+
propDefinition: [
19+
ortto,
20+
"recordId",
21+
],
22+
optional: true,
23+
},
24+
recordType: {
25+
propDefinition: [
26+
ortto,
27+
"recordType",
28+
],
29+
optional: true,
30+
},
31+
data: {
32+
propDefinition: [
33+
ortto,
34+
"data",
35+
],
36+
optional: true,
37+
},
38+
},
39+
async run({ $ }) {
40+
if (this.recordType && this.data) {
41+
await this.ortto.initializeOrUpdateRecord({
42+
recordType: this.recordType,
43+
data: this.data,
44+
});
45+
}
46+
47+
const response = await this.ortto.createUniqueActivity({
48+
activityName: this.activityName,
49+
recordId: this.recordId,
50+
});
51+
52+
$.export("$summary", `Successfully created activity ${response.id}`);
53+
return response;
54+
},
55+
};
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import ortto from "../../ortto.app.mjs";
2+
import { axios } from "@pipedream/platform";
3+
4+
export default {
5+
key: "ortto-create-record",
6+
name: "Create or Update Record",
7+
description: "Initializes a new record (person or organization) or updates a preexisting record in the Ortto account. [See the documentation](https://help.ortto.com/a-250-api-reference)",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
ortto,
12+
recordType: {
13+
propDefinition: [
14+
ortto,
15+
"recordType",
16+
],
17+
},
18+
data: {
19+
propDefinition: [
20+
ortto,
21+
"data",
22+
],
23+
},
24+
},
25+
async run({ $ }) {
26+
const response = await this.ortto.initializeOrUpdateRecord({
27+
recordType: this.recordType,
28+
data: this.data,
29+
});
30+
$.export("$summary", `Successfully initialized or updated record with type: ${this.recordType}`);
31+
return response;
32+
},
33+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import ortto from "../../ortto.app.mjs";
2+
import { axios } from "@pipedream/platform";
3+
4+
export default {
5+
key: "ortto-opt-out-sms",
6+
name: "Opt Out of SMS",
7+
description: "Allows a user to opt-out from all SMS communications. [See the documentation](https://help.ortto.com/a-250-api-reference)",
8+
version: "0.0.1",
9+
type: "action",
10+
props: {
11+
ortto,
12+
userId: {
13+
propDefinition: [
14+
ortto,
15+
"userId",
16+
],
17+
},
18+
},
19+
async run({ $ }) {
20+
const response = await this.ortto.optOutSMS({
21+
pathParams: {
22+
userId: this.userId,
23+
},
24+
});
25+
26+
$.export("$summary", `Successfully opted out SMS for User ID: ${this.userId}`);
27+
return response;
28+
},
29+
};

components/ortto/app/ortto.app.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ export default defineApp({
1010
console.log(Object.keys(this.$auth));
1111
},
1212
},
13-
});
13+
});

components/ortto/ortto.app.mjs

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import { axios } from "@pipedream/platform";
2+
3+
export default {
4+
type: "app",
5+
app: "ortto",
6+
propDefinitions: {
7+
recordType: {
8+
type: "string",
9+
label: "Record Type",
10+
description: "Choose between 'person' or 'organization'",
11+
options: [
12+
"person",
13+
"organization",
14+
],
15+
},
16+
data: {
17+
type: "object",
18+
label: "Record Data",
19+
description: "Data of the record to initialize or update.",
20+
},
21+
activityName: {
22+
type: "string",
23+
label: "Activity Name",
24+
description: "Specify the activity to be created.",
25+
},
26+
recordId: {
27+
type: "string",
28+
label: "Record ID",
29+
description: "Optional: Assign the activity to a preexisting record",
30+
optional: true,
31+
},
32+
userId: {
33+
type: "string",
34+
label: "User ID",
35+
description: "Specify the user ID to opt out from all SMS communications.",
36+
},
37+
},
38+
methods: {
39+
_baseUrl() {
40+
return "https://api.ap3api.com";
41+
},
42+
async _makeRequest(opts = {}) {
43+
const {
44+
$ = this, method = "GET", path = "/", headers, ...otherOpts
45+
} = opts;
46+
return axios($, {
47+
...otherOpts,
48+
method,
49+
url: this._baseUrl() + path,
50+
headers: {
51+
...headers,
52+
"Authorization": `Bearer ${this.$auth.oauth_access_token}`,
53+
},
54+
});
55+
},
56+
async emitContactCreated(opts = {}) {
57+
return this._makeRequest({
58+
method: "POST",
59+
path: "/v1/person/create",
60+
...opts,
61+
});
62+
},
63+
async emitOrganizationCreated(opts = {}) {
64+
return this._makeRequest({
65+
method: "POST",
66+
path: "/v1/organizations/create",
67+
...opts,
68+
});
69+
},
70+
async emitContactUpdated(opts = {}) {
71+
return this._makeRequest({
72+
method: "PATCH",
73+
path: "/v1/person/update",
74+
...opts,
75+
});
76+
},
77+
async emitOrganizationUpdated(opts = {}) {
78+
return this._makeRequest({
79+
method: "PATCH",
80+
path: "/v1/organizations/update",
81+
...opts,
82+
});
83+
},
84+
async createUniqueActivity(opts = {}) {
85+
const {
86+
activityName, recordId, ...otherOpts
87+
} = opts;
88+
return this._makeRequest({
89+
method: "POST",
90+
path: "/v1/activities/create",
91+
data: {
92+
activityName: this.activityName,
93+
recordId: this.recordId,
94+
...otherOpts,
95+
},
96+
});
97+
},
98+
async optOutSMS(opts = {}) {
99+
return this._makeRequest({
100+
method: "POST",
101+
path: `/v1/persons/${this.userId}/sms-opt-out`,
102+
...opts,
103+
});
104+
},
105+
async initializeOrUpdateRecord(opts = {}) {
106+
const {
107+
recordType, data, ...otherOpts
108+
} = opts;
109+
return this._makeRequest({
110+
method: "POST",
111+
path: `/v1/${recordType}s/merge`,
112+
data: {
113+
[recordType]: [
114+
data,
115+
],
116+
async: true,
117+
...otherOpts,
118+
},
119+
});
120+
},
121+
async getNewContacts(opts = {}) {
122+
return this._makeRequest({
123+
method: "GET",
124+
path: "/v1/persons/get",
125+
params: {
126+
sort_order: "asc",
127+
sort_by_field_id: "created_at",
128+
limit: 50,
129+
},
130+
...opts,
131+
});
132+
},
133+
async getNewOrganizations(opts = {}) {
134+
return this._makeRequest({
135+
method: "GET",
136+
path: "/v1/organizations/get",
137+
params: {
138+
sort_order: "asc",
139+
sort_by_field_id: "created_at",
140+
limit: 50,
141+
},
142+
...opts,
143+
});
144+
},
145+
async paginate(fn, ...opts) {
146+
let results = [];
147+
let response = await fn(...opts);
148+
results = results.concat(response.items);
149+
150+
while (response.has_more) {
151+
const nextOpts = {
152+
...opts,
153+
cursor_id: response.cursor_id,
154+
};
155+
response = await fn(...nextOpts);
156+
results = results.concat(response.items);
157+
}
158+
159+
return results;
160+
},
161+
},
162+
};
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import ortto from "../../ortto.app.mjs";
2+
import {
3+
axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
4+
} from "@pipedream/platform";
5+
6+
export default {
7+
key: "ortto-new-contact-created",
8+
name: "New Contact Created",
9+
description: "Emit new event when a contact is created in your Ortto account. [See the documentation](https://help.ortto.com/a-258-retrieve-one-or-more-people-get)",
10+
version: "0.0.{{ts}}",
11+
type: "source",
12+
dedupe: "unique",
13+
props: {
14+
ortto,
15+
db: "$.service.db",
16+
timer: {
17+
type: "$.interface.timer",
18+
default: {
19+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
20+
},
21+
},
22+
},
23+
hooks: {
24+
async deploy() {
25+
const response = await this.ortto.getNewContacts();
26+
const contacts = response.contacts.slice(0, 50);
27+
28+
contacts.forEach((contact) => {
29+
this.$emit(contact, {
30+
id: contact.id,
31+
summary: `New Contact: ${contact.fields["str::first"]} ${contact.fields["str::last"]}`,
32+
ts: Date.parse(contact.fields["date::created_at"]) || Date.now(),
33+
});
34+
});
35+
},
36+
},
37+
methods: {
38+
emitContact(contact) {
39+
this.$emit(contact, {
40+
id: contact.id,
41+
summary: `New Contact: ${contact.fields["str::first"]} ${contact.fields["str::last"]}`,
42+
ts: Date.parse(contact.fields["date::created_at"]) || Date.now(),
43+
});
44+
},
45+
},
46+
async run() {
47+
const lastId = this.db.get("lastId");
48+
const response = await this.ortto.getNewContacts({
49+
params: {
50+
cursor_id: lastId,
51+
},
52+
});
53+
const contacts = response.contacts;
54+
55+
contacts.forEach((contact) => this.emitContact(contact));
56+
57+
if (contacts.length > 0) {
58+
this.db.set("lastId", contacts[contacts.length - 1].id);
59+
}
60+
},
61+
};

0 commit comments

Comments
 (0)