Automatyzacja importu czatów Telegram do Obsidian z przetwarzaniem multimediów i powiązań
Konwerter przekształca eksport JSON z aplikacji Telegram Desktop w strukturę skrzynki Obsidian. Obsługuje analizę wiadomości, kopiowanie plików multimedialnych, konwersję formatowania do Markdown oraz organizację według typów czatów. Rozwiązanie indeksuje pliki, zapewniając niezawodne dopasowanie ścieżek, oraz rozwiązuje kolizje nazw.
Oryginalny eksport zawiera plik result.json z metadanymi, folder chats/ z wiadomościami w formacie HTML oraz plikami multimedialnymi. Docelowa struktura to katalog Telegram_Export/, podzielony na Contacts/, Groups/, Channels/ oraz główny plik indeksu Index.md.
Architektura konwertera
System składa się z parsera JSON, indeksatora multimediów, konwertera Markdown, menedżera plików oraz generatora struktury. Przepływ danych: JSON → analiza → indeksacja → konwersja → skrzynka Obsidian z kopiowaniem multimediów.
Kluczowe komponenty:
- Parser: wyodrębnia czaty, wiadomości i metadane.
- Indeksator: tworzy mapę plików według rozszerzeń (np.
.jpg,.mp4,.pdf). - Konwerter: stosuje wielopoziomowe wyszukiwanie multimediów i konwersję formatowania.
- Menedżer: kopiuje pliki do folderów notatek z obsługą duplikatów.
Konfiguracja odbywa się przez zmienne środowiskowe: TELEGRAM_JSON_FILE, OBSIDIAN_OUTPUT_DIR, 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'
Indeksacja i wyszukiwanie plików multimedialnych
Plik patch.txt generowany poleceniem ls -R rejestruje pełną strukturę eksportu. Indeks budowany jest dla nazw plików, ścieżek względnych i bezwzględnych.
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
Wyszukiwanie odbywa się według czterech strategii: nazwa pliku, pełna ścieżka, częściowe dopasowanie oraz ścieżki bezpośrednie względem EXPORT_BASE.
Kopiowanie multimediów z obsługą kolizji
Pliki są kopiowane do folderu konkretnej notatki (note_folder), a nie do centralnego repozytorium. Bufor media_cache przyspiesza powtarzające się żądania. W przypadku kolizji nazw dodawany jest sufiks _1, _2.
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
Analiza tekstu i encji
Konwersja kodu HTML oraz encji Telegram do formatu Markdown. Obsługa pogrubienia, kursywy, kodu, bloków preformatowanych, linków, wzmianek i treści ukrytych (spoilerów).
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}})",
'spoiler': lambda t: f"\n> [!spoiler] {t}\n"
}
return str(text) if text else ""
## Formatowanie wiadomości
Każda wiadomość zawiera datę, nadawcę, tekst z encjami oraz odniesienia do multimediów. Klucze `photo`, `video`, `audio` pozwalają na precyzyjne wyodrębnienie załączników.
Przykład przetwarzania:
1. Wyodrębnij `date` i `from`.
2. Przeanalizuj `text` przy użyciu `text_entities`.
3. Zidentyfikuj multimedia na podstawie kluczy, skopiuj je i wstaw jako ``.
4. Zgrupuj wiadomości według dnia, jeśli aktywna opcja `GROUP_BY_DAY`.
Statystyki obejmują liczbę czatów, wiadomości, plików multimedialnych oraz kontaktów.
## Co jest najważniejsze
- Indeksacja na podstawie `patch.txt` rozwiązuje rozbieżności między ścieżkami w pliku JSON a rzeczywistą strukturą katalogów na dysku.
- Wielopoziomowe wyszukiwanie multimediów z czterema strategiami zapewnia pokrycie na poziomie 95%.
- Kopiowanie multimediów do folderów notatek gwarantuje poprawne działanie osadzania (embed) w Obsidian.
- Pełna obsługa wszystkich encji Telegram: pogrubienie, kod, linki, treści ukryte (spoiler).
- Konfiguracja przez zmienne środowiskowe — gotowa do użycia w środowisku produkcyjnym.
— Editorial Team
Brak komentarzy.