Туда и дорога, ибо тема белоруссии мне лично уже надоела.
Вы будете удивлены, но эти 44 строчки это все что нужно, чтобы принимать платежи в боте через Qiwi.
Звание самого простого API года, не менее. Понятно, что нужно ещё обмазываться проверкой кодов ответа сервера (если на той стороне что-то пошло не так), но минимальный набор выглядит так.
Три функции.
Создание счета на сумму и валидного до даты/времени (на входе str(datetime)). Даёт ссылку на платёжную форму, в которой клиент платит любой картой российского банка.
Проверка состояния счета (не оплачен, оплачен, просрочен)
Отмена вовремя не оплаченных счетов (не обязательно, это опция).
Всё!
Звание самого простого API года, не менее. Понятно, что нужно ещё обмазываться проверкой кодов ответа сервера (если на той стороне что-то пошло не так), но минимальный набор выглядит так.
Три функции.
Создание счета на сумму и валидного до даты/времени (на входе str(datetime)). Даёт ссылку на платёжную форму, в которой клиент платит любой картой российского банка.
Проверка состояния счета (не оплачен, оплачен, просрочен)
Отмена вовремя не оплаченных счетов (не обязательно, это опция).
Всё!
qiwi_module.py
3.2 KB
Полностью готовый модуль для киви. Обмазан перехватом ошибок, логированием, проверками кода ответа сервера и комментариями. Надеюсь, это ускорит разработку парочки дружественных проектов.
UPD: это устаревшая версия. Актуальная версия и документация лежит на https://git.ssleg.tech/anton/qiwi_module
Вопросы, замечания и благодарности можно складывать под этим постом
https://yangx.top/ssleg/322
UPD: это устаревшая версия. Актуальная версия и документация лежит на https://git.ssleg.tech/anton/qiwi_module
Вопросы, замечания и благодарности можно складывать под этим постом
https://yangx.top/ssleg/322
Поскольку Паша у нас либертарианец, то стандарты ему не писаны и у телеграм свое понимание языка markdown. Причём не описанное в документации, но легко излекающееся из сообщений.
Держите рабочую шпаргалку, как форматировать текст в сообщениях.
В результате получится такая строка:
123 123 123 123123
Держите рабочую шпаргалку, как форматировать текст в сообщениях.
В результате получится такая строка:
123 123 123 123
123
123 123 123Говорят, что на линкус сложно играть. Мне тут захотелось в танчики какие-нибудь погонять - без проблем и даже бесплатно.
Устанавливаешь steam, а там игр на любой вкус. Это пятый час игры с нуля, в первый попавшийся бесплатный симулятор.
Устанавливаешь steam, а там игр на любой вкус. Это пятый час игры с нуля, в первый попавшийся бесплатный симулятор.
Асинхронное программирование это очень круто. Но надо иметь в виду, что все части программы исполняются в произвольном порядке, как будет удобнее планировщику и все что может пойти не так, рано или поздно произойдет.
Например, мы собираем информацию о сообщениях в чате и на ее основании принимаем автоматические решения (разрешить или запретить юзеру что-то делать).
В телеграм для этого используются два разных хандлера.
Один - events.ChatAction(), для событий входа в чат и/или добавления юзера.
Второй - events.NewMessage(), срабатывает на сообщения в чате.
Все это крутится в потоке asyncio и вроде бы логично, что юзер сначала входит в чат, а потом что-то пишет. И времени должно хватать на обработку по порядку (нет).
А теперь реальность. В чат входит бот и сразу что-то постит. Лог с таймингами:
Хандлер ChatAction() получил информацию и поставил ее в общую очередь команд админки.
Но поскольку мой сервер загружен, ботов там уже трое, а процессор один, поток asyncio сжался по времени и всего через 11 миллисекунд уже пошла обработка хандлера NewMessage():
С очевидным итогом "отсутвует такой юзер в бд", ведь он еще никуда не записан, он только поставлен в очередь. Бдыщ!
Вот за этим и нужны внешние ключи в базах данных. Обработчик в модуле упал (но встанет сам, с поступлением следующего сообщения), а база данных сохранила целостность.
Еще через 0,7 секунды (709 миллисекунд) поток доходит до своей очереди команд и записывает юзера в базу. Но уже поздно 😁
Основное, что нужно запомнить и предусматривать всегда. Любая отдельная функция, которая крутится в потоке asyncio, может быть выполнена перед любой другой, даже если по логике вещей этого быть не может.
Поэтому любые зависящие друг от друга функции должны иметь возможность обмениваться сигналами. Например, делать блокировку записи.
Об этом в следующем посте, не переключайтесь 👋
Например, мы собираем информацию о сообщениях в чате и на ее основании принимаем автоматические решения (разрешить или запретить юзеру что-то делать).
В телеграм для этого используются два разных хандлера.
Один - events.ChatAction(), для событий входа в чат и/или добавления юзера.
Второй - events.NewMessage(), срабатывает на сообщения в чате.
Все это крутится в потоке asyncio и вроде бы логично, что юзер сначала входит в чат, а потом что-то пишет. И времени должно хватать на обработку по порядку (нет).
А теперь реальность. В чат входит бот и сразу что-то постит. Лог с таймингами:
Хандлер ChatAction() получил информацию и поставил ее в общую очередь команд админки.
INFO module_one [2020-09-25 06:26:23,321]
вход в <...> #729730 1386306872
INFO module_one [2020-09-25 06:26:23,321]
команда: (6, 0, 1xxxxxxxxx, 0, 0, 1386306872)
Но поскольку мой сервер загружен, ботов там уже трое, а процессор один, поток asyncio сжался по времени и всего через 11 миллисекунд уже пошла обработка хандлера NewMessage():
ERROR updates [2020-09-25 06:26:23,332]
Unhandled exception on mytask
Traceback (most recent call last):
<...>
File "/home/admin_utils/module_three.py", line 25, in mytask
values (%s, %s, %s, %s, %s, %s, %s)''', entry)
psycopg2.errors.ForeignKeyViolation: insert or update on table "vino" violates foreign key constraint "vino_users_user_id_fk"
DETAIL: Key (user_id)=(1386306872) is not present in table "users".
С очевидным итогом "отсутвует такой юзер в бд", ведь он еще никуда не записан, он только поставлен в очередь. Бдыщ!
Вот за этим и нужны внешние ключи в базах данных. Обработчик в модуле упал (но встанет сам, с поступлением следующего сообщения), а база данных сохранила целостность.
Еще через 0,7 секунды (709 миллисекунд) поток доходит до своей очереди команд и записывает юзера в базу. Но уже поздно 😁
INFO module_one [2020-09-25 06:26:24,041]
обработчик начал
INFO module_one [2020-09-25 06:26:24,097]
(1386306872, 'Margarita Del Carmem', 'Peña Almonte', None, None)
INFO module_one [2020-09-25 06:26:24,098]
обработчик закончил
Основное, что нужно запомнить и предусматривать всегда. Любая отдельная функция, которая крутится в потоке asyncio, может быть выполнена перед любой другой, даже если по логике вещей этого быть не может.
Поэтому любые зависящие друг от друга функции должны иметь возможность обмениваться сигналами. Например, делать блокировку записи.
Об этом в следующем посте, не переключайтесь 👋
Как бы помягче объяснить, что Дуров и его команда плохие люди. (мат вырезан цензурой).
Без объявления войны, телеграм 1.5 часа назад изменил формат выдачи постов. Просто потому что может.
Есть канал и привязанный к нему чат. До сегодняшнего дня, посты канала, отображались в чате как форварды, но от пустого юзера. То есть поле from_id всегда было None.
Было два идентификатора: ID канала (2584) и ID чата (0549). Теперь появился третий, виртуальный "пользователь" с ID оканчивающимся на 8824.
Естественно, мне сейчас придётся быстро переписывать в паре мест логику Фомы (моего бота).
P. S. Судя по всему, этот костыль команда телеграм сделала, чтобы "администраторы чатов могли отправлять в чат анонимные сообщения" (из пресс релиза) .
Upd: Ситуация не настолько плоха, как казалось вначале. Они сделали единый ID для костыля, и во всех чатах посты из канала идут от бота телеги. Теперь всегда from_id=1087968824.
Без объявления войны, телеграм 1.5 часа назад изменил формат выдачи постов. Просто потому что может.
Есть канал и привязанный к нему чат. До сегодняшнего дня, посты канала, отображались в чате как форварды, но от пустого юзера. То есть поле from_id всегда было None.
Было два идентификатора: ID канала (2584) и ID чата (0549). Теперь появился третий, виртуальный "пользователь" с ID оканчивающимся на 8824.
Естественно, мне сейчас придётся быстро переписывать в паре мест логику Фомы (моего бота).
P. S. Судя по всему, этот костыль команда телеграм сделала, чтобы "администраторы чатов могли отправлять в чат анонимные сообщения" (из пресс релиза) .
Upd: Ситуация не настолько плоха, как казалось вначале. Они сделали единый ID для костыля, и во всех чатах посты из канала идут от бота телеги. Теперь всегда from_id=1087968824.
Прошло пять часов, и у команды телеграм переполнилась панамка.
Всё вернули как было раньше.
Чтобы вы понимали, в тг порядка 2 млн ботов, владельцы которых были "невероятно счастливы" необходимостью в авральном режиме обновлять свой код.
Начало истории
Всё вернули как было раньше.
Чтобы вы понимали, в тг порядка 2 млн ботов, владельцы которых были "невероятно счастливы" необходимостью в авральном режиме обновлять свой код.
Начало истории
СЛЕГ! <Z> ️
Асинхронное программирование это очень круто. Но надо иметь в виду, что все части программы исполняются в произвольном порядке, как будет удобнее планировщику и все что может пойти не так, рано или поздно произойдет. Например, мы собираем информацию о сообщениях…
Проблему асинхронности пришлось решить радикально.
Ведь благодаря новым фичам, в чатах теперь могут писать люди, в них в принципе не состоящие.
Поэтому алгоритм получился такой:
1) ловим ошибку постгрес, с отсутствием ключа. Запись помещается в кэш (откройте для себя класс питон queue, не пожалеете)
2) раз в минуту этот кэш проверяет обработчик. Если запись находится в очереди менее 30 секунд, он её пропускает.
3) если запись древнее 30 секунд, то проверяется, есть ли юзер в базе. Если его все ещё нет, то его можно записать через запрос get entity, это точно мимопроходивший. После чего внести наконец то запись в таблицу.
P. S. К теме блокировок для разных процессов я ещё вернусь, но на другом материале.
Ведь благодаря новым фичам, в чатах теперь могут писать люди, в них в принципе не состоящие.
Поэтому алгоритм получился такой:
1) ловим ошибку постгрес, с отсутствием ключа. Запись помещается в кэш (откройте для себя класс питон queue, не пожалеете)
2) раз в минуту этот кэш проверяет обработчик. Если запись находится в очереди менее 30 секунд, он её пропускает.
3) если запись древнее 30 секунд, то проверяется, есть ли юзер в базе. Если его все ещё нет, то его можно записать через запрос get entity, это точно мимопроходивший. После чего внести наконец то запись в таблицу.
P. S. К теме блокировок для разных процессов я ещё вернусь, но на другом материале.
Новенькое в падениях телеги. В этот раз пашины гении ночью сломали шифрование. Все авторизованные боты были разлогинены сервером, при этом сессии обозначаются как живые.
Ручками пришлось с утра всех авторизовать заново, а старые сессии терминировать. Проверяйте свое хозяйство, скорее всего проблемы есть у всех.
Upd: Паша официально сообщил, что задело только часть клиентов IOS. Отлично, то есть у них нюансы протокола зависят от платформы. 🙈
Upd2: Товарищ Эшу у себя сбоев не наблюдает. То есть все зависит от используемого фреймворка для ботоводства. 😁
Ручками пришлось с утра всех авторизовать заново, а старые сессии терминировать. Проверяйте свое хозяйство, скорее всего проблемы есть у всех.
Upd: Паша официально сообщил, что задело только часть клиентов IOS. Отлично, то есть у них нюансы протокола зависят от платформы. 🙈
Upd2: Товарищ Эшу у себя сбоев не наблюдает. То есть все зависит от используемого фреймворка для ботоводства. 😁