urllib2
module is the requests
library. More on Habré: "Library to simplify HTTP requests . "python-telegram-bot
library. While on Habré this library was not mentioned.Net
. If you now enter the card number and request a balance, you can see the request generated to receive this data:'Copy as cURL'
. This action will lead to the fact that the clipboard will be the command to call the console utility curl
with the parameters that allow you to send exactly the same request, which was generated by the browser. curl 'http://strelkacard.ru/api/cards/status/?cardnum=12345678901&cardtypeid=3ae427a1-0f17-4524-acb1-a3f50090a8f3' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Encoding: gzip, deflate' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' -H 'Host: strelkacard.ru' -H 'Referer: http://strelkacard.ru/' -H 'User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:44.0) Gecko/20100101 Firefox/44.0'
{"cardactive":false,"balance":100100,"baserate":3000,"cardblocked":false,"numoftrips":0}
-H
arguments and try sending a simple GET request: $ curl 'http://strelkacard.ru/api/cards/status/?cardnum=12345678901&cardtypeid=3ae427a1-0f17-4524-acb1-a3f50090a8f3' {"cardactive":false,"balance":100100,"baserate":3000,"cardblocked":false,"numoftrips":0}
cardnum
, which is responsible for the card number, and cardtypeid
, the name of which suggests that it is responsible for the type of card. If the need for the first parameter is not in doubt, then the significance of the card type is questionable. Especially provided that the user does not choose it. Let's try to get rid of him: $ curl 'http://strelkacard.ru/api/cards/status/?cardnum=12345678901' {"__all__":[" "]}
{"cardactive":false,"balance":100100,"baserate":3000,"cardblocked":false,"numoftrips":0}
balance
. If at the same time we compare the number with the fact that it was displayed in the browser after the execution of the request, it will become obvious that this value has the dimension of kopecks.curl
certainly good, but it's not enough for us to send a request and receive an answer in the form of text. We need to be able to process this text. The Python language supports the conversion of json into its own structure of objects from the box . It also comes standard with a library for sending HTTP urllib2
. Sending a request using this library looks like this: >>> import urllib2 >>> f = urllib2.urlopen('http://strelkacard.ru/api/cards/status/?cardnum=12345678901&cardtypeid=3ae427a1-0f17-4524-acb1-a3f50090a8f3') >>> print(f.read()) {"cardactive":false,"balance":100100,"baserate":3000,"cardblocked":false,"numoftrips":0}
cardnum
parameter, so it would be great to rise one level of abstraction higher and not form the parameter string on our own. Put the requests
library and use it: >>> import requests >>> CARD_TYPE_ID = '3ae427a1-0f17-4524-acb1-a3f50090a8f3' >>> card_number='12345678901' >>> payload = {'cardnum':card_number, 'cardtypeid': CARD_TYPE_ID} >>> r = requests.get('http://strelkacard.ru/api/cards/status/', params=payload) >>> print("Get info for card %s: %d %s" % (card_number, r.status_code, r.text)) Get info for card 12345678901: 200 {"cardactive":false,"balance":100100,"baserate":3000,"cardblocked":false,"numoftrips":0}
requests
library provides a json()
method for converting a json-formatted server response to a Python data structure. >>> r.json() {u'cardactive': False, u'balance': 100100, u'numoftrips': 0, u'baserate': 3000, u'cardblocked': False} >>> r.json()['balance'] 100100
checker.py
file: #!/usr/bin/python import logging import requests CARD_TYPE_ID = '3ae427a1-0f17-4524-acb1-a3f50090a8f3' logger = logging.getLogger(__name__) def get_status(card_number): payload = {'cardnum':card_number, 'cardtypeid': CARD_TYPE_ID} r = requests.get('http://strelkacard.ru/api/cards/status/', params=payload) logger.info("Get info for card %s: %d %s" % (card_number, r.status_code, r.text)) if r.status_code == requests.codes.ok: return r.json() raise ValueError("Can't get info about card with number %s" % card_number) def get_balance(card_number): r = get_status(card_number) return r['balance']/100.
>>> import checker >>> checker.get_balance('12345678901') 1001.0
logging
library. With examples of its use in Russian can be found on Habré . logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
@BotFather
.@BotFather
- token to use the API.python-telegram-bot
wrapper library. Version of the library at the time of publication: 3.3.addTelegramCommandHandler
method addTelegramCommandHandler
the correct object. Examples of use are given in the library description .checker.py
will create the checker.py
file strelka_bot.py
follows: #!/usr/bin/python from telegram import Updater, User import logging import checker TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # Enable Logging logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # Dictionary to store users by its id users = {} class UserInfo: def __init__(self, telegram_user): self.user = telegram_user self.cards = {} def add_card(self, card_number): card = CardInfo(card_number) self.cards[card_number] = CardInfo(card_number) class CardInfo: def __init__(self, card_number): self.card_number = card_number def balance(self): logger.info("Getting balance for card %s" % self.card_number) json = checker.get_status(self.card_number) return json['balance']/100. def log_params(method_name, update): logger.debug("Method: %s\nFrom: %s\nchat_id: %d\nText: %s" % (method_name, update.message.from_user, update.message.chat_id, update.message.text)) def help(bot, update): log_params('help', update) bot.sendMessage(update.message.chat_id , text="""Supported commands: /help - Show help /addcard - Add a card to the list of registered cards /removecard - Remove a card to the list of registered cards /getcards - Returns balance for all registered cards""") def add_card(bot, update, args): log_params('add_card', update) if len(args) != 1: bot.sendMessage(update.message.chat_id, text="Usage:\n/addcard 1234567890") return card_number = args[0] telegram_user = update.message.from_user if not users.has_key(telegram_user.id): users[telegram_user.id] = UserInfo(telegram_user) user = users[telegram_user.id] if not user.cards.has_key(card_number): user.add_card(card_number) bot.sendMessage(update.message.chat_id, text="Card %s has been added successfully" % (card_number)) else: bot.sendMessage(update.message.chat_id, text="Card %s has been already added. Do nothing" % (card_number)) def remove_card(bot, update, args): log_params('remove_card', update) if len(args) != 1: bot.sendMessage(update.message.chat_id, text="Usage:\n/removecard 1234567890") return card_number = args[0] telegram_user = update.message.from_user if not users.has_key(telegram_user.id): bot.sendMessage(update.message.chat_id, text="There are no cards saved for you") return user = users[telegram_user.id] if user.cards.has_key(card_number): user.cards.pop(card_number) bot.sendMessage(update.message.chat_id, text="Card %s has been successfully removed" % (card_number)) else: bot.sendMessage(update.message.chat_id, text="Card %s has not been added. Do nothing" % (card_number)) def get_cards(bot, update): log_params('get_cards', update) telegram_user = update.message.from_user if not users.has_key(telegram_user.id) or len(users[telegram_user.id].cards) == 0: bot.sendMessage(update.message.chat_id , text="There are no saved cards for you. Please add a card by typing /addcard CARD_NUMBER") return user = users[telegram_user.id] cards = user.cards response = "" for card in cards.values(): if len(response) != 0: response += '\n' response += "Card %s balance: %.2f"%(card.card_number, card.balance()) bot.sendMessage(update.message.chat_id, text=response) def main(): updater = Updater(TOKEN) # Get the dispatcher to register handlers dp = updater.dispatcher # Add handlers for Telegram messages dp.addTelegramCommandHandler("help", help) dp.addTelegramCommandHandler("addcard", add_card) dp.addTelegramCommandHandler("removecard", remove_card) dp.addTelegramCommandHandler("getcards", get_cards) updater.start_polling() updater.idle() if __name__ == '__main__': main()
#!/usr/bin/python3 from telegram import Updater, User import logging import checker TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' # Enable Logging logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO) logger = logging.getLogger(__name__) logger.setLevel(logging.DEBUG) # Dictionary to store users by its id users = {} class UserInfo: def __init__(self, telegram_user): self.user = telegram_user self.cards = {} def add_card(self, card_number): card = CardInfo(card_number) self.cards[card_number] = CardInfo(card_number) class CardInfo: def __init__(self, card_number): self.card_number = card_number def balance(self): logger.info("Getting balance for card %s" % self.card_number) json = checker.get_status(self.card_number) return json['balance']/100. def log_params(method_name, update): logger.debug("Method: %s\nFrom: %s\nchat_id: %d\nText: %s" % (method_name, update.message.from_user, update.message.chat_id, update.message.text)) def help(bot, update): log_params('help', update) bot.sendMessage(update.message.chat_id , text="""Supported commands: /help - Show help /addcard - Add a card to the list of registered cards /removecard - Remove a card to the list of registered cards /getcards - Returns balance for all registered cards""") def add_card(bot, update, args): log_params('add_card', update) if len(args) != 1: bot.sendMessage(update.message.chat_id, text="Usage:\n/addcard 1234567890") return card_number = args[0] telegram_user = update.message.from_user if telegram_user.id not in users: users[telegram_user.id] = UserInfo(telegram_user) user = users[telegram_user.id] if card_number not in user.cards: user.add_card(card_number) bot.sendMessage(update.message.chat_id, text="Card %s has been added successfully" % (card_number)) else: bot.sendMessage(update.message.chat_id, text="Card %s has been already added. Do nothing" % (card_number)) def remove_card(bot, update, args): log_params('remove_card', update) if len(args) != 1: bot.sendMessage(update.message.chat_id, text="Usage:\n/removecard 1234567890") return card_number = args[0] telegram_user = update.message.from_user if telegram_user.id not in users: bot.sendMessage(update.message.chat_id, text="There are no cards saved for you") return user = users[telegram_user.id] if card_number in user.cards: user.cards.pop(card_number) bot.sendMessage(update.message.chat_id, text="Card %s has been successfully removed" % (card_number)) else: bot.sendMessage(update.message.chat_id, text="Card %s has not been added. Do nothing" % (card_number)) def get_cards(bot, update): log_params('get_cards', update) telegram_user = update.message.from_user if telegram_user.id not in users or len(users[telegram_user.id].cards) == 0: bot.sendMessage(update.message.chat_id , text="There are no saved cards for you. Please add a card by typing /addcard CARD_NUMBER") return user = users[telegram_user.id] cards = user.cards response = "" for card in list(cards.values()): if len(response) != 0: response += '\n' response += "Card balance for %s: %.2f"%(card.card_number, card.balance()) bot.sendMessage(update.message.chat_id, text=response) def main(): updater = Updater(TOKEN) # Get the dispatcher to register handlers dp = updater.dispatcher # Add handlers for Telegram messages dp.addTelegramCommandHandler("help", help) dp.addTelegramCommandHandler("addcard", add_card) dp.addTelegramCommandHandler("removecard", remove_card) dp.addTelegramCommandHandler("getcards", get_cards) updater.start_polling() updater.idle() if __name__ == '__main__': main()
TOKEN
variable TOKEN
be placed in the token received from @BotFather
.strelka_bot.py
brings our bot to life. $ python simple_strelka_bot.py 2016-03-06 12:02:11,706 - telegram.dispatcher - INFO - Dispatcher started 2016-03-06 12:02:11,706 - telegram.updater - INFO - Updater thread started 2016-03-06 12:02:26,123 - telegram.bot - INFO - Getting updates: [645839879] 2016-03-06 12:02:26,173 - __main__ - DEBUG - Method: get_cards From: {'username': u'username', 'first_name': u'Firstname', 'last_name': u'Lastname', 'id': 12345678} chat_id: 12345678 Text: /getcards
Ctrl+C
combination, which sends an interrupt signal ( SIGINT
)./getcards
.users
variable when changing, so as not to lose state when restarting the bot. The shelve
module is great for this. Examples of use are listed at the end of the documentation page. Its use should not cause difficulties.python-telegram-bot
librarypython-telegram-bot
library description. There is an interesting JobQueue functionality. It allows you to perform pending and repeatable tasks.CardInfo
field that stores the current balance and its value until the last update. And the method for the update itself: some update()
.threshold
. To set the value for this field, you will need a separate command for the bot.requests
library, the Telegram bot API and the python-telegram-bot
library managed to create a bot that notifies users in time that the balance on their cards has dropped to critically low values. The task of replenishing the card has remained beyond the scope, but the functionality of the "personal account" on the official website allows it to be comfortably solved with a PC.shelve
module and JobQueue functionality: strelka_telegram_bot .Source: https://habr.com/ru/post/278847/
All Articles