По вашему запросу ничего не найдено :(
Убедитесь, что запрос написан правильно, или посмотрите другие
наши статьи:
Погружение в aiogram (#5 Отправка стикеров)
Введение
Продолжаем изучать функционал библиотеки aiogram для работы с Telegram ботом. И сейчас в этой статье мы узнаем, как бот может отправлять стикеры пользователю, с ним взаимодействующим.
Note: Не забываем, что работаем с версией Python 3.9 и с версией библиотеки aiogram = 2.25.1
Шаблон проекта можешь скачать с GitHub по ссылке ?
жми сюда
(НЕ ЗАБУДЬ УКАЗАТЬ ТОКЕН СВОЕГО БОТА!)
Отправка стикеров
Для отправки любого вида контента, необходимо использовать объект класса Bot().
Что вообще представляет из себя стикер в Telegram?
Стикеры - это последовательность символов (будем называть её кодом), которые Telegram преобразует в картинку стикера.
У каждого стикера эта последовательность индивидуальна, и как раз-таки она нам нужна для отправки их пользователю с помощью бота.
Последовательность символов выглядит так: CAACAgIAAxkBAAEM1H9m6zpk9-ylY6RxukmDLw3B9DzwZAACEgADA9OlHucXXe19Ah4mNgQ
Встаёт главный вопрос, где мы можем получить этот код?
Но и здесь всё просто, для этого специально был разработан бот
Get Sticker ID
.
Для получения кода необходимо в диалог боту отправить стикер, код которого мы хотим узнать.
Но мы можем и сами узнать код стикера!
Для этого необходимо написать следующий хендлер.
Параметр content_types необходим, чтобы явно указать, какой тип контента мы ожидаем получить.
Запустим скрипт с этим хендлером и посмотрим, что отправит нам наш бот.
При отправке стикеров мы исправно получаем его код. А сейчас увидим, для чего же он нам так нужен.
Напишем хендлер, который будет обрабатываться при получении команды /sticker и отправлять стикер пользователю.
Для отправки стикера воспользуемся методом: await bot.send_sticker().
В параметрах к методу указываем id пользователя, который получит данный стикер (message.from_user.id), в нашем случае это тот, кто и отправил команду /sticker и код стикера.
Проверяем работу скрипта
Получается всё так, как мы и хотели!
Чтобы не засорять диалог с ботом, при написании команды можно в скрипт добавить метод:
await message.delete()
Данный метод удаляет последнее отправленное сообщение боту.
Теперь при отправке команды /sticker бот будет удалять её и отправлять нам стикер.
Попробуй работу скрипта в деле! (НЕ ЗАБУДЬ УКАЗАТЬ ТОКЕН СВОЕГО БОТА)
Заключение
Сегодня мы узнали, как отправлять стикеры, познакомились с новым для себя ботом и смогли реализовать его функционал самостоятельно. Узнали метод для удаления отправленных пользователем сообщений. В следующей статье изучим, как отправлять фото, видео, аудио и документы с помощью бота.
Для того, чтобы вывести Asterisk за пределы корпоративной сети и получить возможность звонить “во внешний мир”, необходимо воспользоваться услугами VoIP – провайдеров.
В сегодняшней статье, мы расскажем как настроить SIP-транк с провайдером Youmagic (MTT) на примере Asterisk 13.7.1 и FreePBX 13.
Создание SIP - транка через FreePBX
Для того, чтобы приступить к настройке нового транка, необходимо с главной страницы перейти по следующему пути: Connectivity -> Trunks. Откроется следующее окно:
Далее нужно нажать кнопку Add Trunk. В появившемся, выпадающем окне выбираем Add SIP (chan_sip) Trunk
В открывшемся окне, указываем имя нового транка и задаём исходящий Caller ID, именно в таком формате будет отображаться Ваш номер телефона при исходящих звонках, если конечно провайдер не перекрывает его другим АОН’ом.
Далее, необходимо перейти на вкладку sip Settings и заполнить её разделы Outgoing и Incoming, в соответствии с данными, полученными от провайдера
Раздел Outgoing заполняется следующим образом:
type=friend
defaultuser=74957775566
secret=Ваш_пароль
host=voip.mtt.ru
dtmfmode=rfc2833
disallow=all
allow=alaw&ulaw&g729
canreinvite=no
insecure=port,invite
qualify=200
Где secret - Ваш пароль, выданный провайдером, defaultuser - Ваш телефонный номер, выданный провайдером и host - адрес провайдерского сервера
В разделе Incoming, необходимо заполнить только последнюю строчку Register String, по следующему шаблону:
defaultuser:Ваш_пароль@host/defaultuser
Соответственно, после замены этих параметров нашими значениями, получится
74957775566:Ваш_пароль@voip.mtt.ru/74957775566
Не забываем нажимать Submit и Apply Config
Входящая маршрутизация МТТ (Youmagic)
Далее нужно создать новый входящий маршрут для звонков, поступающих из нового транка. Для этого переходим в Connectivity -> Inbound Routes, добавляем новый маршрут кнопкой Add Inbound Route. Даем новому маршруту какое-нибудь описание, а в поле DID Number вписываем номер, который приобрели у МТТ(Youmagic). Далее в поле Set Destination выбираем, куда будут отправляться все входящие звонки, поступившие на данный номер. Это может быть что угодно на Вашей АТС: IVR, голосовое приветствие, ринг-группа и так далее. На примере ниже, все звонки будут поступать на IVR.
Исходящая маршрутизация МТТ (Youmagic)
Создаём исходящий маршрут. Переходим в Connectivity -> Outbound Routes, жмём кнопку Add Outbound Route. Указываем имя нового маршрута, наш новый номер и привязываем данный маршрут к ранее созданному транку с помощью Trunk Sequence for Matched Routes
На вкладке Dial Patterns настраиваем шаблоны набора, которые будут использоваться на данном маршруте
Нажимаем кнопки Submit и Apply Config. На этом настройка завершена, теперь можно совершать и принимать вызовы на номер, приобретенный у провайдера Youmagic (МТТ)
Более подробно с настройкой маршрутизации вы можете ознакомиться в статье по ссылке ниже:
Маршрутизация вызовов FreePBX
Настройка через конфигурационные файлы
Если вы производите настройку через конфигурационные файлы Asterisk, то настройка нового транка должна осуществляться в файле sip.conf, как показано ниже:
[general]
register => 74957775566:Ваш_пароль@voip.mtt.ru/74957775566
[youmagic]
type=friend
dtmfmode=rfc2833
host= voip.mtt.ru
disallow=all
allow=g729
directmedia=no
insecure=port,invite
qualify=no
А настройка входящих и исходящих маршрутов производится в файле extensions.conf, следующим образом:
[youmagic]
exten => _8XXXXXXXXXX,1,Dial(SIP/youmagic/${EXTEN})
exten => _8XXXXXXXXXX,n,Hangup
[from-youmagic]
exten => _4957775566,1,Dial (SIP/trunk/${EXTEN})
exten => _4957775566,n,HangUp()
С помощью этого руководства вы научитесь писать модульные тесты для функций Python. Но для чего вообще нужно уделять такое внимание модульным тестам?
Что ж, когда вы работаете над большими проектами, вам часто приходится обновлять какие-то модули и выполнять перепроектирование кода по мере необходимости. Однако такие изменения могут негативно влиять на другие модули, в которых используется этот обновленный модуль. В некоторых случаях это может нарушить существующую функциональность программы.
Как разработчик, вы обязаны протестировать свой программный код с целью убедиться, что все модули в приложении работают должным образом. Модульные тесты позволяют проверять, корректно ли работают маленькие блоки программного кода, и исправлять несоответствия, которые возникают в результате обновлений и перепроектирования.
Это руководство поможет вам научиться обращаться с модульными тестами в Python. Здесь вы узнаете, как использовать встроенный в Python модуль
unittest
для настройки и запуска модульных тестов, а также для написания тестовых примеров для проверки функций Python. Также вы узнаете, как тестировать функции, которые вызывают исключения.
Давайте начнем!
Тестирование в Python – первый этап
Мы начнем с того, что определим функцию Python и напишем модульный тест, чтобы проверить, работает ли она должным образом. Для того, чтобы перейти к настройке модульных тестов, рассмотрим простую функцию
is_prime()
, которая принимает на вход число и проверяет его на простоту.
import math
def is_prime(num):
'''Check if num is prime or not.'''
for i in range(2,int(math.sqrt(num))+1):
if num%i==0:
return False
return True
Давайте запустим Python REPL, вызовем функцию
is_prime()
, передав ей аргументы, и проверим результаты.
>>> from prime_number import is_prime
>>> is_prime(3)
True
>>> is_prime(5)
True
>>> is_prime(12)
False
>>> is_prime(8)
False
>>> assert is_prime(7) == True
Для того, чтобы убедиться, что
is_prime(),
возвращает ожидаемое логическое значение, вы также можете использовать конструкцию
assert
(см. выше). Если значение, которое вернула функция, отличается от ожидаемого логического значения, то возникнет ошибка
AssertionError
.
Такое ручное тестирование будет не самым эффективным вариантом, если вы захотите проверить свою функцию на гораздо большем количестве аргументов. У вас есть возможность настроить автоматическое тестирование, которое будет запускать функцию и проверять выходные данные на соответствие тестовым примерам, которые были определены в тестовом наборе.
Как работать с модулем Python
unittest
В Python втроен модуль
unittest
, с помощью которого можно настраивать автоматические тесты для функций и классов в вашем приложении. Общая процедура для настройки модульных тестов в Python выглядит следующим образом:
# .py
import unittest
from import
# all entries within <> are placeholders
class TestClass(unittest.TestCase):
def test_(self):
# check function_to_test
def test_(self):
# check function_to_test
:
:
:
def test_(self):
# check function_to_test
Фрагмент кода
.py
, который приведен выше, выполняет следующее:
Импортирует встроенный в Python модуль
unittest
.
Импортирует функцию Python
, которую необходимо протестировать, из модуля
, в котором она определена.
Создает тестовый класс (
TestClass
), который наследуется от класса
unittest.TestCase
.
Все тесты, которые должны быть запущены, должны быть определены в качестве методов внутри тестового класса.
?
Примечание
: для того, чтобы
unittest
определял эти методы как тесты и запускал их, названия этих методов должны начинаться с
test_
.
Класс
TestCase
из модуля
unittest
предоставляет полезные методы с утверждениями для проверки того факта, что тестируемая функция возвращает ожидаемые значения.
Ниже перечислены самые распространенные методы с утверждениями, и некоторые из них мы будем использовать в этом руководстве.
Метод
Описание
assertEqual(expected_value,actual_value)
Утверждает, что
expected_value == actual_value
assertTrue(result)
Утверждает, что
bool(result)
это
True
assertFalse(result)
Утверждает, что
bool(result)
это
False
assertRaises(exception, function, *args, **kwargs)
Утверждает, что
function(*args, **kwargs)
вызывает
exception
Для того, чтобы запустить эти тесты, мы должны запустить
unittest
в качестве основного модуля с помощью следующей команды:
$ python -m unittest .py
Для запуска
unittest
в качестве основного модуля мы можем добавить условие
if __name__=='__main__'
.
if __name__=='__main__':
unittest.main()
Добавив if, у нас появится возможность запускать тесты, просто запуская модуль Python, который содержит эти тесты.
$ python .py
Как определять тестовые примеры для функций Python
В этом разделе мы напишем модульные тесты для функции
is_prime()
с помощью уже изученного синтаксиса.
Для того, чтобы протестировать функцию
is_prime()
, которая возвращает логическое значение, мы можем воспользоваться методами
assertTrue()
и
assertFalse()
. Мы определяем четыре метода тестирования в классе
TestPrime
, который наследуется от
unittest.TestCase
.
import unittest
# import the is_prime function
from prime_number import is_prime
class TestPrime(unittest.TestCase):
def test_two(self):
self.assertTrue(is_prime(2))
def test_five(self):
self.assertTrue(is_prime(5))
def test_nine(self):
self.assertFalse(is_prime(9))
def test_eleven(self):
self.assertTrue(is_prime(11))
if __name__=='__main__':
unittest.main()
$ python test_prime.py
Ниже вывод в виде точки ( . ) говорит нам об успешно выполненном тестировании.
Output
....
----------------------------------------------------------------------
Ran 4 tests in 0.001s
OK
В приведенном выше коде есть четыре метода тестирования. Каждый из этих методов проверяет какие-то определенные входные данные. Вместо этого вы можете определить один метод тестирования, который проверял бы результат для всех четырех входных данных.
import unittest
from prime_number import is_prime
class TestPrime(unittest.TestCase):
def test_prime_not_prime(self):
self.assertTrue(is_prime(2))
self.assertTrue(is_prime(5))
self.assertFalse(is_prime(9))
self.assertTrue(is_prime(11))
После того, как мы запустили модуль
test_prime,
мы видим, что успешно было выполнено только одно тестирование. Если какой-либо из методов с утверждением выдает
AssertionError
, то это значит, что тест завершился неудачно.
$ python test_prime.py
Output
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
Как писать модульные тесты для проверки на исключения
В предыдущем разделе мы протестировали функцию
is_prime()
, передавая в качестве входных данных как простые, так и непростые числа. Если более конкретно, то все входные данные были положительными числами.
Мы еще не установили тот факт, что аргументы в вызове функции
is_prime()
должны быть целыми положительными числами. Вы можете использовать подсказки при вводе кода для того, чтобы обеспечить соблюдение типов или выкидывать исключения для недопустимых входных данных.
При тестировании функции
is_prime()
мы не учли следующее:
Если аргумент будет числом с плавающей точкой, то функция
is_prime()
также будет работать и возвращать значение
True
или
False
, что является ошибочным.
Если аргумент будет совершенно другого типа (например, строкой «five» вместо числа 5), то функция выдаст ошибку
TypeError
.
Если аргумент будет отрицательным числом, то функция
math.sqrt()
выдаст ошибку
ValueError
, поскольку квадраты всех действительных чисел (положительных, отрицательных или нуля) всегда неотрицательны.
Давайте проверим то, что мы рассмотрели выше, запустив несколько циклов Python REPL.
>>> from prime_number import is_prime
>>> is_prime('five')
Traceback (most recent call last):
File "", line 1, in
File "/home/bala/unit-test-1/prime_number.py", line 5, in is_prime
for i in range(2,int(math.sqrt(num))+1):
TypeError: must be real number, not str
>>> is_prime(-10)
Traceback (most recent call last):
File "", line 1, in
File "/home/bala/unit-test-1/prime_number.py", line 5, in is_prime
for i in range(2,int(math.sqrt(num))+1):
ValueError: math domain error
>>> is_prime(2.5)
True
Как вызвать исключения для недопустимых входных данных
Для того, чтобы устранить все недочеты, которые мы обсудили выше, мы проверим значение
num
, которое используется в вызове функции, и выбросим исключение, если это будет нужно.
Проверяем, является ли
num
целым числом. Если является, то переходим к следующей проверке. В противном случае выбрасываем исключение
TypeError
.
Проверяем, является ли
num
отрицательным целым числом. Если является, то выбрасываем исключение
ValueError
.
Переопределяем функцию, чтобы она также проверяла значение и выбрасывала по мере необходимости исключения. И получаем:
import math
def is_prime(num):
'''Check if num is prime or not.'''
# raise TypeError for invalid input type
if type(num) != int:
raise TypeError('num is of invalid type')
# raise ValueError for invalid input value
if num < 0:
raise ValueError('Check the value of num; is num a non-negative integer?')
# for valid input, proceed to check if num is prime
for i in range(2,int(math.sqrt(num))+1):
if num%i==0:
return False
return True
Теперь, когда мы изменили функцию так, чтобы мы могли выбрасывать исключения
ValueError
и
TypeError
для недопустимых входных данных, следующий шаг - проверка того, выпадает ли исключение.
Как пользовать методом
assertRaises()
для проверки наличия исключений
Давайте добавим в определение
TestPrime
методы для проверки того, выпадают ли исключения.
Мы определим методы
test_typeerror_1()
и
test_typeerror_2()
для проверки исключения
TypeError
, и метод
test_valueerror()
для проверки исключения
ValueError
.
?
Для вызова метода
assertRaises()
мы можем использовать следующий общий синтаксис:
def test_exception(self):
self.assertRaises(exception-name,function-name,args)
Мы также можем применить и другой синтаксис, используя менеджер контекста (в этом примере мы будем использовать именно его):
def test_exception(self):
with self.assertRaises(exception-name):
function-name(args)
Добавив эти методы тестирования, получим:
import unittest
from prime_number import is_prime
class TestPrime(unittest.TestCase):
def test_prime_not_prime(self):
self.assertTrue(is_prime(2))
self.assertTrue(is_prime(5))
self.assertFalse(is_prime(9))
self.assertTrue(is_prime(11))
def test_typeerror_1(self):
with self.assertRaises(TypeError):
is_prime(6.5)
def test_typeerror_2(self):
with self.assertRaises(TypeError):
is_prime('five')
def test_valueerror(self):
with self.assertRaises(ValueError):
is_prime(-4)
if __name__=='__main__':
unittest.main()
Давайте запустим модуль
test_prime
и посмотрим на результат:
$ python test_prime.py
Output
....
----------------------------------------------------------------------
Ran 4 tests in 0.002s
OK
Во всех примерах, которые мы успели написать до этого момента, все тесты выполнялись успешно. Давайте изменим один из методов, допустим,
test_typeerror_2()
:
def test_typeerror_2(self):
with self.assertRaises(TypeError):
is_prime(5)
Мы вызываем функцию
is_prime()
и передаем ей в качестве аргумента число 5. В данном случае 5 является допустимым вводом, для которого функция возвращает
True
. Поэтому функция не вызывает исключение
TypeError
. А когда мы снова запустим тесты, то увидим, что один тест завершился неудачно.
$ python test_prime.py
Output
..F.
======================================================================
FAIL: test_typeerror_2 (__main__.TestPrime)
----------------------------------------------------------------------
Traceback (most recent call last):
File "test_prime.py", line 17, in test_typeerror_2
is_prime(5)
AssertionError: TypeError not raised
----------------------------------------------------------------------
Ran 4 tests in 0.003s
FAILED (failures=1)
Заключение
Благодарю, что дочитали до конца!
?
Надеюсь, что это руководство помогло вам понять азы модульного тестирования в Python.
Вы научились настраивать тестирования, которые позволяют проверять, работает ли функция должным образом или выкидывает исключение – и все это с помощью встроенного в Python модуля
unittest
.
