Русский
Русский
English
Статистика
Реклама

Бот

Из песочницы Urban Bot или как писать чат-ботов для Telegram, Slack, Facebook на React.js

27.07.2020 22:10:16 | Автор: admin

image


В этой статье я хочу познакомить с новой библиотекой Urban Bot, которая адаптирует React для написания чат-ботов. Ниже я расскажу, зачем эта библиотека появилась на свет, какие дает преимущества и как написать вашего первого чат-бота.


Чат-бот это чаще всего отдельный чат в мессенджере, в котором вы общаетесь не с человеком, а с программой. Он может присылать сообщения в виде текста, изображений, кнопок и многих других UI элементов и реагировать на сообщения от пользователей. Современные чат-боты это полноценные UI приложения внутри мессенджеров.

В отличии от большинства чат-бот библиотек, которые чаще всего просто оборачивают http запросы в функции с готовыми аргументами и предоставляют подписки вида bot.on('message', callback), иногда позволяя передавать контекст между вызовами, Urban Bot предлагает совершенно иной подход к разработке чат-ботов через декларативное программирование и компонентный подход. Живой пример, написанный на Urban Bot, вы можете попробовать в Telegram, cсылка на чат-бот, и посмотреть код на GitHub.


Как мы заметили выше, чат-боты это полноценные UI приложения. А какой язык в 2020 и какая библиотека наиболее подходит для разработки UI приложений? Правильно, JavaScript и React. Такая интеграция позволяет легко и непринужденно строить чат-боты любой сложности без единого знания об API мессенджеров. Далее я расскажу, как создавать простые компоненты и на их основе строить сложных чат-ботов, работать с навигацией, создавать диалоги любой вложенности, писать одно приложение и запускать в любых мессенджерах, и многое другое.


Отправка сообщений


Так выглядит самый простой пример на Urban Bot. Для отправки текстового сообщения нам нужно создать функцию и вернуть из него готовый компонент Text с текстом внутри, который мы хотим отправить. Когда компонент отрендериться, все пользователи чат-бота получат сообщение "Hello, world!".


import React from 'react';import { Text } from '@urban-bot/core';function App() {    return (        <Text>           Hello, world!        </Text>    );}

Изображение можно отправить так:


import React from 'react';import { Image } from '@urban-bot/core';function App() {    const imageByURL =  'https://some-link.com/image.jpg';    return <Image file={imageByURL} />;}

Urban Bot имеет готовый набор компонентов, для каждого вида сообщений, для файлов File, для кнопок ButtonGroup и много других, подробнее можно взглянуть здесь. В каждый из них можно передать определенный набор пропсов, например, имитировать будто бот печатает сообщение 1 секунду <Text simulateTyping={1000}>.


Получение сообщений


Мы рассмотрели как посылать сообщения, давайте разберемся как подписываться на сообщения от пользователей. За подписки в Urban Bot отвечают React Hooks.


Чтобы подписаться на текстовые сообщения, мы можем использовать хук useText.


import React from 'react';import { Text, useText } from '@urban-bot/core';function App() {    useText(({ text }) => {        console.log(`Пользователь отправил сообщение ${text}`);    });    return (        <Text>            Hello, world!        </Text>    );}

Urban Bot предоставляет готовы набор хуков для разных типов сообщений. Например, useImage, если пользователь отправил изображение, useFile и т.д. Полный список здесь. В каждый хук также приходит мета информация, кто отправил сообщение и т.д.


Эхо бот


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


В этом компоненте мы впервые добавим работу с переменными через React хук useState. Этот хук возвращает переменную и функцию, чтобы ее изменять. React.useState нужен, чтобы изменение переменной приводило к ререндеру и, соответсвенно, отправке нового сообщения. Мы определим начальное значение переменной text как "Привет" и передадим в компонент Text. Также мы подпишемся на сообщения от пользователей с помощью хука useText, и будем изменять text через функцию setText. После вызова setText React перерендерит компонент Echo с новым значением, и пользователь получит новое сообщение с тем что он сам отправил боту.


import React from 'react';import { Text, useText } from '@urban-bot/core';function Echo() {    const [text, setText] = React.useState('Привет!');    useText(({ text }) => {        setText(text);    });    return (        <Text>            {text}        </Text>    );}

Кнопки


Давайте также напишем пример с кнопками, сделаем простейший счетчик. Для этого нам понадобятся компоненты ButtonGroup и Button. Каждой кнопке мы определим свой обработчик, который будет менять count на +1 или -1 и будем передавать результат в ButtonGroup в проп title. Мы установим проп isNewMessageEveryRender как false, чтобы при последующих ререндерах отправлялось не новое сообщение с новыми кнопками, а просто изменялось начальное сообщение.


import React from 'react';import { ButtonGroup, Button } from '@urban-bot/core';function Counter() {    const [count, setCount] = React.useState(0);    const increment = () => setCount(count + 1);    const decrement = () => setCount(count - 1);    return (        <ButtonGroup title={count} isNewMessageEveryRender={false}>            <Button onClick={increment}>+1</Button>            <Button onClick={decrement}>-1</Button>        </ButtonGroup>    );}


Мы написали два простых компонента эхо и счетчик. Давайте представим, что мы хотим чтобы они были у нас в одном чат-боте, но работали независимо. Для этого мы можем подключить компонент Router и разделить компоненты по разным путям. Пути это обычные сообщения от пользователей.


Теперь, когда пользователь напишет "/echo" отрендериться компонент Echo, когда "/counter" управление перейдет в Counter. Роуты также могут принимать path как regexp.


import React from 'react';import { Router, Route } from '@urban-bot/core';import { Echo } from './Echo';import { Counter } from './Counter';function App() {    return (        <Router>            <Route path="/echo">                <Echo />            </Route>            <Route path="/counter">                <Counter />            </Route>        </Router>    );}

Визуальный пример, чтобы увидеть как будет работать код.


image


Если вы почувствовали концепцию, то уже поняли, что можно создавать десятки, сотни компонентов, комбинировать их вместе, либо разделять роутером, делиться компонентами между разными чат-ботами и строить действительно сложные SPA внутри мессенджеров.


Форматирование текста


Urban Bot позволяет стилизовать сообщения через привычные HTML теги. Писать жирным <b>, курсивом <i>, зачеркнутым <s>, переносить строки <br /> и так далее, полный список здесь.


Пример
const someCode = `function sum2() {    return 2 + 2;}if (sum2() !== 4) {    console.log('WTF');}`;<Text>    Usual text    <br />    <b>Bold text</b>    <br />    <i>Italic text</i>    <br />    <u>Underscore text</u>    <br />    <s>Strikethrough text</s>    <br />    <q>quote</q>    <br />    <b>        Bold and <s>Strikethrough text</s>    </b>    <br />    <code >Code 2 + 2</code >    <br />    <pre>{someCode}</pre>    <br />    <a href="http://personeltest.ru/aways/github.com/urban-bot/urban-bot">External link</a></Text>


Диалоги


Чат-боты могут вести диалоги с пользователем, что-то спрашивать, реагировать на сообщения в зависимости от ответа пользователя. В Urban Bot встроен компонент Dialog, который позволяет легко создавать диалоги любой сложности.


Пример плоского диалога. Бот задаст первый вопрос, после ответа задаст второй, потом третий, потом запустит callback onFinish с готовыми ответами. На каждом шаге можно обрабатывать ответ пользователя через callback onNext.


import React from 'react';import { Dialog, DialogStep, Text } from '@urban-bot/core';function FlatDialogExample() {    return (        <Dialog onFinish={(answers) => console.log(answers)}>            <DialogStep                content={<Text>Привет, как тебя зовут?</Text>}                 id="name"                onNext={(name) => console.log(name)}            >                <DialogStep                    content={<Text>Cколько тебе лет?</Text>}                    id="age"                >                    <DialogStep                         content={<Text>Из какого ты города?</Text>}                        id="city"                    />                </DialogStep>            </DialogStep>        </Dialog>    );}

Можно получать на следующем шаге прошлый ответ через паттерн render-props .


function FlatDialogExample() {    return (        <Dialog>            <DialogStep content={<Text>Привет, как тебя зовут?</Text>}>                {(name) => (                    <DialogStep                         content={<Text>{`${name}, cколько тебе лет?`}</Text>}                    />                )}            </DialogStep>        </Dialog>    );}

Можно добавить валидацию на каждый шаг.


function FlatDialogExample() {    return (        <Dialog onFinish={(answers) => console.log(answers)}>            <DialogStep                content={<Text>Привет, как тебя зовут?</Text>}                id="name"                validation={{                     isValid: (answer) => answer !== 'Самуэль',                     errorText: 'Самуэль заблокирован.'                 }}            >                // ...            </DialogStep>        </Dialog>    );}

Также возможно построение более сложных диалогов, когда бот отвечает определенным образом в зависимости от ответа пользователя. Для предопределенных ответов можно использовать кнопки.


import React from 'react';import { Dialog, DialogStep, Text, ButtonGroup, Button } from '@urban-bot/core';function TreeDialogExample() {    return (        <Dialog>            <DialogStep                content={                    <ButtonGroup title="Привет, что вы хотите купить?">                        <Button id="hat">Футболка</Button>                        <Button id="glasses">Очки</Button>                    </ButtonGroup>                }            >                <DialogStep                    match="hat"                    content={                        <ButtonGroup title="Футболка какого размера?">                            <Button id="m">S</Button>                            <Button id="s">M</Button>                            <Button id="l">L</Button>                        </ButtonGroup>                    }                />                <DialogStep                    match="glasses"                    content={                        <ButtonGroup title="Очки какого цвета?">                            <Button id="black">Черный</Button>                            <Button id="white">Белый</Button>                        </ButtonGroup>                    }                />            </DialogStep>        </Dialog>    );}

Состояние


Что вы можете использовать для управления состоянием? Все то же что и в любом React приложении. Можете использовать React useState и передавать состояние ниже по дереву компонентов через пропсы или React Context. Можно использовать библиотеки для управления состоянием: Redux (пример), MobX (пример), Apollo и любые другие, которые обычно используют вместе с React, вы можете даже переиспользовать готовые части из готовых React Web или React Native приложений, так как Urban Bot использует тот же чистый React, который работает в миллионах приложений.


Сессия


Urban Bot запускается на сервере, соответсвенно, все логика от всех чатов и пользователей обслуживается на одном железе, что кардинально отличается от стандартных React приложений, которые запускаются на стороне каждого клиента. Urban Bot решает эту проблему на своей стороне и отображает приложение уникальным для каждого пользователя, так что, если вы уже писали на React веб или мобильные приложения, вы не почувствуете разницу.


В любом примере на Urban Bot уже вшита работа с сессией. Например, в примере ниже у каждого пользователя, кто зайдет в персональный чат-бот, будет его собственный счетчик.


function Counter() {    const [count, setCount] = React.useState(0);    const increment = () => setCount(count + 1);    const decrement = () => setCount(count - 1);    return (        <ButtonGroup title={count} isNewMessageEveryRender={false}>            <Button onClick={increment}>+1</Button>            <Button onClick={decrement}>-1</Button>        </ButtonGroup>    );}

Если нам понадобится глобальный счетчик, то к этому примеру можно сделать хук, который будет содержать уже общую информацию.


function Counter() {    const [count, setCount] = useGlobalCount();   // ...}

Также, в любом месте приложения мы можем получить данные о конкретном чате, какой пользователь написал, с каким никнеймом и т.д. Если чат-бот персональный, то chat и from будут совпадать.


import React from 'react';import { Text, useText, useBotContext } from '@urban-bot/core';function UserId() {    const { chat } = useBotContext();    useText(({ from }) => console.log(`Пришло сообщение от ${from.username}`));   return <Text>Чат id {chat.id}</Text>;}

Типизация


Urban Bot написан на TypeScript, соответсвенно проект полностью типизирован, и если вы пишете на TypeScript, вам будет очень удобно.


Запуск в мессенджерах


Большой плюс Urban Bot, что он не привязан ни к одному мессенджеру. Есть основной пакет @urban-bot/core, который позволяет создавать абстрактных чат-ботов, а уже их подключать к определенным мессенджерам. В данный момент есть поддержка Telegram, Slack, Facebook. В дальнейшем, мы планируем добавлять любые мессенджеры, где есть чат-боты и открытое API. Если вам интересно, и вы хотите писать Urban Bot приложения для других мессенджеров, скажем Viber, Discord или у вас есть свой мессенджер то пишите к нам в группу https://t.me/urbanbotjs, одной просьбы будет достаточно, чтобы появилось большая мотивация реализовать ваш функционал.


Теперь перейдем к практике. Выше мы создавали компоненты и приложение, но не запускали его. Для запуска нам нужно выбрать мессенджер или мессенджеры, в которых мы хотим запустить наше приложение.


Скажем, у нас есть готовое приложение App и мы хотим его запустить его в Telegram. Для этого нам понадобится класс UrbanBotTelegram из пакет @urban-bot/telegram. Функция render из @urban-bot/core подобная ReactDOM.render и компонент Root. Мы создаем экземпляр UrbanBotTelegram и передаем туда бот токен из Telegram, также можно передать isPolling, чтобы не настраивать вебхук, и бот работал локально. Готовый экземпляр мы передаем в компонент Root, и оборачиваем наше готовое приложение и, соответсвенно, передаем все в функцию render, которая запустит все процессы.


Более подробная инструкция с видео как разрабатывать локально и деплоить Telegram бота можно прочитать в инструкции.


import React from 'react';import { render, Root } from '@urban-bot/core';import { UrbanBotTelegram } from '@urban-bot/telegram';import { App } from './App';const urbanBotTelegram = new UrbanBotTelegram({    token: 'telegramToken',    isPolling: true,});render(    <Root bot={urbanBotTelegram}>        <App />    </Root>);

Если нам нужно запустить два и более мессенджера, просто используем пакеты других мессенджеров, передаем туда нужные данные и делаем по аналогии с Telegram.


// ...import { UrbanBotSlack } from '@urban-bot/slack';// ...render(    <Root bot={urbanBotTelegram}>        <App />    </Root>);const urbanBotSlack = new UrbanBotSlack({    signingSecret: 'slackSigningSecret',    token: 'slackToken',});render(    <Root bot={urbanBotSlack}>        <App />    </Root>);

Прямой вызов API


С помощью Urban Bot вы можете создавать чат-ботов просто описывая их через компоненты. А что если вам будет нужно вручную вызвать API? Каждый экземпляр UrbanBot* содержит в себе API клиент для активного мессенджера. Рассмотрим пример для Telegram.


Мы можем получить bot с помощью хука useBotContext. bot содержит client и type c типом мессенджера. client будет представлять собой экземпляр библиотеки node-telegram-bot-api . В любом месте приложения можно получить client и вызвать любой метод на ваше усмотрение, скажем блокировать пользователя, если он написал нецензурное сообщение.


import React from 'react';import { useText, useBotContext } from '@urban-bot/core';function SomeComponent() {    const { bot } = useBotContext();    useText(({ text, chat, from }) => {        if (text.includes('бл***')) {            bot.client.kickChatMember(chat.id, from.id);        }    });    // ...}

В каждом мессенджере уникальный API. Если вы разрабатываете несколько мессенджеров одновременно, можно отделять функционал сравнивая bot.type.


import { useBotContext } from '@urban-bot/core';import { UrbanBotTelegram } from '@urban-bot/telegram';import { UrbanBotSlack } from '@urban-bot/slack';function SomeComponent() {    const { bot } = useBotContext();    if (bot.type === UrbanBotTelegram.type) {        // telegram api        bot.client.kickChatMember(/* ... */);    }    if (bot.type === UrbanBotSlack.type) {        // slack api        bot.client.conversations.kick(/* ... */);    }    // ...}

Как попробовать?


У Urban Bot есть стартер, который позволит вам начать разрабатывать чат-ботов за минуту, сделан по аналогии с create-rect-app. Все что вам нужно, чтобы попробовать Urban Bot это выполнить команду в терминале для


TypeScript


npx create-urban-bot my-app

JavaScript


npx create-urban-bot my-app --template js

Команда склонирует шаблон приложения с нужными зависимостями и скриптами на ваш компьютер, и вам останется только открыть проект, передать ваши токены в .env файл и расскоментировать мессенджеры, которые вы хотите разрабатывать. Видео инструкция.


Итого


Несмотря на то что Urban Bot запустился только недавно, на мой взгляд это библиотека с огромным потенциалом. Только представьте, если у вас есть базовые знания React, вы можете написать чат-бот любой сложности на все возможные платформы, создавать и использовать библиотеки с готовым набором компонентов на манер ui-kit, переиспользовать код между вашими другими UI приложеними на React, будь то web или mobile.


Если вы уже разрабатывали чат-ботов, попробуйте Urban Bot, вы почувствуете как библиотека делает за вас кучу работы. Если никогда не разрабатывали, но имеете представление о React, то напишете вашего первого чат-бота за 5 минут. Если вам понравилась идея и хотите, чтобы проект развивался дальше, вступайте в нашу группу в Telegram, ставьте звезду на гитхабе, будем рады любому фидбеку.


Полезные ссылки


Сайт
Github
Группа в Telegram
Наглядный чат-бот в Telegram, с открытым кодом.
Как создать Todo List чат-бот в Telegram с помощью React.js

Подробнее..

Из песочницы Бот Умный планировщик понимает с полуслова

29.07.2020 14:20:10 | Автор: admin
Если вы когда-нибудь желали иметь личного слугу, который бы напоминал вам обо всем, о чем вы ему скажите, но не имели возможности нанять такого, то разработанный мною бот станет ему достойной заменой.



Хотите проверить функционал? Напишите в лс боту по этой ссылке и он ответит вам.

А тем, кому интересно как он работает и как 16-летний школьник смог написать его, я с удовольствием расскажу всё в подробностях в этой статье.

Предыстория


Началось все с другого моего бота для вк на node js, который расшифровывал голосовые сообщения (и так как таких ботов пруд пруди, я решил не писать статью о его разработке, хотя и он имеет несколько отличительных особенностей). После того, как я запустил его, мой отец предложил мне разработать другого бота для нашего семейного чата в телеграмме. Суть этого бота была простой извлекать дату и время из текстового сообщения человека, и, используя телеграмовские отложенные сообщения, создавать напоминания прямо в семейном чате.

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

Разработка


Общие сведения


Этот бот написан на node js и живет на heroku.

Он способен хранить любые текстовые напоминания с точностью до минуты.

Также он может работать в групповых беседах.

На данный момент бот распознает дату и время только на русском языке.

SmartScheduler open source проект, доступный на моем гитхабе.

Извлечение даты и времени из сообщения


Начать я решил с самой сложной задачи: разбиения текстового напоминания на дату и на само напоминание. Для этого пришлось учесть все возможные стандарты написания даты человеком, от в 12:00 до в следующее воскресенье в без двадцати пяти восемь вечера.

Была создана большая база данных (constValues.js), хранящая в себе константные выражения и их свойства, которые человек использует в своей речи. Затем были написаны функции для распознавания каждого варианта написания времени.

К примеру для распознавания даты в виде через X %тип_времени% используется функция FindAdditiveLiterals, а для поиска дня недели FindDayOfWeek.

Для каждого варианта обозначения времени выставлялся свой приоритет.

В итоге алгоритм работы парсера выглядит следующим образом:

  1. Исходная строка делится на слова. Слов, в которых производится поиск времени, не может быть больше 40.
  2. Массив слов пропускается через функцию конвертации слов в числа.
  3. Находятся все указания времени в сообщении, а также помечаются использованные в указаниях слова (например в указании будильник 8 часов отмечаются слова 8 и часов).
  4. Если какая-то характеристика времени не была найдена (например месяц) в текстовом сообщении, то берется текущее значение этой характеристики.
  5. Для окончательного вердикта выбираются указания времени с наибольшим приоритетом и смежные указания, имеющие одинаковое исходное слово (например в слове 10:30 одновременно указан и час, и минута).
  6. После выбора окончательных характеристик времени формируется штамп времени из выбранных минуты, часа, дня, месяца и года.
  7. Из массива слов удаляются все помеченные слова, а из оставшихся формируется текст напоминания.
  8. Если сформированный штамп времени больше текущего времени, то мы считаем что такое напоминание пригодно и функция возвращает объект типа
    { string: answer, string: text, date: date }

    В противном случае функция возвращает объект
    { string: answer, string: text }
    (answer ответ для пользователя, text текст напоминания, date дата напоминания).

База данных напоминаний


Следующими вопросами были где хранить все напоминания и как следить за их выполнением.

Изначально я хотел воспользоваться библиотекой node-schedule, но отказался от этой идеи, так как я не хотел засорять оперативную память всеми напоминаниями.

Вместо этого я решил изучить принцип работы SQL баз данных и создать свою.

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

Чтобы взаимодействовать с бд я написал небольшой скрипт (db.js), в котором реализовал все необходимые функции, такие как инициализация бд, получение списка напоминаний и т.д.

В моей базе данных присутствует две таблицы: первая для хранения напоминаний, вторая для хранения часовых зон пользователей (о ней чуть позже).

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

Также я добавил отображение всех напоминаний через команду /list.



(рядом с каждым напоминанием есть кликабельная команда /N, которая удаляет его при клике на неё)

Настройка часового пояса


До того, как я решил написать эту статью и выложить её на Хабр, в переменных среды был захардкожен часовой пояс Москвы. Для пользования внутри нашей семьи этого было достаточно, но для того, чтобы воспользоваться всеми прелестями и удобствами жизни с ботом SmartScheduler мог каждый, я решил добавить индивидуальную настройку часового пояса.

Для выполнения настройки требуется написать команду /tz, о чем предупредит бот пользователя, если он еще не указал свой часовой пояс:



(из-за того что часовой пояс не указан, в ответе используется не локальное время, а гринвичское)

При вводе команды /tz запускается процесс определения часового пояса и появляется клавиатура с тремя кнопками:



  1. Использование локации пользователя.
  2. Ручной ввод.
  3. Отмена.

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

Пример использования


Вторая кнопка позволяет вручную ввести свою часовую зону в формате HH:MM,
где плюс или минус, HH часы, MM минуты.

Пример использования


Третья кнопка отменяет процесс определения.

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

Финальные доработки


Закончив с основным функционалом, я добавил главную клавиатуры с основными функциями, откорректировал ответы для команд /start и /help, ну и по мелочам.

Также я решил заменить часовой пояс по умолчанию для всех пользователей на Московский.

Результат


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

Больше не нужно листать календарь в поиске нужного дня и крутить часы для выставления нужного времени, достаточно по-человечески сказать боту что и когда, а дальше он сам все сделает.

Заключение


До разработки ботов на node js я был совершенно не знаком с javascriptом, посему все знания, которые я использовал в написании кода, брались из интернета, где зачастую можно найти не совсем то, что тебе на самом деле нужно. Из-за этого, скорее всего, где-то в моем коде встречаются очень глупые ошибки, для определения которых я еще недостаточно много знаю.

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

Но если данная разработка будет пользоваться спросом, то я с удовольствием продолжу улучшать её, а если у вас есть какие-то идеи или вы обнаружили баг, то добро пожаловать на гитхаб проекта. У меня уже есть идеи где и как что изменить (например переписать ужасный спагетти-код в модуле парсинга с использованием нормального Visitor-паттерна), а также в планах добавление поддержки английского языка.

Надеюсь, что этот бот поможет вам также, как помогает мне и моей семье в повседневных делах.

Спасибо за внимание!
Подробнее..

Сервисы на нейронке, которые генерируют поздравления на 8 Марта

05.03.2021 18:07:04 | Автор: admin

К международному празднику разработчики расчехлили кодомёты и явили миру сервисы, генерирующие упоротые поздравления с помощью нейросетей. Делюсь находками.

Neural Shit Bot

Телеграм-бот @NeuralShit помогает придумать дегенератские поздравления c 8 марта с помощью нейросетей StyleGAN2 и AiTextgen. Каждое поздравление сопровождается не менее креативной картинкой. Например, вот:

Генератор открыток с8 Марта

Более культурный сервис генератор открыток на 8 Марта разработали Work Solutions: worksolutions.ru/neuro-march. "Мы обучили нейросеть на тысячах фотографий с цветочками, а также научили ее генерировать поздравительный текст. Теперь она может создавать новые уникальные нейро-открытки!" - говорится в тексте на сайте. После создания открытки можно тут же отправить её адресату в соцсетях.

Яндексовский генератор открыток

Сервис поможет придумать более-менее персональное поздравление, не похожее на эти все здоровья, счастья, любви. Норм вариант, чтобы придумать массовую открытку для рассылки в Ватсапе: yandex.ru/lab/postcard

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

Всем уникальности, эксклюзивности и милых открыток! Да пребудет с нами нейронка.

Подробнее..

Пробуем заработать на сообществе ВКонтакте с помощью пранк бота (Call Prank)

08.11.2020 18:18:22 | Автор: admin

Предисловие:


У меня есть небольшой заброшенный паблик (26к подписчиков), раньше там стоял пранк бот от чатуса, это приносило мне 300-800 рублей в день пассивного заработка, если сделать качественную рассылку можно было получить 1000+. Летом была прекращена поддержка пранк бота, теперь если попытаться заказать звонок, пишет что проходят технические работы. Из-за этого мои много миллионные мечты улетели в трубу. Недавно мой бывший редактор, по совместительству друг, переслал сообщение от фейкового аккаунта, с рассказом о новом сервисе и сказал проверь, х*ли. Я подумал, ну какой нормальный сервис будет пиариться с помощью спама, поэтому купил себе левый аккаунт, создал паблик и попробовал установить через их сервис бота в сообщество. К большому удивлению пранк бот заработал и чтобы окончательно убедиться я попробовал купить звонок. Я его купил, деньги пришли в личный кабинет, естественно я был рад но созрел новый вопрос смогу ли я вывести эти деньги? Поэтому я решил установить бота в своё старое сообщество и посмотреть какой будет выхлоп. Ну шо, погнали?)

Начало новой жизни, с красивыми тёлками и ламбой в гараже:


Когда я только начинал знакомиться с этим сервисом, я не мог найти ссылку на сайт, чтобы авторизоваться Оказалось что у них нет сайта, а весь функционал (Авторизация, добавление бота, вывод средств) встроен в бота. Возможно они не умеют делать сайты, возможно им лень, в общем не знаю в чём причина того что они не сделали сайт или приложение, но если честно так даже удобнее. Так как паблик тут подключается за пару секунд, а дальше тебе придётся только мониторить баланс и в принципе больше никаких действий делать не надо, думаю бот подходит для этого идеально.

  1. Авторизация
    Принцип как на всех сайтах с авторизацией ВКонтакте, переходим по ссылке и нас перенаправляет на страничку где надо нажать Разрешить, а после в чат с ботом. До сих пор удивлён что это реализовано в боте, раньше такого не видел но думаю такое было уже давно.

  2. Подключение сообщества
    Тоже самое что и с авторизацией. Только нужно указать ссылку на сообщество а дальше перейти по ссылке и снова нажать на кнопку Разрешить

  3. Панель управления
    Самая обычная панель управления, ничего интересного. Можно удалить/выключить бота, обновить права на api, итд. Кстати, время установки бота указывается на 3 часа раньше чем МСК.

  4. Тестим пранк бота
    Всё как в чатусе, только гораздо больше категорий. Больше нечего сказать, обычный пранк бот, главное работает.

  5. Рассылки
    Пункта в панели не нашёл, поэтому написал в техподдержку, отвечали долго, где-то часов 10. В двух словах на данный момент рассылки проводят они сами, подбирают время, составляют всё итд. Сказали ещё что функция будет доступна немного позже. А знаете, пусть сами делают их, чтоб я вообще время не тратил) Если же вам они не нужны, то вы можете отказаться, чего делать я вам не советую, потому что рассылки это ключик к нормальному доходу. Я спросил когда вы сделаете рассылку, они ответили что по расписанию рассылки будут в течении 12 часов.


Первая прибыль:


Рассылку они сделали в 15:30, я примерно в это же время делал. С момента установки бота и до момента рассылки прошло около 15 часов, за это время у меня заказали 4-е розыгрыша и 1-но поздравление, суммарная прибыль составила всего лишь 46 руб. Сразу хочу сказать что это было в будний день, утром. Не очень популярное время для заработка. После рассылки ситуация изменилась в корни. Изначально я думал что паблик полностью задохнулся, но нет, там остались люди которые готовы пранковать своих друзей несмотря ни на что) За период с 15:30 до 21:00 бот смог принести мне 708 рублей, мало но так как я получил эти деньги ничего не делая приятно :)


Момент истины, получится ли вывести и не зря ли я радовался Выводить можно на Яд, киви, payeer и карту, на карту не могу, так как минималка 1000 рублей, поэтому выведу на киви. Выбираю киви, ввожу номер, ввожу сумму и подтверждаю выплату. Через 3 минуты начал расстраиваться, через 5 минут почти плакал, а через 10 забил на всё. И как бывает в фильмах выплата пришла. Как я понял пополнения в пранк боте и выплаты из конструктора сделаны через енота, так что выводят не админы а вывод правда автоматический, только не совсем моментальный (может быть это только со мной произошла такая задержка, второй раз пока не выводил) Ссылка на конструктор vk.com/public190102630 (Выплачивает) Ребят, если они начнут кидать, пишите комментарии или в лс, удалю публикацию чтобы не дезинформировать людей
Подробнее..

4 угла хорошо, а 6 лучше гексагональные шахматы в консоли и с ботом

21.08.2020 14:20:51 | Автор: admin
Привет!

Мы учимся на первом курсе бакалавриата Прикладная математика и информатика в Питерской Вышке. Во время работы над семестровым командным проектом по С++ мы решили написать компьютерную версию Интеллектора с ботом шахматную игру на гексагональной доске с особыми фигурами.

В этой статье мы расскажем о том, как шла разработка игры, как приручить гексагональную доску, как можно рисовать в командной строке, а также как мы сделали бота, которого почти не можем победить.



В нашей команде 3 человека: Юра Худяков, Валера Головин, Миша Саврасов. Для каждого из нас это первый командный проект, так что в процессе работы мы не только писали на плюсах, но ещё и учились работать в команде и пользоваться системами контроля версий (в нашем случае git). В проекте есть некоторое количество странностей, в частности, велосипедов есть хорошие готовые решения, которыми можно было бы воспользоваться. Однако цель нашего проекта заключалась в том, чтобы получить опыт, так что многое мы придумывали и реализовывали самостоятельно.

Что такое Интеллектор?


Для начала стоит объяснить, что за игру мы писали.

Игра Интеллектор появилась недавно и пока что набирает популярность. В этом году в Петербурге прошел первый открытый чемпионат.


Интеллектор отличается от шахмат структурой поля, правилами и набором фигур. Впрочем, многие элементы похожи: например, в игре есть фигура Прогрессор, которая выполняет роль Пешки. Она ходит только вперёд и может превратиться в другую фигуру, когда достигает крайнего ряда.

Королём здесь выступает фигура, которая называется Интеллектор. Цель игры срубить эту фигуру, а не поставить ей мат (хотя это почти одно и то же).

Отличия в механике игры возникают из-за специфики поля. Поле Интеллектора симметрично, и это существенно отличает его от шахмат с их королевским и ферзёвым флангами.

Для понимания этой статьи знание правил и умение играть не потребуются.

Общая архитектура


Что мы хотели получить в нашем приложении?


Для того, чтобы игра заработала, нужно реализовать её основную составляющую: логику игры. В неё входит модель доски и правила ходов. Кроме того, для удобства стоит хранить историю ходов и реализовать отмену/повторение хода.

Доску нужно вывести на экран и позволить пользователю играть. Этим занимается графическая составляющая игры интерфейс. В удобном интерфейсе должны быть меню и настройки.

В конце концов, нужен оппонент для игры. Мы решили сделать для этих целей бота, чтобы игрок мог соревноваться с компьютером. При этом сложность бота должна быть регулируемой.

План приложения:


  1. Логика игры
    • Модель гексагональной доски
      Хранится в виде двумерного массива гексагональных клеток
    • Правила перемещения фигур
      Проверка допустимости хода, получение всех доступных ходов для фигуры, для игрока
    • История ходов
      Отмена и повторение хода
  2. Интерфейс
    Планировали 2 интерфейса: ncurses и Qt. В проекте реализован только ncurses, подробнее в разделе Интерфейс.
    • Вывод поля
      Отрисовка и обновление поля в консоли
    • Перемещение курсора клавишами клавиатуры, игра без мышки
    • Отображение текстовой истории ходов
    • Отображение главного меню
  3. Бот
    • Случайный бот
    • Жадный бот
    • Альфа-бета бот
      Оптимизировано перебирает все ходы

Как это сделано?


Очень упрощенно архитектуру приложения описывает эта схема:


Раздел Game отвечает за всю игровую логику и хранит доску.

Когда включена игра с компьютером, Game взаимодействует с ботом из Bot

Controller берёт данные об игре из Game и передаёт их в Interface для отображения игрокам. Interface в свою очередь возвращает результат взаимодействия с пользователем обратно в Game через Controller.

Промежуточное звено в виде контроллера пригождается в том случае, когда интерфейсов несколько (изначально мы планировали сделать 2 интерфейса: консольный и графический). Все они единым образом общаются с игрой через контроллер, вместо того, чтобы каждый из них делал это по-своему.

Технические подробности


Модель игры


Гексагональная доска


Рассмотрим раздел Game из схемы выше. Он должен хранить доску и обрабатывать всю внутриигровую логику.

Для лучшего понимания можно прочитать статью, из которой мы взяли эту идею.

Всю доску мы будем хранить в двумерном массиве клеток, элементы которого индексируются парами координат (w,h) как показано на рисунке ниже. Такой выбор координат кажется естественным, но он неудобен для описания перемещения фигур (проследите, скажем, как меняются координаты при перемещении по диагонали).


Координаты клеток по горизонтальной оси w и вертикальной оси h

Для удобства описания перемещения фигур мы будем использовать трехмерные координаты. Выберем некоторую клетку в качестве опорной с координатами {0,0,0} (для удобства она будет совпадать с клеткой (0, 0) массива).


Трехмерные координаты клеток относительно центральной клетки с координатами {0,0,0}

Смещение вдоль диагонали справа налево, снизу вверх обозначим координатой x, смещение снизу вверх координатой y и смещение вдоль диагонали слева направо, снизу вверх координатой z. При переходе в соседнюю клетку соответствующая координата будет меняться на единицу. Таким образом, каждая клетка получает три координаты, как на рисунке выше.

При этом клетки нумеруются неоднозначно. Например, если из центральной клетки с координатами {0,0,0} мы сдвинемся влево вниз, а затем вверх, то получим координаты клетки {0,1,-1}. Но эта же клетка имеет координаты {1,0,0} если прийти в нее напрямую из центральной клетки, как видно на предыдущем рисунке.


Другой вариант задания координат клетки {1,0,0}.

Обход любой клетки по циклу влево-вниз вверх вправо вниз приводит нас в ту же клетку, но добавляет к её координатам вектор {-1,1,-1}, сумма координат которого равна -1. Выполняя мысленно такой обход в ту же или в обратную сторону несколько раз, мы можем изменять координаты любой клетки на эквивалентные, которые будут отличаться на вектор, пропорциональный {-1,1,-1}. Чтобы избавиться от неоднозначности, в каждом классе эквивалентности выберем в качестве представителя тройку координат, сумма которых равна нулю. Такой выбор координат является единственным (докажите!).

Опишем далее алгоритм перевода из двумерных координат в трехмерные координаты и наоборот внутри класса Position.

Position(int w, int h) // конструктор из двумерных координат        : x_{-w/2  w % 2 - h}        , y_{w % 2 + 2 * h}        , z_{w / 2  h} {}int posW() const { // метод для получения первой координаты двумерного массива    return -x_ + z_;}int posH() const { // метод для получения второй координаты двумерного массива    return (x_ + z_  (x_ + z_)%2) / 2 + y_;}

Обратите внимание, что конструктор выдает координаты (x,y,z), сумма которых равна нулю. При этом конвертация координат (x,y,z) в (w,h) работает корректно для любого набора координат (сумма не обязательно должна быть равна нулю).

Как мы нашли все эти формулы? Методом научного тыка: путем анализа изменения трёхмерных координат при сдвиге одной из двумерных координат на 1 (конструктор) и в обратную сторону (методы).

Пользуясь трехмерными координатами, мы легко можем проверить, что клетки лежат на одной прямой. Например, для проверки, что две клетки лежат на одной диагонали z, надо найти вектор, соединяющий эти клетки, и проверить, что в его классе эквивалентности есть вектор вида {0, 0, z}. Z может быть любым это число дает расстояние между клетками. Очень просто будет реализовывать проверку хода на корректность и находить все клетки, доступные для хода.

В двумерном массиве, который представляет доску, будем хранить информацию о расположении фигур. В каждой клетке, если там стоит какая-то шахматная фигура, будем хранить её тип и цвет.

В нашей реализации в классе доски мы храним только типы фигур в клетках. Нам нужен класс, который сможет по этой доске находить все возможные ходы для фигур и проверять корректность ходов.

Ходы для фигур


Мы сделали класс FigureMoveValidator, у которого 6 наследников для каждого типа фигуры (можно было обойтись и без наследников, если в каждом методе делать switch case на тип фигуры). Конструктор класса имеет 2 параметра: позиция и ссылка на доску. Также в классе есть два метода allMoves и checkMove.

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

Теперь checkMove. Мы помним, что умеем проверять, лежат ли фигуры на одной прямой. Если проверим, что на этой прямой нет других фигур, то получим готовый метод для Доминатора (аналог ладьи). Если фигуры лежат на одной прямой, то мы можем найти расстояние между ними, и получить методы для Прогрессора (пешка), Дефенсера (ходит как король), Интеллектора (король, только не может рубить) и Либератора (может ходить через одну клетку в любую сторону). Остался еще агрессор (аналог слона), который ходит в клетки по диагоналям в шесть направлений от текущей (из клетки {0, 0, 0} в {0, 1, 1}, в {0, 2, 2} и т.д.: см. серые клетки на картинке ниже). Для этой фигуры можно попробовать обнулить одну из координат и проверить, что оставшиеся 2 координаты равны по модулю (спасибо трёхмерным координатам).


Возможные ходы для агрессора

Теперь надо придумать, что делать с ходами. Создадим класс Move, который будет хранить всю необходимую информацию для хода. Мы решили хранить 2 позиции и 4 фигуры: позицию, с которой ходит фигура, позицию, куда она придет, и информацию о том, какие фигуры стояли в каждой из этих клеток и какие будут стоять после применения хода. Это позволит легко реализовать систему истории ходов и откат ходов.

Интерфейс


Архитектура


Приложение написано на консольной библиотеке ncurses (вот туториал к ней). Эта библиотека позволяет создавать псевдографику в консоли. К примеру, на ней основаны Midnight Commander и Nano.

Выбор может показаться весьма странным: есть много других библиотек, более красивых, удобных и кроссплатформенных. Он связан с тем, что изначально мы планировали сделать 2 интерфейса: консольный и графический. Написать 2 интерфейса к моменту сдачи проекта мы не успели и вместо этого сделали больше фич в консольной версии. Хотя архитектурно приложение всё ещё рассчитано на различные интерфейсы.

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

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

Отображение создаёт свою версию доски, но с нужными ей дополнительными параметрами, такими как положение курсора и цвет клеток. Эти параметры не могут быть добавлены в основную модель, так как разным отображениям нужны разные параметры. Например, в консольном интерфейсе нужно хранить положение курсора, а в графическом нет, так как выбор и передвижение фигуры происходит при помощи мышки.

Вот что происходит, если игрок захочет узнать доступные для хода поля:

  1. Игрок перемещает курсор на поле с фигурой и нажимает пробел
  2. Поле с фигурой помечается как выбранное
  3. Интерфейс обращается к методу selectCell у контроллера
  4. Метод selectCell обращается к методу allFigureMoves у модели
  5. allFigureMoves создаёт FigureMoveValidator, который вычисляет все доступные ходы
  6. allFigureMoves передаёт найденные ходы обратно контроллеру
  7. Контроллер передаёт их интерфейсу
  8. Интерфейс перерисовывает поле, подсветив доступные поля


Курсор находится в середине доски: на бледно-синей клетке. До того, как переместить его в это положение, пользователь выбрал фигуру. Доступные ей ходы подсвечиваются зеленым цветом, а сама выделенная клетка фиолетовым.

Как рисуется поле?


Консольный интерфейс отрисовывается в прямоугольном окне со строчками текста. Если ставить символы в нужных местах и раскрашивать их, получается картинка:


(Злой Пакман, нарисованный буквами о)

Функция move(int y, int x) в ncurses меняет текущую позицию, а функция addch(chtype c) добавляет символ и смещает текущую позицию на 1 вправо (x > x+1).

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

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

Ncurses позволяет разработчику изменять атрибуты текста при выводе их в консоль (цвет, жирность, мерцание). Для этого в коде пишется:

attron( *attributes* );addch(c);attroff( *attributes* );

Каждый символ имеет собственный цвет и цвет фона. Современные консоли поддерживают максимум 256 цветов, поэтому приходится работать с ограниченным набором: довольно грустно с точки зрения цветового дизайна.

Изображения для вывода можно хранить в коде (так мы делали изначально), а можно в отдельных файлах и читать из них при запуске программы. Для этого мы придумали собственный формат файла *.btn.

В нём хранится текстовая картинка, которую прочитает и выведет игра. Например, фигура, или надпись White wins/Black wins, или кнопка меню. При этом иногда может понадобиться прозрачность, чтобы не перезатирать нарисованное ранее. Для этого можно в первую строчку добавить решётку # и после список прозрачных символов, которые будут проигнорированы при выводе.

Например, пусть у нас на экране нарисованы 3 прямоугольника:


Добавим в центр прямоугольник из такого файла:

#CAAAAAAAAAACCCCCCCAACCCCCCCAACCCCCCCAACCCCCCCAACCCCCCCAAAAAAAAAA

И получим следующую картинку:


(жёлтым подсвечено для наглядности)

Особенно этот формат пригодился при разработке меню.

Меню


В игре также есть меню, которое содержит настройки и отрисовывается до начала игры и после её завершения.

Кнопки меню читаются из файлов *.btn. На этих кнопках должен быть крупный красивый текст. Красиво рисовать с помощью ASCII символов мы не умеем, зато умеет figlet утилита для вывода ASCII-текста разными шрифтами:


Кнопки обрамляют надписи, прочитанные из файла:


Затем они центрируются и последовательно выводятся:


В некоторые менюшки можно провалиться и, например, настроить сложность и цвет бота:


Самая интересная часть разработки системы меню это объединение её элементов в одну систему. Этим занимается отдельный элемент системы, который мы назвали мультиплексор. Название навеяно терминальными мультиплексорами.

Мультиплексор принимает нажатую пользователем клавишу и рассылает её во все отображаемые сейчас меню. Каждое меню само решает, что с клавишей делать: проигнорировать или как-то обработать. Результат обработки меню возвращает мультиплексору, который решает, что делать дальше: закрыть меню, создать новое, изменить настройки, закрыть приложение

Такой подход оказался удобен для наших потребностей, хотя в общем случае его может не хватить: 2 разных меню могут реагировать на одну и ту же клавишу, и у пользователя должна быть возможность выбрать, какое именно меню должно реагировать. Решением могла бы быть специальная комбинация клавиш, которая бы позволяла переключаться между разными меню. Например, как в tmux. Но это overkill и он не потребовался.

Бот


Как уже упоминалось выше, в нашей игре есть бот. Мы постарались сделать так, чтобы интересно было и новичку, и опытному игроку.

Перед описанием ботов хотелось бы рассказать про некоторые детали реализации. Каждой фигуре мы назначили некоторый вес. Чем он больше, тем ценнее эта фигура. Мы определяем, насколько хорошим является положение на доске, по формуле (сумма весов белых фигур) (сумма весов черных фигур). Белому игроку выгодно максимизировать это выражение, а черному минимизировать.

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

Всего в игре есть три разных вида ботов:

  • RandomBot бот делает случайный возможный ход. Создавался для тестирования.
  • GreedyBot бьет самую дорогую фигуру противника, а если не может бить, ходит случайно.
  • AlphaBetaBot бот, который использует алгоритм альфа-бета отсечения для выбора лучшего хода в дереве игры.

Когда начали экспериментировать с оптимизациями, мы поняли, что без юнит-тестов для бота обойтись не получится, поэтому создали брата-близнеца для AlphaBetaBotа, которого назвали OptimizedAlphaBetaBot. Все идеи для оптимизации мы испытывали именно на OptimizedAlphaBetaBot, а юнит-тесты помогали убедиться, что два брата-близнеца находят одинаковый по полезности ход. RandomBot сослужил нам хорошую службу, генерируя случайные расстановки фигур на доске. Для этого достаточно было попросить RandomBotа сходить несколько десятков раз за обе стороны.

Всего в OptimizedAlphaBetaBot были реализованы 3 крупных оптимизации (здесь они представлены в порядке убывания полезности):

  • Использование откатов ходов. После этой оптимизации больше не нужно было множество раз копировать доску, чтобы сделать какой-то ход.
  • Написание нового класса с говорящим названием FigureKeeper, который хранит список фигур каждого цвета, которые сейчас есть на доске. Стало возможным обойти один std::vector вместо всей доски.
  • Запоминание уже обработанных позиций с помощью std::unordered_map и Zobrish hashing.

Кроме крупных оптимизаций были и более мелкие. Например, если перед сортировкой просчитать все стоимости позиций на доске с учетом определенного хода, то сортировать уже нужно не сложные объекты Move, а просто intы.

Изначально планировалось реализовать несколько наборов оценочных функций: например, фигуру, которой угрожает враг, оценивать в половину стоимости. Но оказалось, что бот играет довольно чисто, теряя мало фигур, поэтому простая сумма оказалась эффективнее.

Однако архитектура бота все еще поддерживает добавление новых оценочных функций. Для этого нужно определить всего три вещи:

  1. Функцию, если нужно посчитать стоимость с нуля по данному расположению фигур
  2. Дельта-функцию, которая должна по данному ходу быстро пересчитать стоимость.
  3. Номер этого набора функций для конструктора специального класса FunctionSet.

Можно включить битву ботов и наблюдать за процессом.


Игра 2 ботов одинаковой сложности (4 уровень из 6 возможных). Курсор всю игру стоит по центру поля

Заключение


Мы реализовали игру, подобную шахматной, но с другими правилами и необычной доской. Нашей реализации есть куда расширяться. Сам Интеллектор тоже сейчас развивается и меняется: недавно вышло обновление правил, которое мы пока не поддержали в своём приложении. Например, теперь нельзя пересекать центральную линию первые 2 хода.

Кроме того, есть разные фичи, которые мы изначально планировали, но к сдаче проекта реализовать не успели. Например, в этом приложении очень хотелось бы видеть сетевую игру. Также не помешал бы красивый кроссплатформенный интерфейс, например, на Qt.

Возможно, в ближайшее время всё или часть из этого появится. А пока что спасибо за чтение!

Github-репозиторий
Подробнее..

Бот для ВКонтакте MDB (школьный проект и проект для Всероссийского конкурса проектных работ)

08.05.2021 20:10:07 | Автор: admin

Привет, Хабр! Хочу вам рассказать о своём исследовательском проекте, в котором я создал игрового ботеца для ВКонтакте.

Ахтунг!

Я не являюсь профессиональным разработчиком, я обычный девятиклассник, любящий иногда покодить на совершенно разных язык. Здесь я просто рассказываю о своём проекте и опыте участия в конкурсе проектных работ.

Эта статья не является пошаговым руководством по созданию бота для ВКонтакте - их достаточно и на Хабре, и за его пределами.

Что за проект?

Я, как администратор немаленькой беседы во ВКонтакте (на тот момент это было ~670 человек), столкнулся с проблемой ужасной активности. Ну серьёзно, человек много, а не пишет никто, очень много незаинтересованных молчунов, которые лишь цифру создают для беседы. Подавляющее большинство пользователей из тех 670 человек просто входили и не появлялись в списке сообщений ни разу.

Чтобы решить эту проблему, я решил попробовать написать своего бота с некоторыми игровыми механиками. Сразу хочу оговориться, что пусть и код писал я сам, мне два раза проводил код ревью мой замечательный приятель, поэтому, пусть сам проект, сама задумка довольно простая, - это не помешало мне набраться опыта от более продвинутого в кодинге человека.

С ботом и своей темой я отправился прямиком на конкурс "Большие вызовы", съездил в лагерь, где с экспертами (а с одним из них мы общаемся до сих пор) я допиливал презентацию, чутка сменил цель, всё подкорректировал, успешно защитился. Сейчас меня ждёт только последний тур заключительного этапа, но это уже совсем другая история.

Что же за системы есть в боте?

В общем и целом, по сути я вдохновлялся другим ботом, в которого любил играть продолжительное время (и закончил только потому, что они его отрубили и делают сейчас игру в приложении ВК).

У меня бот намного проще, но подошёл для проекта в школе и для проекта в конкурсе. Основными характеристиками пользователя являются игровая валюта и опыт. Фактически, всё сводится к фарму опыта и денег ради фарма опыта и денег. За опыт можно устроиться на работу, каждая последующая работа будет давать всё больше денег в 24 часа (без фарма, получение зарплаты только командой раз в сутки), в свою очередь за деньги можно купить машину получше, которая будет давать больший множитель к опыту. Опыт даётся за каждое сообщение кроме команд посимвольно, затем умножается на множитель от автомобиля. Это самое основное, чего я стал требовать от бота. Также есть выдача предупреждений (максимальное их количество - 4).

Да, такого бота я делал около 6 месяцев, постоянно что-то изменяя, добавляя и удаляя.

Давай о реализации уже!

Делал я бота на языке программирования Python с использованием асинхронной библиотеки для написания ботов vkbottle. Работает на CallBack API, в качестве сервера использую aiohttp.

Во входном файле bot.py происходит инициализация сервера, прописаны все роуты (их всего 4 и они очень маленькие), к основному боту добавляются blueprint'ы, о которых пойдёт речь позже.

import pathlibimport aiohttpimport aiohttp_jinja2import jinja2from aiohttp import webimport utils.constsfrom config import SECRET, WEBHOOK_ACCEPT, CONFIRMATION_TOKENfrom routes import actions, admin_realize, global_admin_realize, users_realize, economic_realizefrom utils.db_methods import init_databasefrom middlewares import ExpMiddleware # dead import for include middlewareINDEX_DIR = str(pathlib.Path(__file__).resolve().parent) + '/index_page'utils.consts.BOT.loop.run_until_complete(init_database())utils.consts.BOT.set_blueprints(    actions.bp, admin_realize.bp, global_admin_realize.bp,    users_realize.bp, economic_realize.bp)APP = aiohttp.web.Application()ROUTES = aiohttp.web.RouteTableDef()if not WEBHOOK_ACCEPT:    aiohttp_jinja2.setup(APP, loader=jinja2.FileSystemLoader(str(INDEX_DIR)))    APP.router.add_static('/static/',                          path=str('./index_page/'),                          name='static')@ROUTES.get("/")@aiohttp_jinja2.template('index.html')async def hello(request):    """Root site response"""    return {}@ROUTES.get("/when_update")@aiohttp_jinja2.template('whenupdate.html')async def whenupdate(request):    """When update site response"""    return {}

Все конфиги хранятся в config.py, точнее, там инициализируются константы. Сами значения хранятся в файле .env и с помощью библиотеки dotenv берутся из виртуального окружения по ключу.

import osfrom dotenv import load_dotenvdotenv_path = os.path.join(os.path.dirname(__file__), '.env')if os.path.exists(dotenv_path):    load_dotenv(dotenv_path)# Loading token from .envACCESS_TOKEN = os.getenv("ACCESS_TOKEN")SECRET = os.getenv("SECRET")USER_ACCESS_TOKEN = os.getenv("USER_ACCESS_TOKEN")WEBHOOK_ACCEPT = bool(int(os.getenv("WEBHOOK_ACCEPT", 0)))CONFIRMATION_TOKEN = os.getenv("CONFIRMATION_TOKEN")NEW_START = bool(int(os.getenv("NEW_START", 0)))ADMINS_IN_CONV = list(map(int, os.getenv("ADMINS_IN_CONV").split(',')))

Теперь о том, где хранятся все обработчики команд.

Я их разделил логически на 5 видов: обработчик событий (пользователь вошел в беседу), обработчик сообщений для всех (например, команда /profile), для администраторов беседы (например, /пред чтобы выдать предупреждение пользователю), для администраторов и модераторов бота (например, /бд добавить, чтобы добавить, как ни странно, новый экземпляр какой-то модельки, например, создать новую машину, не взаимодействуя напрямую с БД), и реализация системы экономики (купить или продать машину, поступить на работу и пр.).

Всё это хранится в пяти разных файлах в папке routes:

Вот пример команды покупки машины:

@bp.on.message_handler(AccessForAllRule(), Registered(), text="/купить_машину <c_id>")async def buy_car(message: Message, user: User, c_id: str = None):    if c_id.isdigit():        c_id = int(c_id)        car = await Car.get(id=c_id)        buy_car_user_status = status_on_buy_car(user, car)        if buy_car_user_status == BuyCarUserStatuses.APPROVED:            chat = await Conversation.get(peer_id=message.peer_id)            await User.get(user_id=message.from_id, chat=chat).update(                coins=user.coins - car.cost, car=car            )            await message(f"Машина {car} куплена!")        elif buy_car_user_status == BuyCarUserStatuses.NOT_ENOUGH_MONEY:            await message("У тебя недостаточно денег!")        elif buy_car_user_status == BuyCarUserStatuses.NOT_ENOUGH_EXP:            await message("У тебя недостаточно опыта!")        else:            await message("У тебя уже есть машина!")    else:        await message("Введите цифру-ID машины!")

Все обработчики в пределах одного файла объединяются blueprint'ом, а все "чертежи" подключаются к боту во входном файле.

В обработчиках команд используются различные служебные функции, например, в команде выше есть функция status_on_buy_car, которая говорит, можно ли пользователю купить машину, а если нельзя, то причину этого.

Все подобные функции хранятся в отдельно в папке utils в файле main.py. В этой же папке лежат файлы с константами, функциями для работы с БД, правила и ошибки, которые функции могут raise'ить иногда.

def status_on_buy_car(user: User, car: Car) -> BuyCarUserStatuses:    if user.coins >= car.cost and user.exp >= car.exp_need and user.car is None:        return BuyCarUserStatuses.APPROVED    elif user.coins < car.cost:        return BuyCarUserStatuses.NOT_ENOUGH_MONEY    elif user.exp < car.exp_need:        return BuyCarUserStatuses.NOT_ENOUGH_EXP    else:        return BuyCarUserStatuses.NOW_HAVE_CAR

В качестве ОРМки я использую Tortoise ORM, потому что асинхронно (а смысл в асинхронности фреймворка, если вся работа с БД синхронная?), потому что удобно лично для меня.

Что по итогу?

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

Конечно, в беседе, где бот был, наблюдалось больше сообщений, чем в беседе, где его не было, было больше активности (пусть и не сильно). Это я и записал в вывод.

В результате я получил небольшой научно-исследовательский проект, целью которого было исследовать возможность с помощью бота с игровой механикой повышения активности в беседах. Цель полностью выполнена, это частично возможно, но нужно пробовать различные подходы к решению поставленной проблемы.

Постскриптум

Я открыт к критике в комментариях, за неё отдельное спасибо, ведь именно критика, может даже очень жёсткая, может даже с заминусованной статьёй поможет развиваться мне как разработчику и создателю статей на Хабре.

Бот на GitHub

Подробнее..

Из песочницы Как я сделал бота, который контролирует моих сотрудников, следит за моими тренировками, весом и чтением книг

13.10.2020 00:06:12 | Автор: admin
Привет, меня зовут Антон Ланцов, мне 26 лет. Я рыжий и у меня всегда миллион идей, некоторые из них я реализую успешно, некоторые нет.

Контроль сотрудников


В 2014 году я купил франшизу Клаустрофобии (квесты в реальности). Это был мой первый серьезный бизнес, где требовалось контролировать сотрудников. Ребят, которые вели квесты, мы называли Операторы квеста.

Ежедневно нам приходилось контролировать операторов и собирать следующую информацию:

  1. Время прихода на локацию (клиенты могли прийти в любой момент, а чек был от 2500 рублей, любая потеря критична и досадна).
  2. Время пересменки (чтобы локация не оставалась без оператора).
  3. Время ухода с работы.
  4. Поломки и неисправности квестов (требовалось узнавать это оперативно, чтобы вызвать инженера, а то полетят плохие отзывы, что квест не работает).
  5. Уборка.
  6. Количество игр в день.
  7. Выручка за день.

В то время мы прекрасно обходились общим чатиком во ВКонтакте и Google Sheets:

  1. Время прихода на локацию. Пришел пришли фоточку в чатик.
  2. Время пересменки пришли фоточку в чатик обоих операторов.
  3. Время ухода с работы пришли фоточку в чатик перед уходом.
  4. Поломки и неисправности квестов. Все в Google-таблицу с описанием и фото.
  5. Уборка фоточка в чатик
  6. Количество игр в день Google-таблица отлично справлялась и с этим.
  7. Выручка за день Google-таблица и для этого.

Все это работало только тогда, когда оператор не забывал об этих ежедневных отчетах, которые занимали всего 34 минуты. Напоминать в каждый чат (а чатов было два, так как локаций с квестами у нас было две) было очень утомительно каждый день, да и тот, кто должен был напоминать операторам, мог и сам забыть.

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

Об автоматизации мы только мечтали, ведь API у Google Таблиц и боты во ВКонтакте появились намного позже, чем 2014 год. А потом все никак не доходили руки. Вроде все работает и пусть себе работает.

В феврале 2019 года я продал квесты.

В декабре 2018 я успел открыть одну точку электрокартинга для детей, а в 2016 создал компанию по анализу и оценке потенциала помещения для ритейла.

В электрокартинге сейчас две локации, операторов на которых требуется контролировать каждый день так же, как и в квестах.

В компании по аналитике много так называемых ранеров, которые считают трафик каждый день в разных точках. Штат в офисе тоже есть. За эффективностью их работы тоже надо следить.

К счастью, у нас появились Telegram и Google Таблицы с открытыми API.

По потребностям я сделал бота Пушиста бота для контроля сотрудников и самого себя (назвал его так, потому что он пушает всех от слова push толкать).

Теперь я контролирую операторов в электрокартинге вот так:

image

image

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

image

Ребята отвечают, что за день сделали и как у них дела. Еще бот хвалит и напоминает о каких-то задачах. Работает все как часы, никто ничего не забывает и никому ничего не требуется напоминать вручную.

Создание любого запроса выглядит так:

image

Одна из важнейших фишек, что бота можно добавить в общий чат и он будет всегда автоматом писать туда, когда вы его настроите.

Также на каждый вариант ответа можно настроить реакцию бота.

Пример 1:

Бот: Сколько сегодня выручка?
Сотрудник: 12 тысяч рублей.
Бот: Отлично, вы сегодня молодцы. Приятного отдыха!

Пример 2:

Бот: Сколько сегодня выручка?
Сотрудник: 9000 рублей.
Бот: Неплохо, но этого мало чтобы завоевать мир. Давайте поднапряжем завтра, друзья.

Еще одна уникальность бота в том, что по сути сотрудники видят именно вашу аватарку, а не какую-то бездушную стандартную картинку, поэтому сотрудники всегда ощущают присутствие начальника. Над девушкой лучше с помощью бота не шутить

image

Все ответы записываются в ту Google-таблицу, которую вы привяжете к боту.

image

В Google-таблице я построил графики, на которые любуюсь и смотрю тренды и оцениваю эффективность работы конкретного бизнеса (сами знаете, что из плоской таблицы можно вытянуть очень много полезной информации).

image

Контроль моих тренировок и чтения книг


Статистику я люблю и мне интересно видеть, как я достигаю результатов. Я создал чат Антон Будущего со своим ботом и настроил задачи для себя. Выходит будто я из будущего пинаю себя, чтобы стать лучше. Круто же.

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

По плаванию говорить об успехах рано, начну записывать, когда смогу плавать какие-то стандартные дистанции, пока отрабатываю технику.

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

image

Такой себе я спортсмен, конечно. Но попытка была стоящая. Надо все-таки начать снова. Вот статистика по отжиманиям:

image

С чтением так же. Настроил запрос Сколько страниц ты сегодня прочел?. Читал, но недостаточно, чтобы гордиться этим.

image

Для кого этот бот


Этот бот значительно сокращает время на контроль простых процессов в бизнесе и делает точечный акцент на конкретные метрики, которые можно отслеживать и жизни. Я думаю, что этот бот будет полезен:

Предпринимателю. Контроль сотрудников и бизнеса по конкретным метрикам.

Личному тренеру. Задайте сами себе метрики, которые будут вам помогать совершенствоваться каждый день (Сколько страниц прочел сегодня? Сколько отжался? Поел? Кому сегодня благодарен?).

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

Бизнес-тренеру, трекеру. Достижение результата за счет каждодневного трекинга.

Спортсмену. Трекинг результатов.

Надеюсь, я вас навел на какие-то мысли. Этот бот точно способен изменить нашу жизнь и добавить в нее системности и статистики.

А вот статистика пользователей бота, растет и хорошо.

image
Перечитал статью перед публикацией и понял, что я еще тот начальник-тиран.

Но это совсем не так.

Цифры все ради них!
Подробнее..

Телеграмм-бот для анализа опционов

07.06.2021 10:04:02 | Автор: admin

Опционы - вид ценных бумаг, вызывающих постоянный интерес даже у начинающих трейдеров. Об опционах написано немало статей, поэтому мы опустим ознакомительную часть и будем считать, что читатель знаком с основными терминами опционной торговли. Если что, то их толкование несложно найти в интернете.

После первого знакомства с теорией у начинающих торговцев опционами возникает вопрос: а при каких условиях данный набор опционов даст прибыль, и какую. Даже опытный опционщик сходу не сможет ответить на этот вопрос, если у вас более одного опциона. Для этого необходим анализ опционного портфеля ( набора опционов и , возможно, фьючерсов), который нагляднее всего делается в графическом виде, на диаграмме зависимости прибыли/убытка от стоимости базового актива. В настоящее время существует несколько сайтов для этого, а также отдельных программ.

Автор статьи реализовал анализ опционов с помощью телеграмм-бота, что дает возможность быстрого получения информации об инвестиционном портфеле на смартфоне.

Будем считать, что, кроме опционов, читатель знаком с телеграмм ботами. Поэтому здесь не будет описания создания бота от получения токена до обработки клавиатуры. Вместо этого перечислим концептуальные проблемы, которые возникли при создании программы, и способы их решения.

Запоминание состояния бота между вебхуками

Бот получает сообщения от пользователя через встроенный в телеграмм механизм вебхуков. Каждый вебхук заново запускает программу, но для каждого пользователя необходим свой набор данных. Идентификация пользователей осуществляется через просмотр потока ввода:

$id_init = file_get_contents('php://input');$id=sbs($id_init, '"from":{"id":',',"is_bot":'); //в эту переменную записываем уникальный номер пользователяfunction sbs ($str,$m1,$m2){ //из строки str возвращает подстроку между двумя метками-словами m1 и m2$p1=strpos($str,$m1)+strlen($m1); //длина слова-метки слева$p2=strpos($str,$m2);return substr($str,$p1,$p2-$p1);}

Для каждого пользователя строится следующая структура данных:

  1. файл состояния: переменные флажки , которые описывают в частности, идентификационные номера сообщений ( message_Id) для дальнейшей их редакции, актуальное состояние ( ввод количества, ввод страйка и т.д.), вспомогательные данные для построения графика

  2. файл данных по составу портфеля ( идентификационный номер ценной бумаги, тип, количество, цена, дата экспирации)

  3. файлы для построения графика

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

Построение графика для анализа портфеля

График строится по состоянию на момент экспирации опционов, что дает возможность упрощенно представить график каждого инструмента в виде y=kx+b,

где y это размер прибыли/убытка на момент экспирации

х стоимость базового актива

После записи данных в портфель создаются файлы с расширением png с помощью библиотеки GD в несколько этапов:

1) определение Х-координат всех точек перелома на графике (очевидно, что сумма всех линий даст ломанную кривую)

2) определение масштаба изображения (средняя всех координат точек перелома по оси Х, максимальное отклонение от среднего, и максимальный размер по оси Y)

3) создание ассоциативного массива точек, в котором координата X это ключ, координата Y величина, для всей цифровой полуплоскости:

$typ опцион колл, пут или фьючерс

$q количество ( отрицательное продажа)

$cena цена приобретения ценной бумаги

$strike страйк для опционов

$x0 начальная координата по оси Х

$sx масштаб по оси Х

function pparr($typ, $q, $cena, $strike,$x0,$sx){ //функция выдает одномерный массив - координаты x=>y точек по //типу цб, направлению (покупка продажа), цене приобретения и страйку (для опционов)  if ($q<0) { $q=-$q; $drct='-'; }  else $drct='+'; $a=array(); $b=array(); $delta=$sx; //расстояние между точками равно масштабу $scalx for ($i=0;$i<740;$i++){ //кол во точек 740 определено заранее $xkk=$x0+$delta*$i; //значение по оси X if ($typ=='fut') { if ($drct=='+') $a[$xkk]=($xkk-$cena)*$q; else $a[$xkk]=(-$xkk+$cena)*$q; } if ($typ=='call'){ if ($drct=='+') { if ($xkk<=$strike) $a[$xkk]=-$cena*$q; else $a[$xkk]=$q*($xkk-$strike-$cena);} else { if ($xkk<=$strike) $a[$xkk]=$q*$cena; else $a[$xkk]=(-$xkk+$strike+$cena)*$q;}  } if ($typ=='put'){ if ($drct=='+') { if ($xkk<=$strike) $a[$xkk]=(-$xkk+$strike-$cena)*$q; else $a[$xkk]=-$q*$cena;} else { if ($xkk<=$strike) $a[$xkk]=($xkk-$strike+$cena)*$q; else $a[$xkk]=$cena*$q;}  } $b[(string)$xkk]=(string)$a[$xkk]; }return $b; };

4) создание файлов изображений, при этом одновременно строится график для каждой строки из портфеля ( зеленый цвет) и результирующий для портфеля ( красный цвет). Кроме того, know-how заключается в том, что одновременно строится еще четыре изображения для увеличения/уменьшения изображения по оси Х и по оси Y. За счет этого достигается эффект работы он-лайн с клавишами X+,X-,Y+,Y- под графиком. Таким образом, для каждого пользователя в каждый момент времени существует пять файлов изображения.

Анализ рисков опционного портфеля

В тесной связи с прибыльностью находится понятие риска. В количественном выражении риск по опционному портфелю выражается в сумме так называемого гарантийного обеспечения. Гарантийное обеспечение та сумма, которая списывается со счета трейдера при совершении сделки. Фактически, исходя из данных на текущий момент, блокируется сумма максимального убытка (потерь). Однако, и это самое главное, сумма гарантийного обеспечения, списанная с вашего счета, пересчитывается после каждого клиринга ( утро, обед и вечер). Она может как увеличиваться, так и уменьшаться. При спокойном течении торгов (в пределах какого-то диапазона) вы можете увидеть, что сумма на вашем счете растет за счет уменьшения ГО. Однако, ГО может резко вырасти в экстренных ситуациях ( стихийные бедствия, санкции, войны) и не только в экстренных (праздники) . В этом случае у вас может быть списана дополнительная сумма в рамках увеличения ГО. Если денег на вашем счете не хватит для оплаты увеличившегося ГО, наступает маржин-колл, в рамках которого ваши ценные бумаги будут принудительно списаны по текущей рыночной цене, что ведет к обнулению счета.

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

Гарантийное обеспечение для фьючерсов считается по формуле, которая предложена самой Московской биржей:

ГО=БГО+(Цена-Расчетная_Цена)*БП;

где Расчетная_Цена определяется по результатам клиринга и практически равна цене базового актива на момент клиринга, определяется в пунктах

БП стоимость пункта в рублях, зависит, в частности, от курса доллара,

БГО базовое гарантийное обеспечение, определяется биржей, может произвольно увеличиваться, например, перед праздниками

Таким образом, по фьючерсам ГО считается достаточно просто, поскольку все данные есть в открытом доступе. Что касается опционов и тем более сочетаний их в разных комбинациях, Московская биржа не дает однозначного рецепта, вернее не дает данных для их расчета, а предлагает купить модуль расчета ГО.

В телеграмм-боте предлагается следующий подход: риск по опциону такой же , как по фьючерсу, в той мере, насколько опцион похож на фьючерс. При этом понятно, что нас интересуют только убытки, то есть нижняя полуплоскость нашего графика. Попробуем пояснить с помощью графиков.

Вот как выглядит покупка колла в нашем боте:

Запись в портфеле покупки опциона "колл" страйк 75000 дата экспирации 03.06.2021 по цене 25 Запись в портфеле покупки опциона "колл" страйк 75000 дата экспирации 03.06.2021 по цене 25 График зависимости прибыли/убытка по купленному опциону "колл" в зависимости от стоимости базового актива на дату экспирации График зависимости прибыли/убытка по купленному опциону "колл" в зависимости от стоимости базового актива на дату экспирации

Гарантийное обеспечение=23.

Что нам показывает график: если стоимость базового актива ( в данном случае стоимость фьючерса на курс рубля к доллару) [вечером] 03.06.2021 будет 75000 и ниже, то наш убыток составит 23 . При повышении этой стоимости до 75023 мы выйдем в безубыток, при дальнейшем росте получим прибыль.

Что мы имеем с точки зрения риска: не при каких обстоятельствах наш убыток не превысит сумму 23. Следовательно, наш опцион совершенно не похож на фьючерс, и в расчете ГО мы можем записать просто сумму 23.

Покупка пута примерно та же картина.

Продажа пута.

Запись в портфеле продажи опциона "пут" страйк 72750 по цене 44 с датой экспирации 03.06.2021Запись в портфеле продажи опциона "пут" страйк 72750 по цене 44 с датой экспирации 03.06.2021График зависимости прибыли/убытка по проданному опциону "пут" от стоимости базового актива на дату экспирацииГрафик зависимости прибыли/убытка по проданному опциону "пут" от стоимости базового актива на дату экспирации

Гарантийное обеспечение= 5436.

Можно убедиться, что при стоимости базового актива выше 72750 мы имеем прибыль 44. При снижении стоимости БА до 72706 мы выходим в ноль. При дальнейшем падении стоимости БА наш убыток НИЧЕМ НЕ ОГРАНИЧИВАЕТСЯ.

С точки зрения рисков это фьючерс, купленный по цене 72706. Подставляем это число в формулу ГО для фьючерса и получаем ГО для опциона! Этот ГО достаточно велик (5436), но может превратится в прибыль в течение нескольких дней.

Стоит ли овчинка выделки? Если при условных затратах сегодня 5436 мы получим через несколько дней 44? Мне кажется, риск очень велик. С другой стороны, курс рубля к доллару был таким примерно 3 месяца назад.

С продажей колла будет аналогичная ситуация.

А если одновременно продать пут и кол?

Запись в портфеле продажи опциона "пут" страйк 72750 и продажи опциона "колл" страйк 75000Запись в портфеле продажи опциона "пут" страйк 72750 и продажи опциона "колл" страйк 75000График зависимости прибыли/убытка по портфелю от стоимости базового актива на дату экспирации График зависимости прибыли/убытка по портфелю от стоимости базового актива на дату экспирации

Гарантийное обеспечение не изменилось!

С точки зрения риска понятно почему может реализоваться только один из сценариев либо по фьючерсу, купленному по примерно по 72700 (левая нога) либо по фьючерсу проданному по 75190 ( правая нога). Из них выбираем вариант

с наибольшим ГО , оно и будет мерилом риска.

На графике можно увидеть, что прибыль мы имеем при стоимости базового актива в диапазоне от примерно 72700 до 75190, в остальных случаях получаем убыток, который ничем не ограничивается.

Интерфейс телеграмм-бота

На экране отображаются следующие группы данных:

  • подробная инструкция по работе с ботом

  • текущие котировки ближайших фьючерсов по трем базовым активам

  • таблица Портфель, отображающая состав портфеля, сделанная с помощью интерфейса телеграмм ( можно редактировать)

  • значение гарантийного обеспечения

  • таблица, дублирующая состав портфеля, построенная как изображение формата png, которую можно копировать и сохранять

  • нижняя клавиатура, которую можно скрывать, с кнопками: Добавить позицию в портфель, Анализ портфеля с помощью графика, Обновить котировки

Таблица Портфель создана с помощью InlineKeyboard.

При нажатии на клавиши в этой таблице происходят следующие действия:

  • клавиша в столбце К-во редактирует количество ценных бумаг, соответствующее строке, в которой нажата клавиша

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

  • клавишей Х можно удалить строку.

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

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

Заключение

В телеграмм-боте реализовано запоминание портфеля ценных бумаг для каждого пользователя. Под ценными бумагами понимаются опционы и фьючерсы, базовым активом для которых являются: курс рубля к доллару (Si), стоимость нефти брент (BR), а также индекс РТС (RI). Это самые высоколиквидные деривативы на московской бирже.

В телеграмм-бот заложен алгоритм подсчета гарантийного обеспечения, которое является мерой риска.

С помощью телеграмм-бота можно анализировать опционный портфель на графике прибылей/убытков (P/L график).

Протестировать телеграмм-бота можно по ссылке t.me/@test09062020bot. Или попробовать найти в телеграмме по названию опционный портфель.

Подробнее..

Простейший голосовой помощник на Python

02.10.2020 14:18:50 | Автор: admin


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

Для начала объявим необходимые нам библиотеки:

import speech_recognition as srimport osimport sysimport webbrowserimport pyttsx3 as pfrom datetime import datetimeimport timeimport datetimeimport random

Также не забудем вести лог файл, который понадобится нам, если же мы все-таки решим улучшить бота для работы с нейронной сетью. Многие компании использую нейронную сеть в своих голосовых помощниках для понимания эмоций клиента и соответствующего реагирования на них.

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

#Создаем логchat_log = [['SESSION_ID', 'DATE', 'AUTHOR', 'TEXT', 'AUDIO_NUM']]#Узнаем номер сессииi = 1exit = 0while exit == 0:    session_id = str(i)    if session_id not in os.listdir():        os.mkdir(session_id)        exit = 1    else:        i = i + 1#Первое сообщение пишет botauthor = 'Bot'text = 'Привет! Чем я могу вам помочь?'

В лог файл мы записываем время сообщения, автора (бот или пользователь) и собственно сам сказанный текст.

#Добавляем данные к логу с помощью этой процедурыdef log_me(author, text, audio):     now = datetime.datetime.now()    i = 1    exit = 0    while exit == 0:        audio_num = str(i)+'.wav'        if audio_num not in os.listdir(session_id):            exit = 1        else:            i = i + 1    os.chdir(session_id)    with open(audio_num , "wb") as file:        file.write(audio.get_wav_data())    chat_log.append([now.strftime("%Y-%m-%d %H:%M:%S"), author, text, audio_num])

Выводим первое сообщение за авторством бота: Привет! Чем я могу вам помочь?

# Выводим первое сообщение на экран и записываем в лог    print("Bot: "+ text)log_me(author, text, audio)

А с помощью такой процедуры в Jupyter Notebook мы можем озвучить через устройство воспроизведения, настроенное по умолчанию, сказанные слова:

#Произношение wordsdef talk(words):    engine.say(words)    engine.runAndWait()

Как озвучивать текст мы рассмотрели выше, но как же мы свой голос сможем превратить в текст? Тут нам поможет распознавание речи от Google и некоторые манипуляции с микрофоном.

#Настройка микрофона    def command():    rec = sr.Recognizer()    with sr.Microphone() as source:        #Бот ожидает нашего голоса        print('Bot: ...')        #Небольшая задержка в записи        rec.pause_threshold = 1        #Удаление фонового шума с записи        rec.adjust_for_ambient_noise(source, duration=1)        audio = rec.listen(source)    try:        #Распознание теста с помощью сервиса GOOGLE        text = rec.recognize_google(audio, language="ru-RU").lower()        #Вывод сказанного текста на экран        print('Вы:  ' + text[0].upper() + text[1:])        log_me('User', text, audio)    #Если не распознался тест из аудио    except sr.UnknownValueError:        text = 'Не понимаю. Повторите.'        print('Bot: ' + text)        talk(text)        #Начинаем заново слушать        text = command()        log_me('Bot', text, , Null)    return text

Что может сделать наш помощник кроме того, чтобы нас слушать? Все ограничено нашей фантазией! Рассмотрим несколько интересный примеров.

Начнем с простого, пусть при команде открыть сайт он откроет сайт (не ожидали?).

#Тут расписаны действия, которые будут выполнятся при наличии некоторых словосочетанийdef makeSomething(text):    if 'открой сайт' in text:        print('Bot: Открываю сайт NewTechAudit.')        talk('Открываю сайт NewTechAudit.')        log_me('Bot','Открываю сайт NewTechAudit.', Null)        webbrowser.open('https://newtechaudit.ru/')

Иногда полезно послушать свои слова, да чужими устами. Пусть бот еще умеет и повторять за нами:

#Повторение фразы пользователя    elif 'произнеси' in text or 'скажи' in text or 'повтори' in text:        print('Bot: ' + text[10].upper() + text[11:])        talk(text[10:])        log_me('Bot', text[10].upper() + text[11:] , Null)

Пусть еще и собеседником будет, но начнем мы пока только со знакомства:

#Ответ на вопрос    elif 'своё имя' in text or 'как тебя зовут' in text or 'назови себя' in text:        print('Bot: Меня зовут Bot.')        talk('Меня зовут Bot')        log_me('Bot', 'Меня зовут Bot', Null)

Мы также можем попросить голосового помощника назвать случайное число в выбранных нами пределах в формате: Назови случайное число от (1ое число) до (2ое число).

#Определение случайного числа    elif 'случайное число' in text:        ot=text.find('от')        do=text.find('до')        f_num=int(text[ot+3:do-1])        l_num=int(text[do+3:])        r=str(random.randint(f_num, l_num))        print('Bot: ' + r)        talk(r)        log_me('Bot', r, Null)

Для того, чтобы завершить программу, достаточно только попрощаться с ботом:

#Завершение программы    elif 'пока' in text or 'до свидания' in text:        print('Bot: До свидания!')        talk('До свидания')        log_me('Bot', 'Конец сессии', Null)        os.chdir(session_id)        log_file = open( session_id + ".txt", "w")        for row in chat_log:            np.savetxt(log_file, row)        log_file.close()        sys.exit()

А чтобы все это работало беспрерывно, мы создаем бесконечный цикл.

#Бесконечный цикл для работыwhile True:    makeSomething(command())

Проведем тестовый диалог:



В созданной папке-сессии хранятся все файлы-аудиозаписи нашего голоса и текстовый лог-файл:



В текстовый лог-файл записывается:



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

Этот бот может стать основой для вашего собственного Джарвиса!
Подробнее..

Как я сделал Discord бота для игровой гильдии с помощью .NET Core

05.06.2021 18:10:05 | Автор: admin
Батрак предупреждает о том что к гильдии присоединился игрокБатрак предупреждает о том что к гильдии присоединился игрок

Вступление

Всем привет! Недавно я написал Discord бота для World of Warcraft гильдии. Он регулярно забирает данные об игроках с серверов игры и пишет сообщения в Discord о том что к гильдии присоединился новый игрок или о том что гильдию покинул старый игрок. Между собой мы прозвали этого бота Батрак.

В этой статье я решил поделиться опытом и рассказать как сделать такой проект. По сути мы будем реализовывать микросервис на .NET Core: напишем логику, проведем интеграцию с api сторонних сервисов, покроем тестами, упакуем в Docker и разместим в Heroku. Кроме этого я покажу как реализовать continuous integration с помощью Github Actions.

От вас не потребуется никаких знаний об игре. Я написал материал так чтобы можно было абстрагироваться от игры и сделал заглушку для данных об игроках. Но если у вас есть учетная запись в Battle.net, то вы сможете получать реальные данные.

Для понимания материала, от вас ожидается хотя бы минимальный опыт создания веб сервисов с помощью фреймворка ASP.NET и небольшой опыт работы с Docker.

План

На каждом шаге будем постепенно наращивать функционал.

  1. Создадим новый web api проект с одним контроллером /check. При обращении к этому адресу будем отправлять строку Hello! в Discord чат.

  2. Научимся получать данные о составе гильдии с помощью готовой библиотеки или заглушки.

  3. Научимся сохранять в кэш полученный список игроков чтобы при следующих проверках находить различия с предыдущей версией списка. Обо всех изменениях будем писать в Discord.

  4. Напишем Dockerfile для нашего проекта и разместим проект на хостинге Heroku.

  5. Посмотрим на несколько способов сделать периодическое выполнение кода.

  6. Реализуем автоматическую сборку, запуск тестов и публикацию проекта после каждого коммита в master

Шаг 1. Отправляем сообщение в Discord

Нам потребуется создать новый ASP.NET Core Web API проект.

Создание нового проекта - это одна из фундаментальных вещей которые я не буду подробно расписывать. При работе над проектом используйте сервис Github для хранения кода. В дальнейшем мы воспользуемся несколькими возможностями Github.

Добавим к проекту новый контроллер

[ApiController]public class GuildController : ControllerBase{    [HttpGet("/check")]    public async Task<IActionResult> Check(CancellationToken ct)    {        return Ok();    }}

Затем нам понадобится webhook от вашего Discord сервера. Webhook - это механизм отправки событий. В данном случае, то это адрес к которому можно слать простые http запросы с сообщениями внутри.

Получить его можно в пункте integrations в настройках любого текстового канала вашего Discord сервера.

Создание webhookСоздание webhook

Добавим webhook в appsettings.json нашего проекта. Позже мы унесем его в переменные окружения Heroku. Если вы не знакомы с тем как работать с конфигурацией в ASP Core проектах предварительно изучите эту тему.

{"DiscordWebhook":"https://discord.com/api/webhooks/****/***"}

Теперь создадим новый сервис DiscordBroker, который умеет отправлять сообщения в Discord. Создайте папку Services и поместите туда новый класс, эта папка нам еще пригодится.

По сути этот новый сервис делает post запрос по адресу из webhook и содержит сообщение в теле запроса.

public class DiscordBroker : IDiscordBroker{    private readonly string _webhook;    private readonly HttpClient _client;    public DiscordBroker(IHttpClientFactory clientFactory, IConfiguration configuration)    {        _client = clientFactory.CreateClient();        _webhook = configuration["DiscordWebhook"];    }    public async Task SendMessage(string message, CancellationToken ct)    {        var request = new HttpRequestMessage        {            Method = HttpMethod.Post,            RequestUri = new Uri(_webhook),            Content = new FormUrlEncodedContent(new[] {new KeyValuePair<string, string>("content", message)})        };        await _client.SendAsync(request, ct);    }}

Как видите, мы используем внедрение зависимостей. IConfiguration позволит нам достать webhook из конфигов, а IHttpClientFactory создать новый HttpClient.

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

Не забудьте что новый класс нужно будет зарегистрировать в Startup.

services.AddScoped<IDiscordBroker, DiscordBroker>();

А также нужно будет зарегистрировать HttpClient, для работы IHttpClientFactory.

services.AddHttpClient();

Теперь можно воспользоваться новым классом в контроллере.

private readonly IDiscordBroker _discordBroker;public GuildController(IDiscordBroker discordBroker){  _discordBroker = discordBroker;}[HttpGet("/check")]public async Task<IActionResult> Check(CancellationToken ct){  await _discordBroker.SendMessage("Hello", ct);  return Ok();}

Запустите проект, зайдите по адресу /check в браузере и убедитесь что в Discord пришло новое сообщение.

Шаг 2. Получаем данные из Battle.net

У нас есть два варианта: получать данные из настоящих серверов battle.net или из моей заглушки. Если у вас нет аккаунта в battle.net, то пропустите следующий кусок статьи до момента где приводится реализация заглушки.

Получаем реальные данные

Вам понадобится зайти на https://develop.battle.net/ и получить там две персональных строки BattleNetId и BattleNetSecret. Они будут нужны нам чтобы авторизоваться в api перед отправкой запросов. Поместите их в appsettings.

Подключим к проекту библиотеку ArgentPonyWarcraftClient.

Создадим новый класс BattleNetApiClient в папке Services.

public class BattleNetApiClient{   private readonly string _guildName;   private readonly string _realmName;   private readonly IWarcraftClient _warcraftClient;   public BattleNetApiClient(IHttpClientFactory clientFactory, IConfiguration configuration)   {       _warcraftClient = new WarcraftClient(           configuration["BattleNetId"],           configuration["BattleNetSecret"],           Region.Europe,           Locale.ru_RU,           clientFactory.CreateClient()       );       _realmName = configuration["RealmName"];       _guildName = configuration["GuildName"];   }}

В конструкторе мы создаем новый экземпляр класса WarcraftClient.
Этот класс относится к библиотеке, которую мы установили ранее. С его помощью можно получать данные об игроках.

Кроме этого, нужно создать в appsettings проекта две новых записи RealmName и GuildName. RealmName это название игрового мира, а GuildName это название гильдии. Их будем использовать как параметры при запросе.

Сделаем метод GetGuildMembers чтобы получать состав гильдии и создадим модель WowCharacterToken которая будет представлять собой информацию об игроке.

public async Task<WowCharacterToken[]> GetGuildMembers(){   var roster = await _warcraftClient.GetGuildRosterAsync(_realmName, _guildName, "profile-eu");   if (!roster.Success) throw new ApplicationException("get roster failed");   return roster.Value.Members.Select(x => new WowCharacterToken   {       WowId = x.Character.Id,       Name = x.Character.Name   }).ToArray();}
public class WowCharacterToken{  public int WowId { get; set; }  public string Name { get; set; }}

Класс WowCharacterToken следует поместить в папку Models.

Не забудьте подключить BattleNetApiClient в Startup.

services.AddScoped<IBattleNetApiClient, BattleNetApiClient>();

Берем данные из заглушки

Для начала создадим модель WowCharacterToken и поместим ее в папку Models. Она представляет собой информацию об игроке.

public class WowCharacterToken{  public int WowId { get; set; }  public string Name { get; set; }}

Дальше сделаем вот такой класс

public class BattleNetApiClient{    private bool _firstTime = true;    public Task<WowCharacterToken[]> GetGuildMembers()    {        if (_firstTime)        {            _firstTime = false;            return Task.FromResult(new[]            {                new WowCharacterToken                {                    WowId = 1,                    Name = "Артас"                },                new WowCharacterToken                {                    WowId = 2,                    Name = "Сильвана"                }            });        }        return Task.FromResult(new[]        {            new WowCharacterToken            {                WowId = 1,                Name = "Артас"            },            new WowCharacterToken            {                WowId = 3,                Name = "Непобедимый"            }        });    }}

Он возвращает зашитый в него список игроков. При первом вызове метода мы вернем один список, при последующих другой. Это нужно нам что смоделировать изменчивое поведение api. Этой заглушки хватит чтобы продолжить делать проект.

Сделайте интерфейс и подключите все что мы создали в Startup.

services.AddScoped<IBattleNetApiClient, BattleNetApiClient>();

Выведем результаты в Discord

После того как мы сделали BattleNetApiClient, им можно воспользоваться в контроллере чтобы вывести кол-во игроков в Discord.

[ApiController]public class GuildController : ControllerBase{  private readonly IDiscordBroker _discordBroker;  private readonly IBattleNetApiClient _battleNetApiClient;  public GuildController(IDiscordBroker discordBroker, IBattleNetApiClient battleNetApiClient)  {     _discordBroker = discordBroker;     _battleNetApiClient = battleNetApiClient;  }  [HttpGet("/check")]  public async Task<IActionResult> Check(CancellationToken ct)  {     var members = await _battleNetApiClient.GetGuildMembers();     await _discordBroker.SendMessage($"Members count: {members.Length}", ct);     return Ok();  }}

Шаг 3. Находим новых и ушедших игроков

Нужно научиться определять какие игроки появились или пропали из списка при последующих запросах к api. Для этого мы можем закэшировать список в InMemory кэше (в оперативной памяти) или во внешнем хранилище.

Если закэшировать список в InMemory кэше, то мы потеряем его при перезапуске приложения. Поэтому позже мы подключим базу данных Redis как аддон в Heroku и будем кешировать туда.

А пока что подключим InMemory кэш в Startup.

services.AddMemoryCache(); 

Теперь в нашем распоряжении есть IDistributedCache, который можно подключить через конструктор. Я предпочел не использовать его напрямую , а написать для него обертку. Создайте класс GuildRepository и поместите его в новую папку Repositories.

public class GuildRepository : IGuildRepository{    private readonly IDistributedCache _cache;    private const string Key = "wowcharacters";    public GuildRepository(IDistributedCache cache)    {        _cache = cache;    }    public async Task<WowCharacterToken[]> GetCharacters(CancellationToken ct)    {        var value = await _cache.GetAsync(Key, ct);        if (value == null) return Array.Empty<WowCharacterToken>();        return await Deserialize(value);    }    public async Task SaveCharacters(WowCharacterToken[] characters, CancellationToken ct)    {        var value = await Serialize(characters);        await _cache.SetAsync(Key, value, ct);    }        private static async Task<byte[]> Serialize(WowCharacterToken[] tokens)    {        var binaryFormatter = new BinaryFormatter();        await using var memoryStream = new MemoryStream();        binaryFormatter.Serialize(memoryStream, tokens);        return memoryStream.ToArray();    }    private static async Task<WowCharacterToken[]> Deserialize(byte[] bytes)    {        await using var memoryStream = new MemoryStream();        var binaryFormatter = new BinaryFormatter();        memoryStream.Write(bytes, 0, bytes.Length);        memoryStream.Seek(0, SeekOrigin.Begin);        return (WowCharacterToken[]) binaryFormatter.Deserialize(memoryStream);    }}

Теперь можно написать сервис который будет сравнивать новый список игроков с сохраненным.

public class GuildService{    private readonly IBattleNetApiClient _battleNetApiClient;    private readonly IGuildRepository _repository;    public GuildService(IBattleNetApiClient battleNetApiClient, IGuildRepository repository)    {        _battleNetApiClient = battleNetApiClient;        _repository = repository;    }    public async Task<Report> Check(CancellationToken ct)    {        var newCharacters = await _battleNetApiClient.GetGuildMembers();        var savedCharacters = await _repository.GetCharacters(ct);        await _repository.SaveCharacters(newCharacters, ct);        if (!savedCharacters.Any())            return new Report            {                JoinedMembers = Array.Empty<WowCharacterToken>(),                DepartedMembers = Array.Empty<WowCharacterToken>(),                TotalCount = newCharacters.Length            };        var joined = newCharacters.Where(x => savedCharacters.All(y => y.WowId != x.WowId)).ToArray();        var departed = savedCharacters.Where(x => newCharacters.All(y => y.Name != x.Name)).ToArray();        return new Report        {            JoinedMembers = joined,            DepartedMembers = departed,            TotalCount = newCharacters.Length        };    }}

В качестве возвращаемого результата используется модель Report. Ее нужно создать и поместить в папку Models.

public class Report{   public WowCharacterToken[] JoinedMembers { get; set; }   public WowCharacterToken[] DepartedMembers { get; set; }   public int TotalCount { get; set; }}

Применим GuildService в контроллере.

[HttpGet("/check")]public async Task<IActionResult> Check(CancellationToken ct){   var report = await _guildService.Check(ct);   return new JsonResult(report, new JsonSerializerOptions   {      Encoder = JavaScriptEncoder.Create(UnicodeRanges.BasicLatin, UnicodeRanges.Cyrillic)   });}

Теперь отправим в Discord какие игроки присоединились или покинули гильдию.

if (joined.Any() || departed.Any()){   foreach (var c in joined)      await _discordBroker.SendMessage(         $":smile: **{c.Name}** присоединился к гильдии",         ct);   foreach (var c in departed)      await _discordBroker.SendMessage(         $":smile: **{c.Name}** покинул гильдию",         ct);}

Эту логику я добавил в GuildService в конец метода Check. Писать бизнес логику в контроллере не стоит, у него другое назначение. В самом начале мы делали там отправку сообщения в Discord потому что еще не существовало GuildService.

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

await _warcraftClient.GetCharacterProfileSummaryAsync(_realmName, name.ToLower(), Namespace);

Я решил не добавлять в статью больше кода в BattleNetApiClient, чтобы статья не разрослась до безумных размеров.

Unit тесты

У нас появился класс GuildService с нетривиальной логикой, который будет изменяться и расширяться в будущем. Стоит написать на него тесты. Для этого нужно будет сделать заглушки для BattleNetApiClient, GuildRepository и DiscordBroker. Я специально просил создавать интерфейсы для этих классов чтобы можно было сделать их фейки.

Создайте новый проект для Unit тестов. Заведите в нем папку Fakes и сделайте три фейка.

public class DiscordBrokerFake : IDiscordBroker{   public List<string> SentMessages { get; } = new();   public Task SendMessage(string message, CancellationToken ct)   {      SentMessages.Add(message);      return Task.CompletedTask;   }}
public class GuildRepositoryFake : IGuildRepository{    public List<WowCharacterToken> Characters { get; } = new();    public Task<WowCharacterToken[]> GetCharacters(CancellationToken ct)    {        return Task.FromResult(Characters.ToArray());    }    public Task SaveCharacters(WowCharacterToken[] characters, CancellationToken ct)    {        Characters.Clear();        Characters.AddRange(characters);        return Task.CompletedTask;    }}
public class BattleNetApiClientFake : IBattleNetApiClient{   public List<WowCharacterToken> GuildMembers { get; } = new();   public List<WowCharacter> Characters { get; } = new();   public Task<WowCharacterToken[]> GetGuildMembers()   {      return Task.FromResult(GuildMembers.ToArray());   }}

Эти фейки позволяют заранее задать возвращаемое значение для методов. Для этих же целей можно использовать популярную библиотеку Moq. Но для нашего простого примера достаточно самодельных фейков.

Первый тест на GuildService будет выглядеть так:

[Test]public async Task SaveNewMembers_WhenCacheIsEmpty(){   var wowCharacterToken = new WowCharacterToken   {      WowId = 100,      Name = "Sam"   };      var battleNetApiClient = new BattleNetApiApiClientFake();   battleNetApiClient.GuildMembers.Add(wowCharacterToken);   var guildRepositoryFake = new GuildRepositoryFake();   var guildService = new GuildService(battleNetApiClient, null, guildRepositoryFake);   var changes = await guildService.Check(CancellationToken.None);   changes.JoinedMembers.Length.Should().Be(0);   changes.DepartedMembers.Length.Should().Be(0);   changes.TotalCount.Should().Be(1);   guildRepositoryFake.Characters.Should().BeEquivalentTo(wowCharacterToken);}

Как видно из названия, тест позволяет проверить что мы сохраним список игроков, если кэш пуст. Заметьте, в конце теста используется специальный набор методов Should, Be... Это методы из библиотеки FluentAssertions, которые помогают нам сделать Assertion более читабельным.

Теперь у нас есть база для написания тестов. Я показал вам основную идею, дальнейшее написание тестов оставляю вам.

Главный функционал проекта готов. Теперь можно подумать о его публикации.

Шаг 4. Привет Docker и Heroku!

Мы будем размещать проект на платформе Heroku. Heroku не позволяет запускать .NET проекты из коробки, но она позволяет запускать Docker образы.

Чтобы упаковать проект в Docker нам понадобится создать в корне репозитория Dockerfile со следующим содержимым

FROM mcr.microsoft.com/dotnet/sdk:5.0 AS builderWORKDIR /sourcesCOPY *.sln .COPY ./src/peon.csproj ./src/COPY ./tests/tests.csproj ./tests/RUN dotnet restoreCOPY . .RUN dotnet publish --output /app/ --configuration ReleaseFROM mcr.microsoft.com/dotnet/core/aspnet:3.1WORKDIR /appCOPY --from=builder /app .CMD ["dotnet", "peon.dll"]

peon.dll это название моего Solution. Peon переводится как батрак.

О том как работать с Docker и Heroku можно прочитать здесь. Но я все же опишу последовательность действий.

Вам понадобится создать аккаунт в Heroku, установить Heroku CLI.

Создайте новый проект в heroku и свяжите его с вашим репозиторием.

heroku git:remote -a project_name

Теперь нам необходимо создать файл heroku.yml в папке с проектом. У него будет такое содержимое:

build:  docker:    web: Dockerfile

Дальше выполним небольшую череду команд:

# Залогинимся в heroku registryheroku container:login# Соберем и запушим образ в registryheroku container:push web# Зарелизим приложение из образаheroku container:release web

Можете открыть приложение в браузере с помощью команды:

heroku open

После того как мы разместили приложение в Heroku, нужно подключить базу данных Redis для кэша. Как вы помните InMemory кэш будет исчезать после перезапуска приложения.

Установите для нашего Heroku приложения бесплатный аддон RedisCloud.

Строку подключения для Redis можно будет получить через переменную окружения REDISCLOUD_URL. Она будет доступна, когда приложение будет запущено в экосистеме Heroku.

Нам нужно получить эту переменную в коде приложения.

Установите библиотеку Microsoft.Extensions.Caching.StackExchangeRedis.

С помощью нее можно зарегистрировать Redis реализацию для IDistributedCache в Startup.

services.AddStackExchangeRedisCache(o =>{   o.InstanceName = "PeonCache";   var redisCloudUrl = Environment.GetEnvironmentVariable("REDISCLOUD_URL");   if (string.IsNullOrEmpty(redisCloudUrl))   {      throw new ApplicationException("redis connection string was not found");   }   var (endpoint, password) = RedisUtils.ParseConnectionString(redisCloudUrl);   o.ConfigurationOptions = new ConfigurationOptions   {      EndPoints = {endpoint},      Password = password   };});

В этом коде мы получили переменную REDISCLOUD_URL из переменных окружения системы. После этого мы извлекли адрес и пароль базы данных с помощью класса RedisUtils. Его написал я сам:

public static class RedisUtils{   public static (string endpoint, string password) ParseConnectionString(string connectionString)   {      var bodyPart = connectionString.Split("://")[1];      var authPart = bodyPart.Split("@")[0];      var password = authPart.Split(":")[1];      var endpoint = bodyPart.Split("@")[1];      return (endpoint, password);   }}

На этот класс можно сделать простой Unit тест.

[Test]public void ParseConnectionString(){   const string example = "redis://user:password@url:port";   var (endpoint, password) = RedisUtils.ParseConnectionString(example);   endpoint.Should().Be("url:port");   password.Should().Be("password");}

После того что мы сделали, GuildRepository будет сохранять кэш не в оперативную память, а в Redis. Нам даже не нужно ничего менять в коде приложения.

Опубликуйте новую версию приложения.

Шаг 5. Реализуем циклическое выполнение

Нам нужно сделать так чтобы проверка состава гильдии происходила регулярно, например каждые 15 минут.

Есть несколько способов это реализовать:

Самый простой способ - это сделать задание на сайте https://cron-job.org. Этот сервис будет слать get запрос на /check вашего приложения каждые N минут.

Второй способ - это использовать Hosted Services. В этой статье подробно описано как создать повторяющееся задание в ASP.NET Core проекте. Учтите, бесплатный тариф в Heroku подразумевает что ваше приложение будет засыпать после того как к нему некоторое время не делали запросов. Hosted Service перестанет работать после того как приложение заснет. В этом варианте вам следует перейти на платный тариф. Кстати, так сейчас работает мой бот.

Третий способ - это подключить к проекту специальные Cron аддоны. Например Heroku Scheduler. Можете пойти этим путем и разобраться как создать cron job в Heroku.

Шаг 6. Автоматическая сборка, прогон тестов и публикация

Во-первых, зайдите в настройки приложения в Heroku.

Там есть пункт Deploy. Подключите там свой Github аккаунт и включите Automatic deploys после каждого коммита в master.

Поставьте галочку у пункта Wait for CI to pass before deploy. Нам нужно чтобы Heroku дожидался сборки и прогонки тестов. Если тесты покраснеют, то публикация не случится.

Сделаем сборку и прогонку тестов в Github Actions.

Зайдите в репозиторий и перейдите в пункт Actions. Теперь создайте новый workflow на основе шаблона .NET

В репозитории появится новый файл dotnet.yml. Он описывает процесс сборки.

Как видите по его содержимому, задание build будет запускаться после пуша в ветку master.

on:  push:    branches: [ master ]  pull_request:    branches: [ master ]

Содержимое самого задания нас полностью устраивает. Если вы вчитаетесь в то что там происходит, то увидите что там происходит запуск команд dotnet build и dotnet test.

    steps:    - uses: actions/checkout@v2    - name: Setup .NET      uses: actions/setup-dotnet@v1      with:        dotnet-version: 5.0.x    - name: Restore dependencies      run: dotnet restore    - name: Build      run: dotnet build --no-restore    - name: Test      run: dotnet test --no-build --verbosity normal

Менять в этом файле ничего не нужно, все уже будет работать из коробки.

Запуште что-нибудь в master и посмотрите что задание запускается. Кстати, оно уже должно было запуститься после создания нового workflow.

Отлично! Вот мы и сделали микросервис на .NET Core который собирается и публикуется в Heroku. У проекта есть множество точек для развития: можно было бы добавить логирование, прокачать тесты, повесить метрики и. т. д.

Надеюсь данная статья подкинула вам пару новых идей и тем для изучения. Спасибо за внимание. Удачи вам в ваших проектах!

Подробнее..
Категории: C , Net , Api , Docker , Dotnet , Discord , Bot , Бот , Heroku , Микросервис , Wow

Из песочницы Онлайн Магазин будущего

04.11.2020 18:10:50 | Автор: admin
Последний кризис показал, как важно уметь продавать онлайн. Угроза второй волны гонит магазины в киберпространство.

Мало сделать сайт. Надо привести в него людей. Стоимость привлечения посетителей в веб-магазины зашкаливает. Остается горестно вспоминать те времена, когда пионеры индустрии деловито занимали места на новой торговой площадке. Поисковики были маленькими, а цены зелеными.

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

Мы как-то все привыкли, что серьезный интернет бизнес строится на компьютерном интернете. А между тем

image

Уходим от конкуренции


По данным Digital 2020 больше половины времени(50.1%), которое мы проводим в интернете теперь приходится на мобильные телефоны.
Тренд 1: Мобильный интернет начинает доминировать
Аналитики из App Annie заявляют, что на мобильные приложения теперь приходится 10 из каждых 11 минут пользования мобильным устройством, а на просмотр веб-страниц уходит только 9% нашего мобильного времени. Приходится признать, что роль магазинов здесь выполняют мобильные приложения. Правила игры совсем другие. И конкуренция существенно ниже.
Тренд 2: В мобильной среде первую скрипку играют мобильные приложения

Снимаем ограничения


Обычно мобильные магазины работают с небольшим ассортиментом товаров/услуг. Ограничение напрямую связано с маленьким экраном смартфона.

Мы привыкли использовать меню классификации для поиска товара. Прайс в несколько тысяч наименований, в маленьком окошке, превращается в кошмар с картинками (как же без них). Большой объем данных делает классификатор не эффективным.



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

Похоже, что мы лучше стали общаться с компьютером. Монолог: "Смотри что у меня есть", меняется на диалог: "Что вам угодно?". Если пофантазировать, то вполне естественно сообщить телефону: "Хочу капучино", и получить его, где-нибудь поблизости.
Тренд 3: Среди большого объема данных, доминирует поиск по запросам, близким к естественному общению.
Заменяя классификатор на запросы, мы получим несколько плюшек.

  • Не надо ломать голову что важнее: категория Сапоги/Туфли или Мужские/Женские.
  • Легко использовать сложный товар с характеристиками. Для обуви это размеры и цвет, для автомобилей это марка авто или номер кузова.
  • Мы, побуждаем пользователя формулировать желание. Это помогает онлайн продавцу мониторить ход визита и помогать покупателю не задавая лишних вопросов.

Развивающийся искусственный интеллект делает язык запросов естественнее и точнее. Известны удачные кейсы с запросами по фотографиям или голосом. Обратите внимание, что та-же Яндекс Алиса наиболее полезна именно в мобильном секторе. С компьютера не сделать фотографию или видео так же свободно, как с телефона.
Смартфон в наименьшей степени удобен для коммуникации на экране, в наибольшей для голоса, фото или видео общения.
Примерно половина из 3,7 часов в день, которые люди проводят с мобильными в руках, они тратят на приложения социальных сетей и мессенджеры.

image
Тренд 4: Самые популярные мобильные приложения социальные сети и месcенджеры.
Время подвести итоги и заметить, что интернет смещается в сторону мессенджеров в мобильных устройствах. Вот удивил! Поддержка общения, это прямое назначение телефона. Можно ли утверждать, что к этому стремится центр тяжести всего интернета?

Давайте рассуждать: Интернет, это в первую очередь способ коммуникации. Мобильный телефон это средство коммуникации которое всегда под рукой. Коммуникации с кем? Не только с человеком, но и программой. Самое время вспомнить очередной тренд:


Тренд 5: Чат-боты набирают популярность
В более общем случае я бы сформулировал общее направление так:
Развитие интернета идет в сторону естественного общения человека
с человеком или машиной посредством мобильного терминала.
Я далек от радикальных мыслей, что все остальное вымрет. Думаю, что на горизонте ближайших 5-10 лет будет преобладать такая вот клиент-серверная архитектура, где основными клиентами выступают мобильные телефоны в лице своих владельцев. Не претендуя на роль первооткрывателя посмотрим через призму этой формулировки на онлайн торговлю.

Онлайн магазин будущего, на мой взгляд, должен быть мобильным приложением со способностями естественного общения. Вашим собеседником станет живой консультант или чат-бот. Эдакий продвинутый мессенджер.

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

Написать Мобильное приложение это недешево. А наделить его способностями серьезного чата и подавно. Как оказаться на этой поляне раньше других?

Снижаем стоимость


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

И знаете, выбор пока оказывается не велик Чат-боты, так или иначе, можно сделать во многих мессенджерах, но способности Telegram заметно шире. Самое важное для нас отличие, это возможность программировать кнопки (Помнить и набивать команды вручную, понравится не каждому). Если знаете аналоги напишите пожалуйста в комментарии.

Вдобавок, каналы делают Телеграмм социальной сетью. А это не лишняя плюшка в способностях онлайн магазина.
Телеграмм с чат-ботом это недорогая основа собственного онлайн магазина.
Получается достаточно запрограммировать внутреннюю логику чат-бота, об остальном позаботится мультиплатформенный Telegram.

Я предпринял попытку создать такой чат-бот. То что у меня получилось, после установки Телеграмм, можно посмотреть на https://t.me/repassBot.
Подробнее..

Как чат-боты помогают цирку, вузу и эко-проекту 5 неординарных кейсов на визуальном конструкторе c NLU

19.05.2021 18:19:31 | Автор: admin

Чат-бот МЕГИ и ИКЕА распознает 8 наиболее распространенных фракций отходов и ежедневно обрабатывает порядка 30 сообщений.Бот АкБарс Банка развивает сотрудников и в прошлом году обучил 54% специалистов в компании. Бот Президентской академии в Санкт-Петербурге отвечает на вопросы абитуриентов и в августе 2020 года помог более 1000 поступающим.При этом все кейсы были реализованы на визуальном конструкторе с NLU. Just AI, разработчик технологий в сфере разговорного AI,рассказывает о деталях создания чат-ботов.

Чат-бот МЕГИ и ИКЕА сортирует мусор

Ежегодно в России образуется около 70 млн тонн бытового мусора, это в 10 раз больше веса пирамиды Хеопса. При разложении отходы выделяют опасные химикаты, например, метан, которыми мы же потом и дышим.

МЕГА и ИКЕА реализуют глобальную стратегию по устойчивому развитию ДА людям и планете! и несколько лет назад запустили программу раздельного сбора мусора Правила Деления в Санкт-Петербурге. На территории двух центров МЕГА появились сортировочные пункты, было налажено сотрудничество с перерабатывающими предприятиями. Организаторы движения стали проводить лекции и сделали группу в социальной сети ВКонтакте, на момент публикации в ней состоят более 22 тыс. подписчиков.

Отчасти причина непопулярности экологических инициатив в России в недостаточном эко-образовании населения. Люди не понимают, как, куда и в каком виде можно сдавать отходы. Мы постоянно получали вопросы, принимается та или иная продукция, нужно ли снимать этикетки с бутылок. Нам хотелось сделать так, чтобы любой человек мог мгновенно получить ответы на запросы о маркировке и раздельном сборе отходов, - Александр Страдышев, куратор проекта, МЕГА Парнас.

Количество мусора можно сократить почти на 80%, если органические и пищевые отходы закапывать в почву, а опасные правильно утилизировать.

Организаторы получали так много сообщений ВКонтакте, что решили автоматизировать ответы на типовые запросы. Команда Правил Деления разработала в конструкторе Aimylogiс чат-бота, который теперь помогает администратору группы. Бот представляет собой интерактивный FAQ, где есть ответы на часто задаваемые вопросы: Можно ли это сдать, Где вы находитесь, Время работы станций, Нужно ли снимать этикетку и др.

Чат-бота разрабатывали в несколько этапов. Для начала собрали таблицу со всеми возможными маркировками отходов, их описанием и возможностями приема и переработки. Затем написали сценарии вопросов и ответов, их разработка заняла около недели, и запрограммировали бота. Наконец, доработали формулировки, логотип и удобные для распознавания маркировки.

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

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

Результат

Чат-бот умеет распознавать 8 наиболее распространенных фракций отходов. Ежедневно он обрабатывает порядка 30 сообщений, а в пиковый день помог более чем 500 людям. За все время работы ботом воспользовались 4 430 человек.

Чат-бот Упсала-Цирка знает расписание спектаклей

Единственный в мире цирк для хулиганов Упсала-Цирк, где соединились акробатика, жонглирование, контемпорари, элементы уличной культуры, паркура и брейкданса, не получает финансирование от государства, а работает за счет продажи билетов и поддержки зрителей и партнеров. Для сбора пожертвований у цирка есть отдельный сайт со встроенным чат-ботом.

От AI-технологии в Упсала-Цирке в первую очередь хотели получить больше возможностей для общения со зрителями и волонтерами.

У многих компаний есть одна проблема: люди заходят на сайт, что-то узнают и просто уходят, а мы по факту узнаем, какой был трафик на сайте. Мы хотели собрать контактные данные пользователей, понять, что это за люди, и в дальнейшем отправлять им релевантную информацию, Екатерина Черемисина, PR-менеджер Упсала-Цирка.

Персонажем чат-бота стала собака по кличке Пина, которую списали с реальной собаки режиссера.

Цирк в целом про эмоции и удивление. Кто-то в шутку предложил сделать Пину персонажем чат-бота. Я зацепилась за эту мысль, потому что Пина постоянно в цирке, у всех на виду. Мне показалось, что такой персонаж может заинтересовать и завлечь пользователей, Екатерина Черемисина.

Задумка, действительно, удалась. Бегу за мячиком! Но на пару вопросов отвечу! пишет собака Пина в диалоге. Она может скинуть расписание спектаклей, сориентировать в курсах, объяснить, как добраться до цирка и каким транспортом лучше воспользоваться. В чат-боте есть ветки по вопросам сотрудничества, волонтерства, пожертвований. Также Пина предлагает всем заполнить контактную форму.

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

Результат

За два с половиной месяца работы в цирке роботизированная собака Пина помогла 144 уникальным пользователям. У команды Упсала-Цирка есть задумка встроить в чат-бота окошко для вноса пожертвований. Кроме того, сейчас цирк разрабатывает новый сайт и планирует интегрировать чат-бота туда.

Большие планы связаны с тем, чтобы разделить посетителей, оставивших контактные данные, на сегменты и отправлять им таргетированные рассылки. В зависимости от того, какой контент будет интересно получать пользователям и какой на него пойдет отклик, будет зависеть дальнейшая стратегия работы с аудиторией.

Затрачено на конструктор чат-ботов Aimylogic на момент публикации: 3 960 руб.

Чат-бот АкБарс Банка развивает сотрудников

Технология чат-ботов востребована в HR-сфере, часто ее используются для задач прескрининга кандидатов, онбординга новых сотрудников и опросов. В АкБарс Банке взглянули на возможности технологии шире и разработали 9 ботов, задача которых обучение и развитие персонала.

Мы планировали запустить обучающий, прикладной и массовый продукт в компании, но бюджета на реализацию не было. Также мы понимали, что региональные сотрудники хотят обучаться, но не имеют возможности ездить в командировки, - Марина Вахтина, руководитель Учебного центра Ак Барс Банка.

Чат-боты АкБарс Банка помогают сотрудникам осваивать профессиональные навыки вроде владения Excel и развивать софт-скиллы. Бот Барсик обучает коммуникативным навыкам: он дает задание и варианты ответов, а потом проговаривает правильный вариант и объясняет, почему другие варианты неправильные.

По структуре боты похожи на личный кабинет на edtech-платформах и приложениях, но самостоятельная разработка бота в Aimylogiс сэкономила время и деньги компании, а также дала команде больше свободы по контролю за учебным процессом.

Многие боты задеплоены в телеграм. Мессенджер можно установить на компьютер и смартфон. Соответственно, сотрудник всегда и отовсюду имеет доступ к своим учебным материалам, текстам, видео и оценкам и в любой момент может снова обратиться за информацией, которая не уложилась сразу. Это позволяет обучать сотрудников с минимальным отрывом от рабочего процесса. Кроме того, в компании признали важную социальную функцию обучения с помощью чат-бота: в процессе занятий знакомятся друг с другом и обмениваются практиками сотрудники, которые до этого никогда не пересекались.

Результат

За 3 месяца 2019 года с помощью чат-бота прошли обучение 1798 человек 31% сотрудников компании. Командировочные расходы, связанные с выездами на обучение, упали на 36%.

В 2020 году, когда командировки стали невозможны, значение удаленного обучения существенно возросло. Чат-бот обучил 2726 человек 54% сотрудников. По результатам опроса, в 27 удаленных регионах удовлетворенность обучением выросла с 62 до 75%.

Затрачено на конструктор чат-ботов Aimylogic на момент публикации: 47 200 руб.

Чат-бот Президентской академии помогает абитуриентам

Прием абитуриентов время предельной нагрузки для любого вуза. Чтобы сделать процесс поступления максимально комфортным, в Петербургском РАНХиГС при Президенте РФ действует проект Виртуальный помощник абитуриента. Суть программы в том, что каждый поступающий оставляет электронную почту и потом регулярно получает на нее полезную информацию.

Но на этом в вузе не остановились и решили сделать помощника действительно виртуальным. Для этой роли выбрали чат-бота. Сегодня он работает на сайте вуза и в Telegram. В отличие от сотрудника приемной комиссии бот может отвечать на вопросы в любое время суток. Для популярного вуза, поступать в который едут со всей России, это актуальная задача.

По данным Совета ректоров Санкт-Петербурга и Ленинградской области, 70% из числа поступающих приезжают в наш город из других субъектов России. Чтобы процесс поступления в вуз для них был максимально простым и понятным, мы решили создать консультанта с искусственным интеллектом силу, которая никогда не спит и способна общаться с тысячью пользователями одновременно, говорит директор Северо-Западного института управления Владимир Шамахов.

Стоит сказать, что виртуальный консультант СЗИУ РАНХиГС коренной петербуржец, именно поэтому он готов ответить на вопросы не только о поступлении, но и рассказать абитуриентам о главных достопримечательностях города. Для этого потребуется задать лишь один вопрос: Куда сходить в Петербурге?.

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

Бот может подсказать проходные баллы на ту или иную программу, где найти конкурсные списки поступающих и личный кабинет абитуриента, как и в какие сроки подать документы, а также проинформировать о дополнительных вступительных испытаниях. Индивидуальные запросы абитуриентов чат-бот переводит на сотрудника приемной комиссии.

Результат

Пик вопросов предсказуемо пришелся на время вступительных экзаменов. В августе 2020 года ботом воспользовались более 1000 человек.

Цветочный чат-бот принимает заказы в интернет-магазине

Цветы в интернет-магазине БукетОпт покупают клиенты из разных регионов и даже часовых поясов. Каждый день у них возникают вопросы по ассортименту, доставке и ценам. Сначала их можно было задать по телефону или в чате на сайте, отвечал на них оператор. Сотрудник заканчивал работу в 8 вечера часть вопросов оставалась без ответов, и компания теряла деньги.

Затем для удобства покупателей в БукетОпт подключили Открытые линии Битрикс24. Эта система собирает сообщения с разных площадок Instagram, ВКонтакте, WhatsApp, сохраняет в CRM и ставит в очередь к оператору. Оказалось, что людям удобно задавать вопросы в привычных социальных сетях и мессенджерах число обращений выросло в несколько раз, и ресурса одного оператора перестало хватать. Тогда в компании задумались о виртуальном помощнике.

Люди часто задают однотипные вопросы: оформление заказа, оплата, доставка, ассортимент, и гораздо проще, когда на них отвечает бот. Мы прослушали порядка 300 звонков и выделили 11 групп часто задаваемых вопросов, - Лада Трегубова, маркетолог БукетОпт.

На изучение материалов и инструкций Aimylogic ушла неделя. Основной задачей была верно составить логику вопросов и ответов для чат-бота.

По образованию я лингвист, и интенты, слова и словоформы подобрала достаточно быстро. Люди формулируют свои запросы очень по-разному, а смысл один, - Лада Трегубова.

За время работы чат-бота стало понятно, что лучше работают вопросы, где покупатель выбирает однозначный ответ да или нет. Это сокращает процент ошибок и форс-мажоров, требующих подключения оператора. В ближайших планах переделать часть сценария под закрытые вопросы.

Результат

Бот обслуживает около 1000 диалогов каждый месяц. Их результативность в компании отслеживают по utm-меткам. 1000 запросов дают 269 переходов на сайт, из посетивших интернет-магазин клиентов 23% добавляют заказ в корзину и 14% оплачивают покупку.

В интернет-магазине БукетОпт планируют, что в дальнейшем бот будет собирать контактные данные покупателей, создавать лиды в Битрикс24 и самостоятельно оформлять заказы. Это сократит время покупки и увеличит продуктивность всего интернет-магазина.

Затрачено на конструктор чат-ботов Aimylogic на момент публикации: 68 990 руб.

Подробнее..

Тестируем 11 ботов для прокачки английского в Телеграм полезный инструмент или чушь собачья?

12.02.2021 20:07:41 | Автор: admin

В интернете есть куча статей типа Топ ботов для прокачки английского. Но написаны они так, как будто информация переходит из одного текста в другой, а авторы даже не пытаются проверить их на собственном опыте.

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

Начнем с того, что многие боты, которые мы решили протестировать, оказались нерабочими. В общей сложности мы проверили 23 бота из рейтингов и списков, из которых 12 оказались сломанными.

Интересно, что многие из них раньше работали. К примеру, @slovarikbot.

У него была единственная, но интересная функция: подбирать фрагмент из кино или сериалов как пример использования конкретного слова.

Нужно было вбить слово, и система выдавала 5-секундный отрывок из кино.

Неплохая штука, если хочется посмотреть, как используется конкретное слово в контексте. Может больше фаново, чем обучающе, но все же.

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

Хахаль, ничем не могу помочь, или Боты переводчики

И для начала выделим обычных ботов-переводчиков. Они полезны, если не хочется устанавливать на телефон лишний софт, но функционал их ограничивается только переводом слов и фраз.

@YTranslateBot

@LingvoBot

@multitran_bot

Они отлично выполняют свои функции, но как инструмент для изучения или прокачки английского не подойдут.

С их помощью можно вспомнить перевод, посмотреть транскрипцию или значения слова, но не изучать язык это лишь вспомогательные инструменты.

@LingvoBot

Переводит только слова. Дает максимально краткий перевод в одну строчку, без детализации, нюансов и примеров использования. Очень просто сломать, написав не одно слово, а фразу.

У нас получилось что-то такое:

Хахаль, ничем не могу помочь шедевр.

Система выдает пример фразы в контексте, но качество этих примеров оставляет желать лучшего.

@multitran_bot

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

@YTranslateBot

Хороший бот от Яндекса, который умеет переводить не только отдельные слова, но и фразы. В формате бота доступны 12 языков не густо, но для перевода небольших текстов или отдельных предложений достаточно.


@AndyRobot

Практически во всех топах есть этот бот. Начали мы именно с него.

По факту это обычный чат-бот, который ошибочно считают хорошим инструментом для совершенствования английского. Заметим, не самый лучший чат-бот.

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

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

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

@WordContextBot

Довольно неплохой бот, который помогает разобраться с нюансами использования слов и фраз.

Базовая функция это переводчик. Он дает варианты перевода слов и сразу же его использование в контексте фраз и предложений. Очень удобно. Отдельно стоит упомянуть хорошую верстку примеры и варианты использования не режут глаз и хорошо воспринимаются как с телефона, так и в десктопной версии.

Отдельно есть три дополнительных функции:

  • Показать словосочетания с этим словом

  • Привести примеры в текстах

  • Дать произношение слова

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

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

Как вспомогательный инструмент для обучения вполне неплохо.

@fixmebot

Бот для проверки правописания на английском. Это его единственная функция и он справляется неплохо.

В качестве теста написали два предложения с ошибками бот их выделил и выдал исправленную версию текста.

Результат неплохой, но не отличный. Простой текст с описками бот правит без проблем. Но вот с каверзными ошибками он не справился.

Бота можно добавлять в чаты тогда если кто-то напишет сообщение на английском ошибкой, бот его поправит. Также в описании сказано, что бот успешно проверяет на ошибки и картинки, но здесь начинаются косяки.

Мы попробовали несколько разных вариантов фоток с картинками. На всех были ошибки. Но бот неизменно выдавал, что в тексте ошибок нет.

Не слишком понятно, почему так. Возможно, распознавание текста работает только для сканов, но об этом не сказано ни слова.

В общем, неплохой инструмент для работы с текстом, но вот с картинками бот работать не хочет от слова совсем.

@EnglishSimpleBot

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

Бот действительно сделан хорошо. Есть возможность читать тексты на английском и отмечать неизвестные слова, проходить тесты на конкретные темы, совершенствовать грамматику. Есть справочные материалы по уровням языка, грамматике, книгам и фановая подборка Love is фантиков из популярной жвачки.

Неплохое подспорье для человека с уровнем до Upper Intermediate.

Здесь интересно проработана система изучения лексики. Открываете любой топик или книгу из списка. И когда вы читаете текст, можно любое слово отметить как незнакомое.

А потом в режиме Изучения слов можно учить неизвестные слова.

Механизм интересный. Но как у прикладного инструмента у него есть несколько серьезных минусов.

  • Во-первых, бот не присылает оповещения про тренировки. Поэтому большинство людей балуются им ровно раз и благополучно забывают о нем.

  • Во-вторых, если с небольшими топиками бот работает нормально, то полноценные книги для него оказываются слишком тяжелыми. 3-7 секунд он думает, чтобы открыть новое предложение. За это время можно прочитать его трижды.

  • В-третьих, система изначально считает неизвестными все слова. И блок незнакомые слова во время чтения сильно раздражает. Единственный выход отмечать все слова как известные. Руками. Весь свой словарный запас.

В теории такой бот может стать отличным инструментом для изучения английского. Но это если из всего многообразия вам оставить только доступ в Телеграм.

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

@DualBookBot

Бот для параллельного чтения книг. Тут все просто. На одной странице пишется оригинальный текст книги на английском и сразу же ее перевод на русском. Давно известный инструмент, который помогает преодолеть страх перед книгами на иностранных языках.

Материалов в самом боте не слишком много всего 33, но для начала вполне достаточно. Не все из них книги, поэтому выберите, что нравится.

Мы выбрали Крестного отца Пьюзо.

Механизм крайне простой. Бот выдает текст по абзацам. Сначала оригинал на английском, потом перевод на русский. Работает значительно быстрее, чем функция чтения книг в предыдущем примере.

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

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

Функция добавления слов в словарь и их изучения тоже есть, но она работает неудобно.

Как инструмент очень даже неплох. Один из немногих ботов, который действительно будет полезным для человека, который учит английский.

@AlphaEnglishBot

Очень интересный бот, в котором есть упражнения на грамматику и аудирование, а также викторины.

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

Но вот навигация оставляет желать лучшего. В кнопках бота нет Вернуться назад или Главная. Из-за этого приходится возвращаться в меню путем команды /start. Мелочь, но очень неудобно.

В целом бот интересный, хоть и маленький. Его можно использовать как развлечение для студента, который устал от классических занятий. Но как полноценный инструмент вряд ли.

@languagecenterbot

Бот, который помогает учить теорию английского языка. Своеобразный справочник, который всегда под рукой.

Вроде и неплохо структурирована информация, но чувствуется какая-то небрежность в его реализации. Описки, странная верстка, обилие ненужных смайликов все это сильно отвлекает.

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

@LennyEnglishBot

Бот, который направлен на изучение лексики. Сначала бот будет предлагать вам слова. Нужно отметить, знаете вы конкретную лексему или нет. Затем все неизвестные слова выпадут в простом упражнении, где нужно выбрать правильный перевод слова из четырех вариантов ответа.

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

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

Выводы

Честно говоря, мы рассчитывали на более оптимистичный результат. В статьях из глубин интернета видели боты на любой вкус но реальность оказалась суровой.

Половина ботов из рейтингов и списков банально не работают у них команда команда /start не приводит ни к чему.

Боты-переводчики справляются хорошо. Остальные тоже вроде работают и выполняют свои узкие функции, но полноценными инструментами для изучения английского их назвать никак нельзя.

Побаловаться да, конечно. Разнообразить изучение и попробовать что-то необычное вполне. Использовать время от времени как запасной инструмент можно и так. Но учить язык с их помощью нельзя. Боты не смогут дать даже базового уровня.

У нас сложилось впечатление, что некоторые из популярных ранее ботов были забыты из-за банального падения интереса к ним. Сегодня некоторые такие проекты трансформировались в каналы или же и вовсе поменяли направление. На волне хайпа к ботам их активно разрабатывали, но после оценки реальной их пользы просто списали. Что ж, это закономерно.

А вы использовали когда-нибудь боты для изучения иностранных языков или вообще чего-либо? Потому что говорили о них много, но практически никто их не испытывал на себе. Нам интересно, расскажите, будьте добры.

Бонус: список нерабочих ботов, которые мы протестировали

Здесь под спойлером небольшой список ботов, которые еще есть в рейтингах, даже относительно свежих. Но эти боты уже не подают признаков жизни или не выполняют свои основные функции.

Паровозики, которые не смогли

@slovarikbot бот, который присылает отрывки кино и сериалов в качестве примеров использования английских слов. Трансформирован в пустой канал.

@ErwinChatBot бот, который задает загадки на английском и помогает их решить. Не работает полностью.

@Slangbot бот, который помогал изучать сленговые слова в английском языке. Сейчас почему-то на арабском.

@TopWord_bot бот для изучения лексики. Сейчас пустой, на команду /start не реагирует.

@PronunciationBot бот, который трансформирует английский текст в аудио-сообщение с выбранным акцентов. Общая навигация есть, но аудиосообщение не генерируется, как ни крути.

@BuchBookBot бот, который предлагает читать книги на английском небольшими абзацами. Показывает приветственное сообщение и все.

@thepirate_bot бот для изучение грамматики. Не работает.

@EnjoyEnglish_bot бот для нетривиального тестирования уровня английского. Стартовое сообщение есть, но на /start не реагирует.

@Teacherbot бот для изучения английского в нуля. Полностью пустой.

@englishchatbot чат-бот для обучения английскому. Не работает.

@ILI_bot бот с ежедневными уроками по английскому. Навигация без реакций.

@duolingo_bot обучающий бот от Duolingo. Висит только стартовое сообщение.

Онлайн-школа EnglishDom.com вдохновляем выучить английский через технологии и человеческую заботу

Только для читателей Хабра первый урок с преподавателем в интерактивном цифровом учебнике бесплатно! А при покупке занятий получите до 3 уроков в подарок!

Получи целый месяц премиум-подписки на приложение ED Words в подарок. Введи промокод feb21 на этой странице или прямо в приложении ED Words. Промокод действителен до 28.02.2021.

Наши продукты:

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru