feat: Implement new follower of me trigger for twitter
This commit is contained in:
@@ -0,0 +1,70 @@
|
|||||||
|
import { IJSONObject } from '@automatisch/types';
|
||||||
|
import { URLSearchParams } from 'url';
|
||||||
|
import TwitterClient from '../index';
|
||||||
|
import omitBy from 'lodash/omitBy';
|
||||||
|
import isEmpty from 'lodash/isEmpty';
|
||||||
|
|
||||||
|
export default class GetUserFollowers {
|
||||||
|
client: TwitterClient;
|
||||||
|
|
||||||
|
constructor(client: TwitterClient) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(userId: string, lastInternalId?: string) {
|
||||||
|
const token = {
|
||||||
|
key: this.client.connection.formattedData.accessToken as string,
|
||||||
|
secret: this.client.connection.formattedData.accessSecret as string,
|
||||||
|
};
|
||||||
|
|
||||||
|
let response;
|
||||||
|
const followers: IJSONObject[] = [];
|
||||||
|
|
||||||
|
do {
|
||||||
|
const params: IJSONObject = {
|
||||||
|
pagination_token: response?.data?.meta?.next_token,
|
||||||
|
};
|
||||||
|
|
||||||
|
const queryParams = new URLSearchParams(omitBy(params, isEmpty));
|
||||||
|
|
||||||
|
const requestPath = `/2/users/${userId}/followers${
|
||||||
|
queryParams.toString() ? `?${queryParams.toString()}` : ''
|
||||||
|
}`;
|
||||||
|
|
||||||
|
const requestData = {
|
||||||
|
url: `${TwitterClient.baseUrl}${requestPath}`,
|
||||||
|
method: 'GET',
|
||||||
|
};
|
||||||
|
|
||||||
|
const authHeader = this.client.oauthClient.toHeader(
|
||||||
|
this.client.oauthClient.authorize(requestData, token)
|
||||||
|
);
|
||||||
|
|
||||||
|
response = await this.client.httpClient.get(requestPath, {
|
||||||
|
headers: { ...authHeader },
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.data.meta.result_count > 0) {
|
||||||
|
response.data.data.forEach((tweet: IJSONObject) => {
|
||||||
|
if (!lastInternalId || Number(tweet.id) > Number(lastInternalId)) {
|
||||||
|
followers.push(tweet);
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} while (response.data.meta.next_token && lastInternalId);
|
||||||
|
|
||||||
|
if (response.data?.errors) {
|
||||||
|
const errorMessages = response.data.errors
|
||||||
|
.map((error: IJSONObject) => error.detail)
|
||||||
|
.join(' ');
|
||||||
|
|
||||||
|
throw new Error(
|
||||||
|
`Error occured while fetching user data: ${errorMessages}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return followers;
|
||||||
|
}
|
||||||
|
}
|
@@ -9,6 +9,7 @@ import GetUserByUsername from './endpoints/get-user-by-username';
|
|||||||
import GetUserTweets from './endpoints/get-user-tweets';
|
import GetUserTweets from './endpoints/get-user-tweets';
|
||||||
import CreateTweet from './endpoints/create-tweet';
|
import CreateTweet from './endpoints/create-tweet';
|
||||||
import SearchTweets from './endpoints/search-tweets';
|
import SearchTweets from './endpoints/search-tweets';
|
||||||
|
import GetUserFollowers from './endpoints/get-user-followers';
|
||||||
|
|
||||||
export default class TwitterClient {
|
export default class TwitterClient {
|
||||||
flow: IFlow;
|
flow: IFlow;
|
||||||
@@ -24,6 +25,7 @@ export default class TwitterClient {
|
|||||||
getUserTweets: GetUserTweets;
|
getUserTweets: GetUserTweets;
|
||||||
createTweet: CreateTweet;
|
createTweet: CreateTweet;
|
||||||
searchTweets: SearchTweets;
|
searchTweets: SearchTweets;
|
||||||
|
getUserFollowers: GetUserFollowers;
|
||||||
|
|
||||||
static baseUrl = 'https://api.twitter.com';
|
static baseUrl = 'https://api.twitter.com';
|
||||||
|
|
||||||
@@ -57,5 +59,6 @@ export default class TwitterClient {
|
|||||||
this.getUserTweets = new GetUserTweets(this);
|
this.getUserTweets = new GetUserTweets(this);
|
||||||
this.createTweet = new CreateTweet(this);
|
this.createTweet = new CreateTweet(this);
|
||||||
this.searchTweets = new SearchTweets(this);
|
this.searchTweets = new SearchTweets(this);
|
||||||
|
this.getUserFollowers = new GetUserFollowers(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -285,6 +285,21 @@
|
|||||||
"name": "Test trigger"
|
"name": "Test trigger"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "New follower of me",
|
||||||
|
"key": "myFollowers",
|
||||||
|
"description": "Will be triggered when you have a new follower.",
|
||||||
|
"substeps": [
|
||||||
|
{
|
||||||
|
"key": "chooseConnection",
|
||||||
|
"name": "Choose connection"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "testStep",
|
||||||
|
"name": "Test trigger"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"actions": [
|
"actions": [
|
||||||
|
@@ -2,17 +2,20 @@ import TwitterClient from './client';
|
|||||||
import UserTweets from './triggers/user-tweets';
|
import UserTweets from './triggers/user-tweets';
|
||||||
import SearchTweets from './triggers/search-tweets';
|
import SearchTweets from './triggers/search-tweets';
|
||||||
import MyTweets from './triggers/my-tweets';
|
import MyTweets from './triggers/my-tweets';
|
||||||
|
import MyFollowers from './triggers/my-followers';
|
||||||
|
|
||||||
export default class Triggers {
|
export default class Triggers {
|
||||||
client: TwitterClient;
|
client: TwitterClient;
|
||||||
userTweets: UserTweets;
|
userTweets: UserTweets;
|
||||||
searchTweets: SearchTweets;
|
searchTweets: SearchTweets;
|
||||||
myTweets: MyTweets;
|
myTweets: MyTweets;
|
||||||
|
myFollowers: MyFollowers;
|
||||||
|
|
||||||
constructor(client: TwitterClient) {
|
constructor(client: TwitterClient) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.userTweets = new UserTweets(client);
|
this.userTweets = new UserTweets(client);
|
||||||
this.searchTweets = new SearchTweets(client);
|
this.searchTweets = new SearchTweets(client);
|
||||||
this.myTweets = new MyTweets(client);
|
this.myTweets = new MyTweets(client);
|
||||||
|
this.myFollowers = new MyFollowers(client);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
packages/backend/src/apps/twitter/triggers/my-followers.ts
Normal file
28
packages/backend/src/apps/twitter/triggers/my-followers.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import TwitterClient from '../client';
|
||||||
|
|
||||||
|
export default class MyFollowers {
|
||||||
|
client: TwitterClient;
|
||||||
|
|
||||||
|
constructor(client: TwitterClient) {
|
||||||
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
async run(lastInternalId: string) {
|
||||||
|
return this.getFollowers(lastInternalId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async testRun() {
|
||||||
|
return this.getFollowers();
|
||||||
|
}
|
||||||
|
|
||||||
|
async getFollowers(lastInternalId?: string) {
|
||||||
|
const { username } = await this.client.getCurrentUser.run();
|
||||||
|
const user = await this.client.getUserByUsername.run(username as string);
|
||||||
|
|
||||||
|
const tweets = await this.client.getUserFollowers.run(
|
||||||
|
user.id,
|
||||||
|
lastInternalId
|
||||||
|
);
|
||||||
|
return tweets;
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user