This commit is contained in:
recaptcha 2022-08-10 13:06:23 +02:00
parent d3d221f9e3
commit e59845661f
19 changed files with 4803 additions and 4 deletions

43
.gitignore vendored Normal file
View File

@ -0,0 +1,43 @@
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
pids
*.pid
*.seed
*.pid.lock
lib-cov
coverage
*.lcov
.grunt
bower_components
.lock-wscript
build/Release
node_modules/
jspm_packages/
typings/
*.tsbuildinfo
.npm
.eslintcache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
.node_repl_history
*.tgz
.yarn-integrity
.env
.env.test
.cache
.next
.nuxt
dist
.cache/
.vuepress/dist
.serverless/
.fusebox/
.dynamodb/
.tern-port

18
commands/about.js Normal file
View File

@ -0,0 +1,18 @@
/*
* Хэндлинг команды about
*/
const errorHandler = require("../utils/error-handler");
const functions = require("../utils/functions");
const keyboards = require("../utils/keyboards");
module.exports = bot => async msg => {
try {
const opts = { //Опции (клавиатура и т.д.)
parse_mode: 'Markdown' //Форматирование текста
};
await bot.sendMessage(msg.chat.id, await functions.genAboutText(), opts);
bot.sendSticker(msg.chat.id, "CAACAgIAAxkBAAIFLmLxHZFlrrAaKxTmZdVwQkZ2L1ldAAIkBwACWiM9C1nC26Wtn2hwKQQ")
} catch (error) {
errorHandler(bot, msg.chat.id, error);
}
};

67
commands/account.js Normal file
View File

@ -0,0 +1,67 @@
/*
* Хэндлинг команды account
*/
const errorHandler = require("../utils/error-handler");
const functions = require("../utils/functions");
const api = require("../network/api");
const keyboards = require("../utils/keyboards");
const modelUser = require('../models/user');
const user = require("../models/user");
module.exports = bot => async (msg, match) => {
try {
if(msg.text.startsWith(`/profile`) || msg.text.startsWith(`/anime`)) return; //Из-за небольшого бага пришлось сделать этот фикс-костыль
let chatId = msg.chat.id;
let accountName = match.input.replace(`/account`, ``)
//let args = msg.text.split(/\s/g);
if (accountName) { //Авторизация
accountName = await functions.deleteSymbols(accountName)
accountName = accountName.substr(1)
if(accountName.length < 3) return bot.sendMessage(chatId, `🚫 Никнейм пользователя должен состоять минимум из 3 символов.`);
let userDB = await modelUser.findOne({ _id: msg.from.id })
if(accountName.includes(`https://anixart.tv/profile/`) || accountName.includes(`https://mirror.anixart.tv/profile/`)) { //Если это ссылка (1 способ)
let id = accountName
.replace(`https://anixart.tv/profile/`, ``)
.replace(`https://mirror.anixart.tv/profile/`, ``)
let userAnixart = await api.getProfileById(id);
if(!userAnixart || userAnixart == null || userAnixart.code == 2 || userAnixart.profile == null || !userAnixart.profile) { //Если ссылка неверная
let errMsg = await bot.sendMessage(chatId, `🚫 Ссылка указана неверно.\nПример команды: \`/account https://anixart.tv/profile/0\``, { parse_mode: 'Markdown' });
return functions.deleteMessage(bot, errMsg, 6)
}
if(userDB && userDB.anixartId == userAnixart.profile.id) { //Если пользователь уже в этом аккаунте
let errMsg = bot.sendMessage(chatId, `🚫 Вы уже авторизированы с того же аккаунта!`);
return functions.deleteMessage(bot, errMsg, 6)
}
return bot.sendMessage(msg.chat.id, await functions.genAuthConfirmText(userAnixart.profile), { //Подтверждение
parse_mode: 'Markdown',
reply_markup: await keyboards.authConfirm(msg.from.id, userAnixart.profile.id, userAnixart.profile.login)
}
);
} else { //Второй способ логина
let userAnixart = await api.getProfileByName(accountName)
if(!userAnixart || userAnixart == null || userAnixart.code == 2 || userAnixart.profile == null || !userAnixart.profile) { //Если неверный ник
let errMsg = await bot.sendMessage(chatId, `🚫 Аккаунт, с ником *${accountName}* не найден!\nПерепроверьте Ваш ник и попробуйте снова.\n\n\`ПРИМЕЧАНИЕ: Если Ваш ник указан правильно, то попробуйте воспользоваться авторизацией через АЙДИ.\``, { parse_mode: 'Markdown' });
return functions.deleteMessage(bot, errMsg, 6)
}
if(userDB && userDB.anixartId == userAnixart.profile.id) { //Он уже в этом аккаунте
let errMsg = bot.sendMessage(chatId, `🚫 Вы уже авторизированы с того же аккаунта!`);
return functions.deleteMessage(bot, errMsg, 6)
}
return bot.sendMessage(msg.chat.id, await functions.genAuthConfirmText(userAnixart.profile), { //Подтверждение
parse_mode: 'Markdown',
reply_markup: await keyboards.authConfirm(msg.from.id, userAnixart.profile.id, userAnixart.profile.login)
}
);
}
}
const opts = { //Опции (клавиатура и т.д.)
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.authMenu(msg.from.id)
};
return bot.sendMessage(msg.chat.id, await functions.genAuthMenuText(msg.from.id), opts); //О способах, если аргумента нет
} catch (error) {
errorHandler(bot, msg.chat.id, error);
}
};

46
commands/anime.js Normal file
View File

@ -0,0 +1,46 @@
/*
* Хэндлинг команды anime (сказать, что я заебался делать эту команду - это ничего не сказать, но ебать она ахуенная. Я текуу-у-ууууу)
*/
const errorHandler = require("../utils/error-handler");
const functions = require("../utils/functions");
const keyboards = require("../utils/keyboards");
const api = require("../network/api");
module.exports = bot => async (msg, match) => {
try {
if(msg.text.startsWith(`/profile`) || msg.text.startsWith(`/account`)) return;
//если команда
let animeName = match.input.replace(`/anime`, ``)
if(animeName) {
animeName = await functions.deleteSymbols(animeName)
animeName = animeName.substr(1)
if (animeName.length > 2) {
let search_result = await api.getAnimeByName(animeName);
if(!search_result || search_result == null || search_result.code == 2 || search_result.content.length == 0) {
return bot.sendMessage(msg.chat.id, `🚫 Аниме по такому запросу не были найдены!`);
}
let maxPage = Math.ceil(search_result.total_count/5)
let getButtonMenu = await functions.getButtonMenu(search_result, 1)
let text = `*🔎 Anixart Anime Lists*\n\n*Список аниме:*\n- По запросу: \`${animeName}\`\n- Всего аниме в списке: ${search_result.total_count}\n- Страница: 1/${maxPage}\n\n~~~~~~~~~~~~~~~~~~\n`
text += getButtonMenu.text
return bot.sendMessage(msg.chat.id, text, {
parse_mode: 'Markdown',
reply_markup: await keyboards.searchAnime(msg.from.id, maxPage, 1, getButtonMenu.animeList, animeName)
});
} else {
return bot.sendMessage(msg.chat.id, `🚫 Название должно состоять минимум из 3 символов`);
}
}
const opts = { //Опции (клавиатура и т.д.)
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.animeMenu(msg.from.id)
};
bot.sendMessage(msg.chat.id, await functions.genAnimeMenuText(), opts);
} catch (error) {
errorHandler(bot, msg.chat.id, error);
}
};

7
commands/index.js Normal file
View File

@ -0,0 +1,7 @@
//Простенький перенаправлятор
exports.start = require("./start");
exports.account = require("./account");
exports.profile = require("./profile");
exports.anime = require("./anime");
exports.about = require("./about");
//exports.search = require("./search");

41
commands/profile.js Normal file
View File

@ -0,0 +1,41 @@
/*
* Хэндлинг команды profile
*/
const errorHandler = require("../utils/error-handler");
const functions = require("../utils/functions");
const api = require("../network/api");
const keyboards = require("../utils/keyboards");
const modelUser = require('../models/user');
module.exports = bot => async (msg, match) => {
try {
if(msg.text.startsWith(`/account`) || msg.text.startsWith(`/anime`)) return; //Из-за небольшого бага пришлось сделать этот фикс-костыль
if(msg.from.is_bot) return;
let accountName = match.input.replace(`/profile`, ``)
let chatId = msg.chat.id;
let body
if(accountName) {
accountName = accountName.substr(1)
if (accountName.length < 3) return bot.sendMessage(chatId, `🚫 Никнейм пользователя должен состоять минимум из 3 символов.`);
body = await api.getProfileByName(accountName)
} else {
accountName = accountName.substr(1)
let user = await modelUser.findOne({ _id: msg.from.id })
if(!user) return bot.sendMessage(chatId, "*🚫 Вы не можете просмотреть свой профиль.*\nДля доступа к этой команде Вам нужно войти в аккаунт (требуется только Ваш *ник* или *айди*)\n\n*Используйте:* /account\n\n*Если вы не хотите авторизироваться, то можете просто посмотреть свой профиль, написав:*\n/profile \`(ваш ник на аниксарте без скобок)\`", { parse_mode: 'Markdown' })
body = await api.getProfileById(user.anixartId)
}
if (body == null || body.code == 2 || body.profile == null) return bot.sendMessage(chatId, "🚫 Профиля с таким именем не существует или его невозможно найти.");
let profile = body.profile;
const opts = { //Опции (клавиатура и т.д.)
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.profileKeyboard(msg.from.id, profile)
};
return bot.sendMessage(chatId, await functions.genProfileText(profile), opts);
} catch (error) {
errorHandler(bot, msg.chat.id, error);
}
};

18
commands/start.js Normal file
View File

@ -0,0 +1,18 @@
/*
* Хэндлинг команды start
*/
const errorHandler = require("../utils/error-handler");
const functions = require("../utils/functions");
const keyboards = require("../utils/keyboards");
module.exports = bot => async msg => {
try {
const opts = { //Опции (клавиатура и т.д.)
parse_mode: 'Markdown' //Форматирование текста
};
await bot.sendMessage(msg.chat.id, await functions.genStartText(msg.from), opts);
bot.sendSticker(msg.chat.id, "CAACAgIAAxkBAAIFF2LxHJ4PO_MJruorbcq7M57p3t5RAAIPBwACWiM9C-6cSIsHEOb3KQQ")
} catch (error) {
errorHandler(bot, msg.chat.id, error);
}
};

6
config/index.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
mongodb: {
useNewUrlParser: true,
useUnifiedTopology: true,
}
};

366
handlers/callback-query.js Normal file
View File

@ -0,0 +1,366 @@
const errorHandler = require('../utils/error-handler');
const keyboards = require('../utils/keyboards');
const functions = require('../utils/functions');
const api = require('../network/api');
const commands = require('../commands');
const modelUser = require('../models/user');
module.exports = bot => async callbackQuery => {
try {
let action = callbackQuery.data;
let msg = callbackQuery.message;
let user = callbackQuery.from;
action = action.split(";");
let userClickedId = action[0]
if (userClickedId != parseInt(user.id)) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы не являетесь отправителем сообщения', show_alert: false});
}
switch(action[1]) {
//Меню выбора истории просмотра аниме
case "userAnimeMenu":
var body = await api.getProfileById(action[2])
var profile = body.profile
if (profile.is_stats_hidden) return bot.answerCallbackQuery(callbackQuery.id, {text: 'У данного пользователя скрыта история просмотра аниме', show_alert: false});
var opts = {
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.userAnimeMenuKeyboard(user.id, profile)
};
bot.editMessageText(`*Списки аниме пользователя* \`${profile.login}\`\n\nТут вы можете просмотреть все списки аниме пользователя.\nКнопками ниже выберите интересующую Вас категорию:`, opts);
break;
//Профиль аниксарта
case "profile":
var body = await api.getProfileById(action[2])
var profile = body.profile
if (body.code == 2 || body == null) return bot.sendMessage(chatId, "Данного профиля не существует");
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.profileKeyboard(user.id, profile)
};
bot.editMessageText(await functions.genProfileText(profile), opts);
break;
//Список аниме из истории какого-то типа
case "userAnimeList":
var body = await api.getProfileById(action[5])
var profile = body.profile
var listTypeId = parseInt(action[2])
var animeWatchAndName = await functions.getAnimeWatchName(listTypeId, profile)
if (animeWatchAndName.animeCount < 1) return bot.answerCallbackQuery(callbackQuery.id, {text: 'Данная категория пуста.', show_alert: false});
var page = parseInt(action[3])
var maxPage = Math.ceil(animeWatchAndName.animeCount/5);
var sitePage = Math.floor((page-1)*5/25);
if (page < 1) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже находитесь на первой странице.', show_alert: false});
}
if (action[3] == action[4]) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы не можете этого сделать.', show_alert: false});
}
if (page > maxPage) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже на последней странице', show_alert: false});
}
var jsonAnime = await api.getUserAnimeList(action[5], action[2], sitePage);
var getButtonMenu = await functions.getButtonMenu(jsonAnime, page);
var text = `*Anixart Anime Lists*\n\n*Список аниме пользователя* \`${profile.login}\`\n- Тип: ${animeWatchAndName.listName}\n- Всего аниме в списке: ${animeWatchAndName.animeCount}\n- Страница: ${page}/${maxPage}\n\n~~~~~~~~~~~~~~~~~~\n`
text += getButtonMenu.text
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.userAnimePages(user.id, listTypeId, page, maxPage, getButtonMenu.animeList, profile)
};
bot.editMessageText(text, opts);
break;
//Просмотреть аниме у пользователя
case "userCheckAnime":
if (action[4] == "none") return bot.answerCallbackQuery(callbackQuery.id, {text: 'Это пустой слот', show_alert: false});
var body = await api.getProfileById(action[5])
var profile = body.profile
var listType = action[2];
var page = action[3];
var animeId = action[4];
var animeInfo = await api.getAnimeInfo(animeId)
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.animeCheckHistory(user.id, listType, page, animeId, profile)
};
var text = await functions.genAnimeText(animeInfo.release);
bot.editMessageText(text, opts);
break;
case "auth":
var text
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.authBack(user.id)
};
if(action[2] == "nickname") {
text = functions.genAuthNicknameText()
} else {
text = functions.genAuthIdText()
}
bot.editMessageText(text, opts);
break;
case "authMenu":
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.authMenu(user.id)
};
var text = await functions.genAuthMenuText(user.id)
bot.editMessageText(text, opts);
break;
case "authConfirm":
var anixartId = parseInt(action[2]);
var anixartLogin = action[3];
var userDB = await modelUser.findOne({ _id: user.id });
if(!userDB) {
await modelUser.firstOrCreate(user, anixartId);
} else {
await modelUser.updateOne({_id: user.id}, {$set: {anixartId : anixartId}})
await userDB.save()
}
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
};
var scfMsg = await bot.editMessageText(`*Anixart Auth Confirm*\n\n✅ Вы *успешно* авторизировались в аккаунт *${anixartLogin}*!\n\nТеперь вам доступно:\nКоманда: /profile \`- просмотр своего профиля\``, opts);
functions.deleteMessage(bot, scfMsg, 10)
break;
case "deleteMessage":
try {
bot.deleteMessage(msg.chat.id, msg.message_id)
} catch (error) {
return
}
break;
case "animeMenu":
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.animeMenu(user.id)
};
bot.editMessageText(await functions.genAnimeMenuText(), opts);
break;
case "animeList": //Листы аниме популярное и последнее
var animeType = parseInt(action[2]);
var newPage = parseInt(action[3]);
var page = parseInt(action[4]);
var maxPage = 500;
var sitePage = Math.floor((newPage-1)*5/25);
var category
switch(animeType) {
case 0:
category = "🆕 Последнее"
break;
case 1:
category = "📈 Популярное"
break;
default:
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Произошла ошибка', show_alert: false});
}
if (newPage < 1) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже находитесь на первой странице.', show_alert: false});
}
if (newPage == page) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы не можете этого сделать.', show_alert: false});
}
if (newPage > maxPage) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже на последней странице', show_alert: false});
}
var jsonAnime = await api.getAnimeList(sitePage, animeType);
var getButtonMenu = await functions.getButtonMenu(jsonAnime, newPage);
var text = `*Anixart Anime Lists*\n\n*Список аниме*\n- Тип: ${category}\n- Всего аниме в списке: 2500\n- Страница: ${newPage}/${maxPage}\n\n~~~~~~~~~~~~~~~~~~\n`
text += getButtonMenu.text
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'markdown', //Форматирование текста
reply_markup: await keyboards.animePages(user.id, animeType, maxPage, newPage, getButtonMenu.animeList)
};
bot.editMessageText(text, opts);
break;
case "checkAnime": //Посмотреть аниме в /anime
if (action[4] == "none") return bot.answerCallbackQuery(callbackQuery.id, {text: 'Это пустой слот', show_alert: false});
var animeType = action[2];
var page = action[3];
var animeId = parseInt(action[4]);
var animeInfo = await api.getAnimeInfo(animeId)
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.animeCheck(user.id, animeType, page, animeId)
};
var text = await functions.genAnimeText(animeInfo.release);
bot.editMessageText(text, opts);
break;
case "animeRandom":
var animeInfo = await api.getRandomAnime()
if(animeInfo == null || !animeInfo || animeInfo.code == 2 || !animeInfo.release) return bot.answerCallbackQuery(callbackQuery.id, {text: 'Произошла ошибка', show_alert: false});
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.animeRandom(user.id, animeInfo.release.id)
};
var text = await functions.genAnimeText(animeInfo.release);
bot.editMessageText(text, opts);
break;
case "interesting":
var newPage = parseInt(action[2])
var page = parseInt(action[3])
var jsonAnime = await api.getInterestingAnime()
var maxPage = parseInt(jsonAnime.content.length)
if (jsonAnime == null || !jsonAnime || jsonAnime.code == 2 || !jsonAnime.content) return bot.answerCallbackQuery(callbackQuery.id, {text: 'Произошла ошибка', show_alert: false});
if (newPage < 1) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже находитесь на первой странице.', show_alert: false});
}
if (newPage == page) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы не можете этого сделать.', show_alert: false});
}
if (newPage > maxPage) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже на последней странице', show_alert: false});
}
var text = `*• ${jsonAnime.content[newPage-1].title}*\n${jsonAnime.content[newPage-1].description}\n\n• Аниме: *${newPage}/${maxPage}*\n\`Постер: \`${jsonAnime.content[newPage-1].image}`
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.interestingPages(user.id, newPage, maxPage, parseInt(jsonAnime.content[newPage-1].action))
};
bot.editMessageText(text, opts);
break;
case "checkInteresting":
var newPage = parseInt(action[2]);
var animeId = parseInt(action[3]);
var animeInfo = await api.getAnimeInfo(animeId);
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.checkInterestingAnime(user.id, animeId, newPage)
};
var text = await functions.genAnimeText(animeInfo.release);
bot.editMessageText(text, opts);
break;
case "searchAnimeMenu":
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.searchAnimeMenu(user.id)
};
var text = await functions.searchAnimeMenu();
bot.editMessageText(text, opts);
break;
case "searchAnime":
var newPage = parseInt(action[2])
var page = parseInt(action[3])
var animeName = action[4]
var jsonAnime = await api.getAnimeByName(animeName)
var maxPage = parseInt(Math.ceil(jsonAnime.total_count/5))
if (jsonAnime == null || !jsonAnime || jsonAnime.code == 2 || !jsonAnime.content) return bot.answerCallbackQuery(callbackQuery.id, {text: 'Произошла ошибка', show_alert: false});
if (newPage < 1) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже находитесь на первой странице.', show_alert: false});
}
if (newPage == page) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы не можете этого сделать.', show_alert: false});
}
if (newPage > maxPage) {
return bot.answerCallbackQuery(callbackQuery.id, {text: 'Вы уже на последней странице', show_alert: false});
}
var getButtonMenu = await functions.getButtonMenu(jsonAnime, newPage)
var text = `*🔎 Anixart Anime Lists*\n\n*Список аниме:*\n- По запросу: \`${animeName}\`\n- Всего аниме в списке: ${jsonAnime.total_count}\n- Страница: ${newPage}/${maxPage}\n\n~~~~~~~~~~~~~~~~~~\n`
text += getButtonMenu.text
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'markdown', //Форматирование текста
reply_markup: await keyboards.searchAnime(user.id, maxPage, newPage, getButtonMenu.animeList, animeName)
};
bot.editMessageText(text, opts);
break;
case "searchResult":
if (action[4] == "none") return bot.answerCallbackQuery(callbackQuery.id, {text: 'Это пустой слот', show_alert: false});
var newPage = parseInt(action[2]);
var animeName = action[3];
var animeId = parseInt(action[4]);
var jsonAnime = await api.getAnimeInfo(animeId);
var opts = { //Опции (клавиатура и т.д.)
chat_id: msg.chat.id,
message_id: msg.message_id,
parse_mode: 'Markdown', //Форматирование текста
reply_markup: await keyboards.searchAnimeBack(user.id, newPage, animeName, animeId)
};
var text = await functions.genAnimeText(jsonAnime.release);
bot.editMessageText(text, opts);
break;
default:
return;
}
} catch (error) {
errorHandler(bot, callbackQuery.message.chat.id, error)
}
};

3
handlers/index.js Normal file
View File

@ -0,0 +1,3 @@
// Перенаправление
exports.botError = require("./polling-error");
exports.callbackQuery = require("./callback-query");

View File

@ -0,0 +1,7 @@
/*
* Хэндлек ошибок
*/
module.exports = error => {
if (error.code && error.code !== "EFATAL") console.error(error.response.body);
else console.error(error);
};

41
index.js Normal file
View File

@ -0,0 +1,41 @@
const TelegramBot = require('node-telegram-bot-api');
require("dotenv").config();
const env = process.env;
const mongoose = require('mongoose');
const handlers = require("./handlers");
const commands = require("./commands");
const config = require('./config');
const modelUser = require('./models/user');
const api = require('./network/api');
const bot = new TelegramBot(env.TOKEN, {polling: true});
mongoose
.connect(env.MONGODB_URI, config.mongodb)
.then(() => {
// Commands
bot.onText(/\/start$/i, commands.start(bot));
bot.onText(/\/account/i, commands.account(bot));
bot.onText(/\/profile/i, commands.profile(bot));
bot.onText(/\/anime/i, commands.anime(bot));
bot.onText(/\/about$/i, commands.about(bot));
// Handlers
bot.on("callback_query", handlers.callbackQuery(bot));
bot.on("polling_error", handlers.botError);
bot.on("error", handlers.botError);
//Successful connection
console.log("[Anixart Info] >> Bot was started.")
})
.catch(error => console.error(error));
// bot.onText('test', async (msg) => {
// const chatId = msg.chat.id;
// let animeList = await api.getProfileByName("ice cream")
// console.log(animeList)
// // send a message to the chat acknowledging receipt of their message
// bot.sendMessage(chatId, `a`);
// });

31
models/user.js Normal file
View File

@ -0,0 +1,31 @@
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const UserSchema = new Schema(
{
_id: {
type: Number,
required: true,
},
anixartId: {
type: Number,
required: true,
}
},
{ versionKey: false }
);
// Возвращает пользователя и создаёт его, если нет
UserSchema.statics.firstOrCreate = async function(tgUser, anixartId) {
let user = await this.findById(tgUser.id);
if (!user && !tgUser.is_bot) {
user = await new this({
_id: tgUser.id,
anixartId: anixartId
}).save();
}
return user;
};
module.exports = mongoose.model("users", UserSchema);

153
network/api.js Normal file
View File

@ -0,0 +1,153 @@
const fetch = require('node-fetch'); // Либа для запросов
exports.getProfileById = async (id) => { // Запрос на получение профиля по айди
try {
const response = await fetch('https://api.anixart.tv/profile/' + id + '?token=TOKEN')
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getProfileByName = async (name) => { // Запрос на получение профиля по имени
let todo = {
query: name,
searchBy: 0
}
try {
const response = await fetch('https://api.anixart.tv/search/profiles/0?token=TOKEN', {
method: 'POST',
body: JSON.stringify(todo),
headers: { 'Content-Type': 'application/json' }
})
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
let profile = null
if (body.total_count < 26) {
for(let i = 0; i < body.content.length; i++) {
let profileLogin = body.content[i].login
if(name.toLowerCase() == profileLogin.toLowerCase()) {
profile = exports.getProfileById(body.content[i].id)
break;
}
}
return profile
} else {
for(let i = 0; i < Math.ceil(body.total_count/25); i++) { //Поиск аккаунта на других страницах
let responseMore = await fetch('https://api.anixart.tv/search/profiles/' + i + '?token=TOKEN', {
method: 'POST',
body: JSON.stringify(todo),
headers: { 'Content-Type': 'application/json' }
})
if (responseMore.status !== 200) throw new Error()
let bodyMore = JSON.parse(await responseMore.text())
for(let a = 0; a < bodyMore.content.length; a++) { //поиск на этой странице
let profileLogin = bodyMore.content[a].login
if(profileLogin && name.toLowerCase() == profileLogin.toLowerCase()) {
profile = exports.getProfileById(bodyMore.content[a].id)
break;
}
}
}
return profile
}
} catch (error) {
console.log(error);
return null;
}
}
exports.getUserAnimeList = async (id, listType, page) => { // Запрос на получение списка (просмотренные, в планах и т.д.)
try {
const response = await fetch('https://api.anixart.tv/profile/list/all/' + id + "/" + listType + "/" + page + '?token=TOKEN')
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getAnimeInfo = async (id) => { // Запрос на получение инфы об аниме
try {
const response = await fetch('https://api.anixart.tv/release/' + id + '?token=TOKEN')
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getAnimeList = async (page, type) => { // Запрос на получение листа аниме по жанрам (тут новое, интересное)
let todo = {
sort: parseInt(type),
extended_mode: true
}
try {
const response = await fetch('https://api.anixart.tv/filter/'+ page +'?token=TOKEN', {
method: 'POST',
body: JSON.stringify(todo),
headers: { 'Content-Type': 'application/json' }
})
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getRandomAnime = async () => { // Случайное аниме
try {
const response = await fetch('https://api.anixart.tv/release/random?token=TOKEN')
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getInterestingAnime = async () => { // Интересное
try {
const response = await fetch('https://api.anixart.tv/discover/interesting?token=TOKEN')
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}
exports.getAnimeByName = async (text) => { // Аниме по названию
let todo = {
query: text,
searchBy: 0
}
try {
const response = await fetch('https://api.anixart.tv/search/releases/0?token=TOKEN', {
method: 'POST',
body: JSON.stringify(todo),
headers: { 'Content-Type': 'application/json' }
})
if (response.status !== 200) throw new Error()
let body = JSON.parse(await response.text())
return body
} catch (error) {
console.log(error);
return null;
}
}

3082
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,13 @@
"type": "git",
"url": "https://git.anidev.ru/project/recaptcha/anixart-tg-bot.git"
},
"author": "",
"license": "ISC"
"author": "reCAPTCHA",
"license": "ISC",
"dependencies": {
"dotenv": "^16.0.1",
"mongoose": "^6.5.1",
"node-fetch": "^2.6.7",
"node-telegram-bot-api": "^0.58.0",
"nodemon": "^2.0.19"
}
}

7
utils/error-handler.js Normal file
View File

@ -0,0 +1,7 @@
/*
* Хэндлер ошибок бота
*/
module.exports = (bot, chatId, error) => {
console.error(error);
bot.sendMessage(chatId, "Непредвиденная ошибка.");
};

339
utils/functions.js Normal file
View File

@ -0,0 +1,339 @@
const api = require("../network/api");
const modelUser = require('../models/user');
exports.getHistoryText = async (history) => { // Функция, генерирующая текст истории просмотров последних 5 аниме
let text = ``
if (history.length == 0) {
text = "отсутствует";
return text;
}
text += `\n`
for (let i = 0; i < history.length; i++) {
text += ` \`${history[i].title_ru}${history[i].last_view_episode.name}\`\n`; // {name}, {last view episode}
}
return text;
}
exports.genProfileText = async (profile) => { // Функция, генерирующая всю информацию профиля пользователя
let roles = ``
if(profile.roles.length != 0) { // Если человек имеет роли (Модератор, Администратор, Даббер) кидаем всё в переменную
for (let i = 0; i < profile.roles.length; i++) {
roles += profile.roles[i].name + `${i == profile.roles.length-1 ? `` : `, `}`
}
}
let text = `*Anixart Profile Info*\n\n` +
`*Никнейм:* ${profile.is_sponsor ? `👑 ` : ``}${profile.login}${profile.is_verified ? ` ✔️` : ``} [[${profile.rating_score}]]\n` +
`*Описание:* \`${profile.status == "" ? "Отсутствует" : profile.status}\`\n` +
`*Статус:* _${profile.is_online ? "онлайн" : "оффлайн"}_\n` +
`${profile.roles.length != 0 ? `*Роли*: ${roles}\n\n` : `\n`}` +
`${profile.is_counts_hidden ? `` : `*Комментов:* ${profile.comment_count} | *Видео*: ${profile.video_count}\n*Коллекций:* ${profile.collection_count} | *Друзей:* ${profile.friend_count}\n\n`}` +
`*Приватность:* \n • Статистика ${profile.is_stats_hidden ? "_скрыта_" : "_открыта_"}\n • Активность ${profile.is_counts_hidden ? "_скрыта_" : "_открыта_"}\n\n` +
`${profile.is_stats_hidden ? `` : `*🟩 Смотрю:* ${profile.watching_count}`}\n` +
`${profile.is_stats_hidden ? `` : `*🟪 В планах:* ${profile.plan_count}`}\n` +
`${profile.is_stats_hidden ? `` : `*🟦 Просмотрено:* ${profile.completed_count}`}\n` +
`${profile.is_stats_hidden ? `` : `*🟨 Отложено:* ${profile.hold_on_count}`}\n` +
`${profile.is_stats_hidden ? `` : `*🟥 Брошено:* ${profile.dropped_count}`}\n\n`+
`${profile.is_stats_hidden ? `` : `*Просмотрено недавно:* ` + await exports.getHistoryText(profile.history)}\n\n`
return text
}
exports.genAnimeText = async (anime) => { // Функция, генерирующая всю информацию об аниме
let image = anime.image //Просто постер
let countrySmile = exports.getCountrySmile(anime.country); //Смайлик страны (Китай, Япония)
let date //Дата
if (anime.release_date) date = exports.getMounthYear(anime.release_date); //Месяц выпуска аниме (Осень, Зима)
let episodes = anime.episodes_total == anime.episodes_released
? `${anime.episodes_total ? anime.episodes_total : `?`} эп.`
: `${anime.episodes_released ? anime.episodes_released : `?`} из ${anime.episodes_total ? anime.episodes_total : `?`} эп.` //Кол-во эпизодов
if (anime.duration) episodes += ` по ~${anime.duration} мин.` //Текст длительности
let studio = `` //Студия, авторы
anime.studio ? studio += `Студия \`${anime.studio}\`` : studio += ``; //Если есть студия, добавляем её
anime.author ? studio == `` ? studio += `Автор \`${anime.author}\`` : studio += `, автор \`${anime.author}\`,` : studio += `` //Если есть автор, то добавляем его
anime.director ? studio += ` режиссёр \`${anime.director}\`` : studio += `` //Добавляем режиссёра при наличии его
let rating = `⭐️ Рейтинг: *${(anime.grade).toFixed(1)}* • \`${anime.vote_count} ${exports.declension(anime.vote_count, ["голос", "голоса", "голосов"])}\`\n`;
let text =
`*${anime.title_ru}*\n` +
`${countrySmile} ${anime.country}${date == null ? "" : `, ${date}`}${anime.year ? `, ${anime.year} г.` : ``}\n` +
`📺 ${episodes}\n` +
`📅 ${anime.category.name}, ${(anime.status.name).toLowerCase()}\n` +
`${studio ? `👥 ${studio}\n\n` : `\n`}` +
`*• Жанры:* ${anime.genres}\n\n` +
`\`${anime.description ? anime.description : `Описание не указано`}\`\n\n` +
`${anime.note ? `*${exports.removeTags(anime.note)}*\n\n` : ``}` +
`${anime.status.id == 3 ? `` : rating}` + //Рейтинг + склонения
`🔸 Избранное: *${anime.favorites_count}*\n\n` +
`\`- Постер: \`${image}`
return text
}
exports.getNumberEmoji = number => { //Любое число в смайлики
number = number.toString();
return number
.replace(/0/g, '0⃣')
.replace(/1/g, '1⃣')
.replace(/2/g, '2⃣')
.replace(/3/g, '3⃣')
.replace(/4/g, '4⃣')
.replace(/5/g, '5⃣')
.replace(/6/g, '6⃣')
.replace(/7/g, '7⃣')
.replace(/8/g, '8⃣')
.replace(/9/g, '9⃣');
};
exports.declension = (number, words) => { //Склонения
return words[(number % 100 > 4 && number % 100 < 20) ? 2 : [2, 0, 1, 1, 1, 2][(number % 10 < 5) ? Math.abs(number) % 10 : 5]];
}
exports.getCountrySmile = country => { //Смайлик в зависимости от страны
let countrySmile
switch(country) {
case "Япония":
countrySmile = "🇯🇵"
break;
case "Китай":
countrySmile = "🇨🇳"
break;
default:
countrySmile = "🏳️"
break;
}
return countrySmile;
}
exports.getMounthYear = number => { //Получить месяц. moment.js огромная либа, проще не нагружать и сделать так
let mounth
let date = number.split(".")
switch (parseInt(date[1])) {
case 1:
case 2:
case 12:
mounth = "зима"
break;
case 3:
case 4:
case 5:
mounth = "весна"
break;
case 6:
case 7:
case 8:
mounth = "лето"
break;
case 9:
case 10:
case 11:
mounth = "осень"
break;
default:
mounth = "неизвестно"
break;
}
return mounth;
};
exports.getAnimeWatchName = (listTypeId, profile) => { //Получаем название и кол-во аниме
let animeCount, listName
switch (listTypeId) {
case 1:
animeCount = profile.watching_count; listName = "🟩 Смотрю"
break;
case 2:
animeCount = profile.plan_count; listName = "🟪 В планах"
break;
case 3:
animeCount = profile.completed_count; listName = "🟦 Просмотрено"
break;
case 4:
animeCount = profile.hold_on_count; listName = "🟨 Отложено"
break;
case 5:
animeCount = profile.dropped_count; listName = "🟥 Брошено"
break;
default:
animeCount = 0; listName = "Неизвестно"
}
return {animeCount: animeCount, listName: listName}
}
exports.removeTags = html => {
let text = html.replace(`<br>`, `\n`)
return text.replace(/<(?:.|\n)*?>/gm, ' ');
}
exports.genAuthMenuText = async (id) => {
let user = await modelUser.findOne({ _id: id })
let profile
if(user) profile = await api.getProfileById(user.anixartId);
let text =
`*Anixart Auth*\n\nДля того, чтобы просматривать свой профиль в *Anixart Info*,\n` +
`Вам требуется авторизироваться.\n\n` +
`Существует \`два способа\` авторизации:\n` +
`1⃣ - С помощью вашего ника в *Anixart*\n` +
`2⃣ - с помощью вашего *ID*\n\n` +
`Выберите понравившийся способ, чтобы получить больше информации:\n\n` +
`${user ? `*В данный момент вы уже *\`авторизированы\` *под логином* *${profile.profile.login}*` : ``}`
return text
}
exports.genAuthNicknameText = () => {
let text =
`*Anixart Nickname Auth*\n\n` +
`❓ Авторизация с помощью \`никнейма\`:\n` +
`Для того, чтобы авторизироваться, используя свой никнейм из *Anixart*, Вам требуется:\n` +
`1⃣ Прописать команду:\n/account *ваш_ник*`
return text
}
exports.genAuthIdText = () => {
let text =
`*Anixart Id Auth*\n\n` +
`❓ Авторизация с помощью \`айди\`:\n` +
`Для того, чтобы авторизироваться, используя свой \`айди\` из *Anixart*, Вам требуется:\n\n` +
`1⃣ Зайти в профиль аниксарта\n` +
`2⃣ Найти и зажать своё имя на пару секунд, после чего\n` +
`у Вас скопируется ссылка на Ваш профиль (см. скриншот)\n` +
`3⃣ Прописать команду /account *ссылкаа_профиль*\n\n` +
`\`- Скриншот: \`https://imgur.com/a/PzKq6sq`
return text
}
exports.genAuthConfirmText = async (user) => {
let text =
`*Anixart Confirm*\n\n` +
`Пользователь: \`${user.login}\`\n` +
`Описание: \`${user.status == "" ? "Отсутствует" : user.status}\`\n\n` +
`• Вы подтвержаете, что это Вы?\n\n` +
`\`ПРИМЕЧАНИЕ: Вы в любую секунду сможете сменить профиль, если ошиблись.\``
return text
}
exports.deleteMessage = (bot, message, time) => {
setTimeout(() => {
try {
bot.deleteMessage(message.chat.id, message.message_id);
} catch (error) {
return
}
}, time * 1000);
}
exports.genStartText = async (user) => {
let text =
`*Anixart Start*\n\n` +
`Приветствую, @${user.username}!\n` +
`Перед началом работы с ботом вам требуется \`авторизироваться\`, используя команду /account\n\n` +
`❓ Доступные команды в боте:\n` +
`/start - \`первоначальная настройка и информация\`\n` +
`/account - \`авторизация в боте\`\n` +
`/profile - \`просмотр своего профиля (требуется авторизация)\`\n` +
`/profile (ник пользователя) - \`просмотр профиля человека по нику (вся приватная информация скрыта)\`\n` +
`/anime - \`просмотр новых, популярных, случайных тайтлов\`\n` +
`/about - \`информация о командах, о разработчике и о самом боте\`\n\n` +
`*ПРИМЕЧАНИЕ: авторизация работает через ваш НИК или АЙДИ на Anixart.*\n` +
`*Бот не требует от Вас ваших личных данных.*\n\n` +
`*В данный момент бот работает для узкого количества лиц.*\n` +
`*Разработчик не одобряет подобную деятельность, а потому это вынужденная мера.*\n` +
`*Приносим извинения ~*`
return text
}
exports.genAboutText = async () => {
let text =
`*Anixart About*\n\n` +
`❓ Доступные команды в боте:\n` +
`/start - \`первоначальная настройка и информация\`\n` +
`/account - \`авторизация в боте\`\n` +
`/profile - \`просмотр своего профиля (требуется авторизация)\`\n` +
`/profile (ник пользователя) - \`просмотр профиля человека по нику (вся приватная информация скрыта)\`\n` +
`/anime - \`просмотр новых, популярных, случайных тайтлов\`\n` +
`/about - \`информация о командах, о разработчике и о самом боте\`\n\n` +
`О самом боте:\n` +
`Данный бот является не официальным и некоммерческим продуктом.\n` +
`Бот работает с *не публичным* API \`Anixart'a\`, что противоречит принципам создателя \`Anixarta'a\`.\n` +
`Накрутка, спам, регистрация новых аккаунтов и всё подобное через данного бота невозможна.\n` +
`Бот позволяет лишь показать открытую в профилях информацию, не запуская приложения.\n\n` +
`О создателе:\n` +
`Привет! Я @reCAPTCHAs, создатель этого бота.\n` +
`Если Вы нашли баг, у вас появилось предложение или желание что-то изменить в боте, то cмело пишите в тг.\n` +
`Я буду добавлять *новый функционал*, изменять существующий и изменять дизайн интерфейса с течением времени.\n` +
`*Моя цель*: добиться того, чтобы бота начал поддерживать разработчик \`Anixart'a\`, посему я постараюсь сделать всё возможное, чтобы это произошло.\n\n` +
`*Все права принадлежат Anixart.*`
return text
}
exports.genAnimeMenuText = async () => {
let text =
`📺 Anixart Anime\n\n` +
`Тут вы можете посмотреть аниме из категорий:\n` +
`🆕 • Последнее\n` +
`📈 • Популярное\n` +
// `📣 • Анонсы (В разработке)\n` +
`🔥 • Интересное\n` +
`❓ • Случайное\n` +
`🔎 • По названию\n\n` +
`Кнопками ниже выберите интересующую Вас категорию:`
return text
}
exports.getButtonMenu = async (jsonAnime, page) => {
let text = ``
let animeList = []
//Цикл, который получает 5 аниме для списка из 25 полученных в зависимости от страницы в тг и страницы в api. В рот ебал такую залупу
for (let i = (page-1)*5; i < page*5; i++) { // 5 < 10; 10 < 15 и т.д.
let animeByCount = i > 24 ? i - Math.floor(i/25)*25 : i //Если число больше 25, то отнимает столько, сколько ненужно (костыль ебучий, похуй)
if (jsonAnime.content[animeByCount]) {
text +=
`${exports.getNumberEmoji(i+1)}. *${jsonAnime.content[animeByCount].title_ru}*\n` +
`${jsonAnime.content[animeByCount].status ? `\`- Статус: ${jsonAnime.content[animeByCount].status.name}\`\n` : ``}` +
`\`- ${jsonAnime.content[animeByCount].genres}\`\n\n` // Добавляем в текст
animeList.push({ // Пушим номер аниме по счёту и его айди в аниксарте
count: i+1,
id: jsonAnime.content[animeByCount].id
})
}
}
return {text: text, animeList: animeList}
}
exports.deleteSymbols = async (text) => {
return text
.replace(/_/gi, "")
.replace(/;/gi, "")
.replace(/\*/gi, "")
.replace(/`/gi, "")
.replace(/,/gi, "")
}
exports.searchAnimeMenu = async () => {
let text =
`🔎 Anixart Search\n\n` +
`❓Вы можете найти интересующее Вас аниме по названию.\n` +
`Для этого введите:\n\n` +
`/anime \`(название тайтла без скобок)\`,\n\n` +
`после чего вы должны выбрать нужное аниме.`
return text
}

521
utils/keyboards.js Normal file
View File

@ -0,0 +1,521 @@
const functions = require('../utils/functions');
const modelUser = require('../models/user');
exports.profileKeyboard = async (fromId, profile) => { // /profile
let keyboard = {
inline_keyboard: [
[
{
text: `🔶 Открыть профиль в Anixart`,
url: `https://anixart.tv/profile/${profile.id}`
}
],
[
{
text: '📺 Аниме в закладках',
callback_data: `${fromId};userAnimeMenu;${profile.id}`
}
]
]
}
let user = await modelUser.findOne({ _id: fromId })
if (user && user.anixartId != profile.id) {
keyboard.inline_keyboard.push([{
text: '↩️ Назад к своему профилю',
callback_data: `${fromId};profile;${user.anixartId}`
}])
}
return keyboard
};
exports.userAnimeMenuKeyboard = async (fromId, profile) => { //Меню аниме в /profile
let keyboard = {
inline_keyboard: [
[
{
text: `🟩 Смотрю: ${profile.watching_count}`,
callback_data: `${fromId};userAnimeList;1;1;0;${profile.id}` // {user id}, {callback command}, {list type}, {new page}, {this page}, {anixart id}
},
{
text: `🟪 В планах: ${profile.plan_count}`,
callback_data: `${fromId};userAnimeList;2;1;0;${profile.id}`
}
],
[
{
text: `🟦 Просмотрено: ${profile.completed_count}`,
callback_data: `${fromId};userAnimeList;3;1;0;${profile.id}`
}
],
[
{
text: `🟨 Отложено: ${profile.hold_on_count}`,
callback_data: `${fromId};userAnimeList;4;1;0;${profile.id}`
},
{
text: `🟥 Брошено: ${profile.dropped_count}`,
callback_data: `${fromId};userAnimeList;5;1;0;${profile.id}`
}
],
[
{
text: '⬅️ Назад к профилю',
callback_data: `${fromId};profile;${profile.id}`
}
]
]
}
return keyboard
};
exports.userAnimePages = async (fromId, listType, page, maxPage, animeList, profile) => { //Страницы аниме в /profile
let keyboard = {
inline_keyboard: [
[
{
text: `${animeList[0] ? functions.getNumberEmoji(animeList[0].count) : ``}`,
callback_data: `${fromId};userCheckAnime;${listType};${page};${animeList[0] ? animeList[0].id : "none"};${profile.id}` // {user id}, {callback command}, {list type}, {page}
},
{
text: `${animeList[1] ? functions.getNumberEmoji(animeList[1].count) : ``}`,
callback_data: `${fromId};userCheckAnime;${listType};${page};${animeList[1] ? animeList[1].id : "none"};${profile.id}`
},
{
text: `${animeList[2] ? functions.getNumberEmoji(animeList[2].count) : ``}`,
callback_data: `${fromId};userCheckAnime;${listType};${page};${animeList[2] ? animeList[2].id : "none"};${profile.id}`
},
{
text: `${animeList[3] ? functions.getNumberEmoji(animeList[3].count) : ``}`,
callback_data: `${fromId};userCheckAnime;${listType};${page};${animeList[3] ? animeList[3].id : "none"};${profile.id}`
},
{
text: `${animeList[4] ? functions.getNumberEmoji(animeList[4].count) : ``}`,
callback_data: `${fromId};userCheckAnime;${listType};${page};${animeList[4] ? animeList[4].id : "none"};${profile.id}`
}
],
[
{
text: ``,
callback_data: `${fromId};userAnimeList;${listType};1;${page};${profile.id}`
},
{
text: `◀️`,
callback_data: `${fromId};userAnimeList;${listType};${page-1};${page};${profile.id}`
},
{
text: `▶️`,
callback_data: `${fromId};userAnimeList;${listType};${page+1};${page};${profile.id}`
},
{
text: ``,
callback_data: `${fromId};userAnimeList;${listType};${maxPage};${page};${profile.id}`
}
],
[
{
text: `🔙 Назад к категориям`,
callback_data: `${fromId};userAnimeMenu;${profile.id}`
},
{
text: `↩️ Назад к профилю`,
callback_data: `${fromId};profile;${profile.id}`
}
]
]
}
return keyboard
};
exports.animeCheckHistory = async (fromId, listType, page, animeId, profile) => { //Посмотреть аниме в /profile
let keyboard = {
inline_keyboard: [
[
{
text: `⏸ Открыть аниме в Anixart`,
url: `https://anixart.tv/release/${animeId}`
}
],
[
{
text: `⬅️ Назад к списку`,
callback_data: `${fromId};userAnimeList;${listType};${page};0;${profile.id}` // {user id}, {callback command}, {list type}, {page}, {anixart.id}
}
],
[
{
text: `🔙 Назад к категориям`,
callback_data: `${fromId};userAnimeMenu;${profile.id}`
}
],
[
{
text: `↩️ Назад к профилю`,
callback_data: `${fromId};profile;${profile.id}`
}
]
]
}
return keyboard
};
exports.authMenu = async (fromId) => { // /account
let keyboard = {
inline_keyboard: [
[
{
text: `1⃣ Ник`,
callback_data: `${fromId};auth;nickname`
},
{
text: `2⃣ Айди`,
callback_data: `${fromId};auth;id`
}
]
]
}
return keyboard
};
exports.authBack = async (fromId) => { //Кнопки в /account (назад)
let keyboard = {
inline_keyboard: [
[
{
text: `🔙 Назад к выбору`,
callback_data: `${fromId};authMenu`
}
]
]
}
return keyboard
}
exports.authConfirm = async (fromId, anixartId, anixartLogin) => { //Подтверждение авторизации
let keyboard = {
inline_keyboard: [
[
{
text: `✅ Подтвердить`,
callback_data: `${fromId};authConfirm;${anixartId};${anixartLogin}`
}
],
[
{
text: `❌ Отклонить`,
callback_data: `${fromId};deleteMessage`
}
]
]
}
return keyboard
}
exports.animeMenu = async (fromId) => { // /anime
let keyboard = {
inline_keyboard: [
[
{
text: `🆕 Последнее`,
callback_data: `${fromId};animeList;0;1;0` //{user id}, {callback command}, {anime type}, {newpage}, {page}
},
{
text: `📈 Популярное`,
callback_data: `${fromId};animeList;1;1;0`
}
],
[
{
text: `🔥 Интересное`,
callback_data: `${fromId};interesting;1;0`
},
{
text: `❓ Случайное аниме`,
callback_data: `${fromId};animeRandom`
}
],
[
{
text: `🔎 Поиск аниме`,
callback_data: `${fromId};searchAnimeMenu`
}
]
]
}
return keyboard
}
exports.animeCheck = async (fromId, animeType, page, animeId) => { //Инфа об аниме в команде /anime
let keyboard = {
inline_keyboard: [
[
{
text: `⏸ Открыть аниме в Anixart`,
url: `https://anixart.tv/release/${animeId}`
}
],
[
{
text: `⬅️ Назад к списку`,
callback_data: `${fromId};animeList;${animeType};${page};0;` //{user id}, {callback command}, {anime type}, {newpage}, {page}
}
],
[
{
text: `🔙 Назад к меню аниме`,
callback_data: `${fromId};animeMenu`
}
]
]
}
return keyboard
};
exports.animeRandom = async (fromId, animeId) => { //Случайное аниме
let keyboard = {
inline_keyboard: [
[
{
text: `⏸ Открыть аниме в Anixart`,
url: `https://anixart.tv/release/${animeId}`
}
],
[
{
text: `🔙 Назад к категориям`,
callback_data: `${fromId};animeMenu`
}
],
[
{
text: `❓ Найти другое случайное`,
callback_data: `${fromId};animeRandom`
}
]
]
}
return keyboard
};
exports.animePages = async (fromId, animeType, maxPage, page, animeList) => { //Страницы в популярном, интересном
let keyboard = {
inline_keyboard: [
[
{
text: `${animeList[0] ? functions.getNumberEmoji(animeList[0].count) : ``}`,
callback_data: `${fromId};checkAnime;${animeType};${page};${animeList[0] ? animeList[0].id : "none"}` // {user id}, {callback command}, {list type}, {page}
},
{
text: `${animeList[1] ? functions.getNumberEmoji(animeList[1].count) : ``}`,
callback_data: `${fromId};checkAnime;${animeType};${page};${animeList[1] ? animeList[1].id : "none"}`
},
{
text: `${animeList[2] ? functions.getNumberEmoji(animeList[2].count) : ``}`,
callback_data: `${fromId};checkAnime;${animeType};${page};${animeList[2] ? animeList[2].id : "none"}`
},
{
text: `${animeList[3] ? functions.getNumberEmoji(animeList[3].count) : ``}`,
callback_data: `${fromId};checkAnime;${animeType};${page};${animeList[3] ? animeList[3].id : "none"}`
},
{
text: `${animeList[4] ? functions.getNumberEmoji(animeList[4].count) : ``}`,
callback_data: `${fromId};checkAnime;${animeType};${page};${animeList[4] ? animeList[4].id : "none"}`
}
],
[
{
text: ``,
callback_data: `${fromId};animeList;${animeType};1;${page}`
},
{
text: `◀️`,
callback_data: `${fromId};animeList;${animeType};${page-1};${page}`
},
{
text: `▶️`,
callback_data: `${fromId};animeList;${animeType};${page+1};${page}`
},
{
text: ``,
callback_data: `${fromId};animeList;${animeType};${maxPage};${page}`
}
],
[
{
text: `🔙 Назад к меню аниме`,
callback_data: `${fromId};animeMenu`
}
]
]
}
return keyboard
};
exports.interestingPages = async (fromId, newPage, maxPage, animeId) => { //Страницы в популярном, интересном
let keyboard = {
inline_keyboard: [
[
{
text: `🔥 Открыть тайтл`,
callback_data: `${fromId};checkInteresting;${newPage};${animeId};` // {user id}, {callback command}, {list type}, {page}
}
],
[
{
text: ``,
callback_data: `${fromId};interesting;1;${newPage}`
},
{
text: `◀️`,
callback_data: `${fromId};interesting;${newPage-1};${newPage}`
},
{
text: `▶️`,
callback_data: `${fromId};interesting;${newPage+1};${newPage}`
},
{
text: ``,
callback_data: `${fromId};interesting;${maxPage};${newPage}`
}
],
[
{
text: `🔙 Назад к меню аниме`,
callback_data: `${fromId};animeMenu`
}
]
]
}
return keyboard
};
exports.checkInterestingAnime = async (fromId, animeId, newPage) => { //Посмотреть интересное аниме
let keyboard = {
inline_keyboard: [
[
{
text: `⏸ Открыть аниме в Anixart`,
url: `https://anixart.tv/release/${animeId}`
}
],
[
{
text: `🔥 Назад к интересному`,
callback_data: `${fromId};interesting;${newPage};0`
}
],
[
{
text: `🔙 Назад к меню аниме`,
callback_data: `${fromId};animeMenu`
}
]
]
}
return keyboard
};
exports.searchAnimeMenu = async (fromId) => { //Как найти аниме
let keyboard = {
inline_keyboard: [
[
{
text: `🔙 Назад к меню аниме`,
callback_data: `${fromId};animeMenu`
}
]
]
}
return keyboard
};
exports.searchAnimeBack = async (fromId, page, animeName, animeId) => { //Как найти аниме
let keyboard = {
inline_keyboard: [
[
{
text: `⏸ Открыть аниме в Anixart`,
url: `https://anixart.tv/release/${animeId}`
}
],
[
{
text: `🔙 Назад к результатам`,
callback_data: `${fromId};searchAnime;${page};0;${animeName}`
}
],
[
{
text: `❌ Закрыть поиск`,
callback_data: `${fromId};deleteMessage`
}
]
]
}
return keyboard
};
exports.searchAnime = async (fromId, maxPage, page, animeList, animeName) => { //Страницы в популярном, интересном
let keyboard = {
inline_keyboard: [
[
{
text: `${animeList[0] ? functions.getNumberEmoji(animeList[0].count) : ``}`,
callback_data: `${fromId};searchResult;${page};${animeName};${animeList[0] ? animeList[0].id : "none"}` // {user id}, {callback command}, {list type}, {page}
},
{
text: `${animeList[1] ? functions.getNumberEmoji(animeList[1].count) : ``}`,
callback_data: `${fromId};searchResult;${page};${animeName};${animeList[1] ? animeList[1].id : "none"}`
},
{
text: `${animeList[2] ? functions.getNumberEmoji(animeList[2].count) : ``}`,
callback_data: `${fromId};searchResult;${page};${animeName};${animeList[2] ? animeList[2].id : "none"}`
},
{
text: `${animeList[3] ? functions.getNumberEmoji(animeList[3].count) : ``}`,
callback_data: `${fromId};searchResult;${page};${animeName};${animeList[3] ? animeList[3].id : "none"}`
},
{
text: `${animeList[4] ? functions.getNumberEmoji(animeList[4].count) : ``}`,
callback_data: `${fromId};searchResult;${page};${animeName};${animeList[4] ? animeList[4].id : "none"}`
}
],
[
{
text: ``,
callback_data: `${fromId};searchAnime;1;${page};${animeName}`
},
{
text: `◀️`,
callback_data: `${fromId};searchAnime;${page-1};${page};${animeName}`
},
{
text: `▶️`,
callback_data: `${fromId};searchAnime;${page+1};${page};${animeName}`
},
{
text: ``,
callback_data: `${fromId};searchAnime;${maxPage};${page};${animeName}`
}
],
[
{
text: `❌ Закрыть поиск`,
callback_data: `${fromId};deleteMessage`
}
]
]
}
return keyboard
};