0

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.

0 Answers0