first commit
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
import {Inject, Injectable} from "@nestjs/common";
|
||||
import {TwitterApi} from 'twitter-api-v2';
|
||||
import {TwitterApiAutoTokenRefresher} from '@twitter-api-v2/plugin-token-refresher'
|
||||
|
||||
import {EUploadMimeType} from "twitter-api-v2/dist/esm/types";
|
||||
import {MediaV2MediaCategory} from "twitter-api-v2/dist/esm/types/v2/media.v2.types";
|
||||
import {XCacheService} from "../x-cache/x-cache.service";
|
||||
|
||||
@Injectable()
|
||||
export class XApiService {
|
||||
private clientId = process.env.TWITTER_CLIENT_ID + '';
|
||||
private clientSecret = process.env.TWITTER_CLIENT_SECRET;
|
||||
|
||||
private readonly userClient: any;
|
||||
|
||||
constructor(
|
||||
@Inject() private cacheService: XCacheService,
|
||||
) {
|
||||
}
|
||||
|
||||
async getTwitterClientV2() {
|
||||
return new TwitterApi(
|
||||
{
|
||||
clientId: this.clientId,
|
||||
clientSecret: this.clientSecret,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async getTwitterClientV2ViaAccessToken() {
|
||||
const accessToken = await this.getCacheAccessToken() as string;
|
||||
const refreshToken = await this.getCacheRefreshToken() as string;
|
||||
// console.log({refreshToken});
|
||||
|
||||
// @ts-ignore
|
||||
// @ts-ignore
|
||||
return new TwitterApi(accessToken,
|
||||
{
|
||||
plugins: [
|
||||
new TwitterApiAutoTokenRefresher({
|
||||
refreshCredentials: {
|
||||
clientId: '' + this.clientId,
|
||||
clientSecret: this.clientSecret,
|
||||
},
|
||||
refreshToken,
|
||||
// Hàm này được gọi tự động khi token được refresh thành công
|
||||
onTokenUpdate: async (newTokens) => {
|
||||
console.log('===> Token đã được làm mới:', newTokens);
|
||||
await this.setCacheRefreshToken('' + newTokens.refreshToken);
|
||||
await this.setCacheAccessToken(newTokens.accessToken);
|
||||
},
|
||||
// Hàm xử lý khi refresh thất bại (ví dụ: refresh token cũng hết hạn)
|
||||
onTokenRefreshError: async (error) => {
|
||||
console.error('Không thể refresh token:', error);
|
||||
throw error;
|
||||
},
|
||||
}),
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
async uploadImageV1(media: Buffer, options: {
|
||||
media_type: `${EUploadMimeType}` | EUploadMimeType;
|
||||
media_category?: MediaV2MediaCategory;
|
||||
additional_owners?: string[];
|
||||
}, chunkSize?: number): Promise<string> {
|
||||
const client = await this.getTwitterClientV2ViaAccessToken();
|
||||
// return client.v2.uploadMedia(media, options, chunkSize);
|
||||
return client.v2.uploadMedia(media, options, chunkSize);
|
||||
}
|
||||
|
||||
async postSimpleTweet(content) {
|
||||
const client = await this.getTwitterClientV2ViaAccessToken();
|
||||
return client.v2.tweet(content)
|
||||
}
|
||||
|
||||
async postReply(content: string, tweetId: string) {
|
||||
const client = await this.getTwitterClientV2ViaAccessToken();
|
||||
return client.v2.reply(content, tweetId)
|
||||
}
|
||||
|
||||
async qoute(content: string, tweetId: string) {
|
||||
const client = await this.getTwitterClientV2ViaAccessToken();
|
||||
|
||||
// @ts-ignore
|
||||
if (content.indexOf(`https://x.com/${process.env.TWITTER_USERNAME}/status`) === -1) {
|
||||
//hacking, use tweet instead of quote, because limit x
|
||||
return client.v2.tweet(content)
|
||||
}
|
||||
return client.v2.quote(content, tweetId)
|
||||
}
|
||||
|
||||
async setCacheAccessToken(accessToken: string) {
|
||||
return this.cacheService.setCachedKey('tw_accesstoken', '' + accessToken, 24 * 3600);
|
||||
}
|
||||
|
||||
async delCacheAccessToken() {
|
||||
return this.cacheService.delCachedKey('tw_accesstoken');
|
||||
}
|
||||
|
||||
async getCacheAccessToken() {
|
||||
return this.cacheService.getCachedData('tw_accesstoken')
|
||||
}
|
||||
|
||||
async getCacheRefreshToken() {
|
||||
return this.cacheService.getCachedData('tw_refreshtoken')
|
||||
}
|
||||
|
||||
async setCacheRefreshToken(refreshToken: string) {
|
||||
//30day
|
||||
return this.cacheService.setCachedKey('tw_refreshtoken', refreshToken, 30 * 24 * 3600);
|
||||
}
|
||||
|
||||
async refreshAccessToken() {
|
||||
const client = new TwitterApi({clientId: this.clientId, clientSecret: this.clientSecret});
|
||||
const refreshToken = await this.getCacheRefreshToken();
|
||||
|
||||
const {
|
||||
client: refreshedClient,
|
||||
accessToken,
|
||||
refreshToken: newRefreshToken
|
||||
} = await client.refreshOAuth2Token('' + refreshToken);
|
||||
|
||||
await this.cacheService.setCachedKey('tw_accesstoken_time_add', Date.now(), 3 * 24 * 3600);
|
||||
await this.setCacheAccessToken(accessToken);
|
||||
await this.setCacheRefreshToken('' + refreshToken);
|
||||
// Example request
|
||||
await refreshedClient.v2.me();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user