From 236781177445775b7cc9673f3cf6336526cf8b4d Mon Sep 17 00:00:00 2001 From: bensteUEM Date: Mon, 30 Jan 2023 18:29:45 +0100 Subject: [PATCH] SongBeamerQS #7 and #6 Download SNG if local file does not exist moved api out of read_baiersbronn_ct_songs to generalize and refactored to get_ct_songs_as_df and stubs for tests related to #13 #14 #15 --- TestMain.py | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++- main.py | 41 ++++++++++++++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/TestMain.py b/TestMain.py index cde0ea3..9d0d387 100644 --- a/TestMain.py +++ b/TestMain.py @@ -1,4 +1,5 @@ import logging +import os import unittest import pandas @@ -8,7 +9,7 @@ import SNG_DEFAULTS from main import check_ct_song_categories_exist_as_folder, parse_sng_from_directory, read_baiersbronn_songs_to_df, \ generate_songbook_column, get_ct_songs_as_df, validate_ct_songs_exist_locally_by_name_and_category, \ - clean_all_songs + clean_all_songs, download_missing_online_songs class TestSNG(unittest.TestCase): @@ -132,3 +133,60 @@ def test_emptied_song(self): 'FJ3', ['238 Der Herr segne dich.sng']) self.assertIn('Refrain', songs_temp[0].content.keys()) songs_temp = read_baiersbronn_songs_to_df() + + def test_add_id_to_local_song_if_available_in_ct(self): # TODO #13 + self.assertFalse(True, 'Not Implemented') + + def test_download_missing_online_songs(self): + """ + ELKW1610.krz.tools specific test case for the named function (using 2 specific song IDs) + deletes EG 002 if exists locally + Reads one local sng file (EG 001) + tries to detect that EG002 from CT is missing + downloads the file + checks if download success + deletes file + :return: + """ + + songs_temp = [] + dirname = 'testData/' + dirprefix = 'TEST' + + test2name = '002 Er ist die rechte Freudensonn.sng' + test2path = dirname + '/EG Lieder/' + test2name + + exists = os.path.exists(test2path) + if exists: + os.remove(test2path) + + songs = parse_sng_from_directory(dirname, dirprefix) + + for key, value in SNG_DEFAULTS.KnownFolderWithPrefix.items(): + dirname = './testData/' + key + if not os.path.exists(dirname): + continue + dirprefix = value + songs_temp.extend(parse_sng_from_directory(dirname, dirprefix)) + + df_sng_test = pd.DataFrame(songs_temp, columns=["SngFile"]) + for index, value in df_sng_test['SngFile'].items(): + df_sng_test.loc[(index, 'filename')] = value.filename + df_sng_test.loc[(index, 'path')] = value.path + + api = ChurchToolsApi('https://elkw1610.krz.tools') + ct_songs = [api.get_songs(song_id=762), api.get_songs(song_id=1113)] + df_ct_test = pd.json_normalize(ct_songs) + + result = download_missing_online_songs(df_sng_test, df_ct_test, api) + self.assertTrue(result) + + exists = os.path.exists(test2path) + self.assertTrue(exists) + os.remove(test2path) + + def test_upload_new_local_songs_and_generate_ct_id(self): # TODO #15 + self.assertFalse(True, 'Not Implemented') + + def test_upload_local_songs_by_id(self): + self.assertFalse(True, 'Not Implemented') # TODO #14 diff --git a/main.py b/main.py index 857ceee..dfa7c1c 100644 --- a/main.py +++ b/main.py @@ -326,6 +326,47 @@ def add_id_to_local_song_if_available_in_ct(df_sng, df_ct): overwrite_id_by_name_cat[~missing_files]['SngFile_x'].apply(lambda x: x.write_file()) +def download_missing_online_songs(df_sng, df_ct, ct_api_reference): + """ + Function which will check which songs are missing (by ID) and tries to download them to the respective folders + It is highly recommended to execute add_id_to_local_song_if_available_in_ct() and + upload_new_local_songs_and_generate_ct_id() before in order to try to match all songs local and avoid duplicates + :param df_sng: DataFrame with all local files + :param df_ct: DataFrame with all online files + :param ct_api_reference: direct access to ChurchTools API instance + :return: Success message + :rtype: bool + """ + + compare = validate_ct_songs_exist_locally_by_id(df_ct, df_sng) + song_path = compare[compare['path'].notnull()].iloc[0]['path'] + collection_path = "/".join(song_path.split('/')[:-1]) + + ids = compare[compare['SngFile'].apply(lambda x: not isinstance(x, SngFile))]['id'] + + is_successful = True + for id in ids: + song = ct_api_reference.get_songs(song_id=id) + logging.debug('Downloading CT song id={} "{}" ({})'.format(id, song['name'], song['category'])) + + default_arrangement_id = [item['id'] for item in song['arrangements'] if item['isDefault'] is True][0] + category_name = song['category']['name'] + file_path_in_collection = os.sep.join([collection_path, category_name]) # TODO #7 check if filename exists + filename = '{}.sng'.format(song['name']) + + result = ct_api_reference.file_download(filename=filename, + domain_type='song_arrangement', + domain_identifier=default_arrangement_id, + path_for_download=file_path_in_collection) + if result: + logging.debug('Downloaded {} into {} from CT IT {}'.format(filename, file_path_in_collection, id)) + else: + logging.debug('Failed to download {} into {} from CT IT {}'.format(filename, file_path_in_collection, id)) + is_successful |= result + + return is_successful + + def upload_new_local_songs_and_generate_ct_id(df_sng, df_ct, default_tag_id=52): """ Helper Function which creates new ChurchTools Songs for all SNG Files from dataframe which don't have a song ID