class Cron(object): def __init__(self, args): super(Cron, self).__init__() self.args = args self.query = Query(args); self.action = Action(args); def run(self): crons = self.query.list({}, 'AND', 'cron') output = [] date = int(time.time()) for action in crons: if( action['enable'] ): local = date - (action['tz_offset']*60*60) weekday = dt.utcfromtimestamp(local).weekday() hour = dt.utcfromtimestamp(local).hour minute = dt.utcfromtimestamp(local).minute dates = action['date'].split(',') for dte in dates: action_date = dt.utcfromtimestamp(int(dte) - (action['tz_offset']*60*60)) cron_minute = action_date.minute cron_hour = action_date.hour if( action['repeat'] == 'hour' ): cron = {} # output.append({ str(action_date): (cron_minute < 30 and minute < 30) or (cron_minute > 29 and minute > 29) }) if( (cron_minute < 30 and minute < 30) or (cron_minute > 29 and minute > 29) ): output.append(self.run_cron(action)) cron['action'] = action if( action['repeat'] == 'day' ): cron = {} if( cron_hour == hour ): if( (cron_minute < 30 and minute < 30) or (cron_minute > 29 and minute > 29) ): output.append(self.run_cron(action)) cron['action'] = action if( action['repeat'] == 'week' ): cron = {} cron_weekday = action_date.weekday() if( weekday == cron_weekday and cron_hour == hour ): if( abs(cron_minute-minute) < 30 ): cron['message'] = self.action.send_message(action['bot_id'], action['chat_id'], action['text'], action['tz_offset']) cron['action'] = action output.append(cron) return output def run_cron(self, action): cron = {} if( len(action['cron']) > 0 and action['cron'] != 'null' ): # Cron contains photo or rss configuration cron_obj = json.loads(action['cron']) if 'photo' in cron_obj: cron['photo'] = self.action.send_photo(action['bot_id'], action['chat_id'], action['cron'], action['text'], action['tz_offset']) if( cron_obj['loop'] ): self.query.update({'cron': self.action.next_file(action['cron'], action['bot_id'])}, 'cron', action['id']) if 'rss' in cron_obj: rss_msg = self.complete_rss(cron_obj['resource'], cron_obj['rss']) if( len(rss_msg) > 0 ): cron['message'] = self.action.send_message(action['bot_id'], action['chat_id'], rss_msg, action['tz_offset']) else: cron['message'] = 'Failed to send rss' if 'weather' in cron_obj: weather = self.complete_weather(cron_obj['weather']) cron['weather'] = self.action.send_message(action['bot_id'], action['chat_id'], weather, action['tz_offset']) else: # Cron contains only text for message cron['message'] = self.action.send_message(action['bot_id'], action['chat_id'], action['text'], action['tz_offset']) return cron def complete_rss(self, resource, url): output = [] if( resource == 'newsmaker.md' ): output.append('*{0}* - <DATE>'.format(resource)) try: rss_url = urllib2.urlopen(url) data = rss_url.read() rss_url.close() rss = xmltodict.parse(data) text = [] for k in rss['rss']['channel']['item']: # fields: title, link, guid, description, pubDate text.append('{0} [more..]({1})\n'.format(k['title'].decode('utf8'), k['link'])) if( len(text) > 0 ): output.append('\n'.join(text)) else: output = [] except Exception as e: raise return '\n'.join(output) def complete_weather(self, city): output = [] # Yandex city id - Chisinau - 33815 try: y_url = urllib2.urlopen('http://export.yandex.ru/weather-ng/forecasts/33815.xml') data = y_url.read() y_url.close() rss = xmltodict.parse(data) # Debug # return rss['forecast']['day'] text = [] text.append('*{0}*'.format(rss['forecast']['@city'])) for k in rss['forecast']: if 'fact' in k: fact = rss['forecast']['fact'] text.append('t: *{0} C*'.format(fact['temperature']['#text'])) text.append('humidity: *{0}*'.format(fact['humidity'])) text.append('pressure: *{0}*'.format(fact['pressure']['#text'])) if( len(text) > 0 ): output.append('\n'.join(text)) else: output = [] except Exception as e: raise return '\n'.join(output)
class Action: def __init__(self, args): self.telegram = args.telegram self.query = Query(args); def get_updates(self, bot_id): output = {} bot = self.query.list({'id': bot_id}, 'AND', 'bots') if( len(bot) > 0 ): req = urllib2.Request( '{0}{1}/{2}'.format(self.telegram, bot[0]['token'], 'getUpdates') ) request = urllib2.urlopen(req) response = json.loads(request.read()) if( response['ok'] ): self.update_chats(response['result'], bot_id) output['response'] = response['result'] output['chats'] = self.query.list({'bot_id': bot_id}, 'AND', 'chats') output['ok'] = True output['updates'] = response['result'] else: output['ok'] = False else: output['ok'] = False return output def update_chats(self, updates, bot_id): chats = {} chat_ids = [] output = [] for item in updates: chat = item['message']['from']['id'] if( chat not in chat_ids ): chats["chat_id"] = item['message']['from']['id'] chats["username"] = item['message']['from']['first_name'] chats["first_name"] = item['message']['from']['first_name'] chats["bot_id"] = bot_id chat_ids.append(chats) for chat in chat_ids: if( len(self.query.list({'chat_id': chat['chat_id'], 'bot_id': bot_id}, 'AND', 'chats')) <= 0 ): self.query.insert([chat['chat_id'], chat['username'], chat['first_name'], chat['bot_id']], 'chats') def get_message_atr(self, atributes): output = {} for atr in atributes: if( ':' in atr ): name = atr.split(':', 1)[0] value = atr.split(':', 1)[1] output[name] = value if( not output ): output['error'] = True return output else: output['error'] = False return output def send_message(self, bot_id, ids, text, tz): output = {} bot = self.query.list({'id': bot_id}, 'AND', 'bots') if( len(bot) > 0 ): bot_obj = telebot.TeleBot(str(bot[0]['token'])) chats = ids.split(',') success = [] for chat in chats: try: send = bot_obj.send_message(chat, self.convert_text(text, tz, 'request')) output['send'] = { 'date': str(send.date), 'message_id': str(send.message_id) } output['ok'] = True success.append(chat) except Exception as e: output['status'] = str(e) output['ok'] = False if( output['ok'] ): # message = str(MySQLdb.escape_string( self.convert_text(text, tz, 'save') )) message = self.convert_text(text, tz, 'save') output['saved'] = self.query.insert([', '.join(success), output['send']['date'], message, output['send']['message_id'], bot_id], 'message') output['success'] = success output['text'] = text return output else: output['ok'] = False output['status'] = 'Message not sent' else: output['ok'] = False output['status'] = 'Bot not found' return output def convert_text(self, text, tz, action): date = int(time.time())-(int(tz)*60*60) date = dt.utcfromtimestamp(date).strftime('%H:%M:%S %d/%m/%Y') output = string.replace(text, '<DATE>', date) # if( action == 'request' ): return output # else: # return output.encode('utf8') def send_photo(self, bot_id, ids, file_obj, text, tz): output = {} bot = self.query.list({'id': bot_id}, 'AND', 'bots') user = self.query.list({'id': bot[0]['user_id']}, 'AND', 'users') # file_Obj = json.loads(file_obj) file_Obj = json.loads(file_obj, object_hook=lambda d: namedtuple('X', d.keys())(*d.values())) directory = file_Obj.folder photo = file_Obj.photo if( len(bot) > 0 and len(user) > 0 ): bot_obj = telebot.TeleBot(str(bot[0]['token'])) chats = ids.split(',') success = [] path = '{0}/files/{1}/{2}/{3}'.format(os.getcwd(), user[0]['name'], directory, photo) photo = open(path) for chat in chats: try: bot_obj.send_photo(chat, photo, self.convert_text(text, tz, 'request')) success.append(chat) output['ok'] = True except Exception as e: output['fail'] = str(e) output['ok'] = False if( output['ok'] ): # message = self.convert_text(text, tz, 'save') # output['saved'] = self.query.insert([', '.join(success), output['message']['date'], message, output['message']['message_id'], bot_id], 'message') output['success'] = success else: output['ok'] = False output['status'] = 'Photo not sent' else: output['ok'] = False output['status'] = 'Bot not found' return output def get_messages(self, bot_id): return self.query.list({'bot_id': bot_id}, 'AND', 'message') def get_crons(self, bot_id, cron_id): if( cron_id == 'all' ): return self.query.list({'bot_id': bot_id}, 'AND', 'cron') else: return self.query.list({'bot_id': bot_id, 'id': cron_id}, 'AND', 'cron') def save_cron(self, bot_id, id, chats, text, date, tz, repeat, cron): output = {} if( id == '0' ): self.query.insert([chats, 1, date, repeat, text, tz, bot_id, cron], 'cron') output['cron'] = self.query.list({'bot_id': bot_id}, 'AND', 'cron') output['status'] = 'Saved' output['ok'] = True return output else: return [id, chats, text, date, repeat] # return self.query.update_cron(id, chats, text, date, repeat) def update_cron(self, bot_id, id, values): output = {} update = json.loads(values) self.query.update(update, 'cron', id) output['cron'] = self.query.list({'id': id}, 'AND', 'cron') output['ok'] = True return output def delete_cron(self, bot_id, id): output = {} output['ok'] = self.query.delete('cron', id) output['cron'] = self.query.list({'bot_id': bot_id}, 'AND', 'cron') return output def get_chats(self, bot_id): return self.query.list({'bot_id': bot_id}, 'AND', 'chats') def sign_in(self, name, email, hash): user = {} user['email'] = email output = {} if( len(self.query.list_users(user, 'OR')) == 0 ): self.query.add_user([name, email, hash]) output['ok'] = True output['log_in'] = self.log_in(email, hash) else: output['ok'] = False output['status'] = 'exists' return output; def log_in(self, email, hash): output = {} inputs = {} inputs['email'] = email inputs['hash'] = hash user = self.query.list_users(inputs, 'AND') if( len(user) > 0 ): output['ok'] = True output['user'] = user output['bots'] = self.query.list({'user_id': user[0]['id']}, 'AND', 'bots') else: output['ok'] = False if( len(self.query.list_users({'email': email}, 'AND')) == 0 ): output['email'] = False if( len(self.query.list_users({'hash': hash}, 'AND')) == 0 ): output['hash'] = False return output def get_user(self, id): output = {} output['id'] = id user = self.query.list({'id': id}, 'AND', 'users') if( len(user) > 0 ): output['ok'] = True output['user'] = user output['bots'] = self.query.list({'user_id': id}, 'AND', 'bots') else: output['ok'] = False output['status'] = 'User not found' return output def get_me_bot(self, token): req = urllib2.Request( '{0}{1}/{2}'.format(self.telegram, token, 'getMe') ) request = urllib2.urlopen(req) response = json.loads(request.read()) return response def add_bot(self, user, token): getbot = self.get_me_bot(token) output = {} if( getbot['ok'] ): output['get_me'] = getbot # check bot in db local = self.query.list({'token': token, 'user_id': user}, 'AND', 'bots') if( len(local) > 0 ): output['ok'] = False output['status'] = 'You already have this bot' else: # save bot result = getbot['result'] self.query.insert([token, result['username'], result['first_name'], str(result['id']), user], 'bots') output['bot'] = self.query.list({'token': token, 'user_id': user}, 'AND', 'bots') output['bots'] = self.query.list({'user_id': user}, 'AND', 'bots') output['ok'] = True else: output['ok'] = False output['status'] = 'Token Error' return output def add_channel(self, user_id, channel, bot_id): output = {} user = self.query.list({'id': user_id}, 'AND', 'users') if( len(user) > 0 ): if( len(self.query.list({'chat_id': channel, 'bot_id': bot_id}, 'AND', 'chats')) <= 0 ): self.query.insert([channel, channel, channel, bot_id], 'chats') output['ok'] = True output['chats'] = self.query.list({'bot_id': bot_id}, 'AND', 'chats') else: output['ok'] = False output['status'] = 'Channel is already present' return output def list_files(self, user_id): output = {} user = self.query.list({'id': user_id}, 'AND', 'users') if( len(user) > 0 ): folder = '{0}/files/{1}'.format(os.getcwd(), user[0]['name']) if( not os.path.isdir(folder) ): os.mkdir(folder) output['folders'] = os.listdir(folder) output['files'] = {} for drct in os.listdir(folder): for root, dirs, files in os.walk('{0}/{1}'.format(folder, drct)): output['files'][drct] = [] for file in files: output['files'][drct].append(file) output['files'][drct].sort() output['ok'] = True else: output['ok'] = False output['status'] = 'User not found' return output def next_file(self, file, bot_id): file_obj = json.loads(file) folder = file_obj['folder'] photo = file_obj['photo'] bot = self.query.list({'id': bot_id}, 'AND', 'bots') user = self.query.list({'id': bot[0]['user_id']}, 'AND', 'users') if( len(user) > 0 ): files = self.list_files(user[0]['id']) if( len(files['files']) > 0 ): f_list = files['files'][folder] f_list.sort() index = f_list.index(photo) if( index == len(f_list)-1 ): index = -1 file_obj['photo'] = f_list[index+1] file = json.dumps(file_obj) return file def query_close(self): self.query.db_close()