I'm building a Twitter bot using Node.js, the twitter-api-v2 package, and the node_characterai package. The bot listens to mentions of a specific username and replies to them. However, when setting up the filtered stream, I get an error with a 403 status code.
Here's my code:
const { TwitterApi } = require('twitter-api-v2');
const CharacterAiClient = require('node_characterai');
const characterId = process.env.CHARACTER_API_KEY;
const twitterConsumerKey = process.env.TWITTER_CONSUMER_KEY;
const twitterConsumerSecret = process.env.TWITTER_CONSUMER_SECRET;
const twitterAccessToken = process.env.TWITTER_ACCESS_TOKEN;
const twitterAccessTokenSecret = process.env.TWITTER_ACCESS_TOKEN_SECRET;
const twitterBearerToken = process.env.TWITTER_BEARER_TOKEN;
const characterAi = new CharacterAiClient({ puppeteer: { timeout: 60000 } });
(async () => {
await characterAi.authenticateAsGuest();
})();
const twitterClient = new TwitterApi({
appKey: twitterConsumerKey,
appSecret: twitterConsumerSecret,
accessToken: twitterAccessToken,
bearerToken: twitterAccessTokenSecret,
});
const twitterClientV2AppOnly = new TwitterApi(twitterBearerToken);
async function setupFilteredStream() {
const rules = await twitterClientV2AppOnly.v2.streamRules();
const existingRule = rules.data?.find(
(rule) => rule.value === `@Explainerbot`
);
if (!existingRule) {
await twitterClientV2AppOnly.v2.updateStreamRules([
{
add: [
{
value: `@Explainerbot`,
tag: 'Explainerbot mention',
},
],
},
]);
}
const filteredStream = twitterClientV2AppOnly.v2.searchStream();
filteredStream.on('data', async (tweet) => {
if (
!tweet.matching_rules.some(
(rule) => rule.tag === 'Explainerbot mention'
)
) {
return;
}
const replyToUsername = tweet.includes.users.find(
(user) => user.id === tweet.author_id
)?.username;
const inputText = tweet.text.replace('@Explainerbot', '').trim();
const chat = await characterAi.createOrContinueChat(characterId);
const response = await chat.sendAndAwaitResponse(inputText, true);
const replyText = `@${replyToUsername} ${response.text}`;
await twitterClient.v1.tweet(replyText, {
in_reply_to_status_id: tweet.id,
});
});
filteredStream.on('error', (error) => {
console.error('Filtered stream error:', error);
});
}
setupFilteredStream().catch((error) => {
console.error('Error setting up filtered stream:', error);
});
The error message I'm getting is as follows:
Error setting up filtered stream: ApiResponseError: Request failed with code 403
at RequestHandlerHelper.createResponseError (/home/sojin/Desktop/Twitter-bot/node_modules/twitter-api-v2/dist/cjs/client-mixins/request-handler.helper.js:103:16)
at RequestHandlerHelper.onResponseEndHandler (/home/sojin/Desktop//Twitter-bot/node_modules/twitter-api-v2/dist/cjs/client-mixins/request-handler.helper.js:252:25)
at Gunzip.emit (node:events:513:28)
at endReadableNT (node:internal/streams/readable:1359:12)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
error: true,
type: 'response',
code: 403,
headers: {
date: 'Fri, 05 May 2023 15:55:18 UTC',
perf: '7626143928',
server: 'tsa_k',
'set-cookie': [
'guest_id_marketing=v1%3A168330211836418529; Max-Age=63072000; Expires=Sun, 04 May 2025 15:55:18 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None',
'guest_id_ads=v1%3A168330211836418529; Max-Age=63072000; Expires=Sun, 04 May 2025 15:55:18 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None',
'personalization_id="v1_qV6x3J+Ght2g483ct4CEfA=="; Max-Age=63072000; Expires=Sun, 04 May 2025 15:55:18 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None',
'guest_id=v1%3A168330211836418529; Max-Age=63072000; Expires=Sun, 04 May 2025 15:55:18 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None'
],
'content-type': 'application/json; charset=utf-8',
'cache-control': 'no-cache, no-store, max-age=0',
'content-length': '329',
'x-access-level': 'read',
'x-frame-options': 'SAMEORIGIN',
'content-encoding': 'gzip',
'x-transaction-id': '3b7af46a5684351d',
'x-xss-protection': '0',
'x-rate-limit-limit': '40000',
'x-rate-limit-reset': '1683302381',
'content-disposition': 'attachment; filename=json.json',
'x-content-type-options': 'nosniff',
'x-rate-limit-remaining': '39998',
'strict-transport-security': 'max-age=631138519',
'x-response-time': '177',
'x-connection-hash': '8d5c0691c18884ba01b6c5d2a3c86936a0a0930881d3c9e86c28e4159f4cb5d3'
},
rateLimit: { limit: 40000, remaining: 39998, reset: 1683302381 },
data: {
client_id: '27065914',
detail: 'When authenticating requests to the Twitter API v2 endpoints, you must use keys and tokens from a Twitter developer App that is attached to a Project. You can create a project via the developer portal.',
registration_url: 'https://developer.twitter.com/en/docs/projects/overview',
title: 'Client Forbidden',
required_enrollment: 'Appropriate Level of API Access',
reason: 'client-not-enrolled',
type: 'https://api.twitter.com/2/problems/client-forbidden'
}
}
[node_characterai] Puppeteer - Done with setup
According to the error message, I need to authenticate requests to the Twitter API v2 endpoints using keys and tokens from a Twitter developer App that is attached to a Project. I have created a project and generated the appropriate keys and tokens, but I'm still getting the error.
Can anyone help me understand what I might be doing wrong or how to fix this issue? Please teach me to solve this.