Skip to content

Commit b79de9b

Browse files
committed
easypromos init
1 parent b52b9b5 commit b79de9b

File tree

5 files changed

+433
-4
lines changed

5 files changed

+433
-4
lines changed
Lines changed: 114 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,122 @@
1+
import { axios } from "@pipedream/platform";
2+
13
export default {
24
type: "app",
35
app: "easypromos",
4-
propDefinitions: {},
6+
version: "0.0.{{ts}}",
7+
propDefinitions: {
8+
userid: {
9+
type: "integer",
10+
label: "User ID",
11+
description: "The ID of the user",
12+
async options() {
13+
const users = await this.getUsers();
14+
return users.map((user) => ({
15+
label: user.name,
16+
value: user.id,
17+
}));
18+
},
19+
},
20+
promotionid: {
21+
type: "integer",
22+
label: "Promotion ID",
23+
description: "The ID of the promotion",
24+
async options() {
25+
const promotions = await this.getPromotions();
26+
return promotions.map((promotion) => ({
27+
label: promotion.name,
28+
value: promotion.id,
29+
}));
30+
},
31+
},
32+
},
533
methods: {
6-
// this.$auth contains connected account data
34+
// Existing method
735
authKeys() {
836
console.log(Object.keys(this.$auth));
937
},
38+
// Base URL for the Easypromos API
39+
_baseUrl() {
40+
return "https://api.easypromos.com";
41+
},
42+
// Helper method to make HTTP requests
43+
async _makeRequest(opts = {}) {
44+
const {
45+
$ = this,
46+
method = "GET",
47+
path = "/",
48+
data,
49+
params,
50+
headers = {},
51+
...otherOpts
52+
} = opts;
53+
54+
const requestHeaders = {
55+
...headers,
56+
Authorization: `Bearer ${this.$auth.access_token}`,
57+
};
58+
59+
if (data) {
60+
requestHeaders["Content-Type"] = "application/json";
61+
}
62+
63+
return axios($, {
64+
method,
65+
url: this._baseUrl() + path,
66+
headers: requestHeaders,
67+
data,
68+
params,
69+
...otherOpts,
70+
});
71+
},
72+
// Method to fetch users
73+
async getUsers(opts = {}) {
74+
return this._makeRequest({
75+
method: "GET",
76+
path: "/users",
77+
params: opts.params,
78+
});
79+
},
80+
// Method to fetch promotions
81+
async getPromotions(opts = {}) {
82+
return this._makeRequest({
83+
method: "GET",
84+
path: "/promotions",
85+
params: opts.params,
86+
});
87+
},
88+
// Emit event when a user earns or spends coins
89+
async emitCoinTransaction({
90+
userid, promotionid,
91+
}) {
92+
return this._makeRequest({
93+
method: "POST",
94+
path: "/coin-transactions",
95+
data: {
96+
user_id: userid,
97+
promotion_id: promotionid,
98+
},
99+
});
100+
},
101+
// Emit event when a registered user submits participation
102+
async emitParticipationSubmission({ promotionid }) {
103+
return this._makeRequest({
104+
method: "POST",
105+
path: "/participations",
106+
data: {
107+
promotion_id: promotionid,
108+
},
109+
});
110+
},
111+
// Emit event when a user registers in the promotion
112+
async emitUserRegistration({ promotionid }) {
113+
return this._makeRequest({
114+
method: "POST",
115+
path: "/registrations",
116+
data: {
117+
promotion_id: promotionid,
118+
},
119+
});
120+
},
10121
},
11-
};
122+
};

components/easypromos/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
"publishConfig": {
1313
"access": "public"
1414
}
15-
}
15+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import {
2+
axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
3+
} from "@pipedream/platform";
4+
import easypromos from "../../easypromos.app.mjs";
5+
6+
export default {
7+
key: "easypromos-new-coin-transaction",
8+
name: "New Coin Transaction",
9+
description: "Emit new event when a user earns or spends coins. [See the documentation]()",
10+
version: "0.0.{{ts}}",
11+
type: "source",
12+
dedupe: "unique",
13+
props: {
14+
easypromos,
15+
db: "$.service.db",
16+
timer: {
17+
type: "$.interface.timer",
18+
default: {
19+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
20+
},
21+
},
22+
userid: {
23+
propDefinition: [
24+
easypromos,
25+
"userid",
26+
],
27+
},
28+
promotionid: {
29+
propDefinition: [
30+
easypromos,
31+
"promotionid",
32+
],
33+
},
34+
},
35+
methods: {
36+
async getCoinTransactions(page = 1, perPage = 50, since = null) {
37+
const params = {
38+
promotion_id: this.promotionid,
39+
user_id: this.userid,
40+
page,
41+
perpage: perPage,
42+
};
43+
if (since) {
44+
params.since = since;
45+
}
46+
const response = await this.easypromos._makeRequest({
47+
method: "GET",
48+
path: "/coin-transactions",
49+
params,
50+
});
51+
return response.transactions || [];
52+
},
53+
async _getLastTimestamp() {
54+
return (await this.db.get("lastTimestamp")) || 0;
55+
},
56+
async _setLastTimestamp(timestamp) {
57+
await this.db.set("lastTimestamp", timestamp);
58+
},
59+
},
60+
hooks: {
61+
async deploy() {
62+
try {
63+
let page = 1;
64+
const perPage = 50;
65+
const fetchedTransactions = [];
66+
const lastTimestamp = await this._getLastTimestamp();
67+
68+
while (fetchedTransactions.length < perPage) {
69+
const transactions = await this.getCoinTransactions(page, perPage, lastTimestamp);
70+
if (transactions.length === 0) break;
71+
fetchedTransactions.unshift(...transactions.reverse());
72+
if (transactions.length < perPage) break;
73+
page += 1;
74+
}
75+
76+
const recentTransactions = fetchedTransactions.slice(0, perPage);
77+
for (const transaction of recentTransactions) {
78+
this.$emit(transaction, {
79+
id: transaction.id.toString(),
80+
summary: `Coin transaction: ${transaction.amount} for user ${transaction.user_id}`,
81+
ts: Date.parse(transaction.created),
82+
});
83+
}
84+
85+
if (recentTransactions.length > 0) {
86+
const latestTimestamp = Date.parse(recentTransactions[0].created);
87+
await this._setLastTimestamp(latestTimestamp);
88+
}
89+
} catch (error) {
90+
this.logger.error(`Error deploying source: ${error.message}`);
91+
}
92+
},
93+
async activate() {
94+
// No webhook setup required
95+
},
96+
async deactivate() {
97+
// No webhook teardown required
98+
},
99+
},
100+
async run() {
101+
try {
102+
const lastTimestamp = await this._getLastTimestamp();
103+
let page = 1;
104+
const perPage = 50;
105+
const newTransactions = [];
106+
107+
while (true) {
108+
const transactions = await this.getCoinTransactions(page, perPage, lastTimestamp);
109+
if (transactions.length === 0) break;
110+
111+
for (const transaction of transactions) {
112+
const transactionTimestamp = Date.parse(transaction.created);
113+
if (transactionTimestamp > lastTimestamp) {
114+
newTransactions.push(transaction);
115+
}
116+
}
117+
118+
if (transactions.length < perPage) break;
119+
page += 1;
120+
}
121+
122+
for (const transaction of newTransactions) {
123+
this.$emit(transaction, {
124+
id: transaction.id.toString(),
125+
summary: `Coin transaction: ${transaction.amount} for user ${transaction.user_id}`,
126+
ts: Date.parse(transaction.created),
127+
});
128+
}
129+
130+
if (newTransactions.length > 0) {
131+
const latestTransaction = newTransactions.reduce((a, b) =>
132+
Date.parse(a.created) > Date.parse(b.created)
133+
? a
134+
: b);
135+
await this._setLastTimestamp(Date.parse(latestTransaction.created));
136+
}
137+
} catch (error) {
138+
this.logger.error(`Error running source: ${error.message}`);
139+
}
140+
},
141+
};
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import {
2+
axios, DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
3+
} from "@pipedream/platform";
4+
import appName from "../../easypromos.app.mjs";
5+
6+
export default {
7+
key: "easypromos-new-participation",
8+
name: "New Participation Submitted",
9+
description: "Emit new event when a registered user submits a participation in the promotion. [See the documentation]()",
10+
version: "0.0.{{ts}}",
11+
type: "source",
12+
dedupe: "unique",
13+
props: {
14+
easypromos: {
15+
type: "app",
16+
app: "easypromos",
17+
},
18+
promotionid: {
19+
propDefinition: [
20+
appName,
21+
"promotionid",
22+
],
23+
},
24+
db: "$.service.db",
25+
timer: {
26+
type: "$.interface.timer",
27+
default: {
28+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
29+
},
30+
},
31+
},
32+
hooks: {
33+
async deploy() {
34+
const lastParticipationId = this.db.get("lastParticipationId") || 0;
35+
const participations = await this.easypromos._makeRequest({
36+
method: "GET",
37+
path: "/participations",
38+
params: {
39+
promotion_id: this.promotionid,
40+
limit: 50,
41+
sort: "id_desc",
42+
},
43+
});
44+
45+
const newParticipations = participations.filter((participation) => participation.id > lastParticipationId);
46+
47+
newParticipations.forEach((participation) => {
48+
this.$emit(participation, {
49+
id: participation.id.toString(),
50+
summary: `New Participation by User ID ${participation.user_id}`,
51+
ts: Date.parse(participation.created),
52+
});
53+
});
54+
55+
if (participations.length > 0) {
56+
const maxId = Math.max(...participations.map((p) => p.id));
57+
this.db.set("lastParticipationId", maxId);
58+
}
59+
},
60+
async activate() {
61+
// No webhook setup needed for polling
62+
},
63+
async deactivate() {
64+
// No webhook teardown needed for polling
65+
},
66+
},
67+
async run() {
68+
const lastParticipationId = this.db.get("lastParticipationId") || 0;
69+
70+
const participations = await this.easypromos._makeRequest({
71+
method: "GET",
72+
path: "/participations",
73+
params: {
74+
promotion_id: this.promotionid,
75+
limit: 50,
76+
sort: "id_desc",
77+
},
78+
});
79+
80+
const newParticipations = participations.filter((participation) => participation.id > lastParticipationId);
81+
82+
newParticipations.forEach((participation) => {
83+
this.$emit(participation, {
84+
id: participation.id.toString(),
85+
summary: `New Participation by User ID ${participation.user_id}`,
86+
ts: Date.parse(participation.created) || Date.now(),
87+
});
88+
});
89+
90+
if (participations.length > 0) {
91+
const maxId = Math.max(...participations.map((p) => p.id));
92+
this.db.set("lastParticipationId", maxId);
93+
}
94+
},
95+
};

0 commit comments

Comments
 (0)