Open
Description
When I use sdk to post twitter with code below and I get 403 error. How could I use it correctly?
export class TwitterHandler {
authClient: auth.OAuth2User;
client: Client;
agent: AgentClient;
constructor() {
this.authClient = new auth.OAuth2User({
client_id: envConfig.X_CLIENT_ID,
client_secret: envConfig.X_CLIENT_SECRET,
callback: `${envConfig.SERVER_DOMAIN}/callback`,
scopes: ["tweet.read", "users.read", "tweet.write", "offline.access"],
});
this.client = new Client(this.authClient);
this.agent = new OpenAIAgent();
}
async checkAndUpdateAccessToken() : Promise<void> {
if (this.authClient.isAccessTokenExpired()) {
await this.authClient.refreshAccessToken()
}
}
async sendTweet(text: string): Promise<void> {
try {
let result = await this.agent.responseText(text);
if (!result) {
throw new Error("Processed tweet text cannot be null or empty");
}
await this.checkAndUpdateAccessToken();
console.log("result", result);
console.log("authClient", this.authClient)
await this.client.tweets.createTweet({ text: result })
} catch (error) {
console.error("Error posting tweet:", error);
}
}
}
app.get('/auth', (req, res) => {
const authUrl = twitterHandler.authClient.generateAuthURL({
state: 'state',
code_challenge_method: 'plain',
code_challenge: 'challenge',
});
res.redirect(authUrl);
});
app.get('/callback', async (req, res) => {
const code = req.query.code as string;
console.log("before", twitterHandler.authClient)
let token = await twitterHandler.authClient.requestAccessToken(code);
const userInfo = await twitterHandler.getAuthenticatedUserInfo();
console.log(token.token)
await twitterHandler.sendTweet("hello")
if (userInfo) {
res.send(`Authentication successful! User ID: ${userInfo.id}, User Name: ${userInfo.name}`);
} else {
res.status(500).send("Error fetching user info");
}
});
Expected behavior
When the twitter user call /auth
in the browser, and authorize to the application, then It will post a tweet.
Actual behavior
get error with code 403, more detail in the below
2025-01-10 15:48:00 | {"log":"before OAuth2User { token: undefined }\n","stream":"stdout","time":"2025-01-10T07:48:00.151143423Z"}
-- | --
| 2025-01-10 15:48:00 | {"log":"{\n","stream":"stdout","time":"2025-01-10T07:48:00.548233539Z"}
| 2025-01-10 15:48:00 | {"log":" token_type: 'bearer',\n","stream":"stdout","time":"2025-01-10T07:48:00.548246461Z"}
| 2025-01-10 15:48:00 | {"log":" access_token: 'QVdsT29FM*****OjE',\n","stream":"stdout","time":"2025-01-10T07:48:00.548249972Z"}
| 2025-01-10 15:48:00 | {"log":" scope: 'tweet.write users.read tweet.read offline.access',\n","stream":"stdout","time":"2025-01-10T07:48:00.548253294Z"}
| 2025-01-10 15:48:00 | {"log":" refresh_token: 'MHZTMXNvcC1NS****OnJ0OjE',\n","stream":"stdout","time":"2025-01-10T07:48:00.548256494Z"}
| 2025-01-10 15:48:00 | {"log":" expires_at: 1736502480492\n","stream":"stdout","time":"2025-01-10T07:48:00.548259962Z"}
| 2025-01-10 15:48:00 | {"log":"}\n","stream":"stdout","time":"2025-01-10T07:48:00.548262902Z"}
| 2025-01-10 15:48:02 | {"log":"result Why did *****🐔💰 \n","stream":"stdout","time":"2025-01-10T07:48:02.195043921Z"}
| 2025-01-10 15:48:02 | {"log":"\n","stream":"stdout","time":"2025-01-10T07:48:02.195083118Z"}
| 2025-01-10 15:48:02 | {"log":"But seriously, my dear influencer friend******n! 🐓🚀 \n","stream":"stdout","time":"2025-01-10T07:48:02.195087814Z"}
| 2025-01-10 15:48:02 | {"log":"\n","stream":"stdout","time":"2025-01-10T07:48:02.195091444Z"}
| 2025-01-10 15:48:02 | {"log":"For today's ******","stream":"stdout","time":"2025-01-10T07:48:02.195094169Z"}
| 2025-01-10 15:48:02 | {"log":"authClient OAuth2User {\n","stream":"stdout","time":"2025-01-10T07:48:02.19527886Z"}
| 2025-01-10 15:48:02 | {"log":" token: {\n","stream":"stdout","time":"2025-01-10T07:48:02.19528524Z"}
| 2025-01-10 15:48:02 | {"log":" token_type: 'bearer',\n","stream":"stdout","time":"2025-01-10T07:48:02.195288325Z"}
| 2025-01-10 15:48:02 | {"log":" access_token: 'QVdsT29FMk9****TowOmF0OjE',\n","stream":"stdout","time":"2025-01-10T07:48:02.195291498Z"}
| 2025-01-10 15:48:02 | {"log":" scope: 'tweet.write users.read tweet.read offline.access',\n","stream":"stdout","time":"2025-01-10T07:48:02.195295135Z"}
| 2025-01-10 15:48:02 | {"log":" refresh_token: 'MHZTMXNvcC1NSnI0****ODA0ODA6MTowOnJ0OjE',\n","stream":"stdout","time":"2025-01-10T07:48:02.195298292Z"}
| 2025-01-10 15:48:02 | {"log":" expires_at: 1736502480492\n","stream":"stdout","time":"2025-01-10T07:48:02.195301608Z"}
| 2025-01-10 15:48:02 | {"log":" }\n","stream":"stdout","time":"2025-01-10T07:48:02.195331158Z"}
| 2025-01-10 15:48:02 | {"log":"}\n","stream":"stdout","time":"2025-01-10T07:48:02.19533885Z"}
| 2025-01-10 15:48:02 | {"log":"Error posting tweet: TwitterResponseError\n","stream":"stderr","time":"2025-01-10T07:48:02.273021542Z"}
| 2025-01-10 15:48:02 | {"log":" at request (/app/node_modules/twitter-api-sdk/dist/request.js:67:15)\n","stream":"stderr","time":"2025-01-10T07:48:02.273033255Z"}
| 2025-01-10 15:48:02 | {"log":" at processTicksAndRejections (node:internal/process/task_queues:105:5)\n","stream":"stderr","time":"2025-01-10T07:48:02.273035931Z"}
| 2025-01-10 15:48:02 | {"log":" at async rest (/app/node_modules/twitter-api-sdk/dist/request.js:100:22) {\n","stream":"stderr","time":"2025-01-10T07:48:02.273038241Z"}
| 2025-01-10 15:48:02 | {"log":" status: 403,\n","stream":"stderr","time":"2025-01-10T07:48:02.273040415Z"}
| 2025-01-10 15:48:02 | {"log":" statusText: 'Forbidden',\n","stream":"stderr","time":"2025-01-10T07:48:02.273042335Z"}
| 2025-01-10 15:48:02 | {"log":" headers: {\n","stream":"stderr","time":"2025-01-10T07:48:02.273044301Z"}
| 2025-01-10 15:48:02 | {"log":" 'api-version': '2.120',\n","stream":"stderr","time":"2025-01-10T07:48:02.273046199Z"}
| 2025-01-10 15:48:02 | {"log":" 'cache-control': 'no-cache, no-store, max-age=0',\n","stream":"stderr","time":"2025-01-10T07:48:02.273048098Z"}
| 2025-01-10 15:48:02 | {"log":" 'content-disposition': 'attachment; filename=json.json',\n","stream":"stderr","time":"2025-01-10T07:48:02.273050001Z"}
| 2025-01-10 15:48:02 | {"log":" 'content-encoding': 'gzip',\n","stream":"stderr","time":"2025-01-10T07:48:02.273051938Z"}
| 2025-01-10 15:48:02 | {"log":" 'content-length': '122',\n","stream":"stderr","time":"2025-01-10T07:48:02.273053981Z"}
| 2025-01-10 15:48:02 | {"log":" 'content-type': 'application/json; charset=utf-8',\n","stream":"stderr","time":"2025-01-10T07:48:02.273055835Z"}
| 2025-01-10 15:48:02 | {"log":" date: 'Fri, 10 Jan 2025 07:48:02 UTC',\n","stream":"stderr","time":"2025-01-10T07:48:02.273057724Z"}
| 2025-01-10 15:48:02 | {"log":" perf: '7402827104',\n","stream":"stderr","time":"2025-01-10T07:48:02.273059634Z"}
| 2025-01-10 15:48:02 | {"log":" server: 'tsa_p',\n","stream":"stderr","time":"2025-01-10T07:48:02.273061819Z"}
| 2025-01-10 15:48:02 | {"log":" 'set-cookie': 'guest_id=v1%3A173649528220742917; Max-Age=34214400; Expires=Tue, 10 Feb 2026 07:48:02 GMT; Path=/; Domain=.twitter.com; Secure; SameSite=None',\n","stream":"stderr","time":"2025-01-10T07:48:02.273063748Z"}
| 2025-01-10 15:48:02 | {"log":" 'strict-transport-security': 'max-age=631138519',\n","stream":"stderr","time":"2025-01-10T07:48:02.273065837Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-access-level': 'read-write',\n","stream":"stderr","time":"2025-01-10T07:48:02.27306772Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-app-limit-24hour-limit': '17',\n","stream":"stderr","time":"2025-01-10T07:48:02.273069891Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-app-limit-24hour-remaining': '16',\n","stream":"stderr","time":"2025-01-10T07:48:02.273072615Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-app-limit-24hour-reset': '1736581682',\n","stream":"stderr","time":"2025-01-10T07:48:02.27307566Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-connection-hash': 'b9dbb429a720a831a3f3a37ffe3352ea6926a45e8eff752b7e4298ec4292afe5',\n","stream":"stderr","time":"2025-01-10T07:48:02.2730786Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-content-type-options': 'nosniff',\n","stream":"stderr","time":"2025-01-10T07:48:02.273081951Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-frame-options': 'SAMEORIGIN',\n","stream":"stderr","time":"2025-01-10T07:48:02.273085641Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-rate-limit-limit': '1080000',\n","stream":"stderr","time":"2025-01-10T07:48:02.273087799Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-rate-limit-remaining': '1079999',\n","stream":"stderr","time":"2025-01-10T07:48:02.273089615Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-rate-limit-reset': '1736496182',\n","stream":"stderr","time":"2025-01-10T07:48:02.273091455Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-response-time': '61',\n","stream":"stderr","time":"2025-01-10T07:48:02.273093328Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-transaction-id': 'b018055ffeca5a70',\n","stream":"stderr","time":"2025-01-10T07:48:02.273095182Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-user-limit-24hour-limit': '17',\n","stream":"stderr","time":"2025-01-10T07:48:02.273097111Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-user-limit-24hour-remaining': '16',\n","stream":"stderr","time":"2025-01-10T07:48:02.273098975Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-user-limit-24hour-reset': '1736581682',\n","stream":"stderr","time":"2025-01-10T07:48:02.273100845Z"}
| 2025-01-10 15:48:02 | {"log":" 'x-xss-protection': '0'\n","stream":"stderr","time":"2025-01-10T07:48:02.273102743Z"}
| 2025-01-10 15:48:02 | {"log":" },\n","stream":"stderr","time":"2025-01-10T07:48:02.273113161Z"}
| 2025-01-10 15:48:02 | {"log":" error: {\n","stream":"stderr","time":"2025-01-10T07:48:02.27311512Z"}
| 2025-01-10 15:48:02 | {"log":" detail: 'You are not permitted to perform this action.',\n","stream":"stderr","time":"2025-01-10T07:48:02.273116957Z"}
| 2025-01-10 15:48:02 | {"log":" type: 'about:blank',\n","stream":"stderr","time":"2025-01-10T07:48:02.273118855Z"}
| 2025-01-10 15:48:02 | {"log":" title: 'Forbidden',\n","stream":"stderr","time":"2025-01-10T07:48:02.273120724Z"}
| 2025-01-10 15:48:02 | {"log":" status: 403\n","stream":"stderr","time":"2025-01-10T07:48:02.273122578Z"}
| 2025-01-10 15:48:02 | {"log":" }\n","stream":"stderr","time":"2025-01-10T07:48:02.273124428Z"}
| 2025-01-10 15:48:02 | {"log":"}\n","stream":"stderr","time":"2025-01-10T07:48:02.273126205Z"}
Metadata
Metadata
Assignees
Labels
No labels
Activity