2.88.1 • Published 1 year ago

@lskjs/bots v2.88.1

Weekly downloads
601
License
MIT
Repository
github
Last release
1 year ago

LSK.js – bots

@lskjs/bots – LSK.js module for telegram, slack, discord, whatsapp, twitter, instagram and vk bots creation

LSK logo NPM version NPM downloads NPM Dependency count Have TypeScript types Have tree shaking NPM Package size Package size Ask us in Telegram


Table of contents

⌨️ Install

# yarn
yarn i @lskjs/bots @lskjs/db axios bluebird lodash

# npm
npm i @lskjs/bots @lskjs/db axios bluebird lodash

Bots Plugin Portal

Bots Plugin Portal (@lskjs/bots-plugin-portal) - плагин, позволяющий настраивать реакции бота на различные триггеры.

Конфиг плагина находится по пути bots.plugins.portal и имеет вид:

bots: {
  plugins: {
    portal: {
      group: true,
      rules: [
        //...
      ],
    },
  },
},

Params:

FieldTypeDesription
groupBooleanГруппировать ли медиа-файлы
rulesArray of ObjectsМассив правил, которым следует бот при обработке входящих сообщений или при срабатывании крона

Group values:

FieldValueDescription
grouptrueГруппирует медиа-файлы в одно сообщение и помещает их в ctx.group
groupfalseМедиа-файлы приходят на сервер разными сообщениями
/Reference/: При отправке боту нескольких медиа-файлов одним сообщением, на сервер медиа-файлы приходят разными сообщениями. Т.е. при отправке 5 изображений одним сообщением, на сервер приходит не одно сообщение, а 5.

Правила (rules)

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

Правила состоят из 3-х частей: | Rule Part | Type | Required | Description | | ------ | :------: | :------: | ------ | | cron | Array of String\String | - | Позволяет устанавливать расписания срабатываний экшона | |criteria| Object | - | Критерии срабатывания экшона при обработке действий пользователя | | action | Object | + | Экшоны. Описания действий, которые выполняет бот |

cron

Параметр позволяет устанавливать время срабатывания действия бота. Например, если необходимо установить отправку сообщений в чат каждую минуту, то конфиг будет выглядеть cron: '* * * * *'.

Официальный пакет крона: node-cron - npm

criteria

Параметр позволяет устанавливать критерии на триггеры срабатывания бота. Например, если необходимо, чтобы бот реагировал только на сообщения в определенном чате, то критерий будут выглядеть chatId: 12345678.

Если criteria отсутствует, то правила могут срабатывать только по крону. Если же criteria: {}, то считается, что критерий отбора нет и правила будут срабатывать на любые взаимодействия с ботом.

action

Параметр задает действия бота. Здесь настраивается, будет бот искать сообщения, оправлять или удалять их и тд.

Действия могут быть вложенными и составлять цепочки при помощи полей then и else. При удачном выполнении действия-родителя бот будет выполнять действия из поля then. При неудачном - else. Аналогия с if/else, где if - then, а else - else. Например, при проверке checkMessage, если сообщение существует, то бот пройдет по ветке then, в противном случае по else.

Кроме вложенности, action/then могут быть массивами и содержать параллельные действия.

Examples:

{
  cron: '* * * * *',
  criteria: {
    chatId: 12345678,
  },
  action: {
    type: 'checkMessage',
    chatId: -123114346456,
    userId: 12345678,
    then: {
      type: 'sendMessage',
      text: 'some text by true checkMessage',
      to: 12345678,
    },
    else: {
      type: 'sendMessage',
      text: 'some text by false checkMessage',
      to: 12345678,
    },
  },
},
{
  cron: ['*/20 * * * *', '*/15 * * * * *'],
  action: [
    {
      type: 'sendMessage',
      text: 'some text 1',
      to: 12345678,
    },
    {
      type: 'sendMessage',
      text: 'some text 2',
      to: -87654321123,
    },
  ],
}
{
  criteria: {
    chatId: 12345678,
  },
  action: {
    type: 'reply',
    text: 'some text by reply',
  },
},

Параметры, используемые при настройке критериев:

Criteria FieldTypeValuesDescription
userIdArray of Number\Array of String\Number\StringID пользователя, который взаимодействует с ботом
chatIdArray of Number\Array of String\Number\StringID чата, в котором происходит взаимодействие с ботом
chatTypeStringprivate\group\supergroup\channelТип чата, в котором происходит взаимодействие
messageTypeStringТип сообщения. Различают множество типов сообщений
messageTextString\RegExpТекст сообщения. Например, можно сделать критерий на команду запуска бота messageText: /start
nextRouteString\RegExpСледующий роут. Используется только при заполнении формы. Необходимо устанавливать данный критерий для блокировки каких-либо действий во время заполнения формы в целях избежать спама и лишних триггеров.

Chat types:

  1. private - личные диалог с ботом
  2. group - общий чат
  3. supergroup - общий чат
  4. channel - канал

Message types:

  1. mediaGroup - группа медиа-файлов
  2. audio - приложен аудио-файл
  3. document - приложен документ
  4. animation - гифка
  5. photo - приложено изображение
  6. sticker - стикер
  7. video - приложено видео
  8. video_note - видео-кружочек
  9. voice - голосовое сообщение
  10. contact - контакт
  11. dice - игральная кость
  12. game - игра
  13. poll - голосование
  14. quiz - викторина
  15. location - геоданные
  16. venue - место
  17. text - текстовое сообщение

Список действий, которые реализованы в плагине:

  1. createMessage - создание сообщений
  2. messageAppend - добавление текста в конец
  3. messageTrim - фильтр текста
  4. messageEditExtra - редактирование кнопок
  5. messageAddExtra - добавление кнопок
  6. sendMessage - отправка сообщений
  7. reply - реплай
  8. repost - репост
  9. copyMessage - копирование сообщений
  10. remove - удаление сообщений
  11. findMessage - поиск сообщения
  12. pinChatMessage - закрепление сообщения
  13. messageSplit - разделение сообщения на элементы
  14. messagesJoin - группировка сообщений в одно
  15. checkInterview - проверка заполнения формы
  16. replyInterview - отправка формы

createMessage

createMessage - действие бота, необходимое для создания сообщения и последующего редактирования перед отправкой. После создания сообщения, к нему можно добавить/изменить кнопки, отредактировать его текст и тд.

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

Params:

FieldTypeDescription
textStringтекст сообщения
toArray of Number\Array of String\Number\StringID чата, в который будет отправлено сообщение

Example:

{
  criteria: {},
  action: {
    type: 'createMessage',
    text: "It's field from message text",
    to: 12345678,
  },
},

messageAppend

messageAppend - действие бота, позволяющее добавить текст в конец сообщения.

Params:

FieldTypeDescription
textStringДобавочный текст

Example:

{
  criteria: {
    messageText: /\/trim/,
  },
  action: {
    type: 'messageAppend',
    text: 'by @download4bot',
    then: {
      type: 'repost',
      to: 12345678,
    },
  },
},

messageTrim

messageTrim - действие бота, позволяющее отфильтровать текст сообщения.

Params:

FieldTypeDescription
hashtagsBooleanУдаляет все хештеги из текста сообщения
linksBooleanУдаляет все ссылки из текста сообщения
regExpRegExpПозволяет удалять любые пользовательские шаблоны из текста сообщения

Example:

{
  criteria: {
    messageText: /\/trim/,
  },
  action: {
    type: 'messageTrim',
    hashtags: 1,
    links: 1,
    regExp: /1?123\n?/,
    then: {
      type: 'repost',
      to: 12345678,
    },
  },
},

messageEditExtra

messageEditExtra - действие бота, позволяющее отредактировать клавиатуру сообщения.

Params:

FieldTypeDescription
extraArrayСодержит редактируемые кнопки клавиатуры

Extra params for type LIKE:

FieldTypeRequiredDescription
typeString+Кнопки лайк/дисслайк к сообщению
buttonsArray-Содержит редактируемые кнопки клавиатуры
buttons.disslikeObject-Настройка кнопки дисслайка
buttons.likeObject-Настройка кнопки дисслайка

Extra params for type ANSWER:

FieldTypeRequiredDescription
typeString+Кнопка для установления соединения с другим пользователем через бота (чат)
textString-Настройка текста кнопки

Extra params for type SENDER:

FieldTypeRequiredDescription
typeString+Кнопка для перехода к отправителю сообщения
textString-Настройка текста кнопки

Example:

{
  criteria: {}
  action: {
    type: 'createMessage',
    text: 'Title text',
    then: {
      type: 'messageEditExtra',
      extra: [
        {
          type: 'like',
          buttons: {
            disslike: {
              title: 'test 💔', // default: '💔'
              value: 10, // default: 0
            },
            like: {
              title: 'test ❤️', // default: '❤️'
              value: 0, // default: 0
            },
          },
        },
        {
          type: 'answer',
          text: 'Answer @{ {username} }', // default: '@username'
        },
        {
          type: 'sender',
          text: 'Sender: @{ {username} }', // default: '@username'
        },
      ],
      then: {
        type: 'sendMessage',
        to: 12345678,
      },
    },
  },
},

messageAddExtra

messageAddExtra - действие бота, позволяющее добавить новую клавиатуру сообщения. Если клавиатура уже существует, то messageAddExtra заменит текущую на новую.

Params: | Field | Type | Description | | ------ | :------: | ------ | | extra | Array | Содержит редактируемые кнопки клавиатуры |

Extra params for type LIKE:

FieldTypeRequiredDescription
typeString+Кнопки лайк/дисслайк к сообщению
buttonsArray-Содержит редактируемые кнопки клавиатуры
buttons.disslikeObject-Настройка кнопки дисслайка
buttons.likeObject-Настройка кнопки дисслайка

Extra params for type ANSWER:

FieldTypeRequiredDescription
typeString+Кнопка для установления соединения с другим пользователем через бота (чат)
textString-Настройка текста кнопки

Extra params for type SENDER:

FieldTypeRequiredDescription
typeString+Кнопка для перехода к отправителю сообщения
textString-Настройка текста кнопки

Example:

{
  criteria: {}
  action: {
    type: 'createMessage',
    text: 'Title text',
    then: {
      type: 'messageAddExtra',
      extra: [
        {
          type: 'like',
          buttons: {
            disslike: {
              title: 'New disslike  💔', // default: '💔'
              value: 10, // default: 0
            },
            like: {
              title: 'New like  ❤️', // default: '❤️'
              value: 0, // default: 0
            },
          },
        },
        {
          type: 'answer',
          text: 'Answer @{ {username} }', // default: '@username'
        },
        {
          type: 'sender',
          text: 'Sender: @{ {username} }', // default: '@username'
        },
      ],
      then: {
        type: 'sendMessage',
        to: 12345678,
      },
    },
  },
},

sendMessage

sendMessage - действие бота, при котором бот отправляет сообщение заданному пользователю. Для настройки сообщения используется цепочка действий: createMessage -> messageAddExtra -> messageAppend -> messageTrim -> sendMessage.

Params:

FieldTypeRequiredDescription
textString-Текст сообщения
toArray of String/Array of Number/String/Number-ID получателя(-ей)

Example:

{
  criteria: {},
  action: {
    type: 'createMessage',
    then: {
      type: 'sendMessage',
      text: 'Text by sendMessage',
      to: 12345678,
    },
  },
},

reply

reply - действие бота, при котором бот отвечает на сообщение пользователя.

Params:

FieldTypeRequiredDescription
textString-Текст сообщения

Example:

{
  criteria: {
    messageText: 'ping',
  },
  action: {
    type: 'reply',
    text: 'pong',
  },
},

repost

repost - действие бота, при котором бот пересылает активное сообщение в заданных чат.

Params:

FieldTypeRequiredDescription
toArray of String/Array of Number/String/Number-ID получателя(-ей)

Example:

{
  criteria: {
    chatId: -136512436512436,
  },
  action: {
    type: 'repost',
    to: 12345678,
  },
},

copyMessage

sendMessage - действие бота, при котором бот копирует активное сообщение и пересылает его в заданных чат.

Params:

FieldTypeRequiredDescription
toArray of String/Array of Number/String/Number-ID получателя(-ей)

Example:

{
  criteria: {
    chatId: -136512436512436,
  },
  action: {
    type: 'copyMessage',
    to: 12345678,
  },
},

remove

remove - действие бота, при котором бот удаляет активное сообщение. Активным сообщением является полученное сообщение, либо найденное при помощи findMessage.

Example:

{
  criteria: {
    messageText: 'попит',
  },
  action: {
    type: 'remove',
  },
},

findMessage

findMessage - действие бота, позволяющее найти сообщение в чате по заданным параметрам. Поиск осуществляется в модели BotsTelegramMessageModel.

Params:

FieldTypeRequiredDescription
randomBoolean-Если нашлось несколько сообщений, выбирать ли случайное. По умолчанию: последнее полученное ботом сообщение.
criteriaObject-Критерии поиска сообщения в базе
criteria.userIdArray of Number\Array of String\Number\String-ID пользователя
criteria.chatIdArray of Number\Array of String\Number\String-ID чата
criteria.chatTypeString-Тип чата
criteria.messageTypeString-Тип сообщения
criteria.messageDateNumber-Дата сообщения в ms
criteria.messageTextString\RegExp-Текст сообщения
criteria.messageIdString\RegExp-ID сообщения

Example:

{
  criteria: {
    messageText: '/checkMessage',
  },
  action: {
    type: 'findMessage',
    criteria: {
      chatId: -1232343354655,
      messageText: '*message.text',
    },
    then: {
      type: 'repost',
      to: 12345678,
    },
  },
},

pinChatMessage

pinChatMessage - действие бота, при котором бот закрепляет активное сообщение. Активным сообщением является полученное сообщение, либо сообщение после findMessage/createMessage.

Example:

{
  criteria: {
    messageText: /^#закрепить.*/,
  },
  action: {
    type: 'pinChatMessage',
  },
},

messageSplit

messageSplit - действие бота, позволяющее разделять входящее сообщение на элементы для последующей работы. Например, если пользователь пишет боту сообщение, содержащее 5 изображений и подпись, то бот разделит сообщение на 6 элементов.

Example:

{
  criteria: {},
  action: {
    type: 'messageSplit',
    then: {
      type: 'sendMessage',
      to: 12345678,
    },
  },
},

messagesJoin

messagesJoin - действие бота, позволяющее объединять несколько сообщений, переданных боту (например, пересылая сообщения). Если среди сообщений несколько подписей, то они объединятся в единый текст.

Example:

{
  criteria: {},
  action: {
    type: 'messagesJoin',
    then: {
      type: 'sendMessage',
      to: 12345678,
    },
  },
},

checkInterview

checkInterview - действие бота для проверки, заполнил ли пользователь необходимые формы.

Params:

FieldTypeDescription
typeStringТип действия бота. Запускает проверку на заполненность формы
formsArray of String/StringСписок с названиями форм, которые следует заполнить для прохождения проверки

Example:

{ 
  criteria: {
    messageText: /^(?!\/registration).*$/,
    nextRoute: /^(?!\/interview).*$/,
  },
  action: {
    type: 'checkInterview',
    forms: ['intro'],
    then: [
      type: 'reply',
      text: 'Успех!',
    ],
    else: {
      type: 'reply',
      text: 'Необходима регистрация! /registration'
    },
  },
},

replyInterview

replyInterview - действие бота для отправки формы пользователю.

Params:

FieldTypeValueDescription
typeStringТип действия бота. Отправляет форму пользователю
formNameStringНазвание формы, которая будет отправлена пользователю
modeStringform/dialogРежим работы формы
previewBooleanПараметр, который указывает, необходимо ли выводить title формы перед вводом данных
autosubmitBooleanПараметр, который указывает, необходимо ли подтверждение данных формы

Example:

{
  criteria: {
    chatType: 'private',
    messageText: '/registration',
  },
  action: {
    type: 'replyInterview',
    formName: 'intro',
    mode: 'form',
    preview: false,
    autosubmit: false,
    then: {
      type: 'reply',
      text: 'Успех!',
    },
  },
},

Bots Plugin Interview

Bots Plugin Interview (@lskjs/bots-plugin-interview) - плагин, позволяющий создавать формы ввода в боте. Реализована вариация с классической браузерной формой с подтверждением введенных данных. Режим диалога находится в стации разработки.

Конфиг для плагина состоит из двух частей - interview и portal. Interview отвечает за настройку формы, её полей и их валидацию. Portal реализует взаимодействие с формой. Например, при каких действиях пользователя будет вызвана форма.

Входные данные сохраняются в базу и хранятся в модели BotsTelegramUserModel. Путь в модели meta.interview.[formName].

Interview

Конфиг для настройки формы, её полей и их валиацию.

bot/plugins/interview/forms - обязательный путь до форм.

Params:

FieldTypeDescription
introStringНазвание формы. Название формы должно быть уникально и используется в portal-части для коннекта с формой
intro.titleStringТекст, который видит пользователь при появлении формы
intro.controlsObjectПоля формы, которые будут заполняться пользователем
controls.[name/city/age]StringНазвания полей формы внутри конфига
controls.name.titleStringНазвание поля формы, которое видит пользователь в intro.title
controls.name.placeholderStringТекст, выводимый перед заполнением поля формы
controls.name.formatFuncВалидация входных данных
intro.fieldsArray of StringМассив с активными полями формы

Example:

bots: {
  plugins: {
    interview: {
      forms: {
        intro:  {
          title: 'Добро пожаловать. Для продолжения пройдите краткую регистрацию!',
          controls: {
            name: {
              title: 'Имя',
              placeholder: 'Введите имя',
              format: String,
            },
            city: {
              title: 'Город',
              placeholder: 'Введите город',
            },
            age: {
              title: 'Возраст',
              placeholder: 'Введите ваш возраст',
              format: Number,
            },
          },
          fields: ['name', 'city', 'age'],
        },
      },
    },
  },
},

Portal

см. Bost Plugin Portal - checkInterview & replyInterview.

📖 License

This project is licensed under the MIT License - see the LICENSE file for details

👥 Contributors

👏 Contributing

  1. Fork it (https://github.com/yourname/yourproject/fork)
  2. Create your feature branch (git checkout -b features/fooBar)
  3. Commit your changes (git commit -am 'feat(image): Add some fooBar')
  4. Push to the branch (git push origin feature/fooBar)
  5. Create a new Pull Request

📮 Any questions? Always welcome :)

2.88.1

1 year ago

2.85.0

1 year ago

2.85.1

1 year ago

2.84.11

2 years ago

2.76.0

2 years ago

2.72.0

2 years ago

2.70.0

2 years ago

2.75.1

2 years ago

2.74.0

2 years ago

2.73.0

2 years ago

2.69.1

2 years ago

2.67.0

2 years ago

2.66.0

2 years ago

2.66.1

2 years ago

2.65.0

2 years ago

2.65.1

2 years ago

2.64.0

2 years ago

2.64.1

2 years ago

2.63.0

2 years ago

2.57.0

2 years ago

2.60.1

2 years ago

2.56.0

2 years ago

2.52.0

2 years ago

2.59.0

2 years ago

2.62.0

2 years ago

2.61.0

2 years ago

2.46.0

2 years ago

2.43.0

3 years ago

2.34.0

3 years ago

2.38.0

3 years ago

2.41.0

3 years ago

2.37.0

3 years ago

2.40.0

3 years ago

2.36.1

3 years ago

2.39.1

3 years ago

2.39.0

3 years ago

2.35.0

3 years ago

2.42.1

3 years ago

2.42.0

3 years ago

2.42.3

3 years ago

2.42.2

3 years ago

2.33.1

3 years ago

2.33.0

3 years ago

2.30.0

3 years ago

2.29.0

3 years ago

2.28.0

3 years ago

2.27.0

3 years ago

2.26.0

3 years ago

2.25.0

3 years ago

2.24.0

3 years ago

2.23.4

3 years ago

2.23.2

3 years ago

2.23.0

3 years ago

2.19.1

3 years ago

2.18.0

3 years ago

2.17.0

3 years ago

2.16.1

3 years ago

2.15.0

3 years ago

2.13.0

3 years ago

2.12.3

3 years ago

2.11.0

3 years ago

2.12.0

3 years ago

2.9.1

3 years ago

2.10.2

3 years ago

2.8.0

3 years ago

2.8.4

3 years ago

2.9.0

3 years ago

2.7.0

3 years ago

2.7.1

3 years ago

2.6.1

3 years ago

2.6.0

3 years ago

2.5.2

3 years ago

2.5.1

3 years ago

2.5.3

3 years ago

2.5.0

3 years ago

2.3.0-beta.99

3 years ago

2.3.0-beta.94

3 years ago

2.3.0-beta.95

3 years ago

2.3.0-beta.87

3 years ago

2.3.0-beta.86

3 years ago

2.3.0-beta.89

3 years ago

2.3.0-beta.88

3 years ago

2.3.0-beta.90

3 years ago

2.3.0-beta.92

3 years ago

2.3.0-beta.91

3 years ago

2.3.0-beta.72

3 years ago

2.3.0-beta.74

3 years ago

2.3.0-beta.73

3 years ago

2.3.0-beta.75

3 years ago

2.3.0-beta.71

3 years ago

2.3.0-beta.70

3 years ago

2.3.0-beta.58

3 years ago

2.3.0-beta.55

3 years ago

2.3.0-beta.54

3 years ago

2.3.0-beta.53

3 years ago

2.3.0-beta.52

3 years ago

2.3.0-beta.51

3 years ago

2.3.0-beta.49

3 years ago

2.3.0-beta.48

3 years ago

2.3.0-beta.42

3 years ago

2.3.0-beta.39

3 years ago

2.3.0-beta.41

3 years ago

2.3.0-beta.40

3 years ago

2.3.0-beta.35

3 years ago

2.3.0-beta.33

3 years ago

2.3.0-beta.31

3 years ago

2.3.0-beta.28

3 years ago

2.3.0-beta.25

3 years ago

2.3.0-beta.26

3 years ago

2.3.0-beta.24

3 years ago

2.3.0-beta.22

3 years ago

2.3.0-beta.21

3 years ago

2.3.0-beta.20

3 years ago

2.3.0-beta.19

3 years ago

2.3.0-beta.14

3 years ago

2.3.0-beta.10

3 years ago

2.3.0-beta.6

3 years ago

2.3.0-beta.5

3 years ago

2.3.0-beta.4

3 years ago

2.3.0-beta.2

3 years ago

2.2.1-beta.2

3 years ago

2.2.0-beta.26

3 years ago

2.2.0-beta.24

3 years ago

2.2.0-beta.23

3 years ago

2.2.0-beta.22

3 years ago

2.2.0-beta.20

3 years ago

1.99.1

3 years ago

1.99.0

3 years ago

1.100.1

3 years ago

2.2.0-beta.19

3 years ago

2.2.0-beta.16

3 years ago

2.2.0-beta.17

3 years ago

2.2.0-beta.12

3 years ago

2.2.0-beta.13

3 years ago

2.2.0-beta.14

3 years ago

2.2.0-beta.15

3 years ago

2.2.0-beta.6

3 years ago

2.2.0-beta.7

3 years ago

2.2.0-beta.5

3 years ago

2.2.0-beta.4

3 years ago

2.2.0-beta.3

3 years ago

2.2.0-beta.2

3 years ago

2.2.0-beta.1

3 years ago

2.1.0-beta.5

3 years ago

2.1.0-beta.4

3 years ago

2.1.0-beta.6

3 years ago

2.1.0-beta.2

3 years ago

2.1.0-beta.1

3 years ago

2.1.0-beta.0

3 years ago

2.0.0-beta.7

3 years ago

2.0.0-beta.6

3 years ago

2.0.0-beta.4

3 years ago

2.0.0-beta.2

3 years ago

1.98.0

3 years ago

1.97.0

3 years ago

1.96.0

3 years ago

1.95.0

3 years ago

1.94.0

3 years ago

1.92.0

3 years ago

1.93.0

3 years ago

1.91.0

3 years ago

1.89.2

3 years ago

1.89.1

3 years ago

1.88.0

3 years ago

1.87.0

3 years ago

1.86.0

3 years ago

1.85.0

3 years ago

1.84.0

3 years ago

1.83.0

3 years ago

1.81.8

3 years ago

1.81.9

3 years ago

1.81.6

3 years ago

1.81.7

3 years ago

1.81.5

3 years ago

1.81.1

3 years ago

1.81.3

3 years ago

1.79.0

3 years ago

1.80.0

3 years ago

1.81.0

3 years ago

1.77.1

3 years ago

1.77.2

3 years ago

1.77.3

3 years ago

1.76.0

3 years ago

1.77.0

3 years ago

1.75.2

3 years ago

1.75.1

3 years ago

1.75.0

3 years ago

1.74.0

4 years ago

1.72.0

4 years ago

1.73.0

4 years ago

1.71.0

4 years ago

1.71.1

4 years ago

1.70.0

4 years ago

1.69.2

4 years ago

1.69.1

4 years ago

1.68.0

4 years ago

1.67.1

4 years ago

1.67.0

4 years ago

1.66.1

4 years ago

1.66.0

4 years ago

1.65.0

4 years ago

1.64.0

4 years ago

1.63.0

4 years ago

1.62.0

4 years ago