Skip to content

Commit 90872d4

Browse files
committed
Implemented new-sponsorship-detected polling source with no testing
1 parent 67ffa1c commit 90872d4

File tree

7 files changed

+244
-8
lines changed

7 files changed

+244
-8
lines changed

components/paved/common/constants.mjs

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const BASE_URL = "https://api.paved.com";
2+
const LAST_FROM_DATE = "lastFromDate";
3+
const DEFAULT_LIMIT = 100;
4+
const DEFAULT_MAX = 600;
5+
6+
const API = {
7+
PUBLISHER_PATH: "/publisher/v1",
8+
ADVERTISER_PATH: "/advertiser/v1",
9+
};
10+
11+
export default {
12+
BASE_URL,
13+
API,
14+
DEFAULT_LIMIT,
15+
DEFAULT_MAX,
16+
LAST_FROM_DATE,
17+
};

components/paved/common/utils.mjs

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
async function iterate(iterations) {
2+
const items = [];
3+
for await (const item of iterations) {
4+
items.push(item);
5+
}
6+
return items;
7+
}
8+
9+
export default {
10+
iterate,
11+
};

components/paved/package.json

+5-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@pipedream/paved",
3-
"version": "0.0.1",
3+
"version": "0.1.0",
44
"description": "Pipedream Paved Components",
55
"main": "paved.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.0.0"
1417
}
15-
}
18+
}

components/paved/paved.app.mjs

+96-5
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,102 @@
1+
import { axios } from "@pipedream/platform";
2+
import constants from "./common/constants.mjs";
3+
import utils from "./common/utils.mjs";
4+
15
export default {
26
type: "app",
37
app: "paved",
4-
propDefinitions: {},
8+
propDefinitions: {
9+
slug: {
10+
type: "string",
11+
label: "Newsletter Slug",
12+
description: "Your newsletter slug.",
13+
async options() {
14+
const newsletters = await this.listNewsletters();
15+
return newsletters.map(({
16+
name: label, slug: value,
17+
}) => ({
18+
label,
19+
value,
20+
}));
21+
},
22+
},
23+
},
524
methods: {
6-
// this.$auth contains connected account data
7-
authKeys() {
8-
console.log(Object.keys(this.$auth));
25+
getUrl(path, versionPath = constants.API.PUBLISHER_PATH) {
26+
return `${constants.BASE_URL}${versionPath}${path}`;
27+
},
28+
getHeaders(headers) {
29+
return {
30+
...headers,
31+
Authorization: `Token ${this.$auth.api_key}`,
32+
};
33+
},
34+
_makeRequest({
35+
$ = this, path, headers, ...args
36+
} = {}) {
37+
return axios($, {
38+
...args,
39+
url: this.getUrl(path),
40+
headers: this.getHeaders(headers),
41+
});
42+
},
43+
listNewsletters(args = {}) {
44+
return this._makeRequest({
45+
path: "/newsletters",
46+
...args,
47+
});
48+
},
49+
listSponsorships({
50+
slug, ...args
51+
} = {}) {
52+
return this._makeRequest({
53+
path: `/newsletters/${slug}/sponsorships`,
54+
...args,
55+
});
56+
},
57+
async *getIterations({
58+
resourcesFn, resourcesFnArgs,
59+
fromDate,
60+
max = constants.DEFAULT_MAX,
61+
}) {
62+
let resourcesCount = 0;
63+
64+
while (true) {
65+
const nextResources =
66+
await resourcesFn({
67+
...resourcesFnArgs,
68+
params: {
69+
...resourcesFnArgs?.params,
70+
limit: constants.DEFAULT_LIMIT,
71+
from_date: fromDate,
72+
},
73+
});
74+
75+
if (!nextResources?.length) {
76+
console.log("No more resources found");
77+
return;
78+
}
79+
80+
for (const resource of nextResources) {
81+
yield resource;
82+
resourcesCount += 1;
83+
84+
if (resourcesCount >= max) {
85+
console.log("Reached max resources");
86+
return;
87+
}
88+
}
89+
90+
if (nextResources.length < constants.DEFAULT_LIMIT) {
91+
console.log("No next page found");
92+
return;
93+
}
94+
95+
fromDate = nextResources[nextResources.length - 1].run_date;
96+
}
97+
},
98+
paginate(args = {}) {
99+
return utils.iterate(this.getIterations(args));
9100
},
10101
},
11-
};
102+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {
2+
ConfigurationError,
3+
DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
4+
} from "@pipedream/platform";
5+
import app from "../../paved.app.mjs";
6+
import constants from "../../common/constants.mjs";
7+
8+
export default {
9+
props: {
10+
app,
11+
db: "$.service.db",
12+
timer: {
13+
type: "$.interface.timer",
14+
label: "Polling Schedule",
15+
description: "How often to poll the API",
16+
default: {
17+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
18+
},
19+
},
20+
slug: {
21+
propDefinition: [
22+
app,
23+
"slug",
24+
],
25+
},
26+
},
27+
methods: {
28+
generateMeta() {
29+
throw new ConfigurationError("generateMeta is not implemented");
30+
},
31+
setLastFromDate(value) {
32+
this.db.set(constants.LAST_FROM_DATE, value);
33+
},
34+
getLastFromDate() {
35+
return this.db.get(constants.LAST_FROM_DATE);
36+
},
37+
getResourcesFn() {
38+
throw new ConfigurationError("getResourcesFn is not implemented");
39+
},
40+
getResourcesFnArgs() {
41+
throw new ConfigurationError("getResourcesFnArgs is not implemented");
42+
},
43+
processResource(resource) {
44+
const meta = this.generateMeta(resource);
45+
this.$emit(resource, meta);
46+
},
47+
async processResources(resources) {
48+
const {
49+
setLastFromDate,
50+
processResource,
51+
} = this;
52+
53+
const [
54+
lastResource,
55+
] = Array.from(resources).reverse();
56+
57+
if (lastResource?.run_date) {
58+
setLastFromDate(lastResource.run_date);
59+
}
60+
61+
Array.from(resources)
62+
.forEach(processResource);
63+
},
64+
},
65+
async run() {
66+
const {
67+
app,
68+
getResourcesFn,
69+
getResourcesFnArgs,
70+
processResources,
71+
} = this;
72+
73+
const resources = await app.paginate({
74+
resourcesFn: getResourcesFn(),
75+
resourcesFnArgs: getResourcesFnArgs(),
76+
fromDate: this.getLastFromDate(),
77+
});
78+
79+
processResources(resources);
80+
},
81+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import common from "../common/polling.mjs";
2+
3+
export default {
4+
...common,
5+
key: "paved-new-sponsorship-detected",
6+
name: "New Sponsorship Detected",
7+
description: "Emit new event when a sponsorship is detected on a newsletter similar to yours. [See the documentation](https://docs.paved.com/list-sponsorships)",
8+
version: "0.0.1",
9+
type: "source",
10+
dedupe: "unique",
11+
methods: {
12+
...common.methods,
13+
getResourcesFn() {
14+
return this.app.listSponsorships;
15+
},
16+
getResourcesFnArgs() {
17+
return {
18+
debug: true,
19+
slug: this.slug,
20+
};
21+
},
22+
generateMeta(resource) {
23+
return {
24+
id: resource.id,
25+
summary: `New Sponsorthip: ${resource.advertiser_name}`,
26+
ts: Date.parse(resource.run_date),
27+
};
28+
},
29+
},
30+
};

pnpm-lock.yaml

+4-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)