Skip to content

Commit 146cdc7

Browse files
committed
[refactoring] tests + contrib
1 parent 50a6c87 commit 146cdc7

24 files changed

+19983
-73
lines changed

.github/workflows/python-package.yml

+10-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
strategy:
1717
fail-fast: false
1818
matrix:
19-
python-version: ["3.9", "3.10", "3.11"]
19+
python-version: ["3.11"]
2020

2121
steps:
2222
- uses: actions/checkout@v3
@@ -27,14 +27,19 @@ jobs:
2727
- name: Install dependencies
2828
run: |
2929
python -m pip install --upgrade pip
30+
python setup.py install
3031
python -m pip install flake8 pytest
32+
python -m pip install pytest-cov
3133
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
3234
- name: Lint with flake8
3335
run: |
3436
# stop the build if there are Python syntax errors or undefined names
35-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
36-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
37-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
37+
flake8 --count --max-complexity="14" --doctests --show-source --statistics --max-line-length="125"
3838
- name: Test with pytest
3939
run: |
40-
pytest
40+
pytest --cov
41+
- name: Upload coverage to Codecov
42+
uses: codecov/codecov-action@v4
43+
env:
44+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
45+
files: .coverage

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
# Compiled, optimized or cached files.
55
.cache/
66
__pycache__/
7+
.pytest_cache/
78
*.py[cod]
89
*$py.class
10+
build/
911

1012
# Bot example log.
1113
/example/log/

CONTRIBUTING.md

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Contribute
2+
## Pull request
3+
Если вы решили впервые стать контрибьютером и помочь развитию open-source проекта, этот пункт для вас.
4+
1) Делается fork основного репозитория
5+
2) git clone https://github.com/ваш-логин/bot-golang.git
6+
3) Локальное изменение
7+
4) Сделайте ребейз на remote master ветку
8+
5) git push origin <ваш-логин>
9+
6) В удаленном репозитории нажать _compare&pull request_
10+
11+
Также рекомендуем ознакомиться с подробной инструкцией для контрибьютеров - <a href="https://github.com/firstcontributions/first-contributions">README.md</a>
12+
13+
## Tests
14+
1) Если добавляется новая функциональность, то покрывайте ее тестами
15+
2) Следите за тем, чтобы тесты успешно выполнялись в PR перед мержем.
16+
17+
## Merge
18+
Ветка будет смержена в мастер, когда:
19+
1) Все пайплайны пройдут успешно
20+
2) Новая функциональность будет покрыта тестами
21+
22+
После выполнения всех пунктов один из сотрудников проверит в ближайшее время PR и смержит его.

README.md

+13-30
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,21 @@
1-
<img src="https://github.com/mail-ru-im/bot-python/blob/master/logo.png" width="100" height="100">
1+
<img src="logo_bot.png" width="100" height="100">
22

3-
# 🐍 bot-python
3+
# VK Teams Bot API for Python
4+
[![Python package](https://github.com/mail-ru-im/bot-python/actions/workflows/python-package.yml/badge.svg)](https://github.com/mail-ru-im/bot-python/actions/workflows/python-package.yml)
5+
[![codecov](https://codecov.io/github/mail-ru-im/bot-python/graph/badge.svg?token=ObUFRWSyGv)](https://codecov.io/github/mail-ru-im/bot-python)
6+
[![go.dev reference](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/mail-ru-im/bot-golang)
7+
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
48

5-
Pure Python interface for Bot API.
9+
### [<img src="logo_msg.png" width="16"> VK Teams API Specification](https://teams.vk.com/botapi/)
610

7-
# Table of contents
8-
- [Introduction](#introduction)
9-
- [Getting started](#getting-started)
10-
- [Installing](#installing)
11-
- [API description](#api-description)
11+
## Getting started
1212

13-
# Introduction
14-
15-
This library provides complete Bot API 1.0 interface and compatible with Python 2.7, 3.4, 3.5, 3.6, 3.7, 3.8, 3.9, 3.10.
16-
17-
# Getting started
18-
19-
* Create your own bot by sending the /newbot command to <a href="https://icq.com/people/70001">Metabot</a> and follow the instructions.
13+
* Create your own bot by sending the _/newbot_ command to _Metabot_ and follow the instructions.
2014
>Note: a bot can only reply after the user has added it to his contact list, or if the user was the first to start a dialogue.
21-
* You can configure the domain that hosts your ICQ server. When instantiating the Bot class, add the address of your domain.
22-
> Example: Bot(token=TOKEN, name=NAME, version=VERSION, api_url_base="https://api.icq.net/bot/v1"), by default we use the domain: https://api.icq.net/bot/v1
23-
* If you are Myteam client, you can add flag "is_myteam=True", when instantiating the Bot class. This will let you use additional chat methods.
24-
> Example: Bot(token=TOKEN, name=NAME, is_myteam=True), by default it is False.
25-
15+
* You can configure the domain that hosts your VK Teams server. When instantiating the Bot class, add the address of your domain.
16+
* An example of how to use the framework can be seen in _example/test_bot.py_
2617

27-
> An example of how to use the framework can be seen in example/test_bot.py
28-
29-
# Installing
18+
## Installing
3019
Install using pip:
3120
```bash
3221
pip install --upgrade mailru-im-bot
@@ -37,10 +26,4 @@ Install from sources:
3726
git clone https://github.com/mail-ru-im/bot-python.git
3827
cd bot-python
3928
python setup.py install
40-
```
41-
42-
# API description
43-
<ul>
44-
<li><a href="https://icq.com/botapi/">icq.com/botapi/</a></li>
45-
<li><a href="https://agent.mail.ru/botapi/">agent.mail.ru/botapi/</a></li>
46-
</ul>
29+
```

bot/bot.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@
1717
from . import __version__ as version
1818
from .dispatcher import Dispatcher
1919
from .event import Event
20-
from .handler import *
20+
from .handler import EventType, DefaultHandler, \
21+
NewChatMembersHandler, LeftChatMembersHandler, \
22+
PinnedMessageHandler, MessageHandler, \
23+
EditedMessageHandler, DeletedMessageHandler, \
24+
CommandHandler, HelpCommandHandler, \
25+
StartCommandHandler, UnknownCommandHandler, \
26+
BotButtonCommandHandler, UnPinnedMessageHandler, \
27+
Filter, StopDispatching
2128
from .util import signal_name_by_code
2229
from .myteam import add_chat_members, create_chat
2330
from .types import InlineKeyboardMarkup, Format
@@ -32,6 +39,7 @@ def keyboard_to_json(keyboard_markup):
3239
else:
3340
return keyboard_markup
3441

42+
3543
def format_to_json(format_):
3644
if isinstance(format_, Format):
3745
return format_.to_json()
@@ -40,6 +48,7 @@ def format_to_json(format_):
4048
else:
4149
return format_
4250

51+
4352
class Bot(object):
4453
def __init__(self, token: str, api_url_base: str = None, name: str = None, version: str = None,
4554
timeout_s: int = 20, poll_time_s: int = 60, is_myteam: bool = False):
@@ -107,8 +116,10 @@ def _start_polling(self):
107116
if "description" in response.json() and response.json()["description"] == 'Invalid token':
108117
raise InvalidToken(response.json())
109118

110-
for event in response.json()["events"]:
111-
self.dispatcher.dispatch(Event(type_=EventType(event["type"]), data=event["payload"]))
119+
if "events" in response.json():
120+
for event in response.json()["events"]:
121+
self.dispatcher.dispatch(Event(type_=EventType(event["type"]), data=event["payload"]))
122+
112123
except InvalidToken as e:
113124
self.log.exception("InvalidToken: {e}".format(e=e))
114125
sleep(5)

bot/constant.py

+2
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,13 @@ class ChatType(Enum):
6060
GROUP = "group"
6161
CHANNEL = "channel"
6262

63+
6364
@unique
6465
class ParseMode(Enum):
6566
MARKDOWNV2 = "MarkdownV2"
6667
HTML = "HTML"
6768

69+
6870
@unique
6971
class StyleType(Enum):
7072
BOLD = "bold"

bot/event.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,6 @@ def __init__(self, type_, data):
3636
self.chat_type = data['message']['chat']['type']
3737
self.message_author = data['queryId'].split(':')[1]
3838
self.queryId = data['queryId']
39-
39+
4040
def __repr__(self):
4141
return "Event(type='{self.type}', data='{self.data}')".format(self=self)

bot/filter.py

-1
Original file line numberDiff line numberDiff line change
@@ -220,4 +220,3 @@ class Filter(object):
220220
sender = SenderFilter
221221
callback_data = CallbackDataFilter
222222
callback_data_regexp = CallbackDataRegexpFilter
223-

bot/handler.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,4 +165,4 @@ def check(self, event, dispatcher):
165165
return (
166166
super(BotButtonCommandHandler, self).check(event=event, dispatcher=dispatcher) and
167167
event.type is EventType.CALLBACK_QUERY
168-
)
168+
)

bot/myteam.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from requests import Request
2+
33

44
def add_chat_members(self, chat_id, members):
55
return self.http_session.get(
@@ -11,6 +11,7 @@ def add_chat_members(self, chat_id, members):
1111
}
1212
)
1313

14+
1415
def create_chat(self, name, about="", rules="", members=[], public=False, join_moderation=False, default_role="member"):
1516
return self.http_session.get(
1617
url="{}/chats/createChat".format(self.api_base_url),

bot/types.py

+5-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from .constant import StyleType
44

5+
56
class JsonSerializable(object):
67

78
def to_json(self):
@@ -73,15 +74,16 @@ def to_json(self):
7374
def to_dic(self):
7475
return self.keyboard
7576

77+
7678
class Style(Dictionaryable, JsonSerializable):
7779

7880
def __init__(self):
7981
self.ranges = []
8082

8183
def add(self, offset, length, args=None):
82-
range_ = { "offset": offset, "length": length }
84+
range_ = {"offset": offset, "length": length}
8385
if args is not None:
84-
self.ranges.append({ **range_ , **args})
86+
self.ranges.append({**range_, **args})
8587
else:
8688
self.ranges.append(range_)
8789

@@ -91,6 +93,7 @@ def to_dic(self):
9193
def to_json(self):
9294
return json.dumps(self.ranges)
9395

96+
9497
class Format(Dictionaryable, JsonSerializable):
9598

9699
def __init__(self):

example/decorators_bot.py

-20
This file was deleted.

example/echo_bot.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from bot.bot import Bot
22
from bot.handler import MessageHandler
33

4-
TOKEN = "" #your token here
4+
TOKEN = "" # your token here
55

66
bot = Bot(token=TOKEN)
77

example/format_bot.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
from bot.bot import Bot
22
from bot.handler import MessageHandler
3-
from bot.constant import ParseMode
43
from bot.types import Format
54

65
import logging.config
76

87
logging.config.fileConfig("logging.ini")
98

10-
TOKEN = "" #your token here
9+
TOKEN = "" # your token here
1110

1211
bot = Bot(token=TOKEN, api_url_base="")
1312

13+
1414
def message_cb(bot, event):
1515
bot.send_text(chat_id=event.from_chat, text="*_Hello_*", parse_mode="MarkdownV2")
1616
bot.send_text(chat_id=event.from_chat, text="<s>|</s> World! <s>|</s>", parse_mode="HTML")

example/test_bot.py example/hidden_test_bot.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
CommandHandler, NewChatMembersHandler, LeftChatMembersHandler, PinnedMessageHandler, UnPinnedMessageHandler, \
1111
EditedMessageHandler, DeletedMessageHandler, StartCommandHandler, BotButtonCommandHandler
1212

13+
1314
if sys.version_info[0] == 3:
1415
from gtts import gTTS
1516

@@ -23,7 +24,7 @@
2324
OWNER = "XXXXXXXXX"
2425
TEST_CHAT = "XXXXX"
2526
TEST_USER = "XXXXX"
26-
API_URL = "https://api.icq.net/bot/v1"
27+
API_URL = "http://localhost:8080"
2728

2829

2930
def start_cb(bot, event):
@@ -259,7 +260,7 @@ def main():
259260
bot.dispatcher.add_handler(MessageHandler(filters=Filter.text, callback=message_cb))
260261

261262
# Handler with regexp filter
262-
bot.dispatcher.add_handler(MessageHandler(filters=Filter.regexp("^\d*$"), callback=regexp_only_dig_cb))
263+
bot.dispatcher.add_handler(MessageHandler(filters=Filter.regexp("^\\d*$"), callback=regexp_only_dig_cb))
263264

264265
# Handler for no media file. For example, text file
265266
bot.dispatcher.add_handler(MessageHandler(filters=Filter.data, callback=file_cb))

example/myteam_bot.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
logging.config.fileConfig("logging.ini")
77

8-
TOKEN = "" #your token here
8+
TOKEN = "" # your token here
99

1010
bot = Bot(token=TOKEN, api_url_base="", is_myteam=True)
1111

@@ -17,7 +17,7 @@ def message_cb(bot, event):
1717
bot.add_chat_members(chat_id=resp.json()['sn'], members=["[email protected]", "[email protected]", "[email protected]"])
1818
bot.send_text(chat_id=resp.json()['sn'], text="Hello! And Goodbye!")
1919
bot.delete_chat_members(chat_id=resp.json()['sn'], members=["[email protected]", "[email protected]"])
20-
bot.send_text(chat_id=event.from_chat, text="Bye!")
20+
bot.send_text(chat_id=event.from_chat, text="Bye!")
2121

2222

2323
bot.dispatcher.add_handler(MessageHandler(callback=message_cb))

example/scheduled_bot.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
import time
33
from bot.bot import Bot
44

5-
TOKEN = "" #your toke here
5+
TOKEN = "" # your toke here
66
bot = Bot(token=TOKEN)
77

88
chats_to_send_notifications = [

0 commit comments

Comments
 (0)