mirror of
https://github.com/eternnoir/pyTelegramBotAPI.git
synced 2023-08-10 21:12:57 +03:00
Created util.py to clean up __init__.py and apihelper.py and updated README accordingly
Fixed failing send_document_by_id and send_photo_by_id
This commit is contained in:
@@ -2,18 +2,14 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import threading
|
||||
# Python3 queue support.
|
||||
try:
|
||||
import Queue
|
||||
except ImportError:
|
||||
import queue as Queue
|
||||
import time
|
||||
|
||||
import logging
|
||||
logging.basicConfig()
|
||||
logger = logging.getLogger('Telebot')
|
||||
import re
|
||||
from telebot import apihelper, types
|
||||
|
||||
from telebot import apihelper, types, util
|
||||
|
||||
"""
|
||||
Module : telebot
|
||||
@@ -21,48 +17,6 @@ Module : telebot
|
||||
|
||||
API_URL = r"https://api.telegram.org/"
|
||||
|
||||
|
||||
class ThreadPool:
|
||||
class WorkerThread(threading.Thread):
|
||||
count = 0
|
||||
|
||||
def __init__(self, queue):
|
||||
threading.Thread.__init__(self, name="WorkerThread{0}".format(self.__class__.count + 1))
|
||||
self.__class__.count += 1
|
||||
self.queue = queue
|
||||
self.daemon = True
|
||||
|
||||
self._running = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
while self._running:
|
||||
try:
|
||||
task, args, kwargs = self.queue.get()
|
||||
task(*args, **kwargs)
|
||||
except Queue.Empty:
|
||||
time.sleep(0)
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
|
||||
def __init__(self, num_threads=4):
|
||||
self.tasks = Queue.Queue()
|
||||
self.workers = [self.WorkerThread(self.tasks) for _ in range(num_threads)]
|
||||
|
||||
self.num_threads = num_threads
|
||||
|
||||
def put(self, func, *args, **kwargs):
|
||||
self.tasks.put((func, args, kwargs))
|
||||
|
||||
def close(self):
|
||||
for worker in self.workers:
|
||||
worker.stop()
|
||||
for worker in self.workers:
|
||||
worker.join()
|
||||
|
||||
|
||||
class TeleBot:
|
||||
""" This is TeleBot Class
|
||||
Methods:
|
||||
@@ -82,7 +36,6 @@ class TeleBot:
|
||||
|
||||
def __init__(self, token, create_threads=True, num_threads=4):
|
||||
"""
|
||||
|
||||
:param token: bot API token
|
||||
:param create_threads: Create thread for message handler
|
||||
:param num_threads: Number of worker in thread pool.
|
||||
@@ -104,7 +57,7 @@ class TeleBot:
|
||||
|
||||
self.message_handlers = []
|
||||
if self.__create_threads:
|
||||
self.worker_pool = ThreadPool(num_threads)
|
||||
self.worker_pool = util.ThreadPool(num_threads)
|
||||
|
||||
def get_update(self):
|
||||
"""
|
||||
@@ -158,7 +111,6 @@ class TeleBot:
|
||||
if block:
|
||||
self.__stop_polling.wait()
|
||||
|
||||
|
||||
def __polling(self, none_stop, interval):
|
||||
logger.info('TeleBot: Started polling.')
|
||||
|
||||
@@ -249,7 +201,7 @@ class TeleBot:
|
||||
:param duration:Duration of the audio in seconds
|
||||
:param performer:Performer
|
||||
:param title:Track name
|
||||
:param reply_to_message_id:If the message is a reply, ID of the original messag
|
||||
:param reply_to_message_id:If the message is a reply, ID of the original message
|
||||
:param reply_markup:
|
||||
:return: Message
|
||||
"""
|
||||
@@ -438,7 +390,7 @@ class TeleBot:
|
||||
if message.content_type not in message_handler['content_types']:
|
||||
return False
|
||||
if 'commands' in message_handler and message.content_type == 'text':
|
||||
return apihelper.extract_command(message.text) in message_handler['commands']
|
||||
return util.extract_command(message.text) in message_handler['commands']
|
||||
if 'regexp' in message_handler and message.content_type == 'text' and re.search(message_handler['regexp'],
|
||||
message.text):
|
||||
return True
|
||||
@@ -452,93 +404,55 @@ class TeleBot:
|
||||
if self._test_message_handler(message_handler, message):
|
||||
if self.__create_threads:
|
||||
self.worker_pool.put(message_handler['function'], message)
|
||||
# t = threading.Thread(target=message_handler['function'], args=(message,))
|
||||
# t.start()
|
||||
else:
|
||||
message_handler['function'](message)
|
||||
break
|
||||
|
||||
|
||||
class AsyncTask:
|
||||
def __init__(self, target, *args, **kwargs):
|
||||
self.target = target
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
self.done = False
|
||||
self.thread = threading.Thread(target=self._run)
|
||||
self.thread.start()
|
||||
|
||||
def _run(self):
|
||||
try:
|
||||
self.result = self.target(*self.args, **self.kwargs)
|
||||
except Exception as e:
|
||||
self.result = e
|
||||
self.done = True
|
||||
|
||||
def wait(self):
|
||||
if not self.done:
|
||||
self.thread.join()
|
||||
if isinstance(self.result, Exception):
|
||||
raise self.result
|
||||
else:
|
||||
return self.result
|
||||
|
||||
|
||||
def async():
|
||||
def decorator(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
return AsyncTask(fn, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
class AsyncTeleBot(TeleBot):
|
||||
def __init__(self, *args, **kwargs):
|
||||
TeleBot.__init__(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def get_me(self):
|
||||
return TeleBot.get_me(self)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def get_user_profile_photos(self, *args, **kwargs):
|
||||
return TeleBot.get_user_profile_photos(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_message(self, *args, **kwargs):
|
||||
return TeleBot.send_message(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def forward_message(self, *args, **kwargs):
|
||||
return TeleBot.forward_message(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_photo(self, *args, **kwargs):
|
||||
return TeleBot.send_photo(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_audio(self, *args, **kwargs):
|
||||
return TeleBot.send_audio(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_document(self, *args, **kwargs):
|
||||
return TeleBot.send_document(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_sticker(self, *args, **kwargs):
|
||||
return TeleBot.send_sticker(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_video(self, *args, **kwargs):
|
||||
return TeleBot.send_video(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_location(self, *args, **kwargs):
|
||||
return TeleBot.send_location(self, *args, **kwargs)
|
||||
|
||||
@async()
|
||||
@util.async()
|
||||
def send_chat_action(self, *args, **kwargs):
|
||||
return TeleBot.send_chat_action(self, *args, **kwargs)
|
||||
|
@@ -1,9 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import requests
|
||||
from six import string_types
|
||||
import telebot
|
||||
from telebot import types
|
||||
from telebot import util
|
||||
|
||||
logger = telebot.logger
|
||||
|
||||
@@ -115,7 +115,7 @@ def send_photo(token, chat_id, photo, caption=None, reply_to_message_id=None, re
|
||||
method_url = r'sendPhoto'
|
||||
payload = {'chat_id': chat_id}
|
||||
files = None
|
||||
if not is_string(photo):
|
||||
if not util.is_string(photo):
|
||||
files = {'photo': photo}
|
||||
else:
|
||||
payload['photo'] = photo
|
||||
@@ -148,7 +148,7 @@ def send_video(token, chat_id, data, duration=None, caption=None, reply_to_messa
|
||||
method_url = r'sendVideo'
|
||||
payload = {'chat_id': chat_id}
|
||||
files = None
|
||||
if not is_string(data):
|
||||
if not util.is_string(data):
|
||||
files = {'video': data}
|
||||
else:
|
||||
payload['video'] = data
|
||||
@@ -167,7 +167,7 @@ def send_voice(token, chat_id, voice, duration=None, reply_to_message_id=None, r
|
||||
method_url = r'sendVoice'
|
||||
payload = {'chat_id': chat_id}
|
||||
files = None
|
||||
if not is_string(voice):
|
||||
if not util.is_string(voice):
|
||||
files = {'voice': voice}
|
||||
else:
|
||||
payload['voice'] = voice
|
||||
@@ -185,7 +185,7 @@ def send_audio(token, chat_id, audio, duration=None, performer=None, title=None,
|
||||
method_url = r'sendAudio'
|
||||
payload = {'chat_id': chat_id}
|
||||
files = None
|
||||
if not is_string(audio):
|
||||
if not util.is_string(audio):
|
||||
files = {'audio': audio}
|
||||
else:
|
||||
payload['audio'] = audio
|
||||
@@ -206,7 +206,7 @@ def send_data(token, chat_id, data, data_type, reply_to_message_id=None, reply_m
|
||||
method_url = get_method_by_type(data_type)
|
||||
payload = {'chat_id': chat_id}
|
||||
files = None
|
||||
if not is_string(data):
|
||||
if not util.is_string(data):
|
||||
files = {data_type: data}
|
||||
else:
|
||||
payload[data_type] = data
|
||||
@@ -229,49 +229,6 @@ def _convert_markup(markup):
|
||||
return markup.to_json()
|
||||
return markup
|
||||
|
||||
|
||||
def is_string(var):
|
||||
return isinstance(var, string_types)
|
||||
|
||||
|
||||
def is_command(text):
|
||||
"""
|
||||
Checks if `text` is a command. Telegram chat commands start with the '/' character.
|
||||
:param text: Text to check.
|
||||
:return: True if `text` is a command, else False.
|
||||
"""
|
||||
return text.startswith('/')
|
||||
|
||||
|
||||
def extract_command(text):
|
||||
"""
|
||||
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
|
||||
If `text` is not a command, this function returns None.
|
||||
|
||||
Examples:
|
||||
extract_command('/help'): 'help'
|
||||
extract_command('/help@BotName'): 'help'
|
||||
extract_command('/search black eyed peas'): 'search'
|
||||
extract_command('Good day to you'): None
|
||||
|
||||
:param text: String to extract the command from
|
||||
:return: the command if `text` is a command (according to is_command), else None.
|
||||
"""
|
||||
return text.split()[0].split('@')[0][1:] if is_command(text) else None
|
||||
|
||||
|
||||
def split_string(text, chars_per_string):
|
||||
"""
|
||||
Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
|
||||
This is very useful for splitting one giant message into multiples.
|
||||
|
||||
:param text: The text to split
|
||||
:param chars_per_string: The number of characters per line the text is split into.
|
||||
:return: The splitted text as a list of strings.
|
||||
"""
|
||||
return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)]
|
||||
|
||||
|
||||
class ApiException(Exception):
|
||||
"""
|
||||
This class represents an Exception thrown when a call to the Telegram API fails.
|
||||
|
@@ -28,7 +28,6 @@ class JsonSerializable:
|
||||
Subclasses of this class are guaranteed to be able to be converted to JSON format.
|
||||
All subclasses of this class must override to_json.
|
||||
"""
|
||||
|
||||
def to_json(self):
|
||||
"""
|
||||
Returns a JSON string representation of this class.
|
||||
@@ -44,7 +43,6 @@ class JsonDeserializable:
|
||||
Subclasses of this class are guaranteed to be able to be created from a json-style dict or json formatted string.
|
||||
All subclasses of this class must override de_json.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def de_json(cls, json_type):
|
||||
"""
|
||||
|
126
telebot/util.py
Normal file
126
telebot/util.py
Normal file
@@ -0,0 +1,126 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
import threading
|
||||
from six import string_types
|
||||
|
||||
# Python3 queue support.
|
||||
try:
|
||||
import Queue
|
||||
except ImportError:
|
||||
import queue as Queue
|
||||
|
||||
|
||||
class ThreadPool:
|
||||
class WorkerThread(threading.Thread):
|
||||
count = 0
|
||||
|
||||
def __init__(self, queue):
|
||||
threading.Thread.__init__(self, name="WorkerThread{0}".format(self.__class__.count + 1))
|
||||
self.__class__.count += 1
|
||||
self.queue = queue
|
||||
self.daemon = True
|
||||
|
||||
self._running = True
|
||||
self.start()
|
||||
|
||||
def run(self):
|
||||
while self._running:
|
||||
try:
|
||||
task, args, kwargs = self.queue.get(block=True, timeout=.01)
|
||||
task(*args, **kwargs)
|
||||
except Queue.Empty:
|
||||
pass
|
||||
|
||||
def stop(self):
|
||||
self._running = False
|
||||
|
||||
def __init__(self, num_threads=4):
|
||||
self.tasks = Queue.Queue()
|
||||
self.workers = [self.WorkerThread(self.tasks) for _ in range(num_threads)]
|
||||
|
||||
self.num_threads = num_threads
|
||||
|
||||
def put(self, func, *args, **kwargs):
|
||||
self.tasks.put((func, args, kwargs))
|
||||
|
||||
def close(self):
|
||||
for worker in self.workers:
|
||||
worker.stop()
|
||||
for worker in self.workers:
|
||||
worker.join()
|
||||
|
||||
class AsyncTask:
|
||||
def __init__(self, target, *args, **kwargs):
|
||||
self.target = target
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
|
||||
self.done = False
|
||||
self.thread = threading.Thread(target=self._run)
|
||||
self.thread.start()
|
||||
|
||||
def _run(self):
|
||||
try:
|
||||
self.result = self.target(*self.args, **self.kwargs)
|
||||
except Exception as e:
|
||||
self.result = e
|
||||
self.done = True
|
||||
|
||||
def wait(self):
|
||||
if not self.done:
|
||||
self.thread.join()
|
||||
if isinstance(self.result, Exception):
|
||||
raise self.result
|
||||
else:
|
||||
return self.result
|
||||
|
||||
|
||||
def async():
|
||||
def decorator(fn):
|
||||
def wrapper(*args, **kwargs):
|
||||
return AsyncTask(fn, *args, **kwargs)
|
||||
|
||||
return wrapper
|
||||
|
||||
return decorator
|
||||
|
||||
|
||||
def is_string(var):
|
||||
return isinstance(var, string_types)
|
||||
|
||||
def is_command(text):
|
||||
"""
|
||||
Checks if `text` is a command. Telegram chat commands start with the '/' character.
|
||||
:param text: Text to check.
|
||||
:return: True if `text` is a command, else False.
|
||||
"""
|
||||
return text.startswith('/')
|
||||
|
||||
|
||||
def extract_command(text):
|
||||
"""
|
||||
Extracts the command from `text` (minus the '/') if `text` is a command (see is_command).
|
||||
If `text` is not a command, this function returns None.
|
||||
|
||||
Examples:
|
||||
extract_command('/help'): 'help'
|
||||
extract_command('/help@BotName'): 'help'
|
||||
extract_command('/search black eyed peas'): 'search'
|
||||
extract_command('Good day to you'): None
|
||||
|
||||
:param text: String to extract the command from
|
||||
:return: the command if `text` is a command (according to is_command), else None.
|
||||
"""
|
||||
return text.split()[0].split('@')[0][1:] if is_command(text) else None
|
||||
|
||||
|
||||
def split_string(text, chars_per_string):
|
||||
"""
|
||||
Splits one string into multiple strings, with a maximum amount of `chars_per_string` characters per string.
|
||||
This is very useful for splitting one giant message into multiples.
|
||||
|
||||
:param text: The text to split
|
||||
:param chars_per_string: The number of characters per line the text is split into.
|
||||
:return: The splitted text as a list of strings.
|
||||
"""
|
||||
return [text[i:i + chars_per_string] for i in range(0, len(text), chars_per_string)]
|
Reference in New Issue
Block a user