def get(user): """Revoke access token for user.""" logger.info('Logout by %s' % user['email']) access_token = user['oauth_token'] security.revoke_token(access_token) return "Logout Success", 200
def showSearch(bot, update): show_name = update.callback_query.data[len(constants. WATCH_TELEVISION_CALLBACK):] show_id = select.getShowByName(show_name)[0] telegram_id = update.callback_query.message.chat_id telegram_name = update._effective_user.full_name watch_id = str(telegram_id) + str( constants.NOTIFIER_MEDIA_TYPE_TELEVISION) + str(show_id) desc = telegram_name + " watching " + show_name insert.insertNotifier(watch_id, telegram_id, show_id, constants.NOTIFIER_MEDIA_TYPE_TELEVISION, constants.NOTIFIER_FREQUENCY_IMMEDIATELY, desc) logger.info( __name__, "{} started watching a show: {}".format(telegram_name, show_name)) keyboard = [] for freq in range(len(constants.NOTIFIER_FREQUENCY)): keyboard.append([ telegram.InlineKeyboardButton( constants.NOTIFIER_FREQUENCY[freq], callback_data=constants.WATCH_TELEVISION_FREQ_CALLBACK + str(watch_id) + "," + str(freq)) ]) reply_markup = telegram.InlineKeyboardMarkup(keyboard) bot.edit_message_text(text=constants.WATCH_TELEVISION_FREQUENCY, reply_markup=reply_markup, chat_id=update.callback_query.message.chat_id, message_id=update.callback_query.message.message_id, parse_mode=telegram.ParseMode.MARKDOWN)
def create_user(sender, instance, created, **kwargs): """MEMBER USER'INFO INIT""" if created: password = generate_password() user_info = { 'username': instance.username, 'first_name': instance.first_name, 'last_name': instance.last_name, 'email': instance.email, 'password': make_password(password), 'is_active': True } try: user = User.objects.get(username=instance.username) user.set_password(password) except User.DoesNotExist as e: logger.info(e) user = User(**user_info) user.save() instance.user = user notify_data = { 'action': 'creation', 'e_subject': 'PhytOrganic - Member Creation', 'e_receiver': instance.email, 'e_context': { 'username': instance.username, 'password': password } } notifier(**notify_data) instance.save()
def updateTelevision(bot, job): logger.info(__name__, "Updating television database...") shows = sonarr.getAllShows() if (shows is not None): # Add any new TV series to the database for show in shows: insert.insertTV(show[0], show[1]) # Compare and delete removed shows from database to Sonarr shows_inactive = constants.listDifference(select.getDatabaseShows(), shows) if (len(shows_inactive) > 0): show_ids = sonarr.getAllShowIDs() for show in shows_inactive: if (show[0] in show_ids): update.updateTV(show[0], show[1]) else: delete.deleteTV(show[0]) logger.warning( __name__, "Television series '{}' has been modified in the database". format(show[1])) logger.info(__name__, "Finished updating television database") else: logger.warning( __name__, "Failed to update television database. Will try again at next scheduled run" )
def updateMovies(bot, job): logger.info(__name__, "Updating movies database...") movies = radarr.getAllMovies() if (movies is not None): # Add any new movies to the database for movie in movies: insert.insertMovie(movie[0], movie[1]) # Compare and delete removed movies from database to Radarr movies_inactive = constants.listDifference(select.getDatabaseMovies(), movies) if (len(movies_inactive) > 0): movie_ids = radarr.getAllMovieIDs() for movie in movies_inactive: if (movie[0] in movie_ids): update.updateMovie(movie[0], movie[1]) else: delete.deleteMovie(movie[0]) logger.warning( __name__, "Movie '{}' has been modified the database".format( movie[1])) logger.info(__name__, "Finished updating movie database") else: logger.warning( __name__, "Failed to update movie database. Will try again at next scheduled run" )
def execute(self, *args, **options): """ Execute command """ if("dump" in args): self.dump() else: self.load() logger.info('Done.')
def get(self, user): """Retrieve the logged user details. Return a user model if the authorization code were defined in a header. Return error otherwise """ logger.info('Call user info %s' % user['email']) return user
def setStatus(bot, update): results = update.callback_query.data[len(constants.ACCESS_SETSTATUS_CALLBACK):].split(",") status_code = constants.ACCOUNT_STATUS.index(results[1]) user = select.getUser(results[0]) msg = constants.ACCESS_SUCCESS.format(user[0], user[5], results[1].lower()) update_db.updateUserStatus(user[0], status_code) bot.edit_message_text(text=msg, chat_id=update.callback_query.message.chat_id, message_id=update.callback_query.message.message_id, parse_mode=telegram.ParseMode.MARKDOWN) logger.info(__name__, msg[1:-2], "INFO_BLUE") bot.send_message(chat_id=user[0], text=constants.ACCOUNT_STATUS_MSG[status_code], parse_mode=telegram.ParseMode.MARKDOWN)
def register(bot, update): if(not select.isUserRegistered(update.message.chat_id)): insert.insertUser(update.message.chat_id, constants.ACCOUNT_STATUS_UNVERIFIED, constants.ACCOUNT_DETAIL_SIMPLE, constants.ACCOUNT_UPGRADE_NO, None, update.message.from_user.full_name) update.message.reply_text(constants.ACCOUNT_REGISTER_START.format(constants.BOT_NAME), parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=telegram.ReplyKeyboardMarkup(constants.ACCOUNT_DETAIL_REPLY_MARKUP, resize_keyboard=True)) logger.info(__name__, "User registered - {}: {}".format(update.message.chat_id, update.message.from_user.full_name), "INFO_BLUE") return constants.ACCOUNT_REGISTER_STATE_DETAIL else: update.message.reply_text(constants.ACCOUNT_REGISTER_FAIL_REGISTERED, parse_mode=telegram.ParseMode.MARKDOWN) return ConversationHandler.END
def execute(self, *args, **options): """ Execute command """ self.output_folder = TILES_SETTINGS['TILES_ROOT'] if not os.path.exists(self.output_folder): os.makedirs(self.output_folder) self.builder_args = {} self._build_global_tiles() self._build_area_tiles() logger.info('Done.')
def parseTelegram(): if ('TELEGRAM' in parser): telegram.api = parser['TELEGRAM']['BOT_TOKEN'] telegram.auto_approve = parser.getboolean('TELEGRAM', 'AUTO_APPROVE') telegram.initialize() logger.info(__name__, "Telegram API initialized") else: logger.error( __name__, "Failed to initialize Telegram's API: Check your config.ini") exit()
def movieSearch(bot, update): movie_name = update.callback_query.data[len(constants.UNWATCH_MOVIE_CALLBACK):] movie_id = select.getMovieByName(movie_name)[0] telegram_id = update.callback_query.message.chat_id telegram_name = update._effective_user.full_name watch_id = str(telegram_id)+str(constants.NOTIFIER_MEDIA_TYPE_MOVIE)+str(movie_id) desc = telegram_name + " unwatched " + movie_name delete.deleteNotifier(watch_id) logger.info(__name__, "{} unwatched a show: {}".format(telegram_name, movie_name)) bot.edit_message_text(text=constants.UNWATCH_MOVIES_SUCCESS.format(movie_name), chat_id=update.callback_query.message.chat_id, message_id=update.callback_query.message.message_id, parse_mode=telegram.ParseMode.MARKDOWN)
def addDefaultJobs(): logger.info(__name__, "Adding default scheduler jobs") if (sonarr.enabled): addRepeatingJob(catalogue.updateTelevision, constants.minutesToSeconds(sonarr.update_frequency)) if (radarr.enabled): addRepeatingJob(catalogue.updateMovies, constants.minutesToSeconds(radarr.update_frequency)) addRepeatingJob(notify.notifyDaily, constants.hoursToSeconds(24), notify.secondsToDaily()) addRepeatingJob(notify.notifyWeekly, constants.daysToSeconds(7), notify.secondsToWeekly())
def parseOmbi(): if ('OMBI' in parser): if (parser.getboolean('OMBI', 'ENABLED')): ombi.enabled = True ombi.api = parser['OMBI']['API'] ombi.host = parser['OMBI']['HOST'] ombi.initialize() logger.info(__name__, "Ombi API parsed") else: logger.error(__name__, "Failed to initialize Ombi's API: Check your config.ini") exit()
def parseGeneral(): try: if ('GENERAL' in parser): constants.BOT_NAME = parser['GENERAL']['NAME'] logger.info(__name__, "Parsed general information") else: raise Exception() except: logger.error( __name__, "Failed to get general config information: Check your config.ini") exit()
def notifyImmediately(bot, job): # Pulls the watch_id, and decodes the bytes back to the data try: watch_id = job.context.decode('utf-8') data = watch_id.split(";") except: logger.error(__name__, "notifyImmediately() failed to extract and process watch_id") return True # If the media isn't in the database, refreshes the databases first if(int(data[1]) == constants.NOTIFIER_MEDIA_TYPE_MOVIE and select.getMovie(data[0]) == None and radarr.enabled): catalogue.updateMovies(None, None) elif(int(data[1]) == constants.NOTIFIER_MEDIA_TYPE_TELEVISION and select.getShow(data[0]) == None and sonarr.enabled): catalogue.updateTelevision(None, None) # Gets the metadata for the movie and the list of users who need notifications metadata = select.getMetadata(watch_id, data[1]) users = select.getUsersImmediateUpdate(data[0], data[1]) # If there are no users watching this show or movie, print a log and return if(len(users) == 0): logger.info(__name__, "New content ({}): Notified no users".format(metadata[2]), "INFO_GREEN") return True # Build the messages if(int(data[1]) == constants.NOTIFIER_MEDIA_TYPE_TELEVISION): msg_simple = constants.NOTIFIER_IMMEDIATELY_HEADER + buildSimpleTelevisionMessage(metadata) msg_complex = constants.NOTIFIER_IMMEDIATELY_HEADER + buildComplexTelevisionMessage(metadata) is_upgrade = metadata[9] elif(int(data[1]) == constants.NOTIFIER_MEDIA_TYPE_MOVIE): msg_simple = constants.NOTIFIER_IMMEDIATELY_HEADER + buildSimpleMovieMessage(metadata) msg_complex = constants.NOTIFIER_IMMEDIATELY_HEADER + buildComplexMovieMessage(metadata) is_upgrade = metadata[5] # Process user messages notifications_counter = 0 for user in users: user_data = select.getUser(user[0]) # Checks if the user is banned or restricted if((not constants.RESTRICTED_NOTIFICATIONS or user_data[1] != constants.ACCOUNT_STATUS_RESTRICTED) and user_data[1] != constants.ACCOUNT_STATUS_BANNED): # Checks if the media was an upgrade if(is_upgrade == 1): if(user_data[3] == constants.ACCOUNT_UPGRADE_YES): # Gets the complexity and sends the appropriate message if(user_data[2] == constants.ACCOUNT_DETAIL_SIMPLE): bot.send_message(chat_id=user_data[0], text=msg_simple, parse_mode=telegram.ParseMode.MARKDOWN) elif(user_data[2]== constants.ACCOUNT_DETAIL_COMPLEX): bot.send_message(chat_id=user_data[0], text=msg_complex, parse_mode=telegram.ParseMode.MARKDOWN) notifications_counter += 1 else: # Gets the complexity and sends the appropriate message if(user_data[2] == constants.ACCOUNT_DETAIL_SIMPLE): bot.send_message(chat_id=user_data[0], text=msg_simple, parse_mode=telegram.ParseMode.MARKDOWN) elif(user_data[2]== constants.ACCOUNT_DETAIL_COMPLEX): bot.send_message(chat_id=user_data[0], text=msg_complex, parse_mode=telegram.ParseMode.MARKDOWN) notifications_counter += 1 logger.info(__name__, "New content ({}): notified {} user(s)".format(metadata[2], notifications_counter), "INFO_GREEN")
def notifyWeekly(bot, job): users = select.getUsers() for user in users: # Gets the notifiers notifiers = select.getNotifiersForUserWeekly(user[0], constants.NOTIFIER_MEDIA_TYPE_TELEVISION) # Makes sure the user has at least one TV notifier if(len(notifiers) != 0): # Builds the message msg = buildReportMessage(notifiers, constants.NOTIFIER_WEEKLY_HEADER, constants.NOTIFIER_FREQUENCY_WEEKLY) # Makes sure there is new content to notify the user about and send it if there is if(msg != constants.NOTIFIER_WEEKLY_HEADER): bot.send_message(chat_id=user[0], text=msg, parse_mode=telegram.ParseMode.MARKDOWN) logger.info(__name__, "Weekly content report sent to all applicable users", "INFO_GREEN")
def initParser(): global parser try: parser = configparser.ConfigParser() parser.read(constants.CONFIG_FILE) if not (len(parser) > 1): raise Exception() logger.info(__name__, "Configparser initialized") except: logger.error( __name__, "Failed to load config.ini: Please ensure that a valid config file is located at {}" .format(constants.CONFIG_FILE)) exit()
def member_bv_init(sender, instance, created, **kwargs): """MEMBER BVS INIT""" if created: try: member_bv = MemberBV.objects.get(member=instance) except MemberBV.DoesNotExist as e: logger.info(e) member_bv = MemberBV(member=instance) try: member_bv.save() except IntegrityError as e: logger.error(e) except ValueError as e: logger.error(e)
def member_wallet_init(sender, instance, created, **kwargs): """MEMBER WALLET INIT""" if created: try: member_wallet = MemberWallet.objects.get(member=instance) except MemberWallet.DoesNotExist as e: logger.info(e) member_wallet = MemberWallet(member=instance) try: member_wallet.save() except IntegrityError as e: logger.error(e) except ValueError as e: logger.error(e)
def parseSonarr(): if ('SONARR' in parser): if (parser.getboolean('SONARR', 'ENABLED')): sonarr.enabled = True sonarr.api = parser['SONARR']['API'] sonarr.host = parser['SONARR']['HOST'] sonarr.update_frequency = int(parser['SONARR']['UPDATE_FREQ']) sonarr.initialize() logger.info(__name__, "Sonarr API parsed") else: logger.error( __name__, "Could not read the Sonarr configuration values: Check your config.ini" ) exit()
def _build_global_tiles(self): """ Creates a tiles file on the global extent. Builds a temporary file and overwrites the existing one on success. """ self.builder_args['tiles_url'] = TILES_SETTINGS['TILES_URL'] self.builder_args['tile_format'] = format_from_url(TILES_SETTINGS['TILES_URL']) global_file = os.path.join(self.output_folder, 'global.zip') tmp_gobal_file = global_file + '.tmp' logger.info("Build global tiles file...") tiles = ZipTilesBuilder(filepath=tmp_gobal_file, **self.builder_args) tiles.add_coverage(bbox=TILES_SETTINGS['GLOBAL_MAP_BBOX'], zoomlevels=TILES_SETTINGS['TILES_GLOBAL_ZOOMS']) tiles.run() remove_file(global_file) os.rename(tmp_gobal_file, global_file) logger.info('%s done. size : %s' % (global_file, format_size(os.stat(global_file).st_size)))
def movieSearch(bot, update): movie_name = update.callback_query.data[len(constants.WATCH_MOVIE_CALLBACK ):] movie_id = select.getMovieByName(movie_name)[0] telegram_id = update.callback_query.message.chat_id telegram_name = update._effective_user.full_name watch_id = str(telegram_id) + str( constants.NOTIFIER_MEDIA_TYPE_MOVIE) + str(movie_id) desc = telegram_name + " watching " + movie_name insert.insertNotifier(watch_id, telegram_id, movie_id, constants.NOTIFIER_MEDIA_TYPE_MOVIE, constants.NOTIFIER_FREQUENCY_IMMEDIATELY, desc) logger.info( __name__, "{} started watching a movie: {}".format(telegram_name, movie_name)) bot.edit_message_text( text=constants.WATCH_MOVIES_SUCCESS.format(movie_name), chat_id=update.callback_query.message.chat_id, message_id=update.callback_query.message.message_id, parse_mode=telegram.ParseMode.MARKDOWN)
def _build_area_tiles(self): """ Creates a tiles file for a specific area Builds a temporary file and overwrites the existing one on success. """ for area in Area.objects.all(): area_file = os.path.join(self.output_folder, 'area_%s.zip' % area.id) tmp_area_file = area_file + '.tmp' if not (area.lon and area.lat and area.lon != 1 and area.lat != -1): inds = Individual.objects.filter(area=area) for ind in inds: if ind.lon and ind.lat and ind.lat != 1: coords = [(ind.lon, ind.lat)] break else: coords = [(area.lon, area.lat)] self._build_tiles_along_coords(tmp_area_file, coords) remove_file(area_file) os.rename(tmp_area_file, area_file) logger.info('%s done. %s' % (area_file, format_size(os.stat(area_file).st_size)))
def confirm(bot, update): delete.deleteUser(update.message.chat_id) update.message.reply_text(constants.DELETEACCOUNT_SUCCESS, parse_mode=telegram.ParseMode.MARKDOWN, reply_markup=telegram.ReplyKeyboardRemove()) logger.info(__name__, "User deleted - {}: {}".format(update.message.chat_id, update.message.from_user.full_name), "INFO_BLUE") return ConversationHandler.END
def initialize(): db = sqlite3.connect(constants.DB_FILE) db_cursor = db.cursor() db_cursor.execute("""CREATE TABLE IF NOT EXISTS users( telegram_id INTEGER PRIMARY KEY, status INTEGER, detail INTEGER, upgrade INTEGER, ombi_id TEXT, name TEXT )""" ) db_cursor.execute("""CREATE TABLE IF NOT EXISTS television( tvdb_id INTEGER PRIMARY KEY, name TEXT )""" ) db_cursor.execute("""CREATE TABLE IF NOT EXISTS movies( tmdb_id INTEGER PRIMARY KEY, name TEXT )""" ) db_cursor.execute("""CREATE TABLE IF NOT EXISTS notifiers( watch_id TEXT PRIMARY KEY, telegram_id INTEGER, media_id INTEGER, media_type INTEGER, frequency INTEGER, desc TEXT, FOREIGN KEY(telegram_id) REFERENCES users ON DELETE CASCADE )""" ) db_cursor.execute("""CREATE TABLE IF NOT EXISTS metadata_television( metadata_id TEXT PRIMARY KEY, tvdb_id INTEGER, show_title TEXT, show_type TEXT, episode_title TEXT, season TEXT, episode TEXT, quality TEXT, quality_version TEXT, is_upgrade INTEGER, download_time FLOAT, FOREIGN KEY(tvdb_id) REFERENCES television ON DELETE CASCADE )""" ) db_cursor.execute("""CREATE TABLE IF NOT EXISTS metadata_movies( metadata_id TEXT PRIMARY KEY, tmdb_id INTEGER, movie_title TEXT, quality TEXT, quality_version TEXT, is_upgrade INTEGER, download_time FLOAT, FOREIGN KEY(tmdb_id) REFERENCES movies ON DELETE CASCADE )""" ) db.commit() db.close() logger.info(__name__, "Database tables created/loaded")
from trends import api as api_trends from public import api as api_public blueprint = Blueprint('api', __name__, url_prefix='/api') authorizations = { 'oauth2': { 'type': 'oauth2', 'in': 'header', 'name': 'Authorization' } } api = Api(blueprint, version='1.0', title='Stack API', description='Access stack data.', authorizations=authorizations) app.register_blueprint(blueprint) api.add_namespace(api_auth) logger.info('Auth API was registered.') api.add_namespace(api_user) logger.info('User API was registered.') api.add_namespace(api_public) logger.info('Public API was registered.') api.add_namespace(api_stack) logger.info('Stack API was registered.') api.add_namespace(api_trends) logger.info('Trends API was registered.')
def execute(self, *args, **options): """ Execute command """ self.integrate_translation() logger.info('Done.')
def addSingleJob(func, delay, args): job_queue.run_once(func, delay, context=args) logger.info( __name__, "Single job added to queue: {}, start delay: {}s".format( func.__name__, delay))
def initialize(): global job_queue job_queue = telegram.updater.job_queue logger.info(__name__, "Job queue initialized") addDefaultJobs()
def addRepeatingJob(func, delay, first=0): job_queue.run_repeating(func, interval=delay, first=first) logger.info( __name__, "Repeating job added to queue: {}, repeat delay: {}s, start delay: {}s" .format(func.__name__, delay, first))
def post(self): """Autenticate google user account. Expect a request json with clientId, redirectUri and code attributes. Samples: { 'clientId': your-google-client-id, 'code': '4/xHYKb3CD9gbiXBiL2XPaj_ILlMjXTJbVmBTFCVGBjKo', 'accessType': 'offline', 'redirectUri': u'http://localhost:8080' } """ access_token_url = 'https://www.googleapis.com/oauth2/v4/token' people_api_url = 'https://www.googleapis.com/oauth2/v3/userinfo' tokeninfo_url = 'https://www.googleapis.com/oauth2/v3/tokeninfo' logger.debug('google request =>') logger.debug(request.json) payload = dict(client_id=request.json['clientId'], redirect_uri=request.json['redirectUri'], client_secret=app.config['GOOGLE_CLIENT_SECRET'], code=request.json['code'], grant_type='authorization_code') logger.debug('Google Payload =>') logger.debug(payload) # Step 2. Exchange authorization code for access token. r = requests.post(access_token_url, data=payload) token = json.loads(r.text) logger.debug('Access Token =>') logger.debug(token) # Step 2. Retrieve information about the current user. headers = {'Authorization': 'Bearer {0}'.format(token['access_token'])} r = requests.get(people_api_url, headers=headers) profile = json.loads(r.text) logger.info('Login as => %s' % profile['email']) logger.debug(profile) if security.is_valid_email(profile['email']): # Step 4. Create a new account or return an existing one. r = requests.get('%s?access_token=%s' % (tokeninfo_url, token['access_token'])) token_info = json.loads(r.text) logger.debug('Tokeninfo =>') logger.debug(token_info) # Step 5. Sign-up a user process account = {} try: account = repository.get_document( index=index, doc_type=doc_type, id=profile['sub']) # update refresh_token if it was informed (after revoke token) logger.debug('Account found for %s' % profile['email']) if 'refresh_token' in token: logger.debug('A new refresh_token was defined. It will be updated') repository.update( index=index, doc_type=doc_type, id=profile['sub'], body={"doc": {"refresh_token": token['refresh_token']}} ) # if extits, profile will be the accound founded # profile['refresh_token'] = account["_source"]['refresh_token'] except NotFoundError as e: # create a new user if not exists one account logger.warning('First logging for %s' % profile['email']) account = profile.copy() account['created_at'] = datetime.utcnow() if 'refresh_token' in token: account['refresh_token'] = token['refresh_token'] repository.insert(index=index, doc_type=doc_type, login=account['sub'], document=account) # Step 6. Build and return a json web token. jwt_payload = { 'sub': profile['sub'], 'iat': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(days=5), 'access_token':token['access_token'], 'user': profile } jwt = security.create_token(jwt_payload) return jsonify(token=jwt) # return jsonify(token=token['access_token']) else: return security.response_not_authorized( 403, 'Invalid email domain. Please sign with ciandt.com acccount' )
def initialize(): conversationHandlers() commandHandlers() callbackQueryHandlers() logger.info(__name__, "Telegram command handlers initialized")
def stopServer(): if(server_socket is not None): server_socket.close() logger.info(__name__, "Notification listener stopped")
def execute(self, *args, **options): """ Execute command """ filename = "backup_db4.json" self.integrate_dump_in_db(filename) logger.info('Done.')