Skip to content

Commit

Permalink
VkKeyboard (#148)
Browse files Browse the repository at this point in the history
* VkKeyboard + api version 5.80
* Refactor; Use six module
  • Loading branch information
Igor authored and python273 committed Jul 16, 2018
1 parent a9e425c commit 4d4eaa7
Show file tree
Hide file tree
Showing 13 changed files with 158 additions and 21 deletions.
10 changes: 10 additions & 0 deletions docs/keyboard.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
VkKeyboard
=======

Модуль для удобного создания клавиатур для ботов

.. module:: vk_api.keyboard
.. autoclass:: VkKeyboard
:members:
.. autoclass:: KeyboardColor
:members:
31 changes: 31 additions & 0 deletions examples/keyboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
import vk_api
from vk_api.keyboard import KeyboardColor


def main():
""" Пример создания клавиатуры для отправки ботом """

vk_session = vk_api.VkApi(token='bot_api_token')
vk = vk_session.get_api()

keyboard = vk_api.VkKeyboard(one_time=True)

keyboard.add_button('Белая кнопка', color=KeyboardColor.DEFAULT)
keyboard.add_button('Зелёная кнопка', color=KeyboardColor.POSITIVE)

keyboard.add_line() # Переход на вторую строку
keyboard.add_button('Красная кнопка', color=KeyboardColor.NEGATIVE)

keyboard.add_line()
keyboard.add_button('Синяя кнопка', color=KeyboardColor.PRIMARY)

vk.messages.send(
peer_id=123456,
message='Пример клавиатуры',
keyboard=keyboard.get_keyboard()
)


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
beautifulsoup4
requests
enum34
six
1 change: 1 addition & 0 deletions vk_api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from .exceptions import *
from .requests_pool import VkRequestsPool, vk_request_one_param_pool
from .tools import VkTools
from .keyboard import VkKeyboard
from .upload import VkUpload
from .vk_api import VkApi

Expand Down
2 changes: 2 additions & 0 deletions vk_api/audio_url_decoder.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
# -*- coding: utf-8 -*-
from six.moves import range

from .exceptions import VkAudioUrlDecodeError

VK_STR = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMN0PQRSTUVWXYZO123456789+/="
Expand Down
6 changes: 4 additions & 2 deletions vk_api/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
:copyright: (c) 2018 python273
"""

import six

from .utils import sjson_dumps
from .vk_api import VkApi, VkApiMethod

Expand Down Expand Up @@ -35,7 +37,7 @@ def __init__(self, code, args=None, clean_args=None, return_raw=False):
def compile(self, args):
compiled_args = {}

for key, value in args.items():
for key, value in six.iteritems(args):
if key in self.clean_args:
compiled_args[key] = str(value)
else:
Expand Down Expand Up @@ -74,7 +76,7 @@ def minify(code):
def parse_args(function_args, args, kwargs):
parsed_args = {}

for arg_name in kwargs.keys():
for arg_name in six.iterkeys(kwargs):
if arg_name in function_args:
parsed_args[arg_name] = kwargs[arg_name]
else:
Expand Down
90 changes: 90 additions & 0 deletions vk_api/keyboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
from enum import Enum

import six

from .utils import sjson_dumps


class KeyboardColor(Enum):
""" Возможные цвета кнопок """
PRIMARY = 'primary' # синяя
DEFAULT = 'default' # белая
NEGATIVE = 'negative' # красная
POSITIVE = 'positive' # зелёная


class VkKeyboard(object):
""" Класс для создания клавиатуры для бота (https://vk.com/dev/bots_docs_3)
:param one_time: Если True, клавиатура исчезнет после нажатия на кнопку
:type one_time: bool
"""

__slots__ = ('one_time', 'lines', 'keyboard')

def __init__(self, one_time=False):
self.one_time = one_time
self.lines = [[]]

self.keyboard = {
'one_time': self.one_time,
'buttons': self.lines
}

def get_keyboard(self):
""" Получить json клавиатуры """
return sjson_dumps(self.keyboard)

@classmethod
def get_empty_keyboard(cls):
""" Получить json пустой клавиатуры.
Если отправить пустую клавиатуру, текущая у пользователя исчезнет.
"""
keyboard = cls()
keyboard.keyboard['buttons'] = []
return keyboard.get_keyboard()

def add_button(self, label, color=KeyboardColor.DEFAULT, payload=None):
""" Добавить кнопку. Максимальное количество кнопок на строке - 4
:param label: Надпись на кнопке и текст, отправляющийся при её нажатии.
:type: str
:param color: цвет кнопки.
:type color: KeyboardColor or str
:param payload: Параметр для callback api
:type payload: str or list or dict
"""

current_line = self.lines[-1]

if len(current_line) >= 4:
raise ValueError('Max 4 buttons on a line')

color_value = color

if isinstance(color, KeyboardColor):
color_value = color_value.value

if payload is not None and not isinstance(payload, six.string_types):
payload = sjson_dumps(payload)

current_line.append({
'color': color_value,
'action': {
'type': 'text',
'payload': payload,
'label': label,
}
})

def add_line(self):
""" Создаёт новую строчку, на которой можно размещать кнопки.
Максимальное количество строк - 10
"""

if len(self.lines) >= 10:
raise ValueError('Max 10 lines')

self.lines.append([])
8 changes: 5 additions & 3 deletions vk_api/longpoll.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@

from collections import defaultdict
from datetime import datetime
from enum import Enum, IntEnum
from enum import IntEnum

import requests
import six
from six.moves import range

CHAT_START_ID = int(2E9) # id с которого начинаются беседы

Expand Down Expand Up @@ -228,7 +230,7 @@ class VkPeerFlag(IntEnum):
def get_all_event_attrs():
keys = set()

for l in EVENT_ATTRS_MAPPING.values():
for l in six.itervalues(EVENT_ATTRS_MAPPING):
keys.update(l)

return tuple(keys)
Expand All @@ -237,7 +239,7 @@ def get_all_event_attrs():
ALL_EVENT_ATTRS = get_all_event_attrs()

PARSE_PEER_ID_EVENTS = [
k for k, v in EVENT_ATTRS_MAPPING.items() if 'peer_id' in v
k for k, v in six.iteritems(EVENT_ATTRS_MAPPING) if 'peer_id' in v
]
PARSE_MESSAGE_FLAGS_EVENTS = [
VkEventType.MESSAGE_FLAGS_REPLACE,
Expand Down
7 changes: 2 additions & 5 deletions vk_api/requests_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@
:copyright: (c) 2018 python273
"""

import sys
from collections import namedtuple

from six.moves import range

from .exceptions import VkRequestsPoolException
from .execute import VkFunction
from .utils import sjson_dumps

if sys.version_info.major == 2:
range = xrange


PoolRequest = namedtuple('PoolRequest', ['method', 'values', 'result'])


Expand Down
3 changes: 1 addition & 2 deletions vk_api/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,7 @@
from .exceptions import ApiError, VkToolsException
from .execute import VkFunction

if sys.version_info.major == 2:
range = xrange
from six.moves import range


class VkTools(object):
Expand Down
8 changes: 4 additions & 4 deletions vk_api/upload.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def photo(self, photos, album_id,
""" Загрузка изображений в альбом пользователя
:param photos: путь к изображению(ям) или file-like объект(ы)
:type photos: str, list
:type photos: str or list
:param album_id: идентификатор альбома
:param latitude: географическая широта, заданная в градусах
Expand Down Expand Up @@ -74,7 +74,7 @@ def photo_messages(self, photos):
""" Загрузка изображений в сообщения
:param photos: путь к изображению(ям) или file-like объект(ы)
:type photos: str, list
:type photos: str or list
"""

url = self.vk.method('photos.getMessagesUploadServer')['upload_url']
Expand Down Expand Up @@ -144,7 +144,7 @@ def photo_wall(self, photos, user_id=None, group_id=None):
""" Загрузка изображений на стену пользователя или в группу
:param photos: путь к изображению(ям) или file-like объект(ы)
:type photos: str, list
:type photos: str or list
:param user_id: идентификатор пользователя
:param group_id: идентификатор сообщества (если загрузка идет в группу)
Expand Down Expand Up @@ -194,7 +194,7 @@ def video(self, video_file=None, link=None, name=None, description=None,
""" Загрузка видео
:param video_file: путь к видеофайлу или file-like объект.
:type video_file: object, str
:type video_file: object or str
:param link: url для встраивания видео с внешнего сайта,
например, с Youtube.
Expand Down
4 changes: 3 additions & 1 deletion vk_api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from __future__ import print_function

import six

try:
import simplejson as json
except ImportError:
Expand Down Expand Up @@ -74,7 +76,7 @@ def sjson_dumps(*args, **kwargs):

def cookie_to_dict(cookie):
cookie_dict = {
k: v for k, v in cookie.__dict__.items() if k in HTTP_COOKIE_ARGS
k: v for k, v in six.iteritems(cookie.__dict__) if k in HTTP_COOKIE_ARGS
}

cookie_dict['rest'] = cookie._rest
Expand Down
8 changes: 4 additions & 4 deletions vk_api/vk_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class VkApi(object):
:param scope: Запрашиваемые права, можно передать строкой или числом.
См. :class:`VkUserPermissions`
:type scope: int, str
:type scope: int or str
:param client_secret: Защищенный ключ приложения для Client Credentials Flow
авторизации приложения (https://vk.com/dev/client_cred_flow).
Expand All @@ -91,7 +91,7 @@ class VkApi(object):
def __init__(self, login=None, password=None, token=None,
auth_handler=None, captcha_handler=None,
config=jconfig.Config, config_filename='vk_config.v2.json',
api_version='5.74', app_id=6222115, scope=DEFAULT_USER_SCOPE,
api_version='5.80', app_id=6222115, scope=DEFAULT_USER_SCOPE,
client_secret=None):

self.login = login
Expand Down Expand Up @@ -230,7 +230,7 @@ def _vk_login(self, captcha_sid=None, captcha_key=None):
""" Авторизация ВКонтакте с получением cookies remixsid
:param captcha_sid: id капчи
:type captcha_key: int, str
:type captcha_key: int or str
:param captcha_key: ответ капчи
:type captcha_key: str
Expand Down Expand Up @@ -551,7 +551,7 @@ def method(self, method, values=None, captcha_sid=None, captcha_key=None,
:type values: dict
:param captcha_sid: id капчи
:type captcha_key: int, str
:type captcha_key: int or str
:param captcha_key: ответ капчи
:type captcha_key: str
Expand Down

0 comments on commit 4d4eaa7

Please sign in to comment.