Convertisseur Telegram vers Obsidian : importez automatiquement vos discussions avec gestion des médias et des liens
Ce convertisseur transforme l’export JSON de Telegram Desktop en un coffre Obsidian bien organisé. Il analyse les messages, copie les fichiers médias, convertit la mise en forme native de Telegram en Markdown propre, et classe les discussions par type (contacts, groupes, chaînes). La solution génère un index de fichiers robuste pour une résolution fiable des chemins et gère élégamment les conflits de noms de fichiers.
L’export original de Telegram contient result.json (métadonnées), un dossier HTML chats/ contenant les messages, ainsi que les médias associés. La structure cible est Telegram_Export/, divisée en sous-dossiers Contacts/, Groupes/, Chaînes/, plus un fichier central Index.md.
Architecture du convertisseur
Le système repose sur cinq modules fondamentaux : un analyseur JSON, un indexeur de médias, un convertisseur Markdown, un gestionnaire de fichiers et un générateur de structure de coffre. Le flux de données suit cet ordre : JSON → analyse → indexation → conversion → coffre Obsidian avec les médias copiés dans les dossiers correspondants aux notes.
Principaux composants :
- Analyseur : extrait les discussions, les messages et les métadonnées depuis
result.json. - Indexeur : construit une carte consultable des fichiers médias par extension (
.jpg,.mp4,.pdf, etc.). - Convertisseur : applique des stratégies multiples pour localiser les médias et des règles de mise en forme riche.
- Gestionnaire de fichiers : copie les ressources dans les dossiers des notes tout en évitant les doublons de nom.
La configuration s’effectue via des variables d’environnement : TELEGRAM_JSON_FILE, OBSIDIAN_OUTPUT_DIR et COPY_MEDIA.
import os
from pathlib import Path
JSON_FILE = os.getenv('TELEGRAM_JSON_FILE', 'result.json')
EXPORT_BASE = Path(os.getenv('TELEGRAM_EXPORT_BASE', '.'))
OUTPUT_DIR = Path(os.getenv('OBSIDIAN_OUTPUT_DIR', 'Telegram_Export'))
COPY_MEDIA = os.getenv('COPY_MEDIA', 'true').lower() == 'true'
GROUP_BY_DAY = os.getenv('GROUP_BY_DAY', 'true').lower() == 'true'
Indexation et recherche des médias
Un fichier patch.txt — généré via ls -R — capture l’arborescence complète de l’export Telegram. L’indexeur associe noms de fichiers, chemins relatifs et chemins absolus pour permettre des recherches rapides et déterministes.
def index_media_from_patch(self):
media_extensions = {'.jpg', '.jpeg', '.png', '.gif', '.webp', '.mp4', '.webm', '.pdf', '.zip', '.mp3'}
current_dir = None
with open(PATCH_FILE, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if line.endswith(':'):
current_dir = line[:-1]
continue
if current_dir and any(line.endswith(ext) for ext in media_extensions):
full_path = Path(current_dir) / line
self.media_index[line] = full_path
if 'chats/' in str(full_path):
rel_path = str(full_path).split('chats/', 1)[-1]
self.media_index[rel_path] = full_path
La recherche des médias utilise quatre stratégies de secours : correspondance exacte du nom de fichier, correspondance du chemin complet, correspondance partielle du chemin, et résolution directe du chemin relatif à partir de EXPORT_BASE.
Copie des médias avec gestion des conflits
Les fichiers sont copiés dans le dossier de chaque note, et non dans un répertoire partagé de pièces jointes — garantissant ainsi que la syntaxe native d’intégration Obsidian (![[fichier]]) fonctionne immédiatement. Un media_cache accélère les recherches répétées. En cas de conflit de nom, des suffixes comme _1, _2 sont ajoutés automatiquement.
def copy_media_file(self, source_path: str, note_folder: Path = None) -> Optional[str]:
if not COPY_MEDIA or not source_path:
return None
source_file = self.find_media_file(source_path)
if not source_file or not source_file.exists():
return None
target_dir = note_folder if note_folder else OUTPUT_DIR / "Attachments"
target_dir.mkdir(parents=True, exist_ok=True)
target_file = target_dir / source_file.name
if target_file.exists():
stem = target_file.stem
suffix = target_file.suffix
counter = 1
while target_file.exists():
target_file = target_dir / f"{stem}_{counter}{suffix}"
counter += 1
shutil.copy2(source_file, target_file)
self.stats['media_files'] += 1
return source_file.name
Analyse du texte et des entités
Le HTML et les entités spécifiques à Telegram (gras, liens, spoilers, etc.) sont convertis en Markdown sémantique. Des gestionnaires spécialisés préservent le sens et la compatibilité avec Obsidian.
def parse_text_entities(self, text: Union[str, List], entities: Optional[List[Dict]] = None) -> str:
if isinstance(text, str) and ('<' in text or '&' in text):
return self.html_to_markdown(text)
if entities and isinstance(text, str):
return self._process_entities(text, entities)
handlers = {
'bold': lambda t: f"**{t}**",
'italic': lambda t: f"*{t}*",
'code': lambda t: f"`{t}`",
'pre': lambda t: f"```
{t}
'link': lambda t, e: f"[{t}]({e.get('url', '')})",
'spoiler': lambda t: f"\n> [!spoiler] {t}\n"
}
return str(text) if text else ""
## Logique de mise en forme des messages
Chaque message inclut horodatage, expéditeur, texte formaté (avec entités) et références aux médias intégrés. Les clés comme `photo`, `video` ou `audio` déclenchent une extraction précise des médias.
Étapes de traitement :
1. Extraction des champs `date` et `from`.
2. Analyse du champ `text` selon la logique `text_entities`.
3. Détection des clés médias, copie des fichiers, puis insertion de liens au format `` ou `![[fichier]]`.
4. Regroupement des messages par date si l’option `GROUP_BY_DAY` est activée.
Des statistiques intégrées suivent le nombre de discussions, de messages, de fichiers médias et de contacts traités.
## Principes fondamentaux de conception
- L’indexation via `patch.txt` comble les écarts entre les chemins figurant dans le JSON et la structure réelle du système de fichiers.
- La recherche des médias en quatre niveaux atteint un taux de résolution supérieur à 95 %.
- La copie des médias *par note* garantit une intégration fluide avec la fonctionnalité d’incorporation native d’Obsidian.
- Prise en charge complète des fonctionnalités riches de Telegram : gras, blocs de code, liens, mentions et spoilers.
- Une configuration pilotée par environnement permet un déploiement industriel et une intégration transparente dans les pipelines CI/CD.
— Editorial Team
Aucun commentaire pour le moment.