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

New Components - grain #14685

Merged
merged 11 commits into from
Dec 3, 2024
56 changes: 56 additions & 0 deletions components/grain/actions/get-recording/get-recording.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import {
INTELLIGENCE_NOTES_FORMAT_OPTIONS,
TRANSCRIPT_FORMAT_OPTIONS,
} from "../../common/constants.mjs";
import { parseObject } from "../../common/utils.mjs";
import grain from "../../grain.app.mjs";

export default {
key: "grain-get-recording",
name: "Get Recording",
description: "Fetches a specific recording by its ID from Grain, optionally including the transcript and intelligence notes. [See the documentation](https://grainhq.notion.site/grain-public-api-877184aa82b54c77a875083c1b560de9)",
version: "0.0.1",
type: "action",
props: {
grain,
recordId: {
propDefinition: [
grain,
"recordId",
],
},
transcriptFormat: {
type: "string",
label: "Transcript Format",
description: "Format for the transcript",
options: TRANSCRIPT_FORMAT_OPTIONS,
optional: true,
},
intelligenceNotesFormat: {
type: "string",
label: "Intelligence Notes Format",
description: "Format for the intelligence notes",
options: INTELLIGENCE_NOTES_FORMAT_OPTIONS,
optional: true,
},
allowedIntelligenceNotes: {
type: "string[]",
label: "Allowed Intelligence Notes",
description: "Whitelist of intelligence notes section titles",
optional: true,
},
},
async run({ $ }) {
const response = await this.grain.fetchRecording({
recordId: this.recordId,
params: {
transcript_format: this.transcriptFormat,
intelligence_notes_format: this.intelligenceNotesFormat,
allowed_intelligence_notes: parseObject(this.allowedIntelligenceNotes),
},
});

$.export("$summary", `Successfully fetched recording with ID ${this.recordId}`);
return response;
},
};
25 changes: 25 additions & 0 deletions components/grain/common/constants.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
export const TRANSCRIPT_FORMAT_OPTIONS = [
{
label: "JSON",
value: "json",
},
{
label: "VTT",
value: "vtt",
},
];

export const INTELLIGENCE_NOTES_FORMAT_OPTIONS = [
{
label: "JSON",
value: "json",
},
{
label: "Markdown",
value: "md",
},
{
label: "Text",
value: "text",
},
];
24 changes: 24 additions & 0 deletions components/grain/common/utils.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
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;
};
112 changes: 107 additions & 5 deletions components/grain/grain.app.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,113 @@
import { axios } from "@pipedream/platform";

export default {
type: "app",
app: "grain",
propDefinitions: {},
propDefinitions: {
recordId: {
type: "string",
label: "Record ID",
description: "The ID of the recording to fetch",
async options({ prevContext: { nextPage } }) {
const {
recordings, cursor,
} = await this.listRecordings({
params: {
cursor: nextPage,
},
});
return {
options: recordings.map(({
id: value, title: label,
}) => ({
value,
label,
})),
context: {
nextPage: cursor,
},
};
},
},
viewId: {
type: "string",
label: "View ID",
description: "The ID of the recording to fetch",
async options({
type, prevContext: { nextPage },
}) {
const {
views, cursor,
} = await this.listViews({
params: {
type_filter: type,
cursor: nextPage,
},
});
return {
options: views.map(({
id: value, name: label,
}) => ({
value,
label,
})),
context: {
nextPage: cursor,
},
};
},
},
},
methods: {
// this.$auth contains connected account data
authKeys() {
console.log(Object.keys(this.$auth));
_baseUrl() {
return "https://grain.com/_/public-api";
},
_headers() {
return {
Authorization: `Bearer ${this.$auth.oauth_access_token}`,
};
},
_makeRequest({
$ = this, path, ...opts
}) {
return axios($, {
url: this._baseUrl() + path,
headers: this._headers(),
...opts,
});
},
listRecordings(opts = {}) {
return this._makeRequest({
path: "/recordings",
...opts,
});
},
listViews(opts = {}) {
return this._makeRequest({
path: "/views",
...opts,
});
},
fetchRecording({
recordId, ...opts
}) {
return this._makeRequest({
path: `/recordings/${recordId}`,
...opts,
});
},
createWebhook(opts = {}) {
return this._makeRequest({
method: "POST",
path: "/hooks",
...opts,
});
},
deleteWebhook(hookId) {
return this._makeRequest({
method: "DELETE",
path: `/hooks/${hookId}`,
});
},
},
};
};
7 changes: 5 additions & 2 deletions components/grain/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/grain",
"version": "0.0.1",
"version": "0.1.0",
"description": "Pipedream Grain Components",
"main": "grain.app.mjs",
"keywords": [
Expand All @@ -11,5 +11,8 @@
"author": "Pipedream <[email protected]> (https://pipedream.com/)",
"publishConfig": {
"access": "public"
},
"dependencies": {
"@pipedream/platform": "^3.0.3"
}
}
}
47 changes: 47 additions & 0 deletions components/grain/sources/common/base.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import grain from "../../grain.app.mjs";

export default {
props: {
grain,
http: "$.interface.http",
db: "$.service.db",
},
methods: {
_getHookId() {
return this.db.get("hookId");
},
_setHookId(hookId) {
this.db.set("hookId", hookId);
},
getExtraData() {
return {};
},
},
hooks: {
async activate() {
const response = await this.grain.createWebhook({
data: {
version: 2,
hook_url: this.http.endpoint,
view_id: this.viewId,
actions: this.getAction(),
},
});
this._setHookId(response.id);
},
async deactivate() {
const webhookId = this._getHookId();
await this.grain.deleteWebhook(webhookId);
},
},
async run({ body }) {
if (!body.data) return;

const ts = Date.parse(new Date());
this.$emit(body, {
id: `${body.data.id}-${ts}`,
summary: this.getSummary(body),
ts: ts,
});
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import common from "../common/base.mjs";
import sampleEmit from "./test-event.mjs";

export default {
...common,
key: "grain-new-highlight-instant",
name: "New Highlight (Instant)",
description: "Emit new event when a highlight that matches the filter is added.",
version: "0.0.1",
type: "source",
dedupe: "unique",
props: {
...common.props,
viewId: {
propDefinition: [
common.props.grain,
"viewId",
() => ({
type: "highlights",
}),
],
},
},
methods: {
...common.methods,
getAction() {
return [
"added",
];
},
getSummary({ data }) {
return `New highlight added: ${data.id}`;
},
},
sampleEmit,
};
17 changes: 17 additions & 0 deletions components/grain/sources/new-highlight-instant/test-event.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
"type": "highlight_added",
"user_id": "aea95745-99e9-4609-8623-c9efa2926b82",
"data": {
"id": "vjQRUKsWw0aFpCT3531eGbr8V0HJrMjKMEIcAUmP",
"recording_id": "b5185ccb-9a08-458c-9be1-db17a03fb14c",
"text": "testing 123 #test",
"transcript": "expected, that there was a mews in a lane which runs down by one wall of the garden. I lent the ostlers a hand in rubbing down their horses, and received in exchange twopence, a glass of half-and-half, two fills of shag tobacco, and as much information as I could desire about Miss Adler, to say nothing of half a dozen other people in",
"speakers": ["Andy Arbol"],
"timestamp": 3080,
"duration": 15000,
"created_datetime": "2021-07-29T23:16:34Z",
"url": "https://grain.com/highlight/vjQRUKsWw0aFpCT3531eGbr8V0HJrMjKMEIcAUmP",
"thumbnail_url": "https://media.grain.com/clips/v1/a14e5af9-d28e-43e9-902b-bc07419082eb/57zB8z52l7BKPoOvkS9KNyUi7LDSsNEh.jpeg",
"tags": ["test"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import common from "../common/base.mjs";
import sampleEmit from "./test-event.mjs";

export default {
...common,
key: "grain-new-recording-instant",
name: "New Recording (Instant)",
description: "Emit new event when a recording that matches the filter is added.",
version: "0.0.1",
type: "source",
dedupe: "unique",
props: {
...common.props,
viewId: {
propDefinition: [
common.props.grain,
"viewId",
() => ({
type: "recordings",
}),
],
},
},
methods: {
...common.methods,
getAction() {
return [
"added",
];
},
getSummary({ data }) {
return `New recording added: ${data.id}`;
},
},
sampleEmit,
};
Loading
Loading