Делаю бота в телеграмм который скачивает видео с твиттера, ну ради удобства чтобы не использовать VPN.
Использую VDS нидерланды.
Поссылаю ссылку на видео она пишет ошибку: Error from Twitter API: { statusCode: 403, data: '{"errors":[{"message":"You currently have access to a subset of Twitter API v2 endpoints and limited v1.1 endpoints (e.g. media post, oauth) only. If you need access to this endpoint, you may need a different access level. You can learn more here:
https://developer.twitter.com/en/portal/product","...'
Обошёл всё, токен менял, nodejs переустановливал ничего не работает.
Вот таки сам весь исходник:
require("dotenv").config();
const Twitt = require("twitter");
const TelegramBot = require("node-telegram-bot-api");
const fs = require("fs");
//set directory name for "users.json" file
const dir = `${__dirname}/statistics`;
//create directory
if (!fs.existsSync(dir)) {
fs.mkdirSync(dir);
}
let usersList = [];
fs.writeFile(`${dir}/users.json`, JSON.stringify(usersList), error => {
if (error) throw error;
});
const isTwitterUrl = /https?:\/\/twitter.com\/[0-9-a-zA-Z_]{1,20}\/status\/([0-9]*)/;
let mediaUrl;
let msgId;
let twitt;
let btn;
//twitter API and telegram bot config
const botOpts = {
polling: true
};
const bot = new TelegramBot(process.env.TOKEN, botOpts);
const twitter = new Twitt({
consumer_key: process.env.CONSUMER_KEY,
consumer_secret: process.env.CONSUMER_SECRET,
access_token_key: process.env.ACCESS_TOKEN_KEY,
access_token_secret: process.env.ACCESS_TOKEN_SECRET
});
console.log("running bot...");
console.log(process.env.TOKEN);
//handle any message without twitter url
bot.on("message", msg => {
const chatId = msg.chat.id;
if (!isTwitterUrl.test(msg.text)) {
bot.sendMessage(
chatId,
` Hi, URL Twitter Video.`
);
}
});
//add user to users.json whene send "/start" to bot
bot.onText(/\/start/, (msg, match) => {
const id = msg.from.id;
const name = msg.from.first_name;
const username = msg.from.username;
fs.readFile(`${dir}/users.json`, (error, usersData) => {
if (error) throw error;
let users = JSON.parse(usersData);
if (users.length) {
const userFound = users.find(user => user.id == id);
if (!userFound) {
const newUser = {
id: id,
name: name,
username: username
};
addUser(newUser);
}
} else {
const newUser = {
id: id,
name: name,
username: username
};
addUser(newUser);
}
});
});
//add user to "users.json" file
function addUser(user) {
usersList.push(user);
fs.writeFile(`${dir}/users.json`, JSON.stringify(usersList), error => {
if (error) throw error;
});
}
//handle select quality with callback query
bot.on("callback_query", query => {
const data = query.data;
const chatId = query.message.chat.id;
const qmsgId = query.message.message_id;
quality = mediaUrl.filter(file => file.url.includes(data));
if (quality.length) {
let qualityBtn = [];
let btnIcon;
mediaUrl.forEach(file => {
if (
(file.url.includes("amplify_video") &&
file.url.split("/")[6] == data) ||
file.url.split("/")[7] == data
) {
btnIcon = "✅";
} else {
btnIcon = "";
}
qualityBtn.push([
{
text: `${btnIcon} Quality ${
file.url.includes("amplify_video")
? file.url.split("/")[6]
: file.url.split("/")[7]
}`,
callback_data: file.url.includes("amplify_video")
? file.url.split("/")[6]
: file.url.split("/")[7]
}
]);
});
//set caption for video message and show inline keyboard
const options = {
caption: ` ${twitt.user.name}\n ❤️ Like: ${
twitt.favorite_count
}\n Retweet: ${
twitt.retweet_count
}\n Quality: ${data}\n --- \n @kalsc12345`,
reply_to_message_id: msgId,
reply_markup: {
inline_keyboard: qualityBtn
}
};
bot.sendVideo(chatId, quality[0].url, options).then(done => {
bot.deleteMessage(chatId, qmsgId).catch(error => console.log(error.message));
}).catch(error => {
//show error for available quaity
bot.sendMessage(
chatId,
"⚠️ Error, HD NO.",
{
reply_to_message_id: msgId,
reply_markup: {
inline_keyboard: qualityBtn
}
}
).then(done => {
bot.deleteMessage(chatId, qmsgId).catch(error => console.log(error.message));
}).catch(error => console.log(error.message));
});
} else {
bot.deleteMessage(chatId, qmsgId).catch(error => console.log(error.message));
}
});
bot.onText(isTwitterUrl, (msg, match) => {
const chatId = msg.chat.id;
const twittId = match[1];
msgId = msg.message_id;
//set processing message for user
bot.sendMessage(chatId, "⏳ Progress...", { reply_to_message_id: msgId })
.then(result => {
//send require data for get video
const botMsgId = result.message_id;
getVideo(chatId, twittId, msgId, botMsgId);
});
});
//get video from twitt
function getVideo(chatId, twittId, msgId, botMsgId) {
//set extended mode for return media from request
const twittOpts = {
tweet_mode: "extended"
};
//send request to twitter
twitter.get(`statuses/show/${twittId}`, twittOpts, (error, twittData, response) => {
if (error) {
bot.sendMessage(chatId, "⚠️ Sorry, Error.")
.catch(error => console.log(error.message));
console.log("Error from Twitter API:", error);
} else {
//does tweets have video?
if (
twittData.extended_entities &&
twittData.extended_entities.media[0].type == "video"
) {
mediaUrl = twittData.extended_entities.media[0].video_info.variants.filter(
file => file.content_type == "video/mp4"
);
twitt = twittData;
btn = [];
mediaUrl.forEach(file => {
btn.push([
{
text: ` Quality ${
file.url.includes("amplify_video")
? file.url.split("/")[6]
: file.url.split("/")[7]
}`,
callback_data: file.url.includes("amplify_video")
? file.url.split("/")[6]
: file.url.split("/")[7]
}
]);
});
//edit message to "chose a quality" and show inline keyboard
bot.editMessageText("⬇️ --> HD...", {
chat_id: chatId,
message_id: botMsgId,
reply_markup: {
inline_keyboard: btn
}
}).catch(error => console.log(error.message));
} else {
bot.editMessageText(
`❌ Error, URL NO.`,
{
chat_id: chatId,
message_id: botMsgId
}
).catch(error => console.log(error.message));
}
}
}
);
}