Skip to content
This repository has been archived by the owner on Jun 2, 2019. It is now read-only.

Commit

Permalink
Bot API 3.4
Browse files Browse the repository at this point in the history
- Live location:
- Added `live_period` to method `sendLocation`, and namedtuple
`InlineQueryResultLocation` and `InputLocationMessageContent`
- Added method `editMessageLiveLocation` and `stopMessageLiveLocation`
- Added method `setChatStickerSet` and `deleteChatStickerSet`
- Added `sticker_set_name` and `can_set_sticker_set` to namedtuple
`Chat`
- Added `caption_entities` to namedtuple `Message`
- Added method `editMessageLiveLocation` and `stopMessageLiveLocation`
to class
`Editor`
- Added method `setChatStickerSet` and `deleteChatStickerSet` to class
`Administrator`
- Allowed supplying initial `offset` to `MessageLoop`
- Allowed Bot API access through proxy
  • Loading branch information
nickoala committed Oct 19, 2017
1 parent b2a8fda commit f69784b
Show file tree
Hide file tree
Showing 16 changed files with 197 additions and 58 deletions.
17 changes: 17 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# telepot changelog

## 12.4 (2017-10-19)

- Bot API 3.4
- Live location:
- Added `live_period` to method `sendLocation`, and namedtuple
`InlineQueryResultLocation` and `InputLocationMessageContent`
- Added method `editMessageLiveLocation` and `stopMessageLiveLocation`
- Added method `setChatStickerSet` and `deleteChatStickerSet`
- Added `sticker_set_name` and `can_set_sticker_set` to namedtuple `Chat`
- Added `caption_entities` to namedtuple `Message`
- Added method `editMessageLiveLocation` and `stopMessageLiveLocation` to class
`Editor`
- Added method `setChatStickerSet` and `deleteChatStickerSet` to class
`Administrator`
- Allowed supplying initial `offset` to `MessageLoop`
- Allowed Bot API access through proxy

## 12.3 (2017-08-28)

- Bot API 3.3
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# telepot - Python framework for Telegram Bot API

**[Bot API 3.3](https://core.telegram.org/bots/api)**-compliant!
**[Bot API 3.4](https://core.telegram.org/bots/api)**-compliant!

### [Introduction »](http://telepot.readthedocs.io/en/latest/)
### [Reference »](http://telepot.readthedocs.io/en/latest/reference.html)
Expand Down
6 changes: 6 additions & 0 deletions doc/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,9 @@ Outgoing objects include:

.. automodule:: telepot.text
:members:

``telepot.api``
----------------

.. automodule:: telepot.api
:members:
35 changes: 34 additions & 1 deletion telepot/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from . import exception


__version_info__ = (12, 3)
__version_info__ = (12, 4)
__version__ = '.'.join(map(str, __version_info__))


Expand Down Expand Up @@ -561,13 +561,36 @@ def sendVideoNote(self, chat_id, video_note,
return self._api_request_with_file('sendVideoNote', _rectify(p), 'video_note', video_note)

def sendLocation(self, chat_id, latitude, longitude,
live_period=None,
disable_notification=None,
reply_to_message_id=None,
reply_markup=None):
""" See: https://core.telegram.org/bots/api#sendlocation """
p = _strip(locals())
return self._api_request('sendLocation', _rectify(p))

def editMessageLiveLocation(self, msg_identifier, latitude, longitude,
reply_markup=None):
"""
See: https://core.telegram.org/bots/api#editmessagelivelocation
:param msg_identifier: Same as in :meth:`.Bot.editMessageText`
"""
p = _strip(locals(), more=['msg_identifier'])
p.update(_dismantle_message_identifier(msg_identifier))
return self._api_request('editMessageLiveLocation', _rectify(p))

def stopMessageLiveLocation(self, msg_identifier,
reply_markup=None):
"""
See: https://core.telegram.org/bots/api#stopmessagelivelocation
:param msg_identifier: Same as in :meth:`.Bot.editMessageText`
"""
p = _strip(locals(), more=['msg_identifier'])
p.update(_dismantle_message_identifier(msg_identifier))
return self._api_request('stopMessageLiveLocation', _rectify(p))

def sendVenue(self, chat_id, latitude, longitude, title, address,
foursquare_id=None,
disable_notification=None,
Expand Down Expand Up @@ -725,6 +748,16 @@ def getChatMember(self, chat_id, user_id):
p = _strip(locals())
return self._api_request('getChatMember', _rectify(p))

def setChatStickerSet(self, chat_id, sticker_set_name):
""" See: https://core.telegram.org/bots/api#setchatstickerset """
p = _strip(locals())
return self._api_request('setChatStickerSet', _rectify(p))

def deleteChatStickerSet(self, chat_id):
""" See: https://core.telegram.org/bots/api#deletechatstickerset """
p = _strip(locals())
return self._api_request('deleteChatStickerSet', _rectify(p))

def answerCallbackQuery(self, callback_query_id,
text=None,
show_alert=None,
Expand Down
33 changes: 33 additions & 0 deletions telepot/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,36 @@ async def sendVideoNote(self, chat_id, video_note,
return await self._api_request_with_file('sendVideoNote', _rectify(p), 'video_note', video_note)

async def sendLocation(self, chat_id, latitude, longitude,
live_period=None,
disable_notification=None,
reply_to_message_id=None,
reply_markup=None):
""" See: https://core.telegram.org/bots/api#sendlocation """
p = _strip(locals())
return await self._api_request('sendLocation', _rectify(p))

async def editMessageLiveLocation(self, msg_identifier, latitude, longitude,
reply_markup=None):
"""
See: https://core.telegram.org/bots/api#editmessagelivelocation
:param msg_identifier: Same as in :meth:`.Bot.editMessageText`
"""
p = _strip(locals(), more=['msg_identifier'])
p.update(_dismantle_message_identifier(msg_identifier))
return await self._api_request('editMessageLiveLocation', _rectify(p))

async def stopMessageLiveLocation(self, msg_identifier,
reply_markup=None):
"""
See: https://core.telegram.org/bots/api#stopmessagelivelocation
:param msg_identifier: Same as in :meth:`.Bot.editMessageText`
"""
p = _strip(locals(), more=['msg_identifier'])
p.update(_dismantle_message_identifier(msg_identifier))
return await self._api_request('stopMessageLiveLocation', _rectify(p))

async def sendVenue(self, chat_id, latitude, longitude, title, address,
foursquare_id=None,
disable_notification=None,
Expand Down Expand Up @@ -366,6 +389,16 @@ async def getChatMember(self, chat_id, user_id):
p = _strip(locals())
return await self._api_request('getChatMember', _rectify(p))

async def setChatStickerSet(self, chat_id, sticker_set_name):
""" See: https://core.telegram.org/bots/api#setchatstickerset """
p = _strip(locals())
return await self._api_request('setChatStickerSet', _rectify(p))

async def deleteChatStickerSet(self, chat_id):
""" See: https://core.telegram.org/bots/api#deletechatstickerset """
p = _strip(locals())
return await self._api_request('deleteChatStickerSet', _rectify(p))

async def answerCallbackQuery(self, callback_query_id,
text=None,
show_alert=None,
Expand Down
26 changes: 13 additions & 13 deletions telepot/aio/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import os
import asyncio
import aiohttp
import async_timeout
Expand All @@ -17,7 +16,14 @@
}

_timeout = 30
_proxy = None # (url, (username, password))

def set_proxy(url, basic_auth=None):
global _proxy
if not url:
_proxy = None
else:
_proxy = (url, basic_auth) if basic_auth else (url,)

def _close_pools():
global _pools
Expand All @@ -26,14 +32,6 @@ def _close_pools():

atexit.register(_close_pools)

def _get_env_http_proxy():
"""
Get HTTP_PROXY variable if available, otherwise get http_proxy
If no proxy is defined return None
"""
env_proxy = os.environ.get('HTTP_PROXY')
return env_proxy if env_proxy else os.environ.get('http_proxy')

def _create_onetime_pool():
return aiohttp.ClientSession(
connector=aiohttp.TCPConnector(limit=1, force_close=True),
Expand Down Expand Up @@ -125,10 +123,12 @@ async def _parse(response):

async def request(req, **user_kw):
fn, args, kwargs, timeout, cleanup = _transform(req, **user_kw)

# If http_proxy is set in the environment we should take care of
kwargs['proxy'] = _get_env_http_proxy()


if _proxy:
kwargs['proxy'] = _proxy[0]
if len(_proxy) > 1:
kwargs['proxy_auth'] = aiohttp.BasicAuth(*_proxy[1])

try:
if timeout is None:
async with fn(*args, **kwargs) as r:
Expand Down
8 changes: 4 additions & 4 deletions telepot/aio/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ def __init__(self, bot, on_update):
self._bot = bot
self._update_handler = on_update

async def run_forever(self, relax=0.1, timeout=20, allowed_updates=None, offset=None):
async def run_forever(self, relax=0.1, offset=None, timeout=20, allowed_updates=None):

This comment has been minimized.

Copy link
@das7pad

das7pad Nov 7, 2017

Contributor

@nickoala Why did you changed the sequence here?

This comment has been minimized.

Copy link
@nickoala

nickoala Nov 7, 2017

Author Owner

These parameters are basically passed directly to getUpdates(). I like them to be in the same order as in getUpdates().

This comment has been minimized.

Copy link
@das7pad

das7pad Nov 7, 2017

Contributor

Good point to use the same sequence.

"""
Process new updates in infinity loop
:param relax: int or float
:param relax: float
:param offset: int
:param timeout: int
:param allowed_updates: bool
:param offset: int
"""
while 1:
try:
Expand Down
52 changes: 28 additions & 24 deletions telepot/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,37 +3,41 @@
import json
import re
import os
import urllib.request

from . import exception, _isstring

# Suppress InsecurePlatformWarning
urllib3.disable_warnings()

_POOL_KWARGS_DEFAULT = dict(num_pools=3, maxsize=10, retries=3, timeout=30)
_POOL_KWARGS_ONETIME = dict(num_pools=1, maxsize=1, retries=3, timeout=30)
_PROXY = urllib.request.getproxies().get('http')
_pools = {}
if _PROXY:
try:
_pools['default'] = urllib3.ProxyManager(_PROXY, **_POOL_KWARGS_DEFAULT)
except urllib3.exceptions.ProxySchemeUnknown:
# invalid proxy provided in environment
logging.getLogger(__name__).critical('Invalid `HTTP_PROXY` set: %s',
repr(_PROXY))

_default_pool_params = dict(num_pools=3, maxsize=10, retries=3, timeout=30)
_onetime_pool_params = dict(num_pools=1, maxsize=1, retries=3, timeout=30)

_pools = {
'default': urllib3.PoolManager(**_default_pool_params),
}

_onetime_pool_spec = (urllib3.PoolManager, _onetime_pool_params)


def set_proxy(url, basic_auth=None):
"""
Access Bot API through a proxy.
:param url: proxy URL
:param basic_auth: 2-tuple ``('username', 'password')``
"""
global _pools, _onetime_pool_spec
if not url:
_pools['default'] = urllib3.PoolManager(**_default_pool_params)
_onetime_pool_spec = (urllib3.PoolManager, _onetime_pool_params)
elif basic_auth:
h = urllib3.make_headers(proxy_basic_auth=':'.join(basic_auth))
_pools['default'] = urllib3.ProxyManager(url, headers=h, **_default_pool_params)
_onetime_pool_spec = (urllib3.ProxyManager, dict(proxy_url=url, headers=h, **_onetime_pool_params))
else:
_onetime_pool_spec = (urllib3.ProxyManager,
dict(proxy_url=_PROXY, **_POOL_KWARGS_ONETIME))

if not _pools:
# no proxy set or proxy invalid - use the default route
_pools['default'] = urllib3.PoolManager(**_POOL_KWARGS_DEFAULT)
_onetime_pool_spec = (urllib3.PoolManager, _POOL_KWARGS_ONETIME)

# cleanup
del _PROXY
del _POOL_KWARGS_DEFAULT
del _POOL_KWARGS_ONETIME
_pools['default'] = urllib3.ProxyManager(url, **_default_pool_params)
_onetime_pool_spec = (urllib3.ProxyManager, dict(proxy_url=url, **_onetime_pool_params))

def _create_onetime_pool():
cls, kw = _onetime_pool_spec
Expand Down
9 changes: 0 additions & 9 deletions telepot/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,6 @@ def text(self):
def response(self):
return self.args[2]

def __unicode__(self):
return 'Status %d - First 500 characters are shown below:\n%s' % (self.status, self.text[:500])

def __str__(self):
if PY_3:
return str(self).encode('utf-8')
else:
return unicode(self).encode('utf-8')

class EventNotFound(TelepotException):
def __init__(self, event):
super(EventNotFound, self).__init__(event)
Expand Down
12 changes: 10 additions & 2 deletions telepot/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ class Administrator(object):
- :meth:`.Bot.getChatAdministrators`
- :meth:`.Bot.getChatMembersCount`
- :meth:`.Bot.getChatMember`
- :meth:`.Bot.setChatStickerSet`
- :meth:`.Bot.deleteChatStickerSet`
"""

def __init__(self, bot, chat_id):
Expand All @@ -179,7 +181,9 @@ def __init__(self, bot, chat_id):
'getChat',
'getChatAdministrators',
'getChatMembersCount',
'getChatMember',]:
'getChatMember',
'setChatStickerSet',
'deleteChatStickerSet']:
setattr(self, method, partial(getattr(bot, method), chat_id))


Expand All @@ -197,6 +201,8 @@ class Editor(object):
- :meth:`.Bot.editMessageCaption`
- :meth:`.Bot.editMessageReplyMarkup`
- :meth:`.Bot.deleteMessage`
- :meth:`.Bot.editMessageLiveLocation`
- :meth:`.Bot.stopMessageLiveLocation`
A message's identifier can be easily extracted with :func:`telepot.message_identifier`.
"""
Expand All @@ -214,7 +220,9 @@ def __init__(self, bot, msg_identifier):
for method in ['editMessageText',
'editMessageCaption',
'editMessageReplyMarkup',
'deleteMessage']:
'deleteMessage',
'editMessageLiveLocation',
'stopMessageLiveLocation']:
setattr(self, method, partial(getattr(bot, method), msg_identifier))


Expand Down
12 changes: 8 additions & 4 deletions telepot/loop.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ def __init__(self, bot, on_update):
self._bot = bot
self._update_handler = on_update

def run_forever(self, relax=0.1, timeout=20, allowed_updates=None, offset=None):
def run_forever(self, relax=0.1, offset=None, timeout=20, allowed_updates=None):

This comment has been minimized.

Copy link
@das7pad

das7pad Nov 7, 2017

Contributor

@nickoala Same question as for the aio version: Why did you changed the sequence here?

This comment has been minimized.

Copy link
@nickoala

nickoala Nov 7, 2017

Author Owner

See my answer above 😄

"""
Process new updates in infinity loop
:param relax: int or float
:param relax: float
:param offset: int
:param timeout: int
:param allowed_updates: bool
:param offset: int
"""
while 1:
try:
Expand Down Expand Up @@ -130,6 +130,10 @@ def run_forever(self, *args, **kwargs):
:type relax: float
:param relax: seconds between each :meth:`.getUpdates`
:type offset: int
:param offset:
initial ``offset`` parameter supplied to :meth:`.getUpdates`
:type timeout: int
:param timeout:
``timeout`` parameter supplied to :meth:`.getUpdates`, controlling
Expand Down
Loading

0 comments on commit f69784b

Please sign in to comment.