"""Deezer flow utilities.""" import gzip import os import re import shutil from zipfile import is_zipfile from zipfile import ZipFile import requests from requests import Session FAILED_LOGIN = 'Please enter a correct username and password' def repack_source_file(local_file_path, local_dir, source, one_file=False): """Extract .zip archive locally and put file in gzip archive.""" with ZipFile(local_file_path, 'r') as myzip: myzip.extractall(local_dir) source_files = [] _source_d = {'files': []} if isinstance(source, str) else source for root, _, files in os.walk(local_dir): for name in files: if name == source or name in _source_d['files']: source_files.append(os.path.join(root, name)) files = [] for source_file in source_files: gzip_file = '{}.gz'.format(source_file) filedict = { 'source_file_name': os.path.split(source_file)[1], 'gzip_file_name': os.path.split(gzip_file)[1], 'gzip_file': gzip_file} if (not one_file) or (source in os.path.split(source_file)[1]): # noqa files.append(filedict) with open(source_file, 'rb') as f_in: with gzip.open(gzip_file, 'wb') as f_out: shutil.copyfileobj(f_in, f_out) return files def log_in_to_zephir(zephir_settings) -> Session: """Log in to Deezer's Zephir. Returns: Session: Logged in client. """ _url_login = '{}/accounts/login/'.format(zephir_settings['host']) client = requests.session() client.get(_url_login) # get csrf token login_data = dict( username=zephir_settings['username'], password=zephir_settings['password'], csrfmiddlewaretoken=client.cookies['csrftoken'], next='/' ) login_response = client.post(_url_login, data=login_data) if FAILED_LOGIN in login_response.text: raise ValueError("Was not able to log in to Deezer's Zephir") login_response.raise_for_status() return client def search_for_file_on_zephir(client, zephir_settings, pattern): """Search for a file on Zephir by the provided pattern. Args: client (Session): A client logged in to Zephir. zephir_settings (dict): Settings for connecting to zephir service. pattern (str): A filename pattern to search by. Returns: list: Files matching the pattern. """ _url_directory = '{host}{search}'.format( host=zephir_settings['host'], search=zephir_settings['search']) response = client.get(_url_directory) files = set(x.group() for x in re.finditer( pattern, response.text)) return files def download_file_from_zephir(client, zephir_settings, file_name, local_dir): """Download a file from Zephir to a local file system. Args: client (Session): A client logged in to Zephir. zephir_settings (dict): Settings for connecting to Zephir service. file_name (str): A name of the file to be downloaded. local_dir (str): A local destination directory where the file will be stored. """ _url_file = '{host}{path}{file_name}'.format( host=zephir_settings['host'], path=zephir_settings['path'], file_name=file_name) local_file_path = os.path.join(local_dir, file_name) response = client.get(_url_file) try: response.raise_for_status() except requests.exceptions.HTTPError: FileNotFoundError('Report file was not found in Zephir service') with open(local_file_path, 'wb') as fp: fp.write(response.content) if os.path.getsize(local_file_path) == 0: local_file_path = 'empty_file' if local_file_path != 'empty_file' and not is_zipfile(local_file_path): raise FileNotFoundError('Zephir service have not returned a .zip file') return local_file_path def download_daily_report_from_zephir(zephir_settings, file_name, local_dir): """Download a daily file from Zephir.""" client = log_in_to_zephir(zephir_settings) local_file_path = download_file_from_zephir( client, zephir_settings, file_name, local_dir) return local_file_path def download_invoice_from_zephir(zephir_settings, filename_pattern, local_dir): """Download invoice files (including adj.) from Zephir.""" local_files = [] client = log_in_to_zephir(zephir_settings) files = search_for_file_on_zephir( client, zephir_settings, filename_pattern) if len(files): for file in files: local_file = download_file_from_zephir( client, zephir_settings, file, local_dir) if local_file != 'empty_file': local_files.append(local_file) if len(local_files): return local_files else: raise FileNotFoundError('Report file was found in Zephir, \ but no content available') else: raise FileNotFoundError('Report file was not found in Zephir service')