Skip to main content

bitrixogram

A simple async framework for creating bitrix chat bot in 'aiogram'-like style over Bitrix24 REST API

Supports Bitrix REST API and webhooks, requires JSON format support from the service
Should work on Python 3.x

Documentation

Available on https://github.com/lxxr/bitrixogram

Bitrix24 chatbot api documentation

https://dev.1c-bitrix.ru/learning/course/index.php?COURSE_ID=93&INDEX=Y

https://dev.1c-bitrix.ru/rest_help/index.php

Install

pip install bitrixogram

or

tar.gz and whl - https://pypi.org/project/bitrixogram/

Example:

Project sample structure

├── bot.py
├── handlers
│   ├── any_handler.py
│   └── message_handler.py
├── keyboards
│   └── main_keyboard.py
├── commands
│   └── commands.py
├── config
│   └── config.py

Create Bot and add routers for handle messages.

import asyncio
from aiohttp import ClientSession
import logging

from bitrixogram.core import BitrixBot,WebhookListener,Dispatcher
from handlers import messages_handler, any_handler

import config.settings as config
import commands.commands as reg_commands


async def main():
    logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
                         level=logging.INFO)
    logger = logging.getLogger(__name__)
    async with ClientSession() as session:
        bx= BitrixBot(config.bitrix_bot_endpoint,config.bitrix_bot_auth,config.bitrix_bot_id, session) 
        await bx.register_commands(reg_commands.commands, config.ip_whook_endpoint)
        dp = Dispatcher()
                
        dp.add_router(messages_handler.message_router(bx)) 	            #first router
        #.....................................................              ....
        dp.add_router(any_handler.any_router(bx))                           #last router 
        
        webhooks = WebhookListener(host=config.server_whook_addr_ip, port=config.server_whook_port, dispatcher=dp)
        await webhooks.start()
        logger.info("Bitrix bot webhook listener started")
        
    
        while True:
            await asyncio.sleep(3600)
            logging.info("[Bot] Still active...")
 
if __name__ == "__main__":
    asyncio.run(main())

Handler example

from bitrixogram.core import Router,FSMContext,MagicFilter,Message,Command,State,StatesGroup
from bitrixogram.attach import ReplyAttachMarkup, ReplyAttachBuilder, GridLayout
from keyboards.main_keyboard import get_main_kb

F = MagicFilter()
router = Router()


class TestState(StatesGroup):
    test1_state = State()
    test2_state = State()

def any_router(bx):
    @router.message(TestState.test1_state,((F.text()=="test2") | (F.text()=="test3")))
    async def handle_message_add_event_test_state1(message: Message, fsm: FSMContext):        
        chat_id = message.get_chat_id()
        state= await fsm.get_state()
        print(f"get state test1: {state}")
        await bx.send_message(
            chat_id=chat_id,
            text="any router test - state1"
        )
        await fsm.set_state(TestState.test2_state)
        
    @router.message(TestState.test2_state,(F.text()))        
    async def handle_message_add_event_test_state2(message: Message, fsm: FSMContext):        
        chat_id = message.get_chat_id()
        state= await fsm.get_state()
        print(f"get state test2: {state}")
        await bx.send_message(
            chat_id=chat_id,
            text="any router test - state2"
        )        
        await fsm.clear_state()
        
    @router.message(F.text()=="test")
    async def handle_message_add_event_test(message: Message, fsm: FSMContext):        
        chat_id = message.get_chat_id()
        await fsm.set_state(TestState.test1_state)
        state= await fsm.get_state()
        print(f"set state: {state}")
        await bx.send_message(
            chat_id=chat_id,
            text="any router test"
        
        )
        
    @router.message(F.text())
    async def handle_message_add_event_other_text(message: Message, fsm: FSMContext):        
        chat_id = message.get_chat_id()
        await bx.send_message(chat_id, "Any text handler")
        
    @router.callback_query(F.command())
    async def handle_message_add_event_other_command(command:Command, fsm:FSMContext):
        message_id = command.get_message_id()
	builder = ReplyAttachBuilder()

	column_layout = builder.grid_column_layout().add_item(name="priority", value="High").add_item(name="Category", value="Task")
	block_layout = builder.grid_block_layout().add_item(name="Description", value="new version of API", width=250).add_item(name="Category", value="Task", width=100)
	line_layout = builder.grid_line_layout().add_item(name="Priority", value="High", color="#ff0000", width=250).add_item(name="Category", value="Task")
	#attach example
	attach = (builder
	    .user(name="John Smith", avatar="{image_link}", link="https://api.bitrix24.com/")
	    .link(name="Issue #12345: new API \"Webhook listener\"", link="https://api.bitrix24.com/", desc="release notes", preview="{image_link}", width=1000, height=638)
	    .message("API version [B]im 1.1.0[/B]")
	    .delimiter(size=200, color="#c6c6c6")
	    .grid(column_layout)
	    .grid(block_layout)
	    .grid(line_layout)
	    .image(link="{image_link}", name="img name", preview="{image_preview_link}", width=1000, height=638)
	    .file(link="{file_link}", name="image.jpg", size=1500000)
	    .build()).to_dict()

	keyboard=get_main_kb()
        await bx.command_answer(command=command,text=f"This is command - {command.get_command_name()}", attach=attach ,keyboard=keyboard)

    return router

Keyboard example

from bitrixogram.keyboard import ReplyKeyboardMarkup, ReplyKeyboardBuilder

def get_main_kb() -> ReplyKeyboardMarkup:
    kb = ReplyKeyboardBuilder()
    kb.button(text="-",command="dec")
    kb.button(text="+",command ="inc", bg_color_token="alarm")
    kb.button(text="=",command = "sum", bg_color="#336633", bg_color_token="primary")
    kb.button(text="5",command = "info", bg_color="#336633", bg_color_token="secondary")
    kb.adjust(4)
    return kb.as_markup(resize_keyboard=True)

Commands example

commands = [
              {'COMMAND': 'inc',  'TITLE': '+','PARAMS': 'text' },
              {'COMMAND': 'dec',  'TITLE': '-','PARAMS': 'text' },
	      {'COMMAND': 'info', 'TITLE': '?','PARAMS': 'text' },
              {'COMMAND': 'sum',  'TITLE': '=','PARAMS': 'text' } ]

Config example

#endpoints  
bitrix_bot_endpoint=" https://xxx.xxx.xxx/rest/xx/xxx/" #Webhook for REST API
ip_whook_endpoint='http://WEBHOOK_IP_ADDRESS:WEBHOOK_PORT/' #External webhook server

#webhook server 
server_whook_addr_ip = "LOCAL_SERVER_IP" # Check route from ext interface
server_whook_port = LOCAL_SERVER_PORT

#bitrix bot auth and id
bitrix_bot_auth = "YOUR_BOT_AUTH_TOKEN" #Check in bitrix bot settings
bitrix_bot_id=BITRIX_BOT_CLIENT_ID #Check in bitrix bot settings

Metadata

Release files for bitrixogram 1.0.7

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bitrixogram 1.0.7
File Size Uploaded
bitrixogram-1.0.7.tar.gz 18.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for bitrixogram 1.0.7
File Interpreter ABI Platform
bitrixogram-1.0.7-py3-none-any.whl Python 3 none any Details

Total release size: 36.0 kB

Release files / bitrixogram-1.0.7.tar.gz

Download URL bitrixogram-1.0.7.tar.gz
Size 18.6 kB
Tags Source
SHA-256 checksum
How to use checksums
4cdbde914b14a3f60a8ead2ded1b832fc9a51d6614042400ca8ef287fbd6c4ad
BLAKE2b-256 checksum
How to use checksums
98ee8851c1b35b7e849d49eca851d520a2f8f671674e19a37534664e52b3fc17
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.0 CPython/3.11.5

Release files / bitrixogram-1.0.7-py3-none-any.whl

Download URL bitrixogram-1.0.7-py3-none-any.whl
Size 17.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
eb6cf6bfdc04d96dfa80669a5ea06bdd6352817652bdcd0ef731746f7800b929
BLAKE2b-256 checksum
How to use checksums
f50ae3038959d610eaadb91de08cfd5e56415da394c52bdf5240f17cd0b37f00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/5.1.0 CPython/3.11.5

Release history Release notifications | RSS feed

This release

1.0.7 This release

2 release files

1.0.6

2 release files

1.0.5

2 release files

1.0.4

2 release files

1.0.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page