Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat (ED-77): google sheet into json #78

Draft
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ Gemfile.lock
assets/libs/
node_modules/
vendor
.idea
.idea
scripts/utils/credentials.json
scripts/utils/token.json
.env
50 changes: 50 additions & 0 deletions scripts/collections_sheet_to_json.py
Original file line number Diff line number Diff line change
@@ -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()
40 changes: 0 additions & 40 deletions scripts/modify_json.py

This file was deleted.

50 changes: 46 additions & 4 deletions scripts/resources/books.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand All @@ -17,14 +17,56 @@
"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.",
"importance": 10,
"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 <em>Diccionari Valencià Escolar Il·lustrat</em> 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 <em>Vocabulari Il·lustrat</em> 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 <em>Diccionari Valencià Escolar Il·lustrat (Valencià - Castellà | Castellà - Valencià)</em> 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"
}
]
13 changes: 13 additions & 0 deletions scripts/utils/credentials.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
}
51 changes: 51 additions & 0 deletions scripts/utils/credentials_sheet_handler.py
Original file line number Diff line number Diff line change
@@ -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()
34 changes: 34 additions & 0 deletions scripts/utils/google_libs_handler.py
Original file line number Diff line number Diff line change
@@ -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)