From dff7e57a1463b017b15f0554bd6871548b5d0fa7 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Tue, 27 May 2025 14:03:19 +0700 Subject: [PATCH] feat: threads refresh token implementation --- .../integrations/social/threads.provider.ts | 82 +++++++++++-------- .../src/integrations/social/x.provider.ts | 22 ++++- 2 files changed, 69 insertions(+), 35 deletions(-) diff --git a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts index d2572da5..6bdc260a 100644 --- a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts @@ -25,13 +25,27 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { ]; async refreshToken(refresh_token: string): Promise { + const { access_token } = await ( + await this.fetch( + `https://graph.threads.net/refresh_access_token?grant_type=th_refresh_token&access_token=${refresh_token}` + ) + ).json(); + + const { + id, + name, + picture: { + data: { url }, + }, + } = await this.fetchPageInformation(access_token); + return { - refreshToken: '', - expiresIn: 0, - accessToken: '', - id: '', - name: '', - picture: '', + id, + name, + accessToken: access_token, + refreshToken: access_token, + expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(), + picture: url, username: '', }; } @@ -153,7 +167,8 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { isCarouselItem = false, replyToId?: string ): Promise { - const mediaType = media.url.indexOf('.mp4') > -1 ? 'video_url' : 'image_url'; + const mediaType = + media.url.indexOf('.mp4') > -1 ? 'video_url' : 'image_url'; const mediaParams = new URLSearchParams({ ...(mediaType === 'video_url' ? { video_url: media.url } : {}), ...(mediaType === 'image_url' ? { image_url: media.url } : {}), @@ -234,19 +249,16 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { form.append('media_type', 'TEXT'); form.append('text', message); form.append('access_token', accessToken); - + if (replyToId) { form.append('reply_to_id', replyToId); } const { id: contentId } = await ( - await this.fetch( - `https://graph.threads.net/v1.0/${userId}/threads`, - { - method: 'POST', - body: form, - } - ) + await this.fetch(`https://graph.threads.net/v1.0/${userId}/threads`, { + method: 'POST', + body: form, + }) ).json(); return contentId; @@ -324,32 +336,34 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { } const [firstPost, ...replies] = postDetails; - + // Create the initial thread const initialContentId = await this.createThreadContent( - userId, - accessToken, + userId, + accessToken, firstPost ); - + // Publish the thread const { threadId, permalink } = await this.publishThread( - userId, - accessToken, + userId, + accessToken, initialContentId ); - + // Track the responses - const responses: PostResponse[] = [{ - id: firstPost.id, - postId: threadId, - status: 'success', - releaseURL: permalink, - }]; - + const responses: PostResponse[] = [ + { + id: firstPost.id, + postId: threadId, + status: 'success', + releaseURL: permalink, + }, + ]; + // Handle replies if any let lastReplyId = threadId; - + for (const reply of replies) { // Create reply content const replyContentId = await this.createThreadContent( @@ -358,17 +372,17 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { reply, lastReplyId ); - + // Publish the reply const { threadId: replyThreadId } = await this.publishThread( userId, accessToken, replyContentId ); - + // Update the last reply ID for chaining lastReplyId = replyThreadId; - + // Add to responses responses.push({ id: reply.id, @@ -377,7 +391,7 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { releaseURL: permalink, // Main thread URL }); } - + return responses; } diff --git a/libraries/nestjs-libraries/src/integrations/social/x.provider.ts b/libraries/nestjs-libraries/src/integrations/social/x.provider.ts index 822943a4..7ac3ab2a 100644 --- a/libraries/nestjs-libraries/src/integrations/social/x.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/x.provider.ts @@ -19,7 +19,7 @@ export class XProvider extends SocialAbstract implements SocialProvider { identifier = 'x'; name = 'X'; isBetweenSteps = false; - scopes = []; + scopes = [] as string[]; toolTip = 'You will be logged in into your current account, if you would like a different account, change it first on X'; @@ -313,4 +313,24 @@ export class XProvider extends SocialAbstract implements SocialProvider { status: 'posted', })); } + + communities(accessToken: string, data: {search: string}) { + const [accessTokenSplit, accessSecretSplit] = accessToken.split(':'); + const client = new TwitterApi({ + appKey: process.env.X_API_KEY!, + appSecret: process.env.X_API_SECRET!, + accessToken: accessTokenSplit, + accessSecret: accessSecretSplit, + }); + + return client.v2.searchCommunities(data.search); + + // })).data.map(p => { + // return { + // id: p.id, + // name: p.name, + // accessToken + // } + // }) + } }