Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[refactoring] tests + contrib #43

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.11"]

steps:
- uses: actions/checkout@v3
Expand All @@ -27,14 +27,19 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python setup.py install
python -m pip install flake8 pytest
python -m pip install pytest-cov
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
flake8 --count --max-complexity="14" --doctests --show-source --statistics --max-line-length="125"
- name: Test with pytest
run: |
pytest
pytest --cov
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
files: .coverage
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# Compiled, optimized or cached files.
.cache/
__pycache__/
.pytest_cache/
*.py[cod]
*$py.class
build/

# Bot example log.
/example/log/
Expand Down
22 changes: 22 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Contribute
## Pull request
Если вы решили впервые стать контрибьютером и помочь развитию open-source проекта, этот пункт для вас.
1) Делается fork основного репозитория
2) git clone https://github.com/ваш-логин/bot-golang.git
3) Локальное изменение
4) Сделайте ребейз на remote master ветку
5) git push origin <ваш-логин>
6) В удаленном репозитории нажать _compare&pull request_

Также рекомендуем ознакомиться с подробной инструкцией для контрибьютеров - <a href="https://github.com/firstcontributions/first-contributions">README.md</a>

## Tests
1) Если добавляется новая функциональность, то покрывайте ее тестами
2) Следите за тем, чтобы тесты успешно выполнялись в PR перед мержем.

## Merge
Ветка будет смержена в мастер, когда:
1) Все пайплайны пройдут успешно
2) Новая функциональность будет покрыта тестами

После выполнения всех пунктов один из сотрудников проверит в ближайшее время PR и смержит его.
43 changes: 13 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
<img src="https://github.com/mail-ru-im/bot-python/blob/master/logo.png" width="100" height="100">
<img src="logo_bot.png" width="100" height="100">

# 🐍 bot-python
# VK Teams Bot API for Python
[![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)
[![codecov](https://codecov.io/github/mail-ru-im/bot-python/graph/badge.svg?token=ObUFRWSyGv)](https://codecov.io/github/mail-ru-im/bot-python)
[![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)
![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)

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

# Table of contents
- [Introduction](#introduction)
- [Getting started](#getting-started)
- [Installing](#installing)
- [API description](#api-description)
## Getting started

# Introduction

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.

# Getting started

* Create your own bot by sending the /newbot command to <a href="https://icq.com/people/70001">Metabot</a> and follow the instructions.
* Create your own bot by sending the _/newbot_ command to _Metabot_ and follow the instructions.
>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.
* You can configure the domain that hosts your ICQ server. When instantiating the Bot class, add the address of your domain.
> 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
* 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.
> Example: Bot(token=TOKEN, name=NAME, is_myteam=True), by default it is False.

* You can configure the domain that hosts your VK Teams server. When instantiating the Bot class, add the address of your domain.
* An example of how to use the framework can be seen in _example/test_bot.py_

> An example of how to use the framework can be seen in example/test_bot.py

# Installing
## Installing
Install using pip:
```bash
pip install --upgrade mailru-im-bot
Expand All @@ -37,10 +26,4 @@ Install from sources:
git clone https://github.com/mail-ru-im/bot-python.git
cd bot-python
python setup.py install
```

# API description
<ul>
<li><a href="https://icq.com/botapi/">icq.com/botapi/</a></li>
<li><a href="https://agent.mail.ru/botapi/">agent.mail.ru/botapi/</a></li>
</ul>
```
17 changes: 14 additions & 3 deletions bot/bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,14 @@
from . import __version__ as version
from .dispatcher import Dispatcher
from .event import Event
from .handler import *
from .handler import EventType, DefaultHandler, \
NewChatMembersHandler, LeftChatMembersHandler, \
PinnedMessageHandler, MessageHandler, \
EditedMessageHandler, DeletedMessageHandler, \
CommandHandler, HelpCommandHandler, \
StartCommandHandler, UnknownCommandHandler, \
BotButtonCommandHandler, UnPinnedMessageHandler, \
Filter, StopDispatching
from .util import signal_name_by_code
from .myteam import add_chat_members, create_chat
from .types import InlineKeyboardMarkup, Format
Expand All @@ -32,6 +39,7 @@ def keyboard_to_json(keyboard_markup):
else:
return keyboard_markup


def format_to_json(format_):
if isinstance(format_, Format):
return format_.to_json()
Expand All @@ -40,6 +48,7 @@ def format_to_json(format_):
else:
return format_


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

for event in response.json()["events"]:
self.dispatcher.dispatch(Event(type_=EventType(event["type"]), data=event["payload"]))
if "events" in response.json():
for event in response.json()["events"]:
self.dispatcher.dispatch(Event(type_=EventType(event["type"]), data=event["payload"]))

except InvalidToken as e:
self.log.exception("InvalidToken: {e}".format(e=e))
sleep(5)
Expand Down
2 changes: 2 additions & 0 deletions bot/constant.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,13 @@ class ChatType(Enum):
GROUP = "group"
CHANNEL = "channel"


@unique
class ParseMode(Enum):
MARKDOWNV2 = "MarkdownV2"
HTML = "HTML"


@unique
class StyleType(Enum):
BOLD = "bold"
Expand Down
2 changes: 1 addition & 1 deletion bot/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,6 @@ def __init__(self, type_, data):
self.chat_type = data['message']['chat']['type']
self.message_author = data['queryId'].split(':')[1]
self.queryId = data['queryId']

def __repr__(self):
return "Event(type='{self.type}', data='{self.data}')".format(self=self)
1 change: 0 additions & 1 deletion bot/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,3 @@ class Filter(object):
sender = SenderFilter
callback_data = CallbackDataFilter
callback_data_regexp = CallbackDataRegexpFilter

2 changes: 1 addition & 1 deletion bot/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,4 @@ def check(self, event, dispatcher):
return (
super(BotButtonCommandHandler, self).check(event=event, dispatcher=dispatcher) and
event.type is EventType.CALLBACK_QUERY
)
)
3 changes: 2 additions & 1 deletion bot/myteam.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from requests import Request


def add_chat_members(self, chat_id, members):
return self.http_session.get(
Expand All @@ -11,6 +11,7 @@ def add_chat_members(self, chat_id, members):
}
)


def create_chat(self, name, about="", rules="", members=[], public=False, join_moderation=False, default_role="member"):
return self.http_session.get(
url="{}/chats/createChat".format(self.api_base_url),
Expand Down
7 changes: 5 additions & 2 deletions bot/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from .constant import StyleType


class JsonSerializable(object):

def to_json(self):
Expand Down Expand Up @@ -73,15 +74,16 @@ def to_json(self):
def to_dic(self):
return self.keyboard


class Style(Dictionaryable, JsonSerializable):

def __init__(self):
self.ranges = []

def add(self, offset, length, args=None):
range_ = { "offset": offset, "length": length }
range_ = {"offset": offset, "length": length}
if args is not None:
self.ranges.append({ **range_ , **args})
self.ranges.append({**range_, **args})
else:
self.ranges.append(range_)

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


class Format(Dictionaryable, JsonSerializable):

def __init__(self):
Expand Down
20 changes: 0 additions & 20 deletions example/decorators_bot.py

This file was deleted.

2 changes: 1 addition & 1 deletion example/echo_bot.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from bot.bot import Bot
from bot.handler import MessageHandler

TOKEN = "" #your token here
TOKEN = "" # your token here

bot = Bot(token=TOKEN)

Expand Down
4 changes: 2 additions & 2 deletions example/format_bot.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
from bot.bot import Bot
from bot.handler import MessageHandler
from bot.constant import ParseMode
from bot.types import Format

import logging.config

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

TOKEN = "" #your token here
TOKEN = "" # your token here

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


def message_cb(bot, event):
bot.send_text(chat_id=event.from_chat, text="*_Hello_*", parse_mode="MarkdownV2")
bot.send_text(chat_id=event.from_chat, text="<s>|</s> World! <s>|</s>", parse_mode="HTML")
Expand Down
5 changes: 3 additions & 2 deletions example/test_bot.py → example/hidden_test_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
CommandHandler, NewChatMembersHandler, LeftChatMembersHandler, PinnedMessageHandler, UnPinnedMessageHandler, \
EditedMessageHandler, DeletedMessageHandler, StartCommandHandler, BotButtonCommandHandler


if sys.version_info[0] == 3:
from gtts import gTTS

Expand All @@ -23,7 +24,7 @@
OWNER = "XXXXXXXXX"
TEST_CHAT = "XXXXX"
TEST_USER = "XXXXX"
API_URL = "https://api.icq.net/bot/v1"
API_URL = "http://localhost:8080"


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

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

# Handler for no media file. For example, text file
bot.dispatcher.add_handler(MessageHandler(filters=Filter.data, callback=file_cb))
Expand Down
4 changes: 2 additions & 2 deletions example/myteam_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

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

TOKEN = "" #your token here
TOKEN = "" # your token here

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

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


bot.dispatcher.add_handler(MessageHandler(callback=message_cb))
Expand Down
2 changes: 1 addition & 1 deletion example/scheduled_bot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import time
from bot.bot import Bot

TOKEN = "" #your toke here
TOKEN = "" # your toke here
bot = Bot(token=TOKEN)

chats_to_send_notifications = [
Expand Down
Loading
Loading