Add Black and Flake8

This commit is contained in:
Alex RootJunior 2019-06-29 19:53:18 +03:00
parent 5b9d82f1ca
commit 7c51b1a7d7
124 changed files with 5841 additions and 3772 deletions

View file

@ -35,16 +35,18 @@ from aiogram.utils.executor import start_polling, start_webhook
logging.basicConfig(level=logging.INFO)
# Configure arguments parser.
parser = argparse.ArgumentParser(description='Python telegram bot')
parser.add_argument('--token', '-t', nargs='?', type=str, default=None, help='Set working directory')
parser.add_argument('--sock', help='UNIX Socket path')
parser.add_argument('--host', help='Webserver host')
parser.add_argument('--port', type=int, help='Webserver port')
parser.add_argument('--cert', help='Path to SSL certificate')
parser.add_argument('--pkey', help='Path to SSL private key')
parser.add_argument('--host-name', help='Set webhook host name')
parser.add_argument('--webhook-port', type=int, help='Port for webhook (default=port)')
parser.add_argument('--webhook-path', default='/webhook', help='Port for webhook (default=port)')
parser = argparse.ArgumentParser(description="Python telegram bot")
parser.add_argument(
"--token", "-t", nargs="?", type=str, default=None, help="Set working directory"
)
parser.add_argument("--sock", help="UNIX Socket path")
parser.add_argument("--host", help="Webserver host")
parser.add_argument("--port", type=int, help="Webserver port")
parser.add_argument("--cert", help="Path to SSL certificate")
parser.add_argument("--pkey", help="Path to SSL private key")
parser.add_argument("--host-name", help="Set webhook host name")
parser.add_argument("--webhook-port", type=int, help="Port for webhook (default=port)")
parser.add_argument("--webhook-path", default="/webhook", help="Port for webhook (default=port)")
async def cmd_start(message: types.Message):
@ -53,7 +55,7 @@ async def cmd_start(message: types.Message):
def setup_handlers(dispatcher: Dispatcher):
# This example has only one messages handler
dispatcher.register_message_handler(cmd_start, commands=['start', 'welcome'])
dispatcher.register_message_handler(cmd_start, commands=["start", "welcome"])
async def on_startup(dispatcher, url=None, cert=None):
@ -73,7 +75,7 @@ async def on_startup(dispatcher, url=None, cert=None):
# Set new URL for webhook
if cert:
with open(cert, 'rb') as cert_file:
with open(cert, "rb") as cert_file:
await bot.set_webhook(url, certificate=cert_file)
else:
await bot.set_webhook(url)
@ -83,7 +85,7 @@ async def on_startup(dispatcher, url=None, cert=None):
async def on_shutdown(dispatcher):
print('Shutdown.')
print("Shutdown.")
def main(arguments):
@ -99,8 +101,8 @@ def main(arguments):
webhook_path = args.webhook_path
# Fi webhook path
if not webhook_path.startswith('/'):
webhook_path = '/' + webhook_path
if not webhook_path.startswith("/"):
webhook_path = "/" + webhook_path
# Generate webhook URL
webhook_url = f"https://{host_name}:{webhook_port}{webhook_path}"
@ -116,15 +118,21 @@ def main(arguments):
else:
ssl_context = None
start_webhook(dispatcher, webhook_path,
on_startup=functools.partial(on_startup, url=webhook_url, cert=cert),
on_shutdown=on_shutdown,
host=host, port=port, path=sock, ssl_context=ssl_context)
start_webhook(
dispatcher,
webhook_path,
on_startup=functools.partial(on_startup, url=webhook_url, cert=cert),
on_shutdown=on_shutdown,
host=host,
port=port,
path=sock,
ssl_context=ssl_context,
)
else:
start_polling(dispatcher, on_startup=on_startup, on_shutdown=on_shutdown)
if __name__ == '__main__':
if __name__ == "__main__":
argv = sys.argv[1:]
if not len(argv):

View file

@ -4,10 +4,10 @@ import logging
from aiogram import Bot, Dispatcher, types
from aiogram.utils import exceptions, executor
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
logging.basicConfig(level=logging.INFO)
log = logging.getLogger('broadcast')
log = logging.getLogger("broadcast")
loop = asyncio.get_event_loop()
bot = Bot(token=API_TOKEN, loop=loop, parse_mode=types.ParseMode.HTML)
@ -61,15 +61,15 @@ async def broadcaster() -> int:
count = 0
try:
for user_id in get_users():
if await send_message(user_id, '<b>Hello!</b>'):
if await send_message(user_id, "<b>Hello!</b>"):
count += 1
await asyncio.sleep(.05) # 20 messages per second (Limit: 30 messages per second)
await asyncio.sleep(0.05) # 20 messages per second (Limit: 30 messages per second)
finally:
log.info(f"{count} messages successful sent.")
return count
if __name__ == '__main__':
if __name__ == "__main__":
# Execute broadcaster
executor.start(dp, broadcaster())

View file

@ -11,7 +11,7 @@ from aiogram.utils.exceptions import MessageNotModified, Throttled
logging.basicConfig(level=logging.INFO)
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
loop = asyncio.get_event_loop()
bot = Bot(token=API_TOKEN, loop=loop, parse_mode=types.ParseMode.HTML)
@ -21,16 +21,17 @@ dp.middleware.setup(LoggingMiddleware())
POSTS = {
str(uuid.uuid4()): {
'title': f"Post {index}",
'body': 'Lorem ipsum dolor sit amet, '
'consectetur adipiscing elit, '
'sed do eiusmod tempor incididunt ut '
'labore et dolore magna aliqua',
'votes': random.randint(-2, 5)
} for index in range(1, 6)
"title": f"Post {index}",
"body": "Lorem ipsum dolor sit amet, "
"consectetur adipiscing elit, "
"sed do eiusmod tempor incididunt ut "
"labore et dolore magna aliqua",
"votes": random.randint(-2, 5),
}
for index in range(1, 6)
}
posts_cb = CallbackData('post', 'id', 'action') # post:<id>:<action>
posts_cb = CallbackData("post", "id", "action") # post:<id>:<action>
def get_keyboard() -> types.InlineKeyboardMarkup:
@ -41,69 +42,73 @@ def get_keyboard() -> types.InlineKeyboardMarkup:
for post_id, post in POSTS.items():
markup.add(
types.InlineKeyboardButton(
post['title'],
callback_data=posts_cb.new(id=post_id, action='view'))
post["title"], callback_data=posts_cb.new(id=post_id, action="view")
)
)
return markup
def format_post(post_id: str, post: dict) -> (str, types.InlineKeyboardMarkup):
text = f"{md.hbold(post['title'])}\n" \
f"{md.quote_html(post['body'])}\n" \
f"\n" \
text = (
f"{md.hbold(post['title'])}\n"
f"{md.quote_html(post['body'])}\n"
f"\n"
f"Votes: {post['votes']}"
)
markup = types.InlineKeyboardMarkup()
markup.row(
types.InlineKeyboardButton('👍', callback_data=posts_cb.new(id=post_id, action='like')),
types.InlineKeyboardButton('👎', callback_data=posts_cb.new(id=post_id, action='unlike')),
types.InlineKeyboardButton("👍", callback_data=posts_cb.new(id=post_id, action="like")),
types.InlineKeyboardButton("👎", callback_data=posts_cb.new(id=post_id, action="unlike")),
)
markup.add(
types.InlineKeyboardButton("<< Back", callback_data=posts_cb.new(id="-", action="list"))
)
markup.add(types.InlineKeyboardButton('<< Back', callback_data=posts_cb.new(id='-', action='list')))
return text, markup
@dp.message_handler(commands='start')
@dp.message_handler(commands="start")
async def cmd_start(message: types.Message):
await message.reply('Posts', reply_markup=get_keyboard())
await message.reply("Posts", reply_markup=get_keyboard())
@dp.callback_query_handler(posts_cb.filter(action='list'))
@dp.callback_query_handler(posts_cb.filter(action="list"))
async def query_show_list(query: types.CallbackQuery):
await query.message.edit_text('Posts', reply_markup=get_keyboard())
await query.message.edit_text("Posts", reply_markup=get_keyboard())
@dp.callback_query_handler(posts_cb.filter(action='view'))
@dp.callback_query_handler(posts_cb.filter(action="view"))
async def query_view(query: types.CallbackQuery, callback_data: dict):
post_id = callback_data['id']
post_id = callback_data["id"]
post = POSTS.get(post_id, None)
if not post:
return await query.answer('Unknown post!')
return await query.answer("Unknown post!")
text, markup = format_post(post_id, post)
await query.message.edit_text(text, reply_markup=markup)
@dp.callback_query_handler(posts_cb.filter(action=['like', 'unlike']))
@dp.callback_query_handler(posts_cb.filter(action=["like", "unlike"]))
async def query_post_vote(query: types.CallbackQuery, callback_data: dict):
try:
await dp.throttle('vote', rate=1)
await dp.throttle("vote", rate=1)
except Throttled:
return await query.answer('Too many requests.')
return await query.answer("Too many requests.")
post_id = callback_data['id']
action = callback_data['action']
post_id = callback_data["id"]
action = callback_data["action"]
post = POSTS.get(post_id, None)
if not post:
return await query.answer('Unknown post!')
return await query.answer("Unknown post!")
if action == 'like':
post['votes'] += 1
elif action == 'unlike':
post['votes'] -= 1
if action == "like":
post["votes"] += 1
elif action == "unlike":
post["votes"] -= 1
await query.answer('Voted.')
await query.answer("Voted.")
text, markup = format_post(post_id, post)
await query.message.edit_text(text, reply_markup=markup)
@ -113,5 +118,5 @@ async def message_not_modified_handler(update, error):
return True
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop, skip_updates=True)

View file

@ -7,7 +7,7 @@ import logging
from aiogram import Bot, Dispatcher, executor, md, types
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
logging.basicConfig(level=logging.INFO)
@ -20,14 +20,17 @@ dp = Dispatcher(bot)
async def check_language(message: types.Message):
locale = message.from_user.locale
await message.reply(md.text(
md.bold('Info about your language:'),
md.text(' 🔸', md.bold('Code:'), md.italic(locale.locale)),
md.text(' 🔸', md.bold('Territory:'), md.italic(locale.territory or 'Unknown')),
md.text(' 🔸', md.bold('Language name:'), md.italic(locale.language_name)),
md.text(' 🔸', md.bold('English language name:'), md.italic(locale.english_name)),
sep='\n'))
await message.reply(
md.text(
md.bold("Info about your language:"),
md.text(" 🔸", md.bold("Code:"), md.italic(locale.locale)),
md.text(" 🔸", md.bold("Territory:"), md.italic(locale.territory or "Unknown")),
md.text(" 🔸", md.bold("Language name:"), md.italic(locale.language_name)),
md.text(" 🔸", md.bold("English language name:"), md.italic(locale.english_name)),
sep="\n",
)
)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop, skip_updates=True)

View file

@ -7,7 +7,7 @@ import logging
from aiogram import Bot, Dispatcher, executor, types
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
# Configure logging
logging.basicConfig(level=logging.INFO)
@ -17,7 +17,7 @@ bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)
@dp.message_handler(commands=['start', 'help'])
@dp.message_handler(commands=["start", "help"])
async def send_welcome(message: types.Message):
"""
This handler will be called when client send `/start` or `/help` commands.
@ -25,11 +25,15 @@ async def send_welcome(message: types.Message):
await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")
@dp.message_handler(regexp='(^cat[s]?$|puss)')
@dp.message_handler(regexp="(^cat[s]?$|puss)")
async def cats(message: types.Message):
with open('data/cats.jpg', 'rb') as photo:
await bot.send_photo(message.chat.id, photo, caption='Cats is here 😺',
reply_to_message_id=message.message_id)
with open("data/cats.jpg", "rb") as photo:
await bot.send_photo(
message.chat.id,
photo,
caption="Cats is here 😺",
reply_to_message_id=message.message_id,
)
@dp.message_handler()
@ -37,5 +41,5 @@ async def echo(message: types.Message):
await bot.send_message(message.chat.id, message.text)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, skip_updates=True)

View file

@ -9,7 +9,7 @@ from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.types import ParseMode
from aiogram.utils import executor
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
loop = asyncio.get_event_loop()
@ -27,7 +27,7 @@ class Form(StatesGroup):
gender = State() # Will be represented in storage as 'Form:gender'
@dp.message_handler(commands=['start'])
@dp.message_handler(commands=["start"])
async def cmd_start(message: types.Message):
"""
Conversation's entry point
@ -39,9 +39,11 @@ async def cmd_start(message: types.Message):
# You can use state '*' if you need to handle all states
@dp.message_handler(state='*', commands=['cancel'])
@dp.message_handler(lambda message: message.text.lower() == 'cancel', state='*')
async def cancel_handler(message: types.Message, state: FSMContext, raw_state: Optional[str] = None):
@dp.message_handler(state="*", commands=["cancel"])
@dp.message_handler(lambda message: message.text.lower() == "cancel", state="*")
async def cancel_handler(
message: types.Message, state: FSMContext, raw_state: Optional[str] = None
):
"""
Allow user to cancel any action
"""
@ -51,7 +53,7 @@ async def cancel_handler(message: types.Message, state: FSMContext, raw_state: O
# Cancel state and inform user about it
await state.finish()
# And remove keyboard (just in case)
await message.reply('Canceled.', reply_markup=types.ReplyKeyboardRemove())
await message.reply("Canceled.", reply_markup=types.ReplyKeyboardRemove())
@dp.message_handler(state=Form.name)
@ -60,7 +62,7 @@ async def process_name(message: types.Message, state: FSMContext):
Process user name
"""
async with state.proxy() as data:
data['name'] = message.text
data["name"] = message.text
await Form.next()
await message.reply("How old are you?")
@ -89,7 +91,9 @@ async def process_age(message: types.Message, state: FSMContext):
await message.reply("What is your gender?", reply_markup=markup)
@dp.message_handler(lambda message: message.text not in ["Male", "Female", "Other"], state=Form.gender)
@dp.message_handler(
lambda message: message.text not in ["Male", "Female", "Other"], state=Form.gender
)
async def failed_process_gender(message: types.Message):
"""
In this example gender has to be one of: Male, Female, Other.
@ -100,21 +104,27 @@ async def failed_process_gender(message: types.Message):
@dp.message_handler(state=Form.gender)
async def process_gender(message: types.Message, state: FSMContext):
async with state.proxy() as data:
data['gender'] = message.text
data["gender"] = message.text
# Remove keyboard
markup = types.ReplyKeyboardRemove()
# And send message
await bot.send_message(message.chat.id, md.text(
md.text('Hi! Nice to meet you,', md.bold(data['name'])),
md.text('Age:', data['age']),
md.text('Gender:', data['gender']),
sep='\n'), reply_markup=markup, parse_mode=ParseMode.MARKDOWN)
await bot.send_message(
message.chat.id,
md.text(
md.text("Hi! Nice to meet you,", md.bold(data["name"])),
md.text("Age:", data["age"]),
md.text("Gender:", data["gender"]),
sep="\n",
),
reply_markup=markup,
parse_mode=ParseMode.MARKDOWN,
)
# Finish conversation
data.state = None
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop, skip_updates=True)

View file

@ -24,11 +24,11 @@ from pathlib import Path
from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.middlewares.i18n import I18nMiddleware
TOKEN = 'BOT TOKEN HERE'
I18N_DOMAIN = 'mybot'
TOKEN = "BOT TOKEN HERE"
I18N_DOMAIN = "mybot"
BASE_DIR = Path(__file__).parent
LOCALES_DIR = BASE_DIR / 'locales'
LOCALES_DIR = BASE_DIR / "locales"
bot = Bot(TOKEN, parse_mode=types.ParseMode.HTML)
dp = Dispatcher(bot)
@ -41,16 +41,16 @@ dp.middleware.setup(i18n)
_ = i18n.gettext
@dp.message_handler(commands=['start'])
@dp.message_handler(commands=["start"])
async def cmd_start(message: types.Message):
# Simply use `_('message')` instead of `'message'` and never use f-strings for translatable texts.
await message.reply(_('Hello, <b>{user}</b>!').format(user=message.from_user.full_name))
await message.reply(_("Hello, <b>{user}</b>!").format(user=message.from_user.full_name))
@dp.message_handler(commands=['lang'])
@dp.message_handler(commands=["lang"])
async def cmd_lang(message: types.Message, locale):
await message.reply(_('Your current language: <i>{language}</i>').format(language=locale))
await message.reply(_("Your current language: <i>{language}</i>").format(language=locale))
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, skip_updates=True)

View file

@ -3,7 +3,7 @@ import logging
from aiogram import Bot, types, Dispatcher, executor
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
logging.basicConfig(level=logging.DEBUG)
@ -14,11 +14,12 @@ dp = Dispatcher(bot)
@dp.inline_handler()
async def inline_echo(inline_query: types.InlineQuery):
input_content = types.InputTextMessageContent(inline_query.query or 'echo')
item = types.InlineQueryResultArticle(id='1', title='echo',
input_message_content=input_content)
input_content = types.InputTextMessageContent(inline_query.query or "echo")
item = types.InlineQueryResultArticle(
id="1", title="echo", input_message_content=input_content
)
await bot.answer_inline_query(inline_query.id, results=[item], cache_time=1)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop, skip_updates=True)

View file

@ -2,7 +2,7 @@ import asyncio
from aiogram import Bot, Dispatcher, executor, filters, types
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
loop = asyncio.get_event_loop()
bot = Bot(token=API_TOKEN, loop=loop)
@ -24,13 +24,13 @@ async def send_welcome(message: types.Message):
media = types.MediaGroup()
# Attach local file
media.attach_photo(types.InputFile('data/cat.jpg'), 'Cat!')
media.attach_photo(types.InputFile("data/cat.jpg"), "Cat!")
# More local files and more cats!
media.attach_photo(types.InputFile('data/cats.jpg'), 'More cats!')
media.attach_photo(types.InputFile("data/cats.jpg"), "More cats!")
# You can also use URL's
# For example: get random puss:
media.attach_photo('http://lorempixel.com/400/200/cats/', 'Random cat.')
media.attach_photo("http://lorempixel.com/400/200/cats/", "Random cat.")
# And you can also use file ID:
# media.attach_photo('<file_id>', 'cat-cat-cat.')
@ -39,5 +39,5 @@ async def send_welcome(message: types.Message):
await message.reply_media_group(media=media)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop, skip_updates=True)

View file

@ -7,7 +7,7 @@ from aiogram.dispatcher.handler import CancelHandler, current_handler
from aiogram.dispatcher.middlewares import BaseMiddleware
from aiogram.utils.exceptions import Throttled
TOKEN = 'BOT TOKEN HERE'
TOKEN = "BOT TOKEN HERE"
loop = asyncio.get_event_loop()
@ -28,9 +28,9 @@ def rate_limit(limit: int, key=None):
"""
def decorator(func):
setattr(func, 'throttling_rate_limit', limit)
setattr(func, "throttling_rate_limit", limit)
if key:
setattr(func, 'throttling_key', key)
setattr(func, "throttling_key", key)
return func
return decorator
@ -41,7 +41,7 @@ class ThrottlingMiddleware(BaseMiddleware):
Simple middleware
"""
def __init__(self, limit=DEFAULT_RATE_LIMIT, key_prefix='antiflood_'):
def __init__(self, limit=DEFAULT_RATE_LIMIT, key_prefix="antiflood_"):
self.rate_limit = limit
self.prefix = key_prefix
super(ThrottlingMiddleware, self).__init__()
@ -59,8 +59,8 @@ class ThrottlingMiddleware(BaseMiddleware):
dispatcher = Dispatcher.get_current()
# If handler was configured, get rate limit and key from handler
if handler:
limit = getattr(handler, 'throttling_rate_limit', self.rate_limit)
key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}")
limit = getattr(handler, "throttling_rate_limit", self.rate_limit)
key = getattr(handler, "throttling_key", f"{self.prefix}_{handler.__name__}")
else:
limit = self.rate_limit
key = f"{self.prefix}_message"
@ -85,7 +85,7 @@ class ThrottlingMiddleware(BaseMiddleware):
handler = current_handler.get()
dispatcher = Dispatcher.get_current()
if handler:
key = getattr(handler, 'throttling_key', f"{self.prefix}_{handler.__name__}")
key = getattr(handler, "throttling_key", f"{self.prefix}_{handler.__name__}")
else:
key = f"{self.prefix}_message"
@ -94,7 +94,7 @@ class ThrottlingMiddleware(BaseMiddleware):
# Prevent flooding
if throttled.exceeded_count <= 2:
await message.reply('Too many requests! ')
await message.reply("Too many requests! ")
# Sleep.
await asyncio.sleep(delta)
@ -104,17 +104,19 @@ class ThrottlingMiddleware(BaseMiddleware):
# If current message is not last with current key - do not send message
if thr.exceeded_count == throttled.exceeded_count:
await message.reply('Unlocked.')
await message.reply("Unlocked.")
@dp.message_handler(commands=['start'])
@rate_limit(5, 'start') # this is not required but you can configure throttling manager for current handler using it
@dp.message_handler(commands=["start"])
@rate_limit(
5, "start"
) # this is not required but you can configure throttling manager for current handler using it
async def cmd_test(message: types.Message):
# You can use this command every 5 seconds
await message.reply('Test passed! You can use this command every 5 seconds.')
await message.reply("Test passed! You can use this command every 5 seconds.")
if __name__ == '__main__':
if __name__ == "__main__":
# Setup middleware
dp.middleware.setup(ThrottlingMiddleware())

View file

@ -6,8 +6,8 @@ from aiogram.dispatcher import Dispatcher
from aiogram.types.message import ContentTypes
from aiogram.utils import executor
BOT_TOKEN = 'BOT TOKEN HERE'
PAYMENTS_PROVIDER_TOKEN = '123456789:TEST:1234567890abcdef1234567890abcdef'
BOT_TOKEN = "BOT TOKEN HERE"
PAYMENTS_PROVIDER_TOKEN = "123456789:TEST:1234567890abcdef1234567890abcdef"
loop = asyncio.get_event_loop()
bot = Bot(BOT_TOKEN)
@ -15,85 +15,107 @@ dp = Dispatcher(bot, loop=loop)
# Setup prices
prices = [
types.LabeledPrice(label='Working Time Machine', amount=5750),
types.LabeledPrice(label='Gift wrapping', amount=500)
types.LabeledPrice(label="Working Time Machine", amount=5750),
types.LabeledPrice(label="Gift wrapping", amount=500),
]
# Setup shipping options
shipping_options = [
types.ShippingOption(id='instant', title='WorldWide Teleporter').add(types.LabeledPrice('Teleporter', 1000)),
types.ShippingOption(id='pickup', title='Local pickup').add(types.LabeledPrice('Pickup', 300))
types.ShippingOption(id="instant", title="WorldWide Teleporter").add(
types.LabeledPrice("Teleporter", 1000)
),
types.ShippingOption(id="pickup", title="Local pickup").add(types.LabeledPrice("Pickup", 300)),
]
@dp.message_handler(commands=['start'])
@dp.message_handler(commands=["start"])
async def cmd_start(message: types.Message):
await bot.send_message(message.chat.id,
"Hello, I'm the demo merchant bot."
" I can sell you a Time Machine."
" Use /buy to order one, /terms for Terms and Conditions")
await bot.send_message(
message.chat.id,
"Hello, I'm the demo merchant bot."
" I can sell you a Time Machine."
" Use /buy to order one, /terms for Terms and Conditions",
)
@dp.message_handler(commands=['terms'])
@dp.message_handler(commands=["terms"])
async def cmd_terms(message: types.Message):
await bot.send_message(message.chat.id,
'Thank you for shopping with our demo bot. We hope you like your new time machine!\n'
'1. If your time machine was not delivered on time, please rethink your concept of time'
' and try again.\n'
'2. If you find that your time machine is not working, kindly contact our future service'
' workshops on Trappist-1e. They will be accessible anywhere between'
' May 2075 and November 4000 C.E.\n'
'3. If you would like a refund, kindly apply for one yesterday and we will have sent it'
' to you immediately.')
await bot.send_message(
message.chat.id,
"Thank you for shopping with our demo bot. We hope you like your new time machine!\n"
"1. If your time machine was not delivered on time, please rethink your concept of time"
" and try again.\n"
"2. If you find that your time machine is not working, kindly contact our future service"
" workshops on Trappist-1e. They will be accessible anywhere between"
" May 2075 and November 4000 C.E.\n"
"3. If you would like a refund, kindly apply for one yesterday and we will have sent it"
" to you immediately.",
)
@dp.message_handler(commands=['buy'])
@dp.message_handler(commands=["buy"])
async def cmd_buy(message: types.Message):
await bot.send_message(message.chat.id,
"Real cards won't work with me, no money will be debited from your account."
" Use this test card number to pay for your Time Machine: `4242 4242 4242 4242`"
"\n\nThis is your demo invoice:", parse_mode='Markdown')
await bot.send_invoice(message.chat.id, title='Working Time Machine',
description='Want to visit your great-great-great-grandparents?'
' Make a fortune at the races?'
' Shake hands with Hammurabi and take a stroll in the Hanging Gardens?'
' Order our Working Time Machine today!',
provider_token=PAYMENTS_PROVIDER_TOKEN,
currency='usd',
photo_url='https://images.fineartamerica.com/images-medium-large/2-the-time-machine-dmitriy-khristenko.jpg',
photo_height=512, # !=0/None or picture won't be shown
photo_width=512,
photo_size=512,
is_flexible=True, # True If you need to set up Shipping Fee
prices=prices,
start_parameter='time-machine-example',
payload='HAPPY FRIDAYS COUPON')
await bot.send_message(
message.chat.id,
"Real cards won't work with me, no money will be debited from your account."
" Use this test card number to pay for your Time Machine: `4242 4242 4242 4242`"
"\n\nThis is your demo invoice:",
parse_mode="Markdown",
)
await bot.send_invoice(
message.chat.id,
title="Working Time Machine",
description="Want to visit your great-great-great-grandparents?"
" Make a fortune at the races?"
" Shake hands with Hammurabi and take a stroll in the Hanging Gardens?"
" Order our Working Time Machine today!",
provider_token=PAYMENTS_PROVIDER_TOKEN,
currency="usd",
photo_url="https://images.fineartamerica.com/images-medium-large/2-the-time-machine-dmitriy-khristenko.jpg",
photo_height=512, # !=0/None or picture won't be shown
photo_width=512,
photo_size=512,
is_flexible=True, # True If you need to set up Shipping Fee
prices=prices,
start_parameter="time-machine-example",
payload="HAPPY FRIDAYS COUPON",
)
@dp.shipping_query_handler(func=lambda query: True)
async def shipping(shipping_query: types.ShippingQuery):
await bot.answer_shipping_query(shipping_query.id, ok=True, shipping_options=shipping_options,
error_message='Oh, seems like our Dog couriers are having a lunch right now.'
' Try again later!')
await bot.answer_shipping_query(
shipping_query.id,
ok=True,
shipping_options=shipping_options,
error_message="Oh, seems like our Dog couriers are having a lunch right now."
" Try again later!",
)
@dp.pre_checkout_query_handler(func=lambda query: True)
async def checkout(pre_checkout_query: types.PreCheckoutQuery):
await bot.answer_pre_checkout_query(pre_checkout_query.id, ok=True,
error_message="Aliens tried to steal your card's CVV,"
" but we successfully protected your credentials,"
" try to pay again in a few minutes, we need a small rest.")
await bot.answer_pre_checkout_query(
pre_checkout_query.id,
ok=True,
error_message="Aliens tried to steal your card's CVV,"
" but we successfully protected your credentials,"
" try to pay again in a few minutes, we need a small rest.",
)
@dp.message_handler(content_types=ContentTypes.SUCCESSFUL_PAYMENT)
async def got_payment(message: types.Message):
await bot.send_message(message.chat.id,
'Hoooooray! Thanks for payment! We will proceed your order for `{} {}`'
' as fast as possible! Stay in touch.'
'\n\nUse /buy again to get a Time Machine for your friend!'.format(
message.successful_payment.total_amount / 100, message.successful_payment.currency),
parse_mode='Markdown')
await bot.send_message(
message.chat.id,
"Hoooooray! Thanks for payment! We will proceed your order for `{} {}`"
" as fast as possible! Stay in touch."
"\n\nUse /buy again to get a Time Machine for your friend!".format(
message.successful_payment.total_amount / 100, message.successful_payment.currency
),
parse_mode="Markdown",
)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp, loop=loop)

View file

@ -11,8 +11,8 @@ from aiogram.utils.executor import start_polling
from aiogram.utils.markdown import bold, code, italic, text
# Configure bot here
API_TOKEN = 'BOT TOKEN HERE'
PROXY_URL = 'http://PROXY_URL' # Or 'socks5://...'
API_TOKEN = "BOT TOKEN HERE"
PROXY_URL = "http://PROXY_URL" # Or 'socks5://...'
# If authentication is required in your proxy then uncomment next line and change login/password for it
# PROXY_AUTH = aiohttp.BasicAuth(login='login', password='password')
@ -21,7 +21,7 @@ PROXY_URL = 'http://PROXY_URL' # Or 'socks5://...'
# Also you can use Socks5 proxy but you need manually install aiohttp_socks package.
# Get my ip URL
GET_IP_URL = 'http://bot.whatismyipaddress.com/'
GET_IP_URL = "http://bot.whatismyipaddress.com/"
logging.basicConfig(level=logging.INFO)
@ -36,22 +36,24 @@ async def fetch(url, proxy=None, proxy_auth=None):
return await response.text()
@dp.message_handler(commands=['start'])
@dp.message_handler(commands=["start"])
async def cmd_start(message: types.Message):
content = []
# Make request (without proxy)
ip = await fetch(GET_IP_URL)
content.append(text(':globe_showing_Americas:', bold('IP:'), code(ip)))
content.append(text(":globe_showing_Americas:", bold("IP:"), code(ip)))
# This line is formatted to '🌎 *IP:* `YOUR IP`'
# Make request through proxy
ip = await fetch(GET_IP_URL, bot.proxy, bot.proxy_auth)
content.append(text(':locked_with_key:', bold('IP:'), code(ip), italic('via proxy')))
content.append(text(":locked_with_key:", bold("IP:"), code(ip), italic("via proxy")))
# This line is formatted to '🔐 *IP:* `YOUR IP` _via proxy_'
# Send content
await bot.send_message(message.chat.id, emojize(text(*content, sep='\n')), parse_mode=ParseMode.MARKDOWN)
await bot.send_message(
message.chat.id, emojize(text(*content, sep="\n")), parse_mode=ParseMode.MARKDOWN
)
# In this example you can see emoji codes: ":globe_showing_Americas:" and ":locked_with_key:"
# You can find full emoji cheat sheet at https://www.webpagefx.com/tools/emoji-cheat-sheet/
@ -61,5 +63,5 @@ async def cmd_start(message: types.Message):
# For example emojize('Moon face :new_moon_face:') is transformed to 'Moon face 🌚'
if __name__ == '__main__':
if __name__ == "__main__":
start_polling(dp, loop=loop, skip_updates=True)

View file

@ -2,14 +2,16 @@ from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher, filters
from aiogram.utils import executor
bot = Bot(token='TOKEN')
bot = Bot(token="TOKEN")
dp = Dispatcher(bot)
@dp.message_handler(filters.RegexpCommandsFilter(regexp_commands=['item_([0-9]*)']))
@dp.message_handler(filters.RegexpCommandsFilter(regexp_commands=["item_([0-9]*)"]))
async def send_welcome(message: types.Message, regexp_command):
await message.reply("You have requested an item with number: {}".format(regexp_command.group(1)))
await message.reply(
"You have requested an item with number: {}".format(regexp_command.group(1))
)
if __name__ == '__main__':
if __name__ == "__main__":
executor.start_polling(dp)

View file

@ -13,7 +13,7 @@ from aiogram.dispatcher import Dispatcher
from aiogram.utils.exceptions import Throttled
from aiogram.utils.executor import start_polling
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
logging.basicConfig(level=logging.INFO)
@ -26,18 +26,18 @@ storage = MemoryStorage()
dp = Dispatcher(bot, storage=storage)
@dp.message_handler(commands=['start', 'help'])
@dp.message_handler(commands=["start", "help"])
async def send_welcome(message: types.Message):
try:
# Execute throttling manager with rate-limit equal to 2 seconds for key "start"
await dp.throttle('start', rate=2)
await dp.throttle("start", rate=2)
except Throttled:
# If request is throttled, the `Throttled` exception will be raised
await message.reply('Too many requests!')
await message.reply("Too many requests!")
else:
# Otherwise do something
await message.reply("Hi!\nI'm EchoBot!\nPowered by aiogram.")
if __name__ == '__main__':
if __name__ == "__main__":
start_polling(dp, loop=loop, skip_updates=True)

View file

@ -16,26 +16,28 @@ from aiogram.dispatcher.webhook import get_new_configured_app, SendMessage
from aiogram.types import ChatType, ParseMode, ContentTypes
from aiogram.utils.markdown import hbold, bold, text, link
TOKEN = 'BOT TOKEN HERE'
TOKEN = "BOT TOKEN HERE"
WEBHOOK_HOST = 'example.com' # Domain name or IP addres which your bot is located.
WEBHOOK_HOST = "example.com" # Domain name or IP addres which your bot is located.
WEBHOOK_PORT = 443 # Telegram Bot API allows only for usage next ports: 443, 80, 88 or 8443
WEBHOOK_URL_PATH = '/webhook' # Part of URL
WEBHOOK_URL_PATH = "/webhook" # Part of URL
# This options needed if you use self-signed SSL certificate
# Instructions: https://core.telegram.org/bots/self-signed
WEBHOOK_SSL_CERT = './webhook_cert.pem' # Path to the ssl certificate
WEBHOOK_SSL_PRIV = './webhook_pkey.pem' # Path to the ssl private key
WEBHOOK_SSL_CERT = "./webhook_cert.pem" # Path to the ssl certificate
WEBHOOK_SSL_PRIV = "./webhook_pkey.pem" # Path to the ssl private key
WEBHOOK_URL = f"https://{WEBHOOK_HOST}:{WEBHOOK_PORT}{WEBHOOK_URL_PATH}"
# Web app settings:
# Use LAN address to listen webhooks
# User any available port in range from 1024 to 49151 if you're using proxy, or WEBHOOK_PORT if you're using direct webhook handling
WEBAPP_HOST = 'localhost'
WEBAPP_HOST = "localhost"
WEBAPP_PORT = 3001
BAD_CONTENT = ContentTypes.PHOTO & ContentTypes.DOCUMENT & ContentTypes.STICKER & ContentTypes.AUDIO
BAD_CONTENT = (
ContentTypes.PHOTO & ContentTypes.DOCUMENT & ContentTypes.STICKER & ContentTypes.AUDIO
)
loop = asyncio.get_event_loop()
bot = Bot(TOKEN, loop=loop)
@ -46,19 +48,27 @@ dp = Dispatcher(bot, storage=storage)
async def cmd_start(message: types.Message):
# Yep. aiogram allows to respond into webhook.
# https://core.telegram.org/bots/api#making-requests-when-getting-updates
return SendMessage(chat_id=message.chat.id, text='Hi from webhook!',
reply_to_message_id=message.message_id)
return SendMessage(
chat_id=message.chat.id, text="Hi from webhook!", reply_to_message_id=message.message_id
)
async def cmd_about(message: types.Message):
# In this function markdown utils are userd for formatting message text
return SendMessage(message.chat.id, text(
bold('Hi! I\'m just a simple telegram bot.'),
'',
text('I\'m powered by', bold('Python', Version(*sys.version_info[:]))),
text('With', link(text('aiogram', aiogram.VERSION), 'https://github.com/aiogram/aiogram')),
sep='\n'
), parse_mode=ParseMode.MARKDOWN)
return SendMessage(
message.chat.id,
text(
bold("Hi! I'm just a simple telegram bot."),
"",
text("I'm powered by", bold("Python", Version(*sys.version_info[:]))),
text(
"With",
link(text("aiogram", aiogram.VERSION), "https://github.com/aiogram/aiogram"),
),
sep="\n",
),
parse_mode=ParseMode.MARKDOWN,
)
async def cancel(message: types.Message):
@ -68,7 +78,7 @@ async def cancel(message: types.Message):
# If current user in any state - cancel it.
if await state.get_state() is not None:
await state.set_state(state=None)
return SendMessage(message.chat.id, 'Current action is canceled.')
return SendMessage(message.chat.id, "Current action is canceled.")
# Otherwise do nothing
@ -76,8 +86,10 @@ async def unknown(message: types.Message):
"""
Handler for unknown messages.
"""
return SendMessage(message.chat.id,
f"I don\'t know what to do with content type `{message.content_type()}`. Sorry :c")
return SendMessage(
message.chat.id,
f"I don't know what to do with content type `{message.content_type()}`. Sorry :c",
)
async def cmd_id(message: types.Message):
@ -94,43 +106,53 @@ async def cmd_id(message: types.Message):
target = message.from_user
chat = message.chat
result_msg = [hbold('Info about user:'),
f"First name: {target.first_name}"]
result_msg = [hbold("Info about user:"), f"First name: {target.first_name}"]
if target.last_name:
result_msg.append(f"Last name: {target.last_name}")
if target.username:
result_msg.append(f"Username: {target.mention}")
result_msg.append(f"User ID: {target.id}")
result_msg.extend([hbold('Chat:'),
f"Type: {chat.type}",
f"Chat ID: {chat.id}"])
result_msg.extend([hbold("Chat:"), f"Type: {chat.type}", f"Chat ID: {chat.id}"])
if chat.type != ChatType.PRIVATE:
result_msg.append(f"Title: {chat.title}")
else:
result_msg.append(f"Title: {chat.full_name}")
return SendMessage(message.chat.id, '\n'.join(result_msg), reply_to_message_id=message.message_id,
parse_mode=ParseMode.HTML)
return SendMessage(
message.chat.id,
"\n".join(result_msg),
reply_to_message_id=message.message_id,
parse_mode=ParseMode.HTML,
)
async def on_startup(app):
# Demonstrate one of the available methods for registering handlers
# This command available only in main state (state=None)
dp.register_message_handler(cmd_start, commands=['start'])
dp.register_message_handler(cmd_start, commands=["start"])
# This handler is available in all states at any time.
dp.register_message_handler(cmd_about, commands=['help', 'about'], state='*')
dp.register_message_handler(unknown, content_types=BAD_CONTENT,
func=lambda message: message.chat.type == ChatType.PRIVATE)
dp.register_message_handler(cmd_about, commands=["help", "about"], state="*")
dp.register_message_handler(
unknown,
content_types=BAD_CONTENT,
func=lambda message: message.chat.type == ChatType.PRIVATE,
)
# You are able to register one function handler for multiple conditions
dp.register_message_handler(cancel, commands=['cancel'], state='*')
dp.register_message_handler(cancel, func=lambda message: message.text.lower().strip() in ['cancel'], state='*')
dp.register_message_handler(cancel, commands=["cancel"], state="*")
dp.register_message_handler(
cancel, func=lambda message: message.text.lower().strip() in ["cancel"], state="*"
)
dp.register_message_handler(cmd_id, commands=['id'], state='*')
dp.register_message_handler(cmd_id, func=lambda message: message.forward_from or
message.reply_to_message and
message.chat.type == ChatType.PRIVATE, state='*')
dp.register_message_handler(cmd_id, commands=["id"], state="*")
dp.register_message_handler(
cmd_id,
func=lambda message: message.forward_from
or message.reply_to_message
and message.chat.type == ChatType.PRIVATE,
state="*",
)
# Get current webhook status
webhook = await bot.get_webhook_info()
@ -142,7 +164,7 @@ async def on_startup(app):
await bot.delete_webhook()
# Set new URL for webhook
await bot.set_webhook(WEBHOOK_URL, certificate=open(WEBHOOK_SSL_CERT, 'rb'))
await bot.set_webhook(WEBHOOK_URL, certificate=open(WEBHOOK_SSL_CERT, "rb"))
# If you want to use free certificate signed by LetsEncrypt you need to set only URL without sending certificate.
@ -158,7 +180,7 @@ async def on_shutdown(app):
await dp.storage.wait_closed()
if __name__ == '__main__':
if __name__ == "__main__":
# Get instance of :class:`aiohttp.web.Application` with configured router.
app = get_new_configured_app(dispatcher=dp, path=WEBHOOK_URL_PATH)

View file

@ -5,15 +5,15 @@ from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.utils.executor import start_webhook
API_TOKEN = 'BOT TOKEN HERE'
API_TOKEN = "BOT TOKEN HERE"
# webhook settings
WEBHOOK_HOST = 'https://your.domain'
WEBHOOK_PATH = '/path/to/api'
WEBHOOK_HOST = "https://your.domain"
WEBHOOK_PATH = "/path/to/api"
WEBHOOK_URL = f"{WEBHOOK_HOST}{WEBHOOK_PATH}"
# webserver settings
WEBAPP_HOST = 'localhost' # or ip
WEBAPP_HOST = "localhost" # or ip
WEBAPP_PORT = 3001
logging.basicConfig(level=logging.INFO)
@ -38,6 +38,13 @@ async def on_shutdown(dp):
pass
if __name__ == '__main__':
start_webhook(dispatcher=dp, webhook_path=WEBHOOK_PATH, on_startup=on_startup, on_shutdown=on_shutdown,
skip_updates=True, host=WEBAPP_HOST, port=WEBAPP_PORT)
if __name__ == "__main__":
start_webhook(
dispatcher=dp,
webhook_path=WEBHOOK_PATH,
on_startup=on_startup,
on_shutdown=on_shutdown,
skip_updates=True,
host=WEBAPP_HOST,
port=WEBAPP_PORT,
)