Advertisement
Guest User

esryhsht

a guest
May 21st, 2018
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 14.12 KB | None | 0 0
  1. from telegram.ext import (Updater, CommandHandler, MessageHandler,
  2.                           Filters, CallbackQueryHandler)
  3. from telegram import (ReplyKeyboardMarkup, InlineKeyboardButton,
  4.                       InlineKeyboardMarkup, ParseMode)
  5. import urllib.request as url
  6. import urllib.parse as parse
  7. from bs4 import BeautifulSoup
  8. import logging
  9. from json import loads
  10.  
  11. logging.basicConfig(level=logging.INFO)
  12.  
  13. MAX_SAVED = 10
  14. SAVED_PLACES = 'Сохраненные места'
  15. DELETE_SAVED_PLACE = 'Удалить сохраненное место'
  16. SETTINGS = 'Настройки'
  17. NO_SAVED = 'Пока нет сохраненных запросов.'
  18. SAVE = 'Сохранить запрос'
  19. START_TEXT = "Бот для получения погоды. \
  20. Напишите в сообщения ваш запрос на естественном языке."
  21. PLACES_FILE = 'places.txt'
  22. HELP_TEXT = 'Запрос выполняется в чат с ботом. Есть возможность сохранить \
  23. местоположение после выполнения запроса. Впоследствии список всех сохраненных \
  24. местоположений будет отображаться в меню "Сохраненные места". \
  25. Удалять из этого можно с помощью меню "Удалить сохраненное место". \
  26. С помощью меню "Настройки" настраиваются выбранные единицы измерения.'
  27. CACHE_FILE = 'cache.txt'
  28. INFO_FILE = 'info.txt'
  29. KEY = 'AIzaSyDtoJOHBCcbYQmVVnq9hmrrfa7ntO3N6LI'
  30. HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:46.0) \
  31. Gecko/20800121 Firefox/46.0', 'Accept-Language': 'ru'}
  32.  
  33. KEYBOARD_MARKUP = ReplyKeyboardMarkup([[SAVED_PLACES],
  34.                                        [DELETE_SAVED_PLACE],
  35.                                        [SETTINGS]],
  36.                                       resize_keyboard=True)
  37. SETTINGS_MARKUP = (lambda user_id:
  38.                    InlineKeyboardMarkup([[InlineKeyboardButton('Температура',
  39.                                                                callback_data='T'
  40.                                                                + str(user_id))],
  41.                                          [InlineKeyboardButton('Скорость ветра',
  42.                                                                callback_data='S' +
  43.                                                                str(user_id))]]))
  44.  
  45. TEMP_MARKUP = (lambda user_id:
  46.                InlineKeyboardMarkup([[InlineKeyboardButton('градус Цельсия',
  47.                                                            callback_data='C' +
  48.                                                            str(user_id))],
  49.                                      [InlineKeyboardButton('градус Фаренгейта',
  50.                                                            callback_data='F' +
  51.                                                            str(user_id))]]))
  52.  
  53. SPEED_MARKUP = (lambda user_id:
  54.                 InlineKeyboardMarkup([[InlineKeyboardButton('м/с',
  55.                                                             callback_data='R' +
  56.                                                             str(user_id))],
  57.                                       [InlineKeyboardButton('миль/ч',
  58.                                                             callback_data='A' +
  59.                                                             str(user_id))]]))
  60.  
  61. places = {}
  62. try:
  63.     with open(PLACES_FILE) as f:
  64.         places = eval(f.read())
  65. except FileNotFoundError:
  66.     with open(PLACES_FILE, 'w') as f:
  67.         f.write(str(places))
  68.  
  69.  
  70. cache1 = {}
  71. cache2 = {}
  72. curr_cache = 0
  73. try:
  74.     with open(CACHE_FILE) as f:
  75.         cache1, cache2 = eval(f.readline().strip()), eval(f.readline().strip())
  76.         curr_cache = int(eval(f.readline().strip()))
  77. except FileNotFoundError:
  78.     with open(CACHE_FILE, 'w') as f:
  79.         f.write(str(cache1) + '\n' + str(cache2) + '\n' + str(curr_cache))
  80.  
  81. info = {}
  82. try:
  83.     with open(INFO_FILE) as f:
  84.         info = eval(f.read())
  85. except FileNotFoundError:
  86.     with open(INFO_FILE, 'w') as f:
  87.         f.write(str(info))
  88.  
  89.  
  90. class WeatherInfo:
  91.     def __init__(self, loc_, dts_, dc_, tm_, ttm_, pp_, hm_, ws_):
  92.         self.loc, self.dts, self.dc, self.tm = (loc_, dts_, dc_,
  93.                                                 str(min(int(tm_), int(ttm_))))
  94.         self.ttm, self.pp, self.hm, self.ws = (str(max(int(tm_), int(ttm_))),
  95.                                                pp_, hm_, ws_)
  96.  
  97.     def get_info(self, user_id):
  98.         if user_id not in info:
  99.             info[user_id] = [0, 0]
  100.             with open(INFO_FILE, 'w') as f:
  101.                 f.write(str(info))
  102.         temp, wind = info[user_id][0], info[user_id][1]
  103.         t_res = self.tm
  104.         if temp == 1:
  105.             t_res = self.ttm
  106.         t_wind = self.ws
  107.         if 'ми/ч' in self.ws:
  108.             t_wind = t_wind.replace('ми/ч', 'миль/ч')
  109.         if 'миль/ч' in t_wind and wind == 0:
  110.             t_wind = int(t_wind.split()[0])
  111.             t_wind = '{} м/с'.format(round(t_wind * 0.44704))
  112.         if 'м/с' in t_wind and wind == 1:
  113.             t_wind = int(t_wind.split()[0])
  114.             t_wind = '{} миль/ч'.format(round(t_wind * 2.23693))
  115.         return '\n'.join([self.loc, self.dts, self.dc,
  116.                           'Температура: {}{}{}'.format(t_res, chr(176),
  117.                                                        'C' if not temp
  118.                                                        else 'F'),
  119.                           'Вероятность осадков: {}'.format(self.pp),
  120.                           'Влажность: {}'.format(self.hm),
  121.                           'Ветер: {}'.format(t_wind),
  122.                           '[{}]({})'.format(u"\u200B", get_image(self.loc))])
  123.  
  124.  
  125. def write_new_cache(location):
  126.     global curr_cache
  127.     if location in cache1:
  128.         return
  129.     cache1[location] = curr_cache
  130.     cache2[curr_cache] = location
  131.     curr_cache += 1
  132.     with open(CACHE_FILE, 'w') as f:
  133.         f.write(str(cache1) + '\n' + str(cache2) + '\n' + str(curr_cache))
  134.  
  135.  
  136. def get_cache(location):
  137.     if location not in cache1:
  138.         write_new_cache(location)
  139.     return cache1[location]
  140.  
  141.  
  142. def str_cache(location):
  143.     return str(get_cache(location))
  144.  
  145.  
  146. def get_location(cache):
  147.     return cache2[int(cache)]
  148.  
  149.  
  150. def get_request(question, key):
  151.     return 'http://www.google.ru/search?q={}\
  152. &cr=countryRU&lr=lang_ru&key={}'.format(parse.quote(question), key)
  153.  
  154.  
  155. def get_data(soup, id_search, type_search):
  156.     return soup.find(type_search, {'id': id_search}).text
  157.  
  158.  
  159. def update_info():
  160.     with open(INFO_FILE, 'w') as f:
  161.         f.write(str(info))
  162.  
  163.  
  164. def get_image(location):
  165.     req = url.Request('https://www.google.ru/search?q={}\
  166. &cr=countryRU&lr=lang_ru&tbm=isch&key={}'.format(parse.quote(location), KEY),
  167.                       headers=HEADERS)
  168.     page = url.urlopen(req)
  169.     r = page.read().decode('utf-8')
  170.     soup = BeautifulSoup(r, 'lxml')
  171.     im = soup.find('div', {'class': 'rg_bx rg_di rg_el ivg-i'})
  172.     p = loads(im.text[im.text.find('{'):])['ou']
  173.     return p
  174.  
  175.  
  176. def get_by_question(question, user_id):
  177.     question = 'погода ' + question
  178.     try:
  179.         req = url.Request(get_request(question, KEY), headers=HEADERS)
  180.         page = url.urlopen(req)
  181.         soup = BeautifulSoup(page.read().decode('utf-8'), 'lxml')
  182.         weather = soup.find('div', {'id': 'wob_wc'})
  183.         if weather is None:
  184.             return 'Запрос некорректен. Попробуйте переформулировать.'
  185.         wob_loc = get_data(weather, 'wob_loc', 'div')
  186.         wob_dts = get_data(weather, 'wob_dts', 'div')
  187.         wob_dc = get_data(weather, 'wob_dc', 'span')
  188.         wob_tm = get_data(weather, 'wob_tm', 'span')
  189.         wob_ttm = get_data(weather, 'wob_ttm', 'span')
  190.         wob_pp = get_data(weather, 'wob_pp', 'span')
  191.         wob_hm = get_data(weather, 'wob_hm', 'span')
  192.         wob_ws = get_data(weather, 'wob_ws', 'span')
  193.         return WeatherInfo(wob_loc, wob_dts, wob_dc,
  194.                            wob_tm, wob_ttm, wob_pp,
  195.                            wob_hm, wob_ws).get_info(user_id)
  196.     except Exception as e:
  197.         return 'Произошла ошибка на сервере. Попробуйте позднее.'
  198.  
  199.  
  200. def start(bot, update):
  201.     update.message.reply_text(START_TEXT, reply_markup=KEYBOARD_MARKUP)
  202.  
  203.  
  204. def help_bot(bot, update):
  205.     update.message.reply_text(HELP_TEXT)
  206.  
  207.  
  208. def keyboard_by_user(user_id, erase=False):
  209.     return InlineKeyboardMarkup([[InlineKeyboardButton(name,
  210.                                   callback_data='1' + str_cache(name) if not
  211.                                   erase else '2 {} {}'.format(user_id,
  212.                                                               str_cache(name)))]
  213.                                 for name in places[user_id]])
  214.  
  215.  
  216. def save_location(user_id, location):
  217.     if user_id not in places:
  218.         places[user_id] = [location]
  219.     else:
  220.         if location in places[user_id]:
  221.             return
  222.         places[user_id].append(location)
  223.     if len(places[user_id]) > MAX_SAVED:
  224.         places[user_id].pop(0)
  225.     with open(PLACES_FILE, 'w') as f:
  226.         f.write(str(places))
  227.  
  228.  
  229. def reply_request(bot, update):
  230.     query = update.message.text
  231.     user_id = update.effective_user.id
  232.     if query == SAVED_PLACES:
  233.         if user_id not in places or not places[user_id]:
  234.             update.message.reply_text(NO_SAVED)
  235.             return
  236.         update.message.reply_text(SAVED_PLACES,
  237.                                   reply_markup=keyboard_by_user(user_id))
  238.     elif query == DELETE_SAVED_PLACE:
  239.         if user_id not in places or not places[user_id]:
  240.             update.message.reply_text(NO_SAVED)
  241.             return
  242.         update.message.reply_text(DELETE_SAVED_PLACE,
  243.                                   reply_markup=keyboard_by_user(user_id, True))
  244.     elif query == SETTINGS:
  245.         update.message.reply_text(SETTINGS,
  246.                                   reply_markup=SETTINGS_MARKUP(user_id))
  247.     else:
  248.         ans = get_by_question(query, user_id)
  249.         if len(ans.split('\n')) == 1:
  250.             update.message.reply_text(ans)
  251.             return
  252.         location = ans.split('\n')[0]
  253.         keyboard = None
  254.         keyboard = InlineKeyboardMarkup([[InlineKeyboardButton(SAVE,
  255.                                          callback_data='3 {} {}'.format(str_cache(location),
  256.                                                                         str(user_id)))]])
  257.         if user_id in places and location in places[user_id]:
  258.             keyboard = None
  259.         update.message.reply_text(ans, parse_mode=ParseMode.MARKDOWN,
  260.                                   reply_markup=keyboard)
  261.  
  262.  
  263. def set_t(c):
  264.     if c in 'CF':
  265.         return 'Температура'
  266.     else:
  267.         return 'Скорость ветра'
  268.  
  269.  
  270. def new_val(c):
  271.     if c == 'C':
  272.         return 'градус Цельсия'
  273.     elif c == 'F':
  274.         return 'градус Фаренгейта'
  275.     elif c == 'R':
  276.         return 'м/с'
  277.     else:
  278.         return 'миль/ч'
  279.  
  280.  
  281. def button(bot, update):
  282.     query = update.callback_query
  283.     data = query.data
  284.     if data[0] == 'T':
  285.         user_id = int(data[1:])
  286.         bot.edit_message_reply_markup(chat_id=query.message.chat_id,
  287.                                       message_id=query.message.message_id,
  288.                                       inline_message_id=query.inline_message_id,
  289.                                       reply_markup=TEMP_MARKUP(user_id))
  290.     elif data[0] == 'S':
  291.         user_id = int(data[1:])
  292.         bot.edit_message_reply_markup(chat_id=query.message.chat_id,
  293.                                       message_id=query.message.message_id,
  294.                                       inline_message_id=query.inline_message_id,
  295.                                       reply_markup=SPEED_MARKUP(user_id))
  296.     elif data[0] in 'CFRA':
  297.         user_id = int(data[1:])
  298.         if user_id not in info:
  299.             info[user_id] = [0, 0]
  300.         info[user_id][int(data[0] in 'RA')] = int(data[0] in 'FA')
  301.         update_info()
  302.         bot.send_message(text='*{}* установлено на *{}*'.format(set_t(data[0]),
  303.                                                                 new_val(data[0])),
  304.                          chat_id=query.message.chat_id,
  305.                          parse_mode=ParseMode.MARKDOWN)
  306.     elif data[0] == '1':
  307.         bot.send_message(text=get_by_question(get_location(data[1:]),
  308.                                               update.effective_user.id),
  309.                          chat_id=query.message.chat_id,
  310.                          parse_mode=ParseMode.MARKDOWN)
  311.     elif data[0] == '2':
  312.         data = data.split()
  313.         user_id = int(data[1])
  314.         location = get_location(data[2])
  315.         places[user_id].remove(location)
  316.         bot.send_message(text='*{}* удалено'.format(location),
  317.                          chat_id=query.message.chat_id,
  318.                          parse_mode=ParseMode.MARKDOWN)
  319.         with open(PLACES_FILE, 'w') as f:
  320.             f.write(str(places))
  321.     else:
  322.         data = data.split()
  323.         user_id = int(data[-1])
  324.         location = get_location(data[1])
  325.         save_location(user_id, location)
  326.         bot.send_message(text='*{}* сохранено'.format(location),
  327.                          chat_id=query.message.chat_id,
  328.                          parse_mode=ParseMode.MARKDOWN)
  329.  
  330.  
  331. def execute_bot():
  332.     updater = Updater('569733577:AAGE6Rs5V8ORG7fpHNUKNqCasgL0A1Asfoo',
  333.                       request_kwargs={"proxy_url":
  334.                                       "http://94.177.216.109:8888"})
  335.     updater.dispatcher.add_handler(CommandHandler('start', start))
  336.     updater.dispatcher.add_handler(CommandHandler('help', help_bot))
  337.     updater.dispatcher.add_handler(MessageHandler(Filters.text, reply_request))
  338.     updater.dispatcher.add_handler(CallbackQueryHandler(button))
  339.     updater.start_polling()
  340.     updater.idle()
  341.  
  342.  
  343. if __name__ == '__main__':
  344.     execute_bot()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement