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

Начинающий
Статус
Оффлайн
Регистрация
13 Янв 2019
Сообщения
6
Реакции[?]
5
Поинты[?]
0
Что ж, в данном гайде вы научитесь создавать бота для 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:
{
  "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:
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:
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(паттерн поиска)
Код:
    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:
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 приложения.
 
Участник
Статус
Оффлайн
Регистрация
18 Апр 2016
Сообщения
433
Реакции[?]
257
Поинты[?]
5K
ну давай разберем по частям, тобою написанное

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

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

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

JavaScript:
vk.setOptions({
    token,

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

потом
спрашиваю у мужа, а есть ли в этом смысл, ответ убил.
JavaScript:
if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;
if (context.isGroup) // Если сообщение от группы - выйти
        return;
по факту это не имеет смысла, ибо отрицательный senderId может иметь только группа, так же не имеет смысла и следующая проверка
JavaScript:
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'))
 
Начинающий
Статус
Оффлайн
Регистрация
13 Янв 2019
Сообщения
6
Реакции[?]
5
Поинты[?]
0
ну давай разберем по частям, тобою написанное

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

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

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

JavaScript:
vk.setOptions({
    token,

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

потом
спрашиваю у мужа, а есть ли в этом смысл, ответ убил.
JavaScript:
if (context.senderId < 0) // Если сообщение не из лс с ботом - выйти
        return;
if (context.isGroup) // Если сообщение от группы - выйти
        return;
по факту это не имеет смысла, ибо отрицательный senderId может иметь только группа, так же не имеет смысла и следующая проверка
JavaScript:
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:
 
Сверху Снизу