Create A New Bot
The guideline is described with a view of “Ethora” project usage.
All additional libraries, information etc. are presented with links to third-party websites.
Creating an App for the bot
You will need Dappros Platform Application JWT for the correct functioning of your Bot.
Make sure you have created a new Application or used an existing one and extracted your JWT.
Creating a User Account for the bot
First of all, you need to create a new account for your bot.
To do this, you need to send a request:
https://app-dev.dappros.com/v1/users/
With options:
{
"username": "botUserName",
"password": "password",
"firstName": "Name",
"lastName": "Bot"
}
After that, you will receive the data that is necessary to connect the bot to xmpp
{
"success": true,
"user": {
"defaultWallet": {
"walletAddress": "0xf88D155c6284333AFBd4b6316AC3A9118F181a2f"
},
"tags": [],
"roles": [],
"_id": "631a361d0878476a5704ee06",
"username": "botUserName",
"firstName": "Name",
"lastName": "Bot",
"ACL": {
"ownerAccess": false
},
"appId": "61e55c9d90ea99594bc7e6a2",
"xmppPassword": "bvYXcVfG38",
"emails": [],
"createdAt": "2022-09-08T18:36:13.778Z",
"updatedAt": "2022-09-08T18:36:13.981Z",
"__v": 0
},
"msg": "User created successfully",
"xmppMsg": "User [email protected] successfully registered"
}
From the given example above you’ll need:
- walletAddress
- username (which you specified when creating an account for this bot)
- password (which you specified when creating an account for this bot)
- xmppPassword
Bot connection to xmpp
To connect to the xmpp you can use any library, in our case we use xmppjs. All the detailed information of the library is described on the xmppjs website.
You can find an example of such a connection in the documentation for this library.
We need to use the following data:
const xmpp = client({
service: “dev.dxmpp.com”,
username: (Username of your bot),
password: (Password of your bot),
});
After that, use the logging library methods to see your bot's events:
debug(xmpp, true);
xmpp.on("offline", () => console.log("OFFLINE: xmpp disconnected and no automatic attempt to reconnect will happen"));
xmpp.on('error', err => console.log('ERROR:', err.toString));
xmpp.on('status', status => console.log('STATUS:', status));
To perform actions after your bot has started, use:
xmpp.on('online', jid => {});
At this stage, you can immediately connect to the chat room in which the bot should work, for this use:
xmpp.send(xml('presence', {
from: jid.toString(),
to: myRoomAddress,
}, xml('x', 'http://jabber.org/protocol/muc', xml('history', {maxstanzas: 0})))).catch(console.error);
In order to get the “myRoomAddress”, you need the address of the chat room and the jid of the bot.
To get the address of a chat room, you need to go to the Ethora application, create a room there (or open an existing one), click on the qr code icon and click copy url.
Then copy everything after "https://www.eto.li/go?c=".
This is your first part of the address, now add "@conference.dev.dxmpp.com/" here
Finally, after the described steps, here’s your bot's jid.
Getting bot jid
To get a bot's jid, you need to use this function along with its’ wallet (to format the address):
const getBotName = (walletAddress) => {
try {
return walletAddress.replace(/([A-Z])/g, '_$1').toLowerCase();
} catch (error) {
console.log('getBotName error: ', error);
}
}
You should get a similar result: "0xf88_d155c6284333_a_f_bd4b6316_a_c3_a9118_f181a2f"
At the end, your address will look like this: "855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com/0xf88_d155c6284333_a_f_bd4b6316_a_c3_a9118_f181a2f"
Now you can use this data to connect to the room when the bot starts.
To start the bot use:
xmpp.start().catch(console.error);
Listening to stanza
At this stage your bot is connected, running, and now it can listen to stanza.
In stanza you can find events that you can work with, all messages that users write in the room, etc.
To listen to the stanza use:
xmpp.on("stanza", async stanza => {});
First of all, you need to check that the received message is not from your own bot, so that it does not process its own messages and does not create an eternal loop.
In stanza, you can get the address of the bot in the room using:
const botAddressInTheRoom = stanza.attrs.from.replace(/\w+[.!?]?$/, '') +0xf88_d155c6284333_a_f_bd4b6316_a_c3_a9118_f181a2f; (+ formatted address of your bot)
To get the address of the sender of a message in a room:
const senderAddressInTheRoom = stanza.attrs.from;
Then use the condition provided by the xmppjs documentation to track messages "if (stanza.is("message"))" and add our comparison there
if (stanza.is("message") && senderAddressInTheRoom !== botAddressInTheRoom)
Further, basically, цhat you need to work with next are data and body.
Getting data
body: contains the message,
For example:
name: 'body',
parent: Element {
name: 'message',
parent: Element {
name: 'stream:stream',
parent: null,
children: [],
attrs: [Object]
},
children: [ [Element], [Element], [Element], [Circular *1] ],
attrs: {
'xml:lang': 'en',
to: '[email protected]/1150261366169961610847378',
from: '855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com/0x88_b03e38a4_b5735d685e6_f9_f2475_e_d6b063_a14eb',
type: 'groupchat',
id: 'sendMessage'
}
},
children: [ 'Test message' ],
attrs: {}
}
data: contains the user's data in the application, you will need to use it for further work, such as wallet, user name, jid, etc.
Normal xmpp doesn't have this data, it's only in our Ethora application.
name: 'data',
parent: Element {
name: 'message',
parent: Element {
name: 'stream:stream',
parent: null,
children: [],
attrs: [Object]
},
children: [ [Element], [Element], [Circular *1], [Element] ],
attrs: {
'xml:lang': 'en',
to: '[email protected]/442039186276814977647426',
from: '855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com/0x88_b03e38a4_b5735d685e6_f9_f2475_e_d6b063_a14eb',
type: 'groupchat',
id: 'sendMessage'
}
},
children: [],
attrs: {
xmlns: 'http://dev.dxmpp.com',
senderJID: '[email protected]',
senderFirstName: 'Anton',
senderLastName: 'Kolot',
senderWalletAddress: '0x88B03e38a4B5735d685e6F9F2475ED6b063A14eb',
isSystemMessage: 'false',
tokenAmount: '0',
receiverMessageId: '0',
photoURL: '',
roomJid: '855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com'
}
}
You can get this data in the following way:
stanza.getChild('body')
stanza.getChild('data')
To get a message, for further work with it, use:
stanza.getChild('body').getText();
Now you have the necessary data for work, you can check the message sent by the user, verify that this message was not sent by your bot, and get data about the user who sent the message.
Now let's see how a bot can send a message to a chat room.
Sending a message
To send a message, you need to use the following example:
data.xmpp.send(xml('message', {
to: "855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com",
type: 'groupchat',
id: "sendMessage"
}, xml('data', {
xmlns: "http://dev.dxmpp.com",
senderFirstName: "Name",
senderLastName: "Bot",
photoURL: "https://…url_to_image",
senderJID: "[email protected]",
senderWalletAddress: "0xf88D155c6284333AFBd4b6316AC3A9118F181a2f",
isSystemMessage: false,
tokenAmount: 0,
receiverMessageId: data.receiverMessageId,
roomJid: "855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com",
quickReplies: [],
}), xml('body', {},”Message text”)));
to: The address of the room in which the bot works must be in the format
855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com.
If your bot is running multiple rooms at the same time, you can use the following example to get the address of the current chat room: stanza.attrs.from.substring(0, stanza.attrs.from.lastIndexOf('/') + 1).slice(0, -1)
type: 'groupchat' (In the application, all chats, even one-on-one, are room chats.)
id: "sendMessage" (one type for sending regular messages and messages with buttons)
xmlns: "http://dev.dxmpp.com" (service link)
senderFirstName: The name of the bot that will be displayed in the chat
senderLastName: Last name of the bot that will be displayed in the chat
photoURL: Bot avatar that will be displayed in the chat
senderJID: jid of your bot in the format - its formatted address and service address, for example: [d155c6284333 a f bd4b6316 a c3 a9118 [email protected]|[email protected]]
senderWalletAddress: Bot wallet address (you received it when you created your account)
isSystemMessage: If you are sending a normal message then the status should be false.
If you send a message about the transfer of coins from the bot to the user, then the status must be set to true.
This status changes the display of your bot's message.
tokenAmount: If you send a system message, enter here the number of coins that the bot transfers to the user, then this will be displayed in the chat
receiverMessageId: You should get this parameter in data above.
roomJid: jid of the current chat room (we already got it above when we filled in "to")
quickReplies: Here you can send buttons to the chat, then after the user clicks on the button, process it in the bot.
Button format:
[
{
name: 'Button 1',
value: 'Button 1'
notDisplayedValue: "action1"
},
{
name: 'Button 2',
value: 'Button 2',
notDisplayedValue: "action2"
}
],
name: Button Display Name
value: The value that will be sent to the chat from the user when he clicks on the button.
notDisplayedValue: A value that is sent to data, but is not displayed other than in chat.
If you don't need to use buttons in a message, just leave this blank.
message: The text of the message you want to send. If you want, you can take from data the name of the user you are currently writing a message to.
Send typing
If you want the bot to behave more "humanly", you can send a status that the bot is currently writing a message.
To do this, you need to send the request "isComposing" before sending the message and "pausedComposing" after sending the message (show that the bot has stopped typing the message).
Example:
xmpp.send(xml('message', {
to: "855da3419c96d38f1934c722f4c0d28006345aef25fa0fac6450249e830d2bb5@conference.dev.dxmpp.com",
type: 'groupchat',
id: "isComposing" \ "pausedComposing"
}, xml('composing', {
xmlns: 'http://jabber.org/protocol/chatstates',
}), xml('data', {
xmlns: "http://dev.dxmpp.com",
fullName: Name Bot,
senderWalletAddress: 0xf88D155c6284333AFBd4b6316AC3A9118F181a2f
})));
to: jid of the current chat room (we already got it above when we filled in "to" in send message)
type: 'groupchat' (In the application, all chats, even one-on-one, are room chats.)
id: One of the options: "isComposing" \ "pausedComposing"
- isComposing : bot is composing a message
- pausedComposing : the bot stopped composing a message
fullName: First and last name of your bot
senderWalletAddress: Your bot's wallet
Working with API
All requests that you can make are described in this documentation: https://app-dev.dappros.com/api-docs/#/
But in order to send a request, for example, to transfer a token, you need an authorization token.
To do this, use the authorization request https://app-dev.dappros.com/api-docs/#/Users/post_v1_users_login
Along with the application token:
"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7Il9pZCI6IjYxZTU1YzlkOTBlYTk5NTk0YmM3ZTZhMiIsImFwcE5hbWUiOiJFdGhvcmEiLCJhcHBHb29nbGVJZCI6Ijk3MjkzMzQ3MDA1NC1oYnNmMjlvaHBhdG83NnRpbDJqdGY2amdnMWI0Mzc0Yy5hcHBzLmdvb2dsZXVzZXJjb250ZW50LmNvbSIsImNyZWF0b3JJZCI6IjYyYzNmNGE5M2FkMjcwNjc0YzFmNjJmYiIsImNyZWF0ZWRBdCI6IjIwMjItMDctMDVUMDg6Mjc6MjYuMzM2WiIsIl9fdiI6MH0sImlhdCI6MTY1NzAwOTY1OH0.dnvrO_dQ_2GLyUX-b71CcHFDnphpjeTYOxz6vZ2fsPY"
username and password you should have after creating a bot account.
After a successful request, you will receive user (bot) data and, among other things, your token and refresh token.
A refresh token needs to be updated when it expires.
With these tokens, you can make requests from the documentation.
When sending a transfer request, don't forget to use the send system message to notify users that the token has been sent.