Can you tell me what could be the error in the ban function? Error: The ID in moderator_id must match the user ID found in the request’s OAuth token.
When checking the OAuth token moderator_id is matched to the user ID found in the request.
Script:
const tmi = require(‘tmi.js’);
const axios = require(‘axios’);
const dotenv = require(‘dotenv’);
const express = require(‘express’);
const qs = require(‘qs’);
require(‘dotenv’).config();
const app = express();
const port = 3000;
// Конфигурация бота
const channels = [‘valyoko’, ‘dankzlv’, ‘vitollo_13’, ‘tadzheek’, ‘steel’, ‘ravshann’, ‘renatko’, ‘dedadam’];
const botConfigs = channels.map((channel) => {
return {
options: { debug: true },
identity: {
username: ‘valyoko’,
password: process.env.TWITCH_OAUTH_TOKEN,
},
channels: [channel]
};
});
// Создание клиентов TMI.js для каждого канала
const clients = botConfigs.map((config) => {
const client = new tmi.client(config);
client.on(‘join’, (channel, username, self) => {
if (self && channel.slice(1) === ‘valyoko’) {
console.log(Бот успешно подключился к каналу ${channel}
);
client.say(channel, ‘Бот успешно подключился’);
} else if (self) {
const valyokoClient = clients.find((c) => c.getChannels()?.[0]?.slice(1) === ‘valyoko’);
if (valyokoClient) {
valyokoClient.say(‘valyoko’, Бот подключился к каналу ${channel}
);
}
}
});
client.connect()
.catch((error) => {
console.log(Ошибка подключения к каналу ${config.channels[0]}: ${error}
);
});
return client;
});
// Настройки Twitch API
const clientId = process.env.TWITCH_CLIENT_ID;
const clientSecret = process.env.TWITCH_CLIENT_SECRET;
const redirectUri = ‘http://localhost:3000/auth/twitch/callback’;
const scopes = ‘moderator:manage:banned_users’;
const authorizationUrl = https://id.twitch.tv/oauth2/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&response_type=code&scope=${scopes}
;
// Переменные для хранения токена доступа и времени его получения
let accessToken = null;
let tokenExpiration = 0;
// Обработчик GET-запроса на страницу авторизации Twitch
app.get(‘/auth/twitch’, (req, res) => {
res.redirect(authorizationUrl);
});
// Обработчик GET-запроса на обратный вызов Twitch
app.get(‘/auth/twitch/callback’, async (req, res) => {
const code = req.query.code;
try {
// Получаем токен доступа с помощью кода авторизации
const tokenResponse = await exchangeCodeForToken(code);
accessToken = tokenResponse.access_token;
const expiresIn = tokenResponse.expires_in;
// Устанавливаем время истечения токена на будущее с учетом смещения
tokenExpiration = Date.now() + expiresIn * 1000;
console.log(`Токен доступа успешно обновлен на ${accessToken}`);
res.send('Токен доступа успешно получен. Можете закрыть это окно.');
} catch (error) {
console.log(Ошибка при получении токена доступа: ${error.response.data.message}
);
res.status(500).send(‘Произошла ошибка при получении токена доступа.’);
}
});
// Функция для обмена кода авторизации на токен доступа
async function exchangeCodeForToken(code) {
const tokenUrl = https://id.twitch.tv/oauth2/token
;
try {
const response = await axios.post(tokenUrl, null, {
params: {
client_id: clientId,
client_secret: clientSecret,
code: code,
grant_type: ‘authorization_code’,
redirect_uri: redirectUri
}
});
return response.data;
} catch (error) {
console.log(Ошибка при обмене кода авторизации на токен доступа: ${error}
);
throw error;
}
}
// Функция для проверки и обновления токена доступа
async function checkAndUpdateToken() {
// Проверяем, есть ли у нас действующий токен или он истек
if (!accessToken || tokenExpiration <= Date.now()) {
await getAccessToken();
}
}
// Функция для получения токена доступа
async function getAccessToken() {
const tokenUrl = https://id.twitch.tv/oauth2/token
;
try {
const response = await axios.post(
tokenUrl,
qs.stringify({
client_id: clientId,
client_secret: clientSecret,
grant_type: ‘client_credentials’,
scope: scopes
}),
{
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded’
}
}
);
accessToken = response.data.access_token;
const expiresIn = response.data.expires_in;
// Устанавливаем время истечения токена на будущее с учетом смещения
tokenExpiration = Date.now() + expiresIn * 1000;
console.log(`Токен доступа успешно получен и установлен на ${accessToken}`);
} catch (error) {
console.log(Ошибка при получении токена доступа: ${error.response.data.message}
);
throw error;
}
}
// Функция для выполнения бана пользователя через Twitch API
async function banUser(username, reason) {
const moderatorId = ‘90670041’;
try {
if (!moderatorId) {
console.log(Ошибка при бане пользователя: Не указан moderatorId
);
return;
}
for (let i = 0; i < clients.length; i++) {
const client = clients[i];
const channel = client.getChannels()?.[0]?.slice(1);
if (!channel) {
console.log(`Ошибка при бане пользователя: Клиент не подключен к каналу`);
continue;
}
await checkAndUpdateToken(); // Обновляем токен доступа
const clientId = process.env.TWITCH_CLIENT_ID;
const broadcasterId = process.env[`TWITCH_BROADCASTER_ID_${channel.toUpperCase()}`]; // Получаем идентификатор канала (broadcast_id)
const userId = await getUserId(username, accessToken, clientId);
if (!userId) {
console.log(`Ошибка при бане пользователя: Пользователь ${username} не найден`);
continue;
}
const url = `https://api.twitch.tv/helix/moderation/bans?broadcaster_id=${broadcasterId}&moderator_id=${moderatorId}`;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'Client-Id': clientId,
'Content-Type': 'application/json'
};
const data = {
data: {
user_id: userId,
reason: reason || 'No reason provided'
}
};
await axios.post(url, data, { headers });
// Добавляем паузу в 1 секунду между отправкой сообщений в чат разных каналов
await sleep(1000);
const valyokoClient = clients.find((c) => c.getChannels()?.[0]?.slice(1) === 'valyoko');
if (valyokoClient) {
valyokoClient.say('valyoko', `${username} был забанен на канале ${channel}. Причина: ${reason}`);
}
}
} catch (error) {
console.log(Ошибка при бане пользователя: ${error.response.data.message}
);
}
}
// Функция для выполнения разбана пользователя через Twitch API
async function unbanUser(username) {
const moderatorId = ‘90670041’;
try {
if (!moderatorId) {
console.log(Ошибка при разбане пользователя: Не указан moderatorId
);
return;
}
for (let i = 0; i < clients.length; i++) {
const client = clients[i];
const channel = client.getChannels()?.[0]?.slice(1);
if (!channel) {
console.log(`Ошибка при разбане пользователя: Клиент не подключен к каналу`);
continue;
}
await checkAndUpdateToken(); // Обновляем токен доступа
const clientId = process.env.TWITCH_CLIENT_ID;
const broadcasterId = process.env[`TWITCH_BROADCASTER_ID_${channel.toUpperCase()}`]; // Получаем идентификатор канала (broadcast_id)
const userId = await getUserId(username, accessToken, clientId);
if (!userId) {
console.log(`Ошибка при разбане пользователя: Пользователь ${username} не найден`);
continue;
}
const url = `https://api.twitch.tv/helix/moderation/bans?broadcaster_id=${broadcasterId}&user_id=${userId}&moderator_id=${moderatorId}`;
const headers = {
'Authorization': `Bearer ${accessToken}`,
'Client-Id': clientId
};
await axios.delete(url, { headers });
// Добавляем паузу в 1 секунду между отправкой сообщений в чат разных каналов
await sleep(1000);
const valyokoClient = clients.find((c) => c.getChannels()?.[0]?.slice(1) === 'valyoko');
if (valyokoClient) {
valyokoClient.say('valyoko', `${username} был разбанен на канале ${channel}`);
}
}
} catch (error) {
console.log(Ошибка при разбане пользователя: ${error.response.data.message}
);
}
}
// Функция для получения User ID пользователя или канала
async function getUserId(username, accessToken, clientId) {
try {
const response = await axios.get(https://api.twitch.tv/helix/users?login=${username}
, {
headers: {
‘Authorization’: Bearer ${accessToken}
,
‘Client-Id’: clientId
}
});
const userData = response.data.data[0];
if (!userData) {
console.log(`Пользователь ${username} не найден`);
return null;
}
const userId = userData.id;
return userId;
} catch (error) {
console.log(Ошибка при получении User ID для пользователя ${username}: ${error.response.data.message}
);
return null;
}
}
// Функция для добавления паузы
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
// Обработка сообщений чата
clients.forEach((client) => {
client.on(‘message’, (channel, userstate, message, self) => {
if (message.toLowerCase().startsWith('!ban ‘) && userstate.username.toLowerCase() === ‘valyoko’) {
const params = message.slice(5).trim().split(’ ‘);
const bannedUser = params[0];
const reason = params.slice(1).join(’ ‘);
banUser(bannedUser, reason);
} else if (message.toLowerCase().startsWith(’!unban ') && userstate.username.toLowerCase() === ‘valyoko’) {
const unbannedUser = message.slice(7).trim();
unbanUser(unbannedUser);
}
});
});
Token validation