def sync_google_photos(): logging.debug('Google Photos Sync Starting') try: logging.debug('Setting Session Credentials') session_credentials = google.oauth2.credentials.Credentials( **flask.session['credentials']) logging.debug('Building Google Photos API') photos_api = googleapiclient.discovery.build( config.get('API_SERVICE_NAME'), config.get('API_VERSION'), cache_discovery=False, credentials=session_credentials, ) album_dict = photos_api.albums().list().execute() logging.debug('Reading Google Albums') sync_albums(album_dict['albums'], photos_api) credentials.save_data(session_credentials) logging.debug('Google Photos Sync Complete') except Exception as e: logging.critical('Failed to Sync Google Photos', e) return False return True
def sync_media(media_files: list, path: str): for media in media_files: file_name = os.path.join(path, media['filename']) if config.get( 'API_FORCE_MEDIA_UPDATE') or not os.path.isfile(file_name): if media['mimeType'].startswith('video'): media_url = media['baseUrl'] + config.get( 'API_DOWNLOAD_VIDEO_EXTENSION') else: media_url = media['baseUrl'] + config.get( 'API_MAX_RESOLUTION_EXTENSION') download_media(media_url, file_name)
def remove_old_albums(local_album_names: list, album_names: list): for remove_album in [ path for path in local_album_names if path not in album_names ]: path = os.path.join(config.get('DOWNLOAD_PHOTO_PATH'), remove_album) shutil.rmtree(path) logging.debug('Removed Album: ' + path)
def authorize(): if check_online_status(): flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( client_secret.get_local_json_path(), scopes=config.get('API_SERVICE_SCOPES'), ) # The URI created here must exactly match one of the authorized # redirect URIs for the OAuth 2.0 client, which you configured in the # API Console. If this value doesn't match an authorized URI, # you will get a 'redirect_uri_mismatch' error. flow.redirect_uri = flask.url_for('oauth2callback', _external=True) authorization_url, state = flow.authorization_url( # Enable offline access so that you can refresh an access token # without re-prompting the user for permission. Recommended for # web server apps. access_type='offline', # Enable incremental authorization. Recommended as a best # practice. include_granted_scopes='true', ) # Store the state so the callback can verify the auth server response. flask.session['state'] = state return flask.redirect(authorization_url) return flask.redirect('/')
def sync_albums(albums: dict, photos_api): for album in albums: logging.debug('Reading Google Album: ' + album['title']) if album_in_sync_list(album['title']): logging.debug('Syncing Google Album: ' + album['title']) body = {"albumId": album['id']} path = os.path.join( config.get('DOWNLOAD_PHOTO_PATH'), album['title'], ) verify_path_exists(path) media_file_names = [] read_album(body, path, media_file_names, photos_api) remove_old_files(media_file_names, path) remove_old_albums( os.listdir(config.get('DOWNLOAD_PHOTO_PATH')), [t['title'] for t in albums], )
def index(): if not os.path.isfile(credentials.get_local_json_path()): logging.debug('Loading initial Setup GUI') return flask.render_template('setup.html') else: if check_online_status(): global last_api_call # If Authorization is required, return Google OAuth2 Login if 'credentials' not in flask.session or not google_photos.sync_google_photos( ): return flask.redirect('authorize') last_api_call = int(time.time()) return flask.render_template( 'play.html', refresh=int(config.get('LIMIT_DISPLAY_REFRESH_MILLISECONDS')), )
def oauth2callback(): if check_online_status(): # Specify the state when creating the flow in the callback so that it # can verified in the authorization server response. state = flask.session['state'] flow = google_auth_oauthlib.flow.Flow.from_client_secrets_file( client_secret.get_local_json_path(), scopes=config.get('API_SERVICE_SCOPES'), state=state, ) flow.redirect_uri = flask.url_for('oauth2callback', _external=True) # Use the authorization server's response to fetch the OAuth 2.0 tokens. authorization_response = flask.request.url flow.fetch_token(authorization_response=authorization_response) # Store credentials in the session. credentials.save_data(flow.credentials) return flask.redirect('/')
def album_in_sync_list(album_name: str) -> bool: return any({ True for album in config.get('ALBUM_SYNC_LIST') if album == album_name or ( '*' in album and album.replace('*', '') in album_name) })
def random_media_info(): filename = Media().random_media(config.get('DOWNLOAD_PHOTO_PATH')) return flask.jsonify(**{ 'filename': filename, 'mimetype': mimetypes.guess_type(filename)[0], })
import requests from gframe import google_photos from gframe.client_secret import client_secret from gframe.config import config from gframe.credentials import credentials from gframe.local_media import Media logging.debug('Setting Environment Variables') # Disable HTTPS os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1' # Relax Tokens os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1' app = flask.Flask(__name__) app.secret_key = config.get('SECRET_KEY') # Force JSON to Return as Pretty/Readable Print app.config['JSONIFY_PRETTYPRINT_REGULAR'] = True @app.route('/') def index(): if not os.path.isfile(credentials.get_local_json_path()): logging.debug('Loading initial Setup GUI') return flask.render_template('setup.html') else: if check_online_status(): global last_api_call # If Authorization is required, return Google OAuth2 Login if 'credentials' not in flask.session or not google_photos.sync_google_photos(