@pipedream/twitter 0.3.3 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/actions/add-user-to-list/add-user-to-list.mjs +62 -0
- package/actions/advanced-search/advanced-search.mjs +113 -0
- package/actions/common.mjs +29 -0
- package/actions/create-tweet/create-tweet.mjs +146 -0
- package/actions/delete-tweet/delete-tweet.mjs +42 -0
- package/actions/follow-user/follow-user.mjs +48 -0
- package/actions/get-tweet/get-tweet.mjs +42 -0
- package/actions/get-user/get-user.mjs +50 -0
- package/actions/like-tweet/like-tweet.mjs +42 -0
- package/actions/list-favorites/list-favorites.mjs +63 -0
- package/actions/list-followers/list-followers.mjs +67 -0
- package/actions/list-lists/list-lists.mjs +69 -0
- package/actions/list-mentions/list-mentions.mjs +55 -0
- package/actions/list-pending-followers/list-pending-followers.mjs +32 -0
- package/actions/list-retweets/list-retweets.mjs +54 -0
- package/actions/list-user-tweets/list-user-tweets.mjs +80 -0
- package/actions/retweet/retweet.mjs +27 -0
- package/actions/simple-search/simple-search.mjs +62 -0
- package/actions/simple-search-in-list/simple-search-in-list.mjs +48 -0
- package/actions/unfollow-user/unfollow-user.mjs +48 -0
- package/actions/unlike-tweet/unlike-tweet.mjs +40 -0
- package/package.json +21 -21
- package/readme.md +0 -4
- package/sources/common/followed.mjs +37 -0
- package/sources/common/followers.mjs +158 -0
- package/sources/common/tweets.mjs +154 -0
- package/sources/{language-codes.js → language-codes.mjs} +6 -2
- package/sources/my-liked-tweets/my-liked-tweets.mjs +29 -0
- package/sources/my-tweets/my-tweets.mjs +48 -0
- package/sources/new-follower-of-me/new-follower-of-me.mjs +69 -0
- package/sources/new-follower-of-user/new-follower-of-user.mjs +25 -0
- package/sources/new-list-followed/new-list-followed.mjs +24 -0
- package/sources/new-trends-by-geo/new-trends-by-geo.mjs +39 -0
- package/sources/new-tweet-in-list/new-tweet-in-list.mjs +49 -0
- package/sources/new-unfollower-of-me/{new-unfollower-of-me.js → new-unfollower-of-me.mjs} +5 -4
- package/sources/new-unfollower-of-user/new-unfollower-of-user.mjs +25 -0
- package/sources/new-user-followed/new-user-followed.mjs +25 -0
- package/sources/search-mentions/search-mentions.mjs +143 -0
- package/sources/tweets-liked-by-user/tweets-liked-by-user.mjs +37 -0
- package/sources/user-tweets/user-tweets.mjs +49 -0
- package/sources/watch-retweets-of-me/watch-retweets-of-me.mjs +36 -0
- package/sources/watch-retweets-of-my-tweet/watch-retweets-of-my-tweet.mjs +44 -0
- package/sources/watch-retweets-of-user-tweet/watch-retweets-of-user-tweet.mjs +34 -0
- package/twitter.app.mjs +1149 -0
- package/sources/common-followers.js +0 -99
- package/sources/my-liked-tweets/my-liked-tweets.js +0 -26
- package/sources/my-tweets/my-tweets.js +0 -83
- package/sources/new-follower-of-me/new-follower-of-me.js +0 -68
- package/sources/new-follower-of-user/new-follower-of-user.js +0 -69
- package/sources/new-trends-by-geo/new-trends-by-geo.js +0 -29
- package/sources/new-unfollower-of-user/new-unfollower-of-user.js +0 -22
- package/sources/search-mentions/search-mentions.js +0 -76
- package/sources/tweets-liked-by-user/tweets-liked-by-user.js +0 -27
- package/sources/user-tweets/user-tweets.js +0 -66
- package/twitter.app.js +0 -461
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import twitter from "../../twitter.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
props: {
|
|
5
|
+
db: "$.service.db",
|
|
6
|
+
twitter,
|
|
7
|
+
timer: {
|
|
8
|
+
label: "Polling interval",
|
|
9
|
+
description: "Pipedream will poll the Twitter API on this schedule",
|
|
10
|
+
type: "$.interface.timer",
|
|
11
|
+
default: {
|
|
12
|
+
intervalSeconds: 60 * 15,
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
hooks: {
|
|
17
|
+
async activate() {
|
|
18
|
+
await this._provisionFollowersCache();
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
deactivate() {
|
|
22
|
+
this._clearFollowersCache();
|
|
23
|
+
},
|
|
24
|
+
methods: {
|
|
25
|
+
/**
|
|
26
|
+
* This method returns the size of the internal cache used by the event
|
|
27
|
+
* source to keep track of the latest Twitter followers of the corresponding
|
|
28
|
+
* account.
|
|
29
|
+
*
|
|
30
|
+
* The size represents the maximum amount of entries/ID's that will be
|
|
31
|
+
* cached at any given time (or 0 for unlimited). Keep in mind that the
|
|
32
|
+
* Pipedream platform itself imposes size limits as well in terms of DB
|
|
33
|
+
* usage.
|
|
34
|
+
*
|
|
35
|
+
* @returns The maximum amount of Twitter followers entries to be cached at
|
|
36
|
+
* any given moment (or 0 for unlimited).
|
|
37
|
+
*/
|
|
38
|
+
getFollowersCacheSize() {
|
|
39
|
+
return 0;
|
|
40
|
+
},
|
|
41
|
+
getScreenName() {
|
|
42
|
+
// When screen name is not explicitly provided, the Twitter API defaults
|
|
43
|
+
// it to the user making the API request
|
|
44
|
+
return undefined;
|
|
45
|
+
},
|
|
46
|
+
/**
|
|
47
|
+
* This function provides the list of relevant, follower-related, user ID's
|
|
48
|
+
* that are used by the event source to emit events. How each event source
|
|
49
|
+
* that implements it depends on the purpose of the event source itself. For
|
|
50
|
+
* example, an event source that emits an event for every new follower will
|
|
51
|
+
* implement this function in such a way that its result is a list of user
|
|
52
|
+
* ID's for each new follower detected.
|
|
53
|
+
*
|
|
54
|
+
* @returns the list of relevant user ID's for this event source to process
|
|
55
|
+
*/
|
|
56
|
+
getRelevantIds() {
|
|
57
|
+
return [];
|
|
58
|
+
},
|
|
59
|
+
generateMeta(data) {
|
|
60
|
+
const {
|
|
61
|
+
timestamp,
|
|
62
|
+
user,
|
|
63
|
+
} = data;
|
|
64
|
+
const {
|
|
65
|
+
id_str: id,
|
|
66
|
+
screen_name: summary,
|
|
67
|
+
} = user;
|
|
68
|
+
// Event timestamp is expressed in seconds, whereas Javascript timestamps
|
|
69
|
+
// are expressed in milliseconds
|
|
70
|
+
const ts = timestamp * 1000;
|
|
71
|
+
return {
|
|
72
|
+
id,
|
|
73
|
+
summary,
|
|
74
|
+
ts,
|
|
75
|
+
};
|
|
76
|
+
},
|
|
77
|
+
_clearFollowersCache() {
|
|
78
|
+
this.setFollowersCache([]);
|
|
79
|
+
},
|
|
80
|
+
async _provisionFollowersCache() {
|
|
81
|
+
const screenName = this.getScreenName();
|
|
82
|
+
const followerIdsGen = this.twitter.scanFollowerIds(screenName);
|
|
83
|
+
const maxFollowerListSize = Math.max(this.getFollowersCacheSize(), 0);
|
|
84
|
+
const result = [];
|
|
85
|
+
for await (const id of followerIdsGen) {
|
|
86
|
+
if (maxFollowerListSize !== 0 && maxFollowerListSize === result.length) {
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
result.push(id);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.setFollowersCache(result);
|
|
94
|
+
return result;
|
|
95
|
+
},
|
|
96
|
+
getFollowersCache() {
|
|
97
|
+
return this.db.get("followers");
|
|
98
|
+
},
|
|
99
|
+
setFollowersCache(followers) {
|
|
100
|
+
const followersCacheSize = Math.max(this.getFollowersCacheSize(), 0);
|
|
101
|
+
const trimmedFollowers = followersCacheSize !== 0
|
|
102
|
+
? followers.slice(0, followersCacheSize)
|
|
103
|
+
: followers;
|
|
104
|
+
this.db.set("followers", trimmedFollowers);
|
|
105
|
+
console.log(`
|
|
106
|
+
Updated followers cache: ${trimmedFollowers.length} records
|
|
107
|
+
`);
|
|
108
|
+
},
|
|
109
|
+
/**
|
|
110
|
+
* This generator method scans the list of Twitter followers until it finds
|
|
111
|
+
* the ID of a follower that was already processed.
|
|
112
|
+
*
|
|
113
|
+
* @param {string[]} processedFollowerIds a list of the ID's of the most
|
|
114
|
+
* recent Twitter followers processed by the event source
|
|
115
|
+
* @yields the ID of a new Twitter follower
|
|
116
|
+
*/
|
|
117
|
+
async *scanNewFollowers(processedFollowerIds = []) {
|
|
118
|
+
const processeedFollowerIdsSet = new Set(processedFollowerIds);
|
|
119
|
+
const screenName = this.getScreenName();
|
|
120
|
+
const followerIdsGen = this.twitter.scanFollowerIds(screenName);
|
|
121
|
+
for await (const id of followerIdsGen) {
|
|
122
|
+
if (processeedFollowerIdsSet.has(id)) {
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
yield id;
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
async getUnfollowers() {
|
|
129
|
+
const prevFollowers = this.getFollowersCache();
|
|
130
|
+
const currFollowers = await this._provisionFollowersCache();
|
|
131
|
+
const currFollowersSet = new Set(currFollowers);
|
|
132
|
+
return prevFollowers.filter((pf) => !currFollowersSet.has(pf));
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
async run(event) {
|
|
136
|
+
const { timestamp } = event;
|
|
137
|
+
const relevantIds = await this.getRelevantIds();
|
|
138
|
+
if (relevantIds.length <= 0) {
|
|
139
|
+
console.log(`
|
|
140
|
+
No changes in followers data for this event source to emit a new event
|
|
141
|
+
`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
const users = await this.twitter.lookupUsers({
|
|
146
|
+
userIdArray: relevantIds,
|
|
147
|
+
});
|
|
148
|
+
users.forEach((user) => {
|
|
149
|
+
const data = {
|
|
150
|
+
timestamp,
|
|
151
|
+
user,
|
|
152
|
+
};
|
|
153
|
+
user.profile_url = `https://twitter.com/${user.screen_name}/`;
|
|
154
|
+
const meta = this.generateMeta(data);
|
|
155
|
+
this.$emit(user, meta);
|
|
156
|
+
});
|
|
157
|
+
},
|
|
158
|
+
};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import twitter from "../../twitter.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
props: {
|
|
5
|
+
db: "$.service.db",
|
|
6
|
+
twitter,
|
|
7
|
+
count: {
|
|
8
|
+
propDefinition: [
|
|
9
|
+
twitter,
|
|
10
|
+
"count",
|
|
11
|
+
],
|
|
12
|
+
},
|
|
13
|
+
maxRequests: {
|
|
14
|
+
propDefinition: [
|
|
15
|
+
twitter,
|
|
16
|
+
"maxRequests",
|
|
17
|
+
],
|
|
18
|
+
},
|
|
19
|
+
timer: {
|
|
20
|
+
label: "Polling interval",
|
|
21
|
+
description: "Pipedream will poll the Twitter API on this schedule",
|
|
22
|
+
type: "$.interface.timer",
|
|
23
|
+
default: {
|
|
24
|
+
intervalSeconds: 60 * 15,
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
methods: {
|
|
29
|
+
_compareByIdAsc({ id_str: a }, { id_str: b }) {
|
|
30
|
+
const A = BigInt(a);
|
|
31
|
+
const B = BigInt(b);
|
|
32
|
+
if (A < B) return -1;
|
|
33
|
+
if (A > B) return 1;
|
|
34
|
+
return 0;
|
|
35
|
+
},
|
|
36
|
+
sortTweets(tweets) {
|
|
37
|
+
return tweets
|
|
38
|
+
.sort(this._compareByIdAsc);
|
|
39
|
+
},
|
|
40
|
+
/**
|
|
41
|
+
* This function returns the Twitter screen name of the subject account
|
|
42
|
+
*
|
|
43
|
+
* @returns a string containing the relevant Twitter screen name
|
|
44
|
+
*/
|
|
45
|
+
getScreenName() {
|
|
46
|
+
throw new Error("getScreenName is not implemented");
|
|
47
|
+
},
|
|
48
|
+
/**
|
|
49
|
+
* This function provides the list of options for the `tweetId` user prop.
|
|
50
|
+
* It is meant to be called by Pipedream during the setup of the user prop
|
|
51
|
+
* and not during normal operations of the event source.
|
|
52
|
+
*
|
|
53
|
+
* @param {object} context the context object for the pagination of the
|
|
54
|
+
* prop options
|
|
55
|
+
* @param {object} context.prevContext the context object of a previous
|
|
56
|
+
* call to this method
|
|
57
|
+
* @returns an object containing the list of Tweet ID options for the
|
|
58
|
+
* `tweetId` user prop and the context for pagination
|
|
59
|
+
*/
|
|
60
|
+
async tweetIdOptions(context) {
|
|
61
|
+
const { prevContext = {} } = context;
|
|
62
|
+
const {
|
|
63
|
+
screenName = await this.getScreenName(),
|
|
64
|
+
sinceId = "1",
|
|
65
|
+
} = prevContext;
|
|
66
|
+
|
|
67
|
+
const userTimelineOpts = {
|
|
68
|
+
screenName,
|
|
69
|
+
sinceId,
|
|
70
|
+
count: 10,
|
|
71
|
+
trim_user: true,
|
|
72
|
+
exclude_replies: false,
|
|
73
|
+
include_rts: false,
|
|
74
|
+
};
|
|
75
|
+
const tweets = await this.twitter.getUserTimeline(userTimelineOpts);
|
|
76
|
+
if (tweets.length === 0) {
|
|
77
|
+
// There are no more tweets to go through
|
|
78
|
+
return {
|
|
79
|
+
options: null,
|
|
80
|
+
context: prevContext,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const sortedTweets = this.sortTweets(tweets);
|
|
85
|
+
const { id_str: lastId } = sortedTweets[sortedTweets.length - 1];
|
|
86
|
+
const options = sortedTweets.map(({
|
|
87
|
+
full_text: fullText,
|
|
88
|
+
id_str: idStr,
|
|
89
|
+
}) => ({
|
|
90
|
+
label: fullText,
|
|
91
|
+
value: idStr,
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
return {
|
|
95
|
+
options,
|
|
96
|
+
context: {
|
|
97
|
+
screenName,
|
|
98
|
+
sinceId: lastId,
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
},
|
|
102
|
+
getSinceId() {
|
|
103
|
+
return this.db.get("sinceId") || "1";
|
|
104
|
+
},
|
|
105
|
+
setSinceId(sinceId = "1") {
|
|
106
|
+
this.db.set("sinceId", sinceId);
|
|
107
|
+
},
|
|
108
|
+
generateMeta(tweet) {
|
|
109
|
+
const {
|
|
110
|
+
created_at: createdAt,
|
|
111
|
+
full_text: fullText,
|
|
112
|
+
id_str: id,
|
|
113
|
+
text,
|
|
114
|
+
} = tweet;
|
|
115
|
+
const summary = fullText || text;
|
|
116
|
+
const ts = this.twitter.parseDate(createdAt);
|
|
117
|
+
return {
|
|
118
|
+
id,
|
|
119
|
+
summary,
|
|
120
|
+
ts,
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
/**
|
|
124
|
+
* The purpose of this function is to retrieve the relevant Tweets for the
|
|
125
|
+
* event source that implements it. For example, if the event source emits
|
|
126
|
+
* an event for each new Tweet of a specific user, the implementation of
|
|
127
|
+
* this function will perform the retrieval of such Tweets and return it as
|
|
128
|
+
* a list of [Tweet
|
|
129
|
+
* objects](https://developer.twitter.com/en/docs/twitter-api/v1/data-dictionary/object-model/tweet)
|
|
130
|
+
*
|
|
131
|
+
* @returns a list of Tweet objects for which to emit new events
|
|
132
|
+
*/
|
|
133
|
+
retrieveTweets() {
|
|
134
|
+
throw new Error("retrieveTweets is not implemented");
|
|
135
|
+
},
|
|
136
|
+
},
|
|
137
|
+
async run() {
|
|
138
|
+
const tweets = await this.retrieveTweets();
|
|
139
|
+
if (tweets.length === 0) {
|
|
140
|
+
console.log("No new tweets available. Skipping...");
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const sortedTweets = this.sortTweets(tweets);
|
|
145
|
+
const { id_str: lastId } = sortedTweets[sortedTweets.length - 1];
|
|
146
|
+
this.setSinceId(lastId);
|
|
147
|
+
|
|
148
|
+
// Emit array of tweet objects
|
|
149
|
+
sortedTweets.forEach((tweet) => {
|
|
150
|
+
const meta = this.generateMeta(tweet);
|
|
151
|
+
this.$emit(tweet, meta);
|
|
152
|
+
});
|
|
153
|
+
},
|
|
154
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import twitter from "../../twitter.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "twitter-my-liked-tweets",
|
|
5
|
+
name: "My Liked Tweets",
|
|
6
|
+
description: "Emit new Tweets you like on Twitter",
|
|
7
|
+
version: "0.0.7",
|
|
8
|
+
type: "source",
|
|
9
|
+
props: {
|
|
10
|
+
twitter,
|
|
11
|
+
timer: {
|
|
12
|
+
label: "Polling interval",
|
|
13
|
+
description: "Pipedream will poll the Twitter API on this schedule",
|
|
14
|
+
type: "$.interface.timer",
|
|
15
|
+
default: {
|
|
16
|
+
intervalSeconds: 60 * 15,
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
dedupe: "unique",
|
|
21
|
+
async run() {
|
|
22
|
+
(await this.twitter.getLikedTweets()).reverse().forEach((tweet) => {
|
|
23
|
+
this.$emit(this.twitter.enrichTweet(tweet), {
|
|
24
|
+
id: tweet.id_str,
|
|
25
|
+
summary: tweet.full_text,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
},
|
|
29
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import base from "../common/tweets.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...base,
|
|
5
|
+
key: "twitter-my-tweets",
|
|
6
|
+
name: "My Tweets",
|
|
7
|
+
description: "Emit new Tweets you post to Twitter",
|
|
8
|
+
version: "0.0.9",
|
|
9
|
+
type: "source",
|
|
10
|
+
props: {
|
|
11
|
+
...base.props,
|
|
12
|
+
includeRetweets: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
base.props.twitter,
|
|
15
|
+
"includeRetweets",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
includeReplies: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
base.props.twitter,
|
|
21
|
+
"includeReplies",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
methods: {
|
|
26
|
+
...base.methods,
|
|
27
|
+
shouldExcludeReplies() {
|
|
28
|
+
return this.includeReplies === "exclude";
|
|
29
|
+
},
|
|
30
|
+
shouldIncludeRetweets() {
|
|
31
|
+
return this.includeRetweets !== "exclude";
|
|
32
|
+
},
|
|
33
|
+
async getScreenName() {
|
|
34
|
+
const { screen_name: screenName } = await this.twitter.verifyCredentials();
|
|
35
|
+
return screenName;
|
|
36
|
+
},
|
|
37
|
+
async retrieveTweets() {
|
|
38
|
+
const screenName = await this.getScreenName();
|
|
39
|
+
return this.twitter.getUserTimeline({
|
|
40
|
+
screenName,
|
|
41
|
+
count: this.count,
|
|
42
|
+
sinceId: this.getSinceId(),
|
|
43
|
+
excludeReplies: this.shouldExcludeReplies(),
|
|
44
|
+
includeRts: this.shouldIncludeRetweets(),
|
|
45
|
+
});
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import common from "../common/followers.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...common,
|
|
5
|
+
key: "twitter-new-follower-of-me",
|
|
6
|
+
name: "New Follower of Me",
|
|
7
|
+
description: "Emit new event when a user follows you on Twitter",
|
|
8
|
+
version: "0.0.8",
|
|
9
|
+
type: "source",
|
|
10
|
+
props: {
|
|
11
|
+
...common.props,
|
|
12
|
+
followersCacheSize: {
|
|
13
|
+
type: "integer",
|
|
14
|
+
label: "Followers Cache Size",
|
|
15
|
+
description: "The maximum amount of follower ID's that will be cached at any given time",
|
|
16
|
+
min: 10,
|
|
17
|
+
max: 100,
|
|
18
|
+
default: 100,
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
methods: {
|
|
22
|
+
...common.methods,
|
|
23
|
+
_getHasExecuted() {
|
|
24
|
+
return this.db.get("hasExecuted");
|
|
25
|
+
},
|
|
26
|
+
_setHasExecuted(hasExecuted) {
|
|
27
|
+
this.db.set("hasExecuted", hasExecuted);
|
|
28
|
+
},
|
|
29
|
+
_wasComponentExecuted() {
|
|
30
|
+
return !!this._getHasExecuted();
|
|
31
|
+
},
|
|
32
|
+
_markComponentAsExecuted() {
|
|
33
|
+
this._setHasExecuted(true);
|
|
34
|
+
},
|
|
35
|
+
getFollowersCacheSize() {
|
|
36
|
+
return this.followersCacheSize;
|
|
37
|
+
},
|
|
38
|
+
async getRelevantIds() {
|
|
39
|
+
const mostRecentFollowers = this.getFollowersCache();
|
|
40
|
+
if (!this._wasComponentExecuted()) {
|
|
41
|
+
this._markComponentAsExecuted();
|
|
42
|
+
|
|
43
|
+
// The first time this event source is executed, it will emit an event
|
|
44
|
+
// for the most recent followers.
|
|
45
|
+
// We reverse the list of new followers so that the event source emits the
|
|
46
|
+
// events for each follower in the same order that the followers followed
|
|
47
|
+
// the account, from least to most recent.
|
|
48
|
+
return mostRecentFollowers.reverse();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const newFollowersGen = this.scanNewFollowers(mostRecentFollowers);
|
|
52
|
+
const newFollowers = [];
|
|
53
|
+
for await (const id of newFollowersGen) {
|
|
54
|
+
newFollowers.push(id);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const followersCache = [
|
|
58
|
+
...newFollowers,
|
|
59
|
+
...mostRecentFollowers,
|
|
60
|
+
];
|
|
61
|
+
this.setFollowersCache(followersCache);
|
|
62
|
+
|
|
63
|
+
// We reverse the list of new followers so that the event source emits the
|
|
64
|
+
// events for each follower in the same order that the followers followed
|
|
65
|
+
// the account, from least to most recent.
|
|
66
|
+
return newFollowers.reverse();
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import base from "../new-follower-of-me/new-follower-of-me.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...base,
|
|
5
|
+
key: "twitter-new-follower-of-user",
|
|
6
|
+
name: "New Follower of User",
|
|
7
|
+
description: "Emit new event when a specific user gains a follower",
|
|
8
|
+
version: "0.0.8",
|
|
9
|
+
type: "source",
|
|
10
|
+
props: {
|
|
11
|
+
...base.props,
|
|
12
|
+
screenName: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
base.props.twitter,
|
|
15
|
+
"screenName",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
methods: {
|
|
20
|
+
...base.methods,
|
|
21
|
+
getScreenName() {
|
|
22
|
+
return this.screenName;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import common from "../common/followed.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...common,
|
|
5
|
+
key: "twitter-new-list-followed",
|
|
6
|
+
name: "New List Followed",
|
|
7
|
+
description: "Emit new event when the authenticated user follows a List",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "source",
|
|
10
|
+
dedupe: "unique",
|
|
11
|
+
methods: {
|
|
12
|
+
...common.methods,
|
|
13
|
+
async getFollowed() {
|
|
14
|
+
return this.twitter.getLists({});
|
|
15
|
+
},
|
|
16
|
+
generateMeta(list) {
|
|
17
|
+
return {
|
|
18
|
+
id: list.id,
|
|
19
|
+
summary: list.name,
|
|
20
|
+
ts: Date.now(),
|
|
21
|
+
};
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import twitter from "../../twitter.app.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
key: "twitter-new-trends-by-geo",
|
|
5
|
+
name: "New Trends by Geo",
|
|
6
|
+
description: "Emit new event when a new topic is trending on Twitter in a specific geographic location",
|
|
7
|
+
version: "0.0.7",
|
|
8
|
+
type: "source",
|
|
9
|
+
props: {
|
|
10
|
+
twitter,
|
|
11
|
+
trendLocation: {
|
|
12
|
+
propDefinition: [
|
|
13
|
+
twitter,
|
|
14
|
+
"trendLocation",
|
|
15
|
+
],
|
|
16
|
+
},
|
|
17
|
+
timer: {
|
|
18
|
+
label: "Polling interval",
|
|
19
|
+
description: "Pipedream will poll the Twitter API on this schedule",
|
|
20
|
+
type: "$.interface.timer",
|
|
21
|
+
default: {
|
|
22
|
+
intervalSeconds: 60 * 15,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
dedupe: "unique",
|
|
27
|
+
async run() {
|
|
28
|
+
(await this.twitter.getTrends({
|
|
29
|
+
id: this.trendLocation,
|
|
30
|
+
})).forEach((geo) => {
|
|
31
|
+
geo.trends.reverse().forEach((trend) => {
|
|
32
|
+
this.$emit(trend, {
|
|
33
|
+
id: trend.query,
|
|
34
|
+
summary: trend.name,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
},
|
|
39
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import base from "../common/tweets.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...base,
|
|
5
|
+
key: "twitter-new-tweet-in-list",
|
|
6
|
+
name: "New Tweet in List",
|
|
7
|
+
description: "Emit new Tweets posted by members of a list",
|
|
8
|
+
version: "0.0.5",
|
|
9
|
+
type: "source",
|
|
10
|
+
props: {
|
|
11
|
+
...base.props,
|
|
12
|
+
includeRetweets: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
base.props.twitter,
|
|
15
|
+
"includeRetweets",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
list: {
|
|
19
|
+
propDefinition: [
|
|
20
|
+
base.props.twitter,
|
|
21
|
+
"list",
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
includeEntities: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
label: "Entities",
|
|
27
|
+
description: `
|
|
28
|
+
Include the 'entities' node, which offers a variety of metadata about the
|
|
29
|
+
tweet in a discreet structure, including: user_mentions, urls, and hashtags
|
|
30
|
+
`,
|
|
31
|
+
default: false,
|
|
32
|
+
},
|
|
33
|
+
},
|
|
34
|
+
methods: {
|
|
35
|
+
...base.methods,
|
|
36
|
+
shouldIncludeRetweets() {
|
|
37
|
+
return this.includeRetweets !== "exclude";
|
|
38
|
+
},
|
|
39
|
+
retrieveTweets() {
|
|
40
|
+
return this.twitter.getListTweets({
|
|
41
|
+
listId: this.list,
|
|
42
|
+
count: this.count,
|
|
43
|
+
sinceId: this.getSinceId(),
|
|
44
|
+
includeEntities: this.includeEntities,
|
|
45
|
+
includeRetweets: this.shouldIncludeRetweets(),
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
},
|
|
49
|
+
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import common from "../common/followers.mjs";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export default {
|
|
4
4
|
...common,
|
|
5
5
|
key: "twitter-new-unfollower-of-me",
|
|
6
6
|
name: "New Unfollower of Me",
|
|
7
|
-
description: "Emit
|
|
8
|
-
version: "0.0.
|
|
7
|
+
description: "Emit new event when a user unfollows you on Twitter",
|
|
8
|
+
version: "0.0.9",
|
|
9
|
+
type: "source",
|
|
9
10
|
methods: {
|
|
10
11
|
...common.methods,
|
|
11
12
|
getRelevantIds() {
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import base from "../new-unfollower-of-me/new-unfollower-of-me.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...base,
|
|
5
|
+
key: "twitter-new-unfollower-of-user",
|
|
6
|
+
name: "New Unfollower of User",
|
|
7
|
+
description: "Emit new event when a specific user loses a follower on Twitter",
|
|
8
|
+
version: "0.0.7",
|
|
9
|
+
type: "source",
|
|
10
|
+
props: {
|
|
11
|
+
...base.props,
|
|
12
|
+
screenName: {
|
|
13
|
+
propDefinition: [
|
|
14
|
+
base.props.twitter,
|
|
15
|
+
"screenName",
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
},
|
|
19
|
+
methods: {
|
|
20
|
+
...base.methods,
|
|
21
|
+
getScreenName() {
|
|
22
|
+
return this.screenName;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import common from "../common/followed.mjs";
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
...common,
|
|
5
|
+
key: "twitter-new-user-followed",
|
|
6
|
+
name: "New User Followed",
|
|
7
|
+
description: "Emit new event when the authenticated user follows a User",
|
|
8
|
+
version: "0.0.1",
|
|
9
|
+
type: "source",
|
|
10
|
+
dedupe: "unique",
|
|
11
|
+
methods: {
|
|
12
|
+
...common.methods,
|
|
13
|
+
async getFollowed() {
|
|
14
|
+
const { users } = await this.twitter.getUserFollows({});
|
|
15
|
+
return users;
|
|
16
|
+
},
|
|
17
|
+
generateMeta(user) {
|
|
18
|
+
return {
|
|
19
|
+
id: user.id,
|
|
20
|
+
summary: user.name,
|
|
21
|
+
ts: Date.now(),
|
|
22
|
+
};
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
};
|