Use this library to develop a bot for Viber platform. The library is available on GitHub as well as a package on PyPI.
This package can be imported using pip by adding the following to your requirements.txt:
License
This library is released under the terms of the Apache 2.0 license. See License for more information.
Library Prerequisites
- python >= 2.7.0
- Get your Viber Public Account authentication token. Your token is generated and provided to you during the Public Account creation process. As a Public Account admin, you can always find the account token in the "edit info" page.
- Certification - You'll need a trusted (ca.pem) certificate, not self-signed. You can find one at Let's Encrypt or buy one.
Let's get started!
Installing
Creating a basic Viber bot is simple:
- Install the library though pip
pip install viberbot - Import
viberbot.apilibrary to your project - Create a Public Account and use the API key from https://developers.viber.com
- Configure your bot as described in the documentation below
- Start your web server
- Call
set_webhook(url)with your web server url
A simple Echo Bot
Firstly, let's import and configure our bot
from viberbot import Api from viberbot.api.bot_configuration import BotConfiguration bot_configuration = BotConfiguration( name='PythonSampleBot', avatar='http://viber.com/avatar.jpg', auth_token='YOUR_AUTH_TOKEN_HERE' ) viber = Api(bot_configuration)
Create an HTTPS server
Next thing you should do is starting a https server.
and yes, as we said in the prerequisites it has to be https server. Create a server however you like, for example with Flask:
from flask import Flask, request, Response app = Flask(__name__) @app.route('/incoming', methods=['POST']) def incoming(): logger.debug("received request. post data: {0}".format(request.get_data())) # handle the request here return Response(status=200) context = ('server.crt', 'server.key') app.run(host='0.0.0.0', port=443, debug=True, ssl_context=context)
Setting a webhook
After the server is up and running you can set a webhook. Viber will push messages sent to this URL. web server should be internet-facing.
viber.set_webhook('https://mybotwebserver.com:443/')
Logging
This library uses the standard python logger. If you want to see its logs you can configure the logger:
logger = logging.getLogger() logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) logger.addHandler(handler)
Do you supply a basic types of messages?
Well, funny you ask. Yes we do. All the Message types are located in viberbot.api.messages package. Here's some examples:
from viberbot.api.messages import ( TextMessage, ContactMessage, PictureMessage, VideoMessage ) from viberbot.api.messages.data_types.contact import Contact # creation of text message text_message = TextMessage(text="sample text message!") # creation of contact message contact = Contact(name="Viber user", phone_number="0123456789") contact_message = ContactMessage(contact=contact) # creation of picture message picture_message = PictureMessage(text="Check this", media="http://site.com/img.jpg") # creation of video message video_message = VideoMessage(media="http://mediaserver.com/video.mp4", size=4324)
Have you noticed how we created the TextMessage? There's a all bunch of message types you should get familiar with.
- Text Message
- Url Message
- Contact Message
- Picture Message
- Video Message
- Location Message
- Sticker Message
- Rich Media Message
Creating them is easy! Every message object has it's own unique constructor corresponding to it's API implementation, click on them to see it! Check out the full API documentation for more advanced uses.
Let's add it all up and reply with a message!
from flask import Flask, request, Response from viberbot import Api from viberbot.api.bot_configuration import BotConfiguration from viberbot.api.messages import VideoMessage from viberbot.api.messages.text_message import TextMessage import logging from viberbot.api.viber_requests import ViberConversationStartedRequest from viberbot.api.viber_requests import ViberFailedRequest from viberbot.api.viber_requests import ViberMessageRequest from viberbot.api.viber_requests import ViberSubscribedRequest from viberbot.api.viber_requests import ViberUnsubscribedRequest app = Flask(__name__) viber = Api(BotConfiguration( name='PythonSampleBot', avatar='http://site.com/avatar.jpg', auth_token='445da6az1s345z78-dazcczb2542zv51a-e0vc5fva17480im9' )) @app.route('/', methods=['POST']) def incoming(): logger.debug("received request. post data: {0}".format(request.get_data())) # every viber message is signed, you can verify the signature using this method if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')): return Response(status=403) # this library supplies a simple way to receive a request object viber_request = viber.parse_request(request.get_data()) if isinstance(viber_request, ViberMessageRequest): message = viber_request.message # lets echo back viber.send_messages(viber_request.sender.id, [ message ]) elif isinstance(viber_request, ViberSubscribedRequest): viber.send_messages(viber_request.get_user.id, [ TextMessage(text="thanks for subscribing!") ]) elif isinstance(viber_request, ViberFailedRequest): logger.warn("client failed receiving message. failure: {0}".format(viber_request)) return Response(status=200) if __name__ == "__main__": context = ('server.crt', 'server.key') app.run(host='0.0.0.0', port=443, debug=True, ssl_context=context)
As you can see there's a bunch of Request types here's a list of them.
Viber API
Api class
from viberbot import Api
- Api
- init(bot_configuration)
- .set_webhook(url, webhook_events) ⇒
List of registered event_types - .unset_webhook() ⇒
None - .get_account_info() ⇒
object - .verify_signature(request_data, signature) ⇒
boolean - .parse_request(request_data) ⇒
ViberRequest - .send_messages(to, messages) ⇒
list of message tokens sent - .get_online(viber_user_ids) ⇒
dictionary of users status - .get_user_details(viber_user_id) ⇒
dictionary of user's data
New Api()
| Param | Type | Description |
|---|---|---|
| bot_configuration | object |
BotConfiguration |
Api.set_webhook(url)
| Param | Type | Description |
|---|---|---|
| url | string |
Your web server url |
| webhook_events | list |
optional list of subscribed events |
Returns List of registered event_types. Example
event_types = viber.set_webhook('https://example.com/incoming')
Api.unset_webhook()
Returns None. Example
Api.get_account_info()
Returns an object with the following JSON. Example
account_info = viber.get_account_info()
Api.verify_signature(request_data, signature)
| Param | Type | Description |
|---|---|---|
| request_data | string |
the post data from request |
| signature | string |
sent as header X-Viber-Content-Signature |
Returns a boolean suggesting if the signature is valid. Example
if not viber.verify_signature(request.get_data(), request.headers.get('X-Viber-Content-Signature')): return Response(status=403)
Api.parse_request(request_data)
| Param | Type | Description |
|---|---|---|
| request_data | string |
the post data from request |
Returns a ViberRequest object. Example
There's a list of ViberRequest objects
viber_request = viber.parse_request(request.get_data())
Api.send_messages(to, messages)
| Param | Type | Description |
|---|---|---|
| to | string |
receiver viberId |
| messages | list |
list of Message objects |
Returns list of message tokens of the messages sent. Example
tokens = viber.send_messages(to=viber_request.get_sender().get_id(), messages=[TextMessage(text="sample message")])
Api.get_online(viber_user_ids)
| Param | Type | Description |
|---|---|---|
| viber_user_ids | array of strings |
Array of Viber user ids |
Returns a dictionary of users.
users = Api.get_online(["user1id", "user2id"])
Api.get_user_details(viber_user_id)
| Param | Type | Description |
|---|---|---|
| viber_user_ids | string |
Viber user id |
The get_user_details function will fetch the details of a specific Viber user based on his unique user ID. The user ID can be obtained from the callbacks sent to the PA regrading user's actions. This request can be sent twice during a 12 hours period for each user ID.
user_data = Api.get_user_details("userId")
Request object
| Param | Type | Notes |
|---|---|---|
| event_type | string |
according to EventTypes enum |
| timestamp | long |
Epoch of request time |
- ViberRequest
- .event_type ⇒
string - .timestamp ⇒
long
- .event_type ⇒
ViberConversationStartedRequest object
Inherits from ViberRequest
Conversation started event fires when a user opens a conversation with the PA using the “message” button (found on the PA’s info screen) or using a deep link.
This event is not considered a subscribe event and doesn't allow the PA to send messages to the user; however, it will allow sending one "welcome message" to the user. See sending a welcome message below for more information.
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.CONVERSATION_STARTED |
| message_token | string |
Unique ID of the message |
| type | string |
The specific type of conversation_started event. |
| context | string |
Any additional parameters added to the deep link used to access the conversation passed as a string |
| user | UserProfile |
the user started the conversation UserProfile |
| subscribed | boolean |
Indicates whether a user is already subscribed |
- ViberConversationStartedRequest
- message_token ⇒
string - type ⇒
string - context ⇒
string - user ⇒
UserProfile
- message_token ⇒
ViberDeliveredRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.DELIVERED |
| message_token | string |
Unique ID of the message |
| user_id | string |
Unique Viber user id |
- ViberDeliveredRequest
- message_token ⇒
string - user_id ⇒
string
- message_token ⇒
ViberFailedRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.FAILED |
| message_token | string |
Unique ID of the message |
| user_id | string |
Unique Viber user id |
| desc | string |
Failure description |
- ViberFailedRequest
- message_token ⇒
string - user_id ⇒
string - desc ⇒
string
- message_token ⇒
ViberMessageRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.MESSAGE |
| message_token | string |
Unique ID of the message |
| message | Message |
Message object |
| sender | UserProfile |
the user started the conversation UserProfile |
- ViberMessageRequest
- message_token ⇒
string - message ⇒
Message - sender ⇒
UserProfile
- message_token ⇒
ViberSeenRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.SEEN |
| message_token | string |
Unique ID of the message |
| user_id | string |
Unique Viber user id |
- ViberSeenRequest
- message_token ⇒
string - user_id ⇒
string
- message_token ⇒
ViberSubscribedRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.SUBSCRIBED |
| user | UserProfile |
the user started the conversation UserProfile |
- ViberSubscribedRequest
- user ⇒
UserProfile
- user ⇒
ViberUnsubscribedRequest object
Inherits from ViberRequest
| Param | Type | Notes |
|---|---|---|
| event_type | string |
always equals to the value of EventType.UNSUBSCRIBED |
| user_id | string |
Unique Viber user id |
- ViberUnsubscribedRequest
- get_user_id() ⇒
string
- get_user_id() ⇒
UserProfile object
| Param | Type | Notes |
|---|---|---|
| id | string |
--- |
| name | string |
--- |
| avatar | string |
Avatar URL |
| country | string |
currently set in CONVERSATION_STARTED event only |
| language | string |
currently set in CONVERSATION_STARTED event only |
Message Object
Common Members for Message interface:
| Param | Type | Description |
|---|---|---|
| timestamp | long |
Epoch time |
| keyboard | JSON |
keyboard JSON |
| trackingData | JSON |
JSON Tracking Data from Viber Client |
Common Constructor Arguments Message interface:
| Param | Type | Description |
|---|---|---|
| optionalKeyboard | JSON |
Writing Custom Keyboards |
| optionalTrackingData | JSON |
Data to be saved on Viber Client device, and sent back each time message is received |
TextMessage object
| Member | Type |
|---|---|
| text | string |
message = TextMessage(text="my text message")
URLMessage object
| Member | Type | Description |
|---|---|---|
| media | string |
URL string |
message = URLMessage(media="http://my.siteurl.com");
ContactMessage object
| Member | Type |
|---|---|
| contact | Contact |
from viberbot.api.messages.data_types.contact import Contact contact = Contact(name="Viber user", phone_number="+0015648979", avatar="http://link.to.avatar") contact_message = ContactMessage(contact=contact)
PictureMessage object
| Member | Type | Description |
|---|---|---|
| media | string |
url of the message (jpeg only) |
| text | string |
|
| thumbnail | string |
message = PictureMessage(media="http://www.thehindubusinessline.com/multimedia/dynamic/01458/viber_logo_JPG_1458024f.jpg", text="Viber logo")
VideoMessage object
| Member | Type | Description |
|---|---|---|
| media | string |
url of the video |
| size | int |
|
| thumbnail | string |
|
| duration | int |
message = VideoMessage(media="http://site.com/video.mp4", size=21499)
LocationMessage object
| Member | Type |
|---|---|
| location | Location |
from viberbot.api.messages.data_types.location import Location location = Location(lat=0.0, lon=0.0) location_message = LocationMessage(location=location)
StickerMessage object
| Member | Type |
|---|---|
| sticker_id | int |
message = StickerMessage(sticker_id=40100);
FileMessage object
| Member | Type |
|---|---|
| media | string |
| size | long |
| file_name | string |
message = FileMessage(media=url, size=sizeInBytes, file_name=file_name)
RichMediaMessage object
| Member | Type |
|---|---|
| rich_media | string (JSON) |
SAMPLE_RICH_MEDIA = """{ "BgColor": "#69C48A", "Buttons": [ { "Columns": 6, "Rows": 1, "BgColor": "#454545", "BgMediaType": "gif", "BgMedia": "http://www.url.by/test.gif", "BgLoop": true, "ActionType": "open-url", "Silent": true, "ActionBody": "www.tut.by", "Image": "www.tut.by/img.jpg", "TextVAlign": "middle", "TextHAlign": "left", "Text": "<b>example</b> button", "TextOpacity": 10, "TextSize": "regular" } ] }""" SAMPLE_ALT_TEXT = "upgrade now!" message = RichMediaMessage(rich_media=SAMPLE_RICH_MEDIA, alt_text=SAMPLE_ALT_TEXT);
Sending a welcome message
The Public Accounts API allows sending messages to users only after they subscribe to the PA. However, Viber will allow the PA to send one "welcome message" to a user as the user opens the conversation, before the user subscribes.
The welcome message will be sent as a response to a conversation_started callback, which will be received from Viber once the user opens the conversation with the Public Account. To learn more about this event and when is it triggered see Conversation started in the Callbacks section.
Welcome message flow
Sending a welcome message will be done according to the following flow:
- User opens 1-on-1 conversation with PA.
- Viber server send “conversation_started” even to PA’s webhook.
- PA receives the “conversation_started” and responds with an HTTP response which includes the welcome message as the response body.
The welcome message will be a JSON constructed according to the send_message requests structure, but without the receiver parameter. An example welcome message would look like this:
@app.route('/', methods=['POST']) def incoming(): viber_request = viber.parse_request(request.get_data()) if isinstance(viber_request, ViberConversationStartedRequest) : viber.send_messages(viber_request.get_user().get_id(), [ TextMessage(text="Welcome!") ]) return Response(status=200)
Community
Join the conversation on Gitter.