Urban Bot or how to write chat bots for Telegram, Slack, Facebook ... on React.js

image



In this article, I want to introduce a new Urban Bot library that adapts React for writing chat bots. Below I will tell you why this library was born, what advantages it provides, and how to write your first chatbot.



A chatbot is most often a separate chat in a messenger, in which you communicate not with a person, but with a program. It can send messages in the form of text, images, buttons and many other UI elements and respond to messages from users. Modern chat bots are full-fledged UI applications inside instant messengers.

- , 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="https://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




All Articles