• Я зарабатываю 100 000 RUB / месяц на этом сайте!

    А знаешь как? Я всего-лишь публикую (создаю темы), а админ мне платит. Трачу деньги на мороженое, робуксы и сервера в Minecraft. А ещё на паль из Китая. 

    Хочешь так же? Пиши и узнавай условия: https://t.me/alex_redact
    Реклама: https://t.me/yougame_official

Пишем бота для вк | Гайд для самых маленьких | нодажээс

Начинающий
Начинающий
Статус
Оффлайн
Регистрация
13 Янв 2019
Сообщения
6
Реакции
5
Что ж, в данном гайде вы научитесь создавать бота для VK. Для этого вам не нужны какие-либо сильные познания в NodeJS, да и в пг в целом. Для полного понимания картины, я буду описывать все свои действия, а строчки кода комментировать.
Что же нам потребуется?
Любой редактор кода(visualstudio code, notepad++, webstorm и т.п)
И прямые руки

Для начала составим план:
  1. Установка Nodejs;
  2. Инициализация проекта и установка модулей;
  3. Инициализация зависимостей;
  4. Простой "Ответчик на сообщения";
  5. Обращение к методам api vk.

1. Итак, перейдем по ссылке
Пожалуйста, авторизуйтесь для просмотра ссылки.
. Выбираем Currect(Текущую) версию установщика, выбираем удобную для вас платформу, скачиваем.
В моем случае, я выбрал Установщик Windows.

Дальше нас встречает дефолтный установщик. Принимаем лицензионное соглашение, выбираем путь, соглашаемся со всем, что есть в инсталлере, после чего ожидаем окончания установки окружения.

2. Создадим папку (название не имеет значения). Запустим из этой папки консоль, зажав SHIFT и нажав правую кнопку мыши, после чего выберете: для Windows 7 - Командная строка, а для Windows 10 - PowerShell. (Команды для всех консолей одинаковы, поэтому поводу не переживайте).
1577813838091.png


В открывшейся консоли пишем:
npm -v node -v
Если консоль не выдала ошибок, то окружение установлено корректно и можно продолжать.

Инициализируем npm проект, командной
npm init
Данная команда создаст файл json, в котором будет храниться вся информация о проекте.

Установим нужные модули:
npm install vk-io --save
vk-io - модуль для работы с vk api.

Давайте отредактируем файл package.json.
Поначалу у нас будет так:
JSON:
Expand Collapse Copy
{
  "name": "guide",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vk-io": "^4.0.0-rc.30"
  }
}
Сейчас нас интересует графа scripts.
Уберем "test" и добавим "start" и запишем туда "node index.js".
После чего сохраним наш файл.
Для чего мы это делали, я опишу далее
В итоге ваш файл должен выглядеть так:
1577818701238.png

Теперь создадим файл index.js, открыв его в редакторе кода, изменим кодировку с Ascii на UTF-8.

3.

Режимы работы API, указываются в apiMode
sequential - Все запросы идут последовательно​
parallel - Все запросы собираются пачкой по apiExecuteCount в метод execute​
parallel_selected - Выбранные методы собираются пачкой по apiExecuteCount в метод execute, остальные методы последовательно​

метод setOptions устанавливает параметры для работы API
JavaScript:
Expand Collapse Copy
const { VK } = require('vk-io'); // Инициализация класса VK из модуля vk-io
const vk = new VK(); // Инициализация новой инстанции
const token = 'TOKENVK'; // Инициализация переменной token в качестве констатны


vk.setOptions({
    token: token, // Токен
    apiMode: 'parallel', // Режим работы API
/* Можете указать еще эти параметры.
    pollingWait: по умолчанию 3000 - Время ожидания попытки запроса после ошибки
    pollingGroupId:  - Id группы для polling
    pollingAttempts: Кол-во попыток пвтора запроса после ошибки
*/
});

Добавим прослушку сообщений, добавив это в наш код:
JavaScript:
Expand Collapse Copy
vk.updates.use(async (context, next) => { //прослушка входящих сообщений

    if (!context.senderId) // Если отсуствует id отправителя - выйти
        return;

    if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;

    if (context.isGroup) // Если сообщение от группы - выйти
        return;

    if (context.is('message') && context.isOutbox) // Если сообщение исходящее - выйти
        return;

    await next(); // Продолжить промежуточный код
});

context - наследуемая переменная, в которой хранится данные (если человеческим языком).
next - приводит к промежуточному коду.

Создадим функцию start, в которую требуется передать строку, сама функция будет запускать polling.

function start (start) {
vk.updates.start();
console.log(start);


И сразу вызовем ее, добавив start('Бот запущен!');

4. Сделаем обработчик команд.
Для этого в классе updates есть метод hear. Он проверяет, какой тип у запроса, если type == message и context.text === "Команда", выполнится код.
Добавим команду !помощь, в которую мы передадим текст "Команд нету".
Для этого мы будем использовать регулярные выражения regexp(паттерн поиска)
Код:
Expand Collapse Copy
    vk.updates.hear(/!помощь/i, async(context) => {
        context.reply(`Команд нету`);
    });
async означает, что функция выполнится асинхронно.

В итоге наш код должен выглядеть так:
const { VK } = require('vk-io'); // Инициализация класса VK из модуля vk-io
const vk = new VK(); // Инициализация новой инстанции
const token = 'TOKENVK'; // Инициализация переменной TOKEN в качестве констатны.


vk.setOptions({
token: token, // Токен
apiMode: 'parallel', // Режим работы API
/* Можете указать еще эти параметры.
pollingWait: по умолчанию 3000 - Время ожидания попытки запроса после ошибки
pollingGroupId: - Id группы для polling
pollingAttempts: Кол-во попвыток запроса после запроса к api
*/
});

vk.updates.use(async (context, next) => { //прослушка сообщений

if (!context.senderId) // Если отсуствует id отправителя - выйти
return;

if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
return;

if (context.isGroup) // Если сообщение от группы - выйти
return;

if (context.is('message') && context.isOutbox) // Если сообщение исходящее - выйти
return;

await next(); // Продолжить промежуточный код
});

vk.updates.hear(/!помощь/i, async(context) => {
context.reply(`Команд нету`);
});

start('Бот успешно запущен');

function start (start) {
vk.updates.start();
console.log(start);
}
Попробуем запустить. Для этого в нашей консоли пропишем npm start
Json-файл мы изменяли именно для этой команды.

Если вы сделали все верно, то скрипт должен запуститься, а бот заработать.
1577821214395.png



5. Запросы к vk api.

Для запросов к api не нужно использовать никаких классов, достаточно просто ввести название и вызвать.
Создадим АСИНХРОННУЮ функцию, которая будет получать информацию о пользователе, в функцию нужно передавать id пользователя, назовем функцию getFirstName. Почему асинхронную? - потому что мы не можем выполнить асинхронное действие и получить имя, поэтому функция async.
Весь код должен выглядеть теперь так:
JavaScript:
Expand Collapse Copy
const { VK } = require('vk-io'); // Инициализация класса VK из модуля vk-io
const vk = new VK(); // Инициализация новой инстанции
const token = 'TOKEN'; // Инициализация переменной TOKEN в качестве констатны.

vk.setOptions({
    token: token, // Токен
    apiMode: 'parallel', // Режим работы API
/* Можете указать еще эти параметры.
    pollingWait: по умолчанию 3000 - Время ожидания попытки запроса после ошибки
    pollingGroupId:  - Id группы для polling
    pollingAttempts: Кол-во попвыток запроса после запроса к api
*/
});
vk.updates.use(async (context, next) => { //прослушка сообщений
    if (!context.senderId) // Если отсуствует id отправителя - выйти
        return;
    if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;
    if (context.isGroup) // Если сообщение от группы - выйти
        return;
    if (context.is('message') && context.isOutbox) // Если сообщение исходящее - выйти
        return;
    console.log('[' + await getFirstName(context.senderId) + ']: ' + context.text);
    await next(); // Продолжить промежуточный код
});
    vk.updates.hear(/!помощь/i, async(context) => {
        await context.reply(`Команд нету`);
    });
start('Бот успешно запущен');
function start (start) {
    vk.updates.start();
    console.log(start);
}
async function getFirstName (id) {
    const resp = await vk.api.users.get({
        user_ids: id
    });
    return resp[0].first_name;
}

Мы добавили вызов метода console.log, в который передали имя отправителя и его сообщение.(Заметьте, перед вызовом функции стоит await, что означает асинхронный вызов функции).



На этом все.

Я постарался описать все, если кому-то что-то непонятно - пишите.
В следующих гайдах мы научимся писать ботов для VK на яп Python,PHP.
Научимся писать ботов для discord на яп NodeJS, PHP, Python.
Научимся создавать vk mini apps приложения.
 
Следующий гайд будет о дискорде
 
ну давай разберем по частям, тобою написанное

JavaScript:
Expand Collapse Copy
const token = 'TOKEN'; // Инициализация переменной TOKEN в качестве констатны.

vk.setOptions({
    token: token, // Токен
    apiMode: 'parallel', // Режим работы API
/* Можете указать еще эти параметры.
    pollingWait: по умолчанию 3000 - Время ожидания попытки запроса после ошибки
    pollingGroupId:  - Id группы для polling
    pollingAttempts: Кол-во попвыток запроса после запроса к api
*/
});
в рамках гайда мог бы объяснить разницу в parallel, parallel_selected и обычном режиме, если конечно сам понимаешь в чем здесь разница и как оно влияет на работу твоего бота

зачем выносить токен в отдельную переменную, не совсем понятно, ибо если ты хочешь в будущем получить доступ к нему, то ты можешь использовать vk.token, и раз уж ты вынес в переменную, то можно было написать так

JavaScript:
Expand Collapse Copy
vk.setOptions({
    token,

    apiMode: 'parallel'
});

и зачем юзать vk.setOptions, когда ты можешь это указать в самом начале, const vk = new VK({ ... });

потом
спрашиваю у мужа, а есть ли в этом смысл, ответ убил.
JavaScript:
Expand Collapse Copy
if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;
if (context.isGroup) // Если сообщение от группы - выйти
        return;
по факту это не имеет смысла, ибо отрицательный senderId может иметь только группа, так же не имеет смысла и следующая проверка
JavaScript:
Expand Collapse Copy
if (context.is('message') && context.isOutbox) // Если сообщение исходящее - выйти
        return;
поскольку senderId может быть только в "сообщении", а вот проверка на исходящее это да, полезно.

мелкая придирка к

console.log('[' + await getFirstName(context.senderId) + ']: ' + context.text);

ибо можно было записать как

console.log(`[${ await getFirstName(context.senderId) }]: ${ context.text }`);

что выглядит банально красивее и соответствует airbnb стилю (советую ознакомиться https://github.com/airbnb/javascript)

кстати, проверку на наличие текста ты не делаешь, а ведь его может и не быть =)
а про выполнения users.get на каждое сообщение, я молчу

ну и с функцией start я тоже не понял прикола.
я уже ответил здесь https://yougame.biz/threads/108556/#post-1190359 как было бы правильнее

кстати, vk.updates.use это не только прослушка сообщений, это мидлварь, в который идут события с комментариев/стены/сообщений, так что правильнее было бы в самом начале сделать проверку if (ctx.is('message'))
 
ну давай разберем по частям, тобою написанное

JavaScript:
Expand Collapse Copy
const token = 'TOKEN'; // Инициализация переменной TOKEN в качестве констатны.

vk.setOptions({
    token: token, // Токен
    apiMode: 'parallel', // Режим работы API
/* Можете указать еще эти параметры.
    pollingWait: по умолчанию 3000 - Время ожидания попытки запроса после ошибки
    pollingGroupId:  - Id группы для polling
    pollingAttempts: Кол-во попвыток запроса после запроса к api
*/
});
в рамках гайда мог бы объяснить разницу в parallel, parallel_selected и обычном режиме, если конечно сам понимаешь в чем здесь разница и как оно влияет на работу твоего бота

зачем выносить токен в отдельную переменную, не совсем понятно, ибо если ты хочешь в будущем получить доступ к нему, то ты можешь использовать vk.token, и раз уж ты вынес в переменную, то можно было написать так

JavaScript:
Expand Collapse Copy
vk.setOptions({
    token,

    apiMode: 'parallel'
});

и зачем юзать vk.setOptions, когда ты можешь это указать в самом начале, const vk = new VK({ ... });

потом
спрашиваю у мужа, а есть ли в этом смысл, ответ убил.
JavaScript:
Expand Collapse Copy
if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;
if (context.isGroup) // Если сообщение от группы - выйти
        return;
по факту это не имеет смысла, ибо отрицательный senderId может иметь только группа, так же не имеет смысла и следующая проверка
JavaScript:
Expand Collapse Copy
if (context.is('message') && context.isOutbox) // Если сообщение исходящее - выйти
        return;
поскольку senderId может быть только в "сообщении", а вот проверка на исходящее это да, полезно.

мелкая придирка к

console.log('[' + await getFirstName(context.senderId) + ']: ' + context.text);

ибо можно было записать как

console.log(`[${ await getFirstName(context.senderId) }]: ${ context.text }`);

что выглядит банально красивее и соответствует airbnb стилю (советую ознакомиться
Пожалуйста, авторизуйтесь для просмотра ссылки.
)

кстати, проверку на наличие текста ты не делаешь, а ведь его может и не быть =)
а про выполнения users.get на каждое сообщение, я молчу

ну и с функцией start я тоже не понял прикола.
я уже ответил здесь https://yougame.biz/threads/108556/#post-1190359 как было бы правильнее

кстати, vk.updates.use это не только прослушка сообщений, это мидлварь, в который идут события с комментариев/стены/сообщений, так что правильнее было бы в самом начале сделать проверку if (ctx.is('message'))
Спасибо за критику. Приятно, что кто-то еще всерьез занят этой темой. Учту и исправлю.:CoolCat:
 
Назад
Сверху Снизу