Powrót do strony głównej

Konwerter Telegram do Obsidian dla IT

Konwerter przenosi eksport JSON Telegram do Obsidian z zachowaniem mediów, formatowania i struktury czatów. Zaimplementowano indeksowanie plików, wielopoziomowe wyszukiwanie i przetwarzanie encji. Nadaje się do tworzenia bazy offline z tysięcy wiadomości.

Import czatów Telegram do Obsidian: kod i schemat
Advertisement 728x90

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.

Google AdInline article slot

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.

Google AdInline article slot
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).

Google AdInline article slot
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 `![plik](ścieżka)`.
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

Advertisement 728x90

Czytaj dalej