diff --git a/.gitignore b/.gitignore index 53af7d0b..8d0b0387 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,7 @@ Gemfile.lock assets/libs/ node_modules/ vendor -.idea \ No newline at end of file +.idea +scripts/utils/credentials.json +scripts/utils/token.json +.env \ No newline at end of file diff --git a/scripts/collections_sheet_to_json.py b/scripts/collections_sheet_to_json.py new file mode 100644 index 00000000..86f89abc --- /dev/null +++ b/scripts/collections_sheet_to_json.py @@ -0,0 +1,50 @@ +import os.path +import json +from dotenv import load_dotenv + +from utils.credentials_sheet_handler import update_credentials, get_absolute_path +from utils.google_libs_handler import get_credentials, fetch_sheet_data + +load_dotenv() +SCOPES = ["https://www.googleapis.com/auth/spreadsheets.readonly"] +DENES_SPREADSHEET_ID = os.environ.get('DENES_SPREADSHEET_ID') +FETCH_RANGE = "collections" +CLIENT_ID_DENES_SHEET = os.environ.get('CLIENT_ID_DENES_SHEET') +CLIENT_SECRET_DENES_SHEET = os.environ.get('CLIENT_SECRET_DENES_SHEET') +CREDENTIALS_FILENAME = "credentials.json" +TOKEN_FILENAME = "token.json" +OUTPUT_COLLECTIONS_FILE = "collections.json" + + +def transform_to_json(values): + if not values: + print("No data found.") + return [] + + header = values[0] + data = [] + # Transform rows into a list of dictionaries + for row in values[1:]: + row_data = {header[i]: row[i] if i < len(row) else "" for i in range(len(header))} + data.append(row_data) + return data + + +def write_to_file(data, filename): + with open(filename, "w", encoding='utf-8') as json_file: + json.dump(data, json_file, indent=4, ensure_ascii=False) + print(f"Data has been written to {filename}") + + +def main(): + credentials_path = get_absolute_path(CREDENTIALS_FILENAME) + update_credentials(CLIENT_ID_DENES_SHEET, CLIENT_SECRET_DENES_SHEET, credentials_path) + credentials = get_credentials(credentials_path, get_absolute_path(TOKEN_FILENAME), SCOPES) + + values = fetch_sheet_data(credentials, DENES_SPREADSHEET_ID, FETCH_RANGE) + data = transform_to_json(values) + write_to_file(data, OUTPUT_COLLECTIONS_FILE) + + +if __name__ == "__main__": + main() diff --git a/scripts/modify_json.py b/scripts/modify_json.py deleted file mode 100644 index 83ccbf5d..00000000 --- a/scripts/modify_json.py +++ /dev/null @@ -1,40 +0,0 @@ -import json -import os -import random -import string - - -def load_json(file_path): - with open(file_path, 'r', encoding='utf-8') as file: - return json.load(file) - - -def save_json(data, file_path): - with open(file_path, 'w', encoding='utf-8') as file: - json.dump(data, file, ensure_ascii=False, indent=4) - - -def generate_random_string(length=8): - letters = string.ascii_lowercase - return ''.join(random.choice(letters) for i in range(length)) - - -def add_filename_field(data): - for item in data: - item['filename'] = generate_random_string() - return data - - -def main(): - # Use raw string (r) to avoid issues with backslashes - input_file_path = r'C:\Users\dotae\PycharmProjects\CescFe.github.io\tests\resources\books\sample_books.json' - output_file_path = r'C:\Users\dotae\PycharmProjects\CescFe.github.io\tests\resources\books\sample_books.json' - - data = load_json(input_file_path) - modified_data = add_filename_field(data) - save_json(modified_data, output_file_path) - print(f"Modified JSON has been saved to {output_file_path}") - - -if __name__ == "__main__": - main() diff --git a/scripts/resources/books.json b/scripts/resources/books.json index 71731c82..0152461c 100644 --- a/scripts/resources/books.json +++ b/scripts/resources/books.json @@ -3,8 +3,8 @@ "layout": "book", "title": "Gènesi de l'AVL. El Debat", "author": "Manuel Sanchis-Guarner Cabanilles", - "isbn": "9788416473632", - "pvp": "12.00", + "isbn": "978-84-16473-63-2", + "pvp": "12.00€", "year": 2024, "description": "Gènesi de l'AVL. El debat.", "description_long": "Manuel Sanchis-Guarner Cabanilles, fill de l'il·lustre filòleg, narra de primera mà el procés de debat al sí del Consell Valencià de Cultura que donà origen al dictamen de creació de l'Acadèmia Valenciana de la Llengua.", @@ -17,8 +17,8 @@ "layout": "book", "title": "L'aportació de Ferrer Pastor a la lexicografia catalano-valenciana", "author": "Emili Casanova", - "isbn": "9788416473588", - "pvp": "39.99", + "isbn": "978-84-16473-58-8", + "pvp": "39.99€", "year": 2022, "description": "L'aportació de Ferrer Pastor a la lexicografia catalano-valenciana. Paraules del Diccionari General, 1985 absents del diccionari Fabra, 1986, 22ªED.", "description_long": "En el present assaig, Emili Casanova analitza les aportacions a la llengua de l'obra de Ferrer Pastor.", @@ -26,5 +26,47 @@ "category": "poesia", "img": "assets/img/collection_preview/collection_default.png", "filename": "aportacio-ferrer-pastor-a-la-lexicografia" + }, + { + "layout": "book", + "title": "Diccionari Valencià Escolar Il·lustrat (Senzill)", + "author": "Francesc Ferrer Pastor", + "isbn": "978-84-96545-35-9", + "pvp": "11.95€", + "year": 2024, + "description": "Diccionari Valencià Escolar Il·lustrat (Valencià - Castellà)", + "description_long": "El Diccionari Valencià Escolar Il·lustrat de Francesc Ferrer Pastor és una eina fonamental per a estudiants i docents. Aquest diccionari ofereix una doble funció: d'una banda, proporciona la traducció i definició clara i precisa de paraules en valencià; de l'altra, inclou il·lustracions que faciliten la comprensió visual dels termes. Aquest diccionari és ideal per a l'aprenentatge a les escoles. Francesc Ferrer Pastor, reconegut lexicògraf, va elaborar aquesta obra amb rigor i passió per la llengua, fent-la accessible i atractiva per als joves lectors.", + "importance": 3, + "category": "diccionari", + "img": "assets/img/book_covers/dicc_senzill.png", + "filename": "diccionari-escolar-illustrat" + }, + { + "layout": "book", + "title": "Vocabulari Il·lustrat", + "author": "Francesc Ferrer Pastor", + "isbn": "978-84-96545-33-5", + "pvp": "14.96€", + "year": 2024, + "description": "Vocabulari Il·lustrat (Castellà - Valencià | Valencià - Castellà)", + "description_long": "El Vocabulari Il·lustrat de Francesc Ferrer Pastor és una eina fonamental per a estudiants i docents. Aquest vocabulari ofereix una doble funció: d'una banda, proporciona la traducció i definició clara i precisa de paraules tant en valencià com en castellà; de l'altra, inclou il·lustracions que faciliten la comprensió visual dels termes. Aquest vocabulari és ideal per a l'aprenentatge a les escoles. Francesc Ferrer Pastor, reconegut lexicògraf, va elaborar aquesta obra amb rigor i passió per la llengua, fent-la accessible i atractiva per als joves lectors.", + "importance": 1, + "category": "diccionari", + "img": "assets/img/book_covers/vocabulari.png", + "filename": "vocabulari-illustrat" + }, + { + "layout": "book", + "title": "Diccionari Valencià Escolar Il·lustrat (Doble)", + "author": "Francesc Ferrer Pastor", + "isbn": "978-84-96545-34-2", + "pvp": "15.85€", + "year": 2024, + "description": "Diccionari Valencià Escolar Il·lustrat (Valencià - Castellà | Castellà - Valencià)", + "description_long": "El Diccionari Valencià Escolar Il·lustrat (Valencià - Castellà | Castellà - Valencià) de Francesc Ferrer Pastor és una eina fonamental per a estudiants i docents. Aquest diccionari ofereix una doble funció: d'una banda, proporciona la traducció i definició clara i precisa de paraules tant en valencià com en castellà; de l'altra, inclou il·lustracions que faciliten la comprensió visual dels termes. Aquest diccionari és ideal per a l'aprenentatge a les escoles. Francesc Ferrer Pastor, reconegut lexicògraf, va elaborar aquesta obra amb rigor i passió per la llengua, fent-la accessible i atractiva per als joves lectors.", + "importance": 2, + "category": "diccionari", + "img": "assets/img/book_covers/dicc_doble.png", + "filename": "diccionari-escolar-doble-illustrat" } ] diff --git a/scripts/utils/credentials.json b/scripts/utils/credentials.json new file mode 100644 index 00000000..9dc2ab8c --- /dev/null +++ b/scripts/utils/credentials.json @@ -0,0 +1,13 @@ +{ + "installed": { + "client_id": "", + "project_id": "denessheetsproject", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_secret": "", + "redirect_uris": [ + "http://localhost" + ] + } +} \ No newline at end of file diff --git a/scripts/utils/credentials_sheet_handler.py b/scripts/utils/credentials_sheet_handler.py new file mode 100644 index 00000000..cba0d870 --- /dev/null +++ b/scripts/utils/credentials_sheet_handler.py @@ -0,0 +1,51 @@ +import os +import json +from dotenv import load_dotenv + + +def check_environment_variables(client_id_denes_sheet, client_secret_denes_sheet): + if not client_id_denes_sheet or not client_secret_denes_sheet: + raise ValueError(f"Missing {client_id_denes_sheet} or {client_secret_denes_sheet} environment variables") + + +def get_absolute_path(credentials_relative_path): + script_dir = os.path.dirname(os.path.abspath(__file__)) + credentials_absolute_path = os.path.join(script_dir, credentials_relative_path) + return credentials_absolute_path + + +def load_credentials(credentials_absolute_path): + with open(credentials_absolute_path, 'r', encoding='utf-8') as json_file: + credentials_json_data = json.load(json_file) + return credentials_json_data + + +def update_credentials_data(credentials_json_data, client_id_denes_sheet, client_secret_denes_sheet): + credentials_json_data['installed']['client_id'] = client_id_denes_sheet + credentials_json_data['installed']['client_secret'] = client_secret_denes_sheet + + +def save_credentials(credentials_json_data, credentials_path): + with open(credentials_path, 'w', encoding='utf-8') as json_file: + json.dump(credentials_json_data, json_file, indent=4, ensure_ascii=False) + print(f"Updated {credentials_path} with environment variables") + + +def update_credentials(client_id_denes_sheet, client_secret_denes_sheet, credentials_path): + check_environment_variables(client_id_denes_sheet, client_secret_denes_sheet) + credentials = load_credentials(credentials_path) + update_credentials_data(credentials, client_id_denes_sheet, client_secret_denes_sheet) + save_credentials(credentials, credentials_path) + + +def main(): + load_dotenv() + credentials_relative_path = "credentials.json" + client_id_denes_sheet = os.getenv('CLIENT_ID_DENES_SHEET') + client_secret_denes_sheet = os.getenv('CLIENT_SECRET_DENES_SHEET') + credentials_path = get_absolute_path(credentials_relative_path) + update_credentials(client_id_denes_sheet, client_secret_denes_sheet, credentials_path) + + +if __name__ == "__main__": + main() diff --git a/scripts/utils/google_libs_handler.py b/scripts/utils/google_libs_handler.py new file mode 100644 index 00000000..5ff3b2f0 --- /dev/null +++ b/scripts/utils/google_libs_handler.py @@ -0,0 +1,34 @@ +import os + +from google.auth.transport.requests import Request +from google.oauth2.credentials import Credentials +from google_auth_oauthlib.flow import InstalledAppFlow +from googleapiclient.discovery import build +from googleapiclient.errors import HttpError + +from .credentials_sheet_handler import get_absolute_path + + +def get_credentials(credentials_path, token_filename, scopes): + credentials = None + if os.path.exists(get_absolute_path(token_filename)): + credentials = Credentials.from_authorized_user_file(get_absolute_path(token_filename), scopes) + if not credentials or not credentials.valid: + if credentials and credentials.expired and credentials.refresh_token: + credentials.refresh(Request()) + else: + flow = InstalledAppFlow.from_client_secrets_file(credentials_path, scopes) + credentials = flow.run_local_server(port=0) + with open(get_absolute_path(token_filename), "w") as token: + token.write(credentials.to_json()) + return credentials + + +def fetch_sheet_data(credentials, spreadsheet_id, fetch_range): + try: + service = build("sheets", "v4", credentials=credentials) + sheets = service.spreadsheets() + result = sheets.values().get(spreadsheetId=spreadsheet_id, range=fetch_range).execute() + return result.get("values", []) + except HttpError as error: + print(error)