orgmode-to-gemini-blog/utils.py

294 lines
10 KiB
Python
Raw Permalink Normal View History

2024-11-14 13:32:56 +01:00
#!/bin/python3
2024-11-15 15:56:11 +01:00
import os
2024-11-14 13:32:56 +01:00
import re
2024-11-15 15:56:11 +01:00
import shutil
from datetime import datetime
2024-11-15 23:55:20 +01:00
import unicodedata
2024-11-15 15:56:11 +01:00
from website_config import *
2024-11-14 13:32:56 +01:00
# this path should be customized
org_roam_dir: str = '/home/tykayn/Nextcloud/textes/orgmode/org-roam/'
2024-11-15 15:56:11 +01:00
# Trouver l'identifiant OrgROAM
2024-11-14 13:32:56 +01:00
pattern_roam_id_search = r':ID:(?:\s+)?([a-zA-Z0-9-]+)'
2024-11-15 15:56:11 +01:00
# Expression régulière pour extraire la date et le slug du nom de fichier org
2024-11-19 13:49:39 +01:00
regex = r"^([a-zA-Z0-9_-]+)\_\_(-[a-zA-Z0-9_-]+)\.org$"
2024-11-15 15:56:11 +01:00
# Recherche de date de création du fichier org-roam dans un article gemini
2024-11-19 13:49:39 +01:00
regex_orgroam = regex
2024-11-15 15:56:11 +01:00
# show_logs=True
show_logs = global_config["show_logs"]
def mylog(*content):
"""Fonction qui imprime tous les arguments passés selon le niveau de debug souhaité."""
if show_logs:
2024-11-19 13:49:39 +01:00
for c in content:
print(' ',c)
2024-11-15 15:56:11 +01:00
def trouver_nom_article(fichier_org, blog_name, format="html"):
mylog('fichier_org, ', fichier_org)
with open(fichier_org, 'r') as file:
lignes = file.readlines()
nom_article = ''
mylog('trouver_nom_article format', format)
# Expressions régulières pour trouver les titres de niveau 1 et 2
if format == 'html':
titre_niveau_1 = r'<h1\s+(?:id|data-created)="[^"]*">(.*?)</h1>'
titre_niveau_2 = r'^\<h2.*?\>(.+)\<\/h2\>$'
else:
titre_niveau_1 = r'^\*+ (.+)$'
titre_niveau_2 = r'^\*\*+ (.+)$'
# Itérer sur les lignes du fichier
for ligne in lignes:
# Rechercher un titre de niveau 1
titre_niveau_1_match = re.match(titre_niveau_1, ligne)
if titre_niveau_1_match:
titre_niveau_1_texte = titre_niveau_1_match.group(1)
if titre_niveau_1_texte.lower() != "article" and titre_niveau_1_texte.lower() != "liens":
nom_article = titre_niveau_1_texte
break
else:
# Si le premier titre de niveau 1 est "Article", rechercher le premier titre de niveau 2
titre_niveau_2_match = re.match(titre_niveau_2, ligne)
if titre_niveau_2_match:
nom_article = titre_niveau_2_match.group(1)
break
mylog(f"Nom de l'article : {nom_article}")
return nom_article.replace(blog_name + '_', '').replace('_', ' ')
2024-11-19 13:49:39 +01:00
def find_year_and_slug_on_filename(fichier):
2024-11-15 15:56:11 +01:00
fichier = fichier.replace('..', '.')
2024-11-19 13:49:39 +01:00
# mylog(f" ------------ find_year_and_slug in {fichier} -------------")
slug = ''
2024-11-15 15:56:11 +01:00
annee = '2024'
date_str = '2024-00-00'
date = '2024-00-00'
2024-11-19 13:49:39 +01:00
boom = fichier.split('__')
# print(boom)
2024-11-15 15:56:11 +01:00
2024-11-19 13:49:39 +01:00
if boom :
date_str = boom[0]
2024-11-15 15:56:11 +01:00
annee = date_str[:4]
2024-11-19 13:49:39 +01:00
slug = boom[1].replace('.org', '')
# date = datetime.strptime(date_str, "%Y%m%dT%H%M%S")
2024-11-15 15:56:11 +01:00
# Convertir la date en objet datetime
if "-" in date_str:
2024-11-19 13:49:39 +01:00
slug = enlever_premier_tiret_ou_underscore(slug)
# mylog(f" find_year_and_slug : Fichier: {fichier}")
# mylog(f" find_year_and_slug : année: {annee}")
# mylog(f" find_year_and_slug : str(date): {str(date)}")
# mylog(f" find_year_and_slug : slug: {slug}")
mylog(f" find_year_and_slug : chemin: {annee}/{slug}/")
return [date_str, annee, slug]
return [date_str, annee, fichier.replace(' ', '-').replace('.org', '')]
2024-11-15 15:56:11 +01:00
def enlever_premier_tiret_ou_underscore(chaîne):
if chaîne.startswith('-') or chaîne.startswith('_'):
chaîne = chaîne[1:]
return chaîne
# création des dossiers intermédiaires s'il y en a
# déplace le fichier dans le dossier spécifié
def create_path_folders_and_move_file(path, file):
os.makedirs(os.path.dirname(path), exist_ok=True)
shutil.move(file, path)
def get_files_list_of_folder(folder_path):
# Vérifie si le dossier existe
if not os.path.exists(folder_path):
print(f" ------------ build_indexes: Erreur : Le dossier '{folder_path}' n'existe pas.")
return
mylog('----------- get_files_list_of_folder: folder_path : ', folder_path)
# Liste les fichiers articles, trie par nom décroissant
try:
fichiers_md = sorted(
2024-11-15 16:24:31 +01:00
[f.replace('.' + global_config['source_files_extension'], '.gmi') for f in os.listdir(folder_path) if
f.endswith(global_config['source_files_extension'])], reverse=True)
2024-11-15 15:56:11 +01:00
print('fichiers trouvés:', len(fichiers_md))
return fichiers_md
except OSError as e:
print(f" ------------ build_indexes: Erreur lors de la lecture du dossier : {e}")
return
2024-11-14 13:32:56 +01:00
2024-11-14 16:22:34 +01:00
2024-11-14 13:32:56 +01:00
def get_id_of_roam_note_content(content):
match = re.search(pattern_roam_id_search, content)
if match:
return match.group(1)
return None
2024-11-14 16:22:34 +01:00
2024-11-14 13:32:56 +01:00
def find_first_level1_title(content):
pattern = r'^\* (.+)$'
match = re.search(pattern, content, re.MULTILINE)
if match:
if match.group(1) != 'Article':
return match.group(1)
else:
pattern = r'^\*\* (.+)$'
match = re.search(pattern, content, re.MULTILINE)
if match:
return match.group(1)
return None
2024-11-18 11:18:50 +01:00
def find_extract_in_content_org(org_content):
# Supprimer les lignes qui commencent par #+
org_content = re.sub(r'^\s*#\+.*\n', '', org_content, flags=re.MULTILINE)
# Supprimer les sections de logbook
org_content = re.sub(r'^\*\* Logbook\n.*?(?=\*\* |\Z)', '', org_content, flags=re.DOTALL | re.MULTILINE)
# Supprimer les propriétés
org_content = re.sub(r'^:PROPERTIES:\n.*?:END:\n', '', org_content, flags=re.DOTALL | re.MULTILINE)
# Supprimer les lignes vides supplémentaires
org_content = re.sub(r'\n\s*\n+', '\n', org_content)
# Supprimer les espaces en début et fin de chaque ligne
org_content = '\n'.join(line.strip() for line in org_content.splitlines())
# Supprimer les espaces en début et fin du contenu final
return org_content.strip()
2024-11-14 16:22:34 +01:00
def extract_body_content(html_content):
2024-11-15 15:56:11 +01:00
pattern = r'<body.*?>(.*?)</body>'
2024-11-14 16:22:34 +01:00
match = re.search(pattern, html_content, re.DOTALL)
if match:
return match.group(1)
else:
2024-11-15 01:45:11 +01:00
print('---- extract_body_content : no body found in this html')
return html_content
2024-11-14 16:22:34 +01:00
2024-11-20 00:24:09 +01:00
def add_tags_from_content(tags=None, file_content="", words_to_check=None):
"""
Ajoute des tags à l'ensemble `tags` si les mots correspondants sont trouvés dans le contenu du fichier.
:param tags: Ensemble de tags (set). Si None, un nouvel ensemble est créé (type set, optionnel).
:param file_content: Contenu du fichier (str).
:param words_to_check: Liste de mots à repérer (list). Si None, une liste vide est utilisée (type list, optionnel).
:return: Ensemble de tags mis à jour (set).
"""
# Initialiser l'ensemble tags s'il est None
if tags is None:
tags = set()
# Initialiser la liste words_to_check s'il est None
if words_to_check is None:
words_to_check = []
# Convertir le contenu du fichier en minuscules pour une recherche insensible à la casse
file_content_lower = file_content.lower()
# Parcourir chaque mot à vérifier
for word in words_to_check:
# Vérifier si le mot est présent dans le contenu du fichier
if word.lower() in file_content_lower:
# Ajouter le tag correspondant à l'ensemble de tags
tags.add(word)
return tags
def extract_tags_from_file(file_path, excluded_tags):
tags = set()
with open(file_path, 'r', encoding='utf-8') as file_content:
tag_found = False
for line in file_content:
if global_config['automatic_tagging_enabled']:
tags = add_tags_from_content(tags, line, global_config['auto_tag_terms'])
# Check for orgmode tags :tag1:tag2:
if ':' in line:
for word in line.split():
if len(word) and word.startswith(':') and word.endswith(':'):
tag = word[1:-1]
if tag not in excluded_tags:
tags.add(tag)
tag_found = True
# Check for #+tags: tag1,tag2
if line.startswith('#+tags:'):
for tag in line[len('#+tags:'):].split(','):
tag = tag.strip()
if tag and tag not in excluded_tags:
tags.add(tag)
tag_found = True
if not tag_found:
print('no tag in the article', file_path)
return tags
2024-11-14 16:22:34 +01:00
def remove_properties_section(text):
pattern = r"<h1 id=\"article\">Article</h1>.+?</ul>"
replacement = ""
return re.sub(pattern, replacement, text, flags=re.DOTALL)
def remove_article_head_properties_orgmode(text):
pattern = r":PROPERTIES:.+?:END:"
replacement = ""
return re.sub(pattern, replacement, text, flags=re.DOTALL)
def remove_hint_html(text):
pattern = r"<p>ceci<sub>estduhtml</sub></p>"
replacement = ""
return re.sub(pattern, replacement, text, flags=re.DOTALL)
2024-11-15 16:24:31 +01:00
2024-11-15 23:55:20 +01:00
def slugify_title(title_text):
"""
Transforme un titre en un slug valide.
:param title_text: Titre en texte (str).
:return: Slug en minuscules avec des tirets (str).
"""
title_text = unicodedata.normalize('NFKD', title_text).encode('ascii', 'ignore').decode('ascii')
title_text = title_text.lower()
title_text = re.sub(r'[^a-z0-9\s-]', '', title_text)
title_text = re.sub(r'\s+', '-', title_text)
title_text = re.sub(r'-+', '-', title_text)
title_text = title_text.strip('-')
return title_text
2024-11-18 11:18:50 +01:00
def find_slug_in_file_basename(file_basename) -> str:
2024-11-15 16:24:31 +01:00
"""
Extrait l'année et le slug du nom de fichier selon le format spécifié.
:param file_basename: Nom de fichier (str).
:return: Tuple contenant l'année et le slug (année, slug) ou None si non trouvé.
"""
2024-11-19 23:50:42 +01:00
pattern = regex_orgroam
2024-11-15 16:24:31 +01:00
match = re.match(pattern, file_basename)
if match:
year = match.group(1)
slug = match.group(2)
2024-11-15 23:55:20 +01:00
# prendre la partie finale du nom du fichier
splitted = slug.split('_')
# print('len(splitted)', len(splitted), splitted)
if len(splitted) > 1:
slug = splitted[len(splitted)-1]
# final_slug=slug.replace("_cipherbliss_blog_","")
# final_slug=final_slug.replace("_blog_cil_gometz_","")
slug=enlever_premier_tiret_ou_underscore(slug)
2024-11-15 16:24:31 +01:00
2024-11-15 23:55:20 +01:00
slug = f"{year}/{slug}"
return slug
2024-11-15 16:24:31 +01:00
return None
2024-11-15 23:55:20 +01:00