Files
dedinit.ru/docs/Telegram_frontend.md
estorozhenko d426aa39ed chore(docs): уборка структуры — вся документация в docs/, краткий README, добавлен AGENTS.md
- AGENTS.md: правила проекта (структура доков, стек, статьи, деплой, git, openspec, проверки)
- README.md: сокращён до введения + указателей на docs/
- docs/: DEPLOY_INSTRUCTIONS, ROADMAP, PAPERMOD_PARAMS, QWEN, gitea-setup,
  Telegram_frontend, ssh_setup, archive/PROJECT_SUMMARY (из .qwen/)
- tools/: winscp_script.txt переехал из корня к deploy_sftp.py
- Makefile и deploy_sftp.py: ссылки на docs/DEPLOY_INSTRUCTIONS.md
2026-09-12 09:58:09 +00:00

16 KiB
Raw Permalink Blame History

Запрос:

Давай посмотрим как сделать красивое представление постов из Телеграма в моём блоге с темой pappermode для hugo. Для телеграма есть вот такой виджет для встаивания поста в любой сойт. Мне очень нравится как это выглядит. https://core.telegram.org/widgets/post. Ты сможешь каким-то образом скопировать оформление и что тебе для этого от меня нужно?

Ответ:

Отличная идея! Виджет Telegram выглядит действительно красиво и минималистично. Давайте разберем варианты интеграции с Hugo PaperMod.

Что мне нужно от вас:

  1. Ссылка на ваш Telegram-канал (публичный)
  2. Предпочтительный способ интеграции (выберите один):
    • Простое встраивание через iframe (официальный виджет)
    • Кастомный shortcode с похожим дизайном
    • Автоматический импорт постов как контента Hugo

Варианты решения:

Вариант 1: Официальный виджет Telegram (самый простой)

Можно создавать shortcode для Hugo, который встраивает посты:

<!-- layouts/shortcodes/telegram-post.html -->
<div class="telegram-embed-wrapper">
  <blockquote class="telegram-post">
    <a href="{{ .Get 0 }}">Смотреть пост в Telegram</a>
  </blockquote>
  <script async src="https://telegram.org/js/telegram-widget.js" 
          data-telegram-post="{{ .Get 0 }}"
          data-width="100%"
          data-userpic="{{ default "true" (.Get 1) }}"
          data-color="{{ default "#2481cc" (.Get 2) }}"
          data-dark="{{ default "false" (.Get 3) }}"></script>
</div>

Использование:

{{< telegram-post "https://t.me/yourchannel/123" >}}

Вариант 2: Кастомный стиль (полный контроль)

Я могу помочь создать собственный CSS-дизайн, имитирующий стиль Telegram с:

  • Адаптивной версткой
  • Поддержкой темной/светлой темы PaperMod
  • Кастомными цветами
  • Оптимизацией под мобильные устройства

Вариант 3: Автоматический импорт (самый мощный)

Создать скрипт, который:

  • Скачивает посты из канала
  • Конвертирует их в Markdown для Hugo
  • Сохраняет медиафайлы
  • Создает фронтматтер с датами и тегами

Какой вариант вас больше интересует? Или, может быть, комбинация нескольких подходов?

Также покажите, пожалуйста, ваш текущий сайт (если уже есть), чтобы я мог предложить стили, которые будут гармонично сочетаться с PaperMod.

Отлично! Раз у вас уже есть структура с папками по ID постов, давайте определим полную структуру layouts для типа контента "telegram-posts".

Необходимые layouts:

layouts/
├── telegram/                    # или telegram-posts
│   ├── list.html               # Страница списка всех постов
│   ├── single.html             # Страница отдельного поста
│   ├── baseof.html            # Базовый шаблон (опционально)
│   └── summary.html           # Карточка поста для списка (важно!)
├── partials/
│   ├── telegram-card.html     # Компонент карточки поста
│   └── telegram-header.html   # Шапка с аватаром и именем канала
└── shortcodes/
    └── telegram-embed.html    # Шорткод для встраивания

Ключевой момент: summary.html - это то, что будет отображаться в списках (на главной, в разделах).

Что нужно от вас:

  1. Как называется ваш content type? (telegram, posts, tg-posts?)
  2. Покажите структуру папок с одним постом:
    content/
    └── telegram/
        └── 123/
            ├── index.md
            ├── photo1.jpg
            └── video.mp4
    
  3. Какие поля во фронтматтере index.md? (date, title, text, media и т.д.)

Как только покажете структуру - создам:

  • ✅ Карточки в стиле Telegram (копирование дизайна виджета)
  • ✅ Список постов с пагинацией
  • ✅ Отдельные страницы постов
  • ✅ Адаптацию под PaperMod (темная/светлая тема)
  • ✅ CSS стили с анимациями

Покажите пример вашего index.md и я начну создавать шаблоны! 🚀

Отлично! Теперь давайте создадим полную интеграцию.

План действий:

1. Сначала создайте структуру в Hugo:

cd ваш-hugo-сайт
mkdir -p content/telegram
mkdir -p layouts/telegram
mkdir -p layouts/partials
mkdir -p assets/css

2. Напишите скрипт синхронизации (Python):

Создайте scripts/sync_telegram.py:

#!/usr/bin/env python3
import shutil
import yaml
from pathlib import Path

ARCHIVES_DIR = Path("../telegram-archiver/archives/dedinit")
CONTENT_DIR = Path("content/telegram")

def sync_telegram_posts():
    CONTENT_DIR.mkdir(parents=True, exist_ok=True)
    
    for post_folder in ARCHIVES_DIR.iterdir():
        if not post_folder.is_dir():
            continue
            
        post_id = post_folder.name
        dest_folder = CONTENT_DIR / post_id
        dest_folder.mkdir(parents=True, exist_ok=True)
        
        # Копируем index.md
        src_md = post_folder / "index.md"
        if src_md.exists():
            # Читаем и добавляем type
            content = src_md.read_text(encoding='utf-8')
            if 'type: telegram' not in content:
                content = content.rstrip() + "\ntype: telegram\n"
                src_md.write_text(content, encoding='utf-8')
            shutil.copy2(src_md, dest_folder / "index.md")
        
        # Копируем медиафайлы
        for media_file in post_folder.glob("*"):
            if media_file.name != "index.md":
                shutil.copy2(media_file, dest_folder / media_file.name)
        
        print(f"Synced post {post_id}")

if __name__ == "__main__":
    sync_telegram_posts()

3. Создайте базовый шаблон layouts/telegram/single.html:

{{ define "main" }}
<article class="telegram-post-container">
  <div class="telegram-post">
    <!-- Header -->
    <div class="telegram-post-header">
      <div class="telegram-post-avatar">
        <img src="{{ .Site.Params.telegram.avatar | default "images/telegram-avatar.jpg" }}" alt="{{ .Site.Params.telegram.channelName | default "Telegram Channel" }}">
      </div>
      <div class="telegram-post-info">
        <div class="telegram-post-channel">{{ .Site.Params.telegram.channelName | default "Channel" }}</div>
        <div class="telegram-post-date">{{ .Date.Format "Jan 2, 2006 at 15:04" }}</div>
      </div>
    </div>

    <!-- Content -->
    <div class="telegram-post-content">
      {{ .Content }}
    </div>

    <!-- Media Files -->
    {{ if .Params.media_files }}
    <div class="telegram-post-media">
      {{ range .Params.media_files }}
        {{ if eq .type "photo" }}
        <div class="telegram-photo">
          <img src="{{ $.RelPermalink }}{{ .filename }}" alt="{{ .caption | default "Photo" }}" loading="lazy">
          {{ if .caption }}
          <div class="telegram-photo-caption">{{ .caption }}</div>
          {{ end }}
        </div>
        {{ else if eq .type "video" }}
        <div class="telegram-video">
          <video controls poster="{{ $.RelPermalink }}{{ .filename | replaceRE "\\.mp4$" ".jpg" }}">
            <source src="{{ $.RelPermalink }}{{ .filename }}" type="video/mp4">
          </video>
        </div>
        {{ end }}
      {{ end }}
    </div>
    {{ end }}

    <!-- Footer -->
    <div class="telegram-post-footer">
      <span class="telegram-views">{{ .Params.views | default "—" }} views</span>
      <a href="{{ .Site.Params.telegram.channelUrl }}/{{ .Params.message_id }}" target="_blank" class="telegram-link">
        Open in Telegram →
      </a>
    </div>
  </div>

  {{ template "_internal/disqus.html" . }}
</article>
{{ end }}

4. Создайте шаблон списка layouts/telegram/list.html:

{{ define "main" }}
<div class="telegram-list-container">
  <header class="telegram-list-header">
    <h1 class="telegram-list-title">{{ .Title }}</h1>
    {{ if .Site.Params.telegram.channelName }}
    <p class="telegram-list-description">Archive of {{ .Site.Params.telegram.channelName }}</p>
    {{ end }}
  </header>

  <div class="telegram-posts-grid">
    {{ range .Pages }}
    <article class="telegram-post-card">
      <a href="{{ .Permalink }}" class="telegram-post-card-link">
        <div class="telegram-post-card-header">
          <div class="telegram-post-card-date">{{ .Date.Format "Jan 2, 2006" }}</div>
        </div>
        
        <div class="telegram-post-card-content">
          {{ .Summary | truncate 200 }}
        </div>

        {{ if .Params.media_files }}
        <div class="telegram-post-card-media">
          {{ range first 1 .Params.media_files }}
            {{ if eq .type "photo" }}
            <img src="{{ $.RelPermalink }}{{ .filename }}" alt="" loading="lazy">
            {{ end }}
          {{ end }}
        </div>
        {{ end }}

        <div class="telegram-post-card-footer">
          <span>Message #{{ .Params.message_id }}</span>
        </div>
      </a>
    </article>
    {{ end }}
  </div>

  {{ template "_internal/pagination.html" . }}
</div>
{{ end }}

5. Создайте CSS стили assets/css/telegram.css:

/* Telegram Post Styles - PaperMod Compatible */

:root {
  --telegram-bg: var(--theme);
  --telegram-card-bg: var(--code-bg);
  --telegram-text: var(--primary);
  --telegram-secondary: var(--secondary);
  --telegram-border: var(--border);
  --telegram-blue: #2481cc;
  --telegram-blue-hover: #1a68a8;
}

/* Single Post */
.telegram-post-container {
  max-width: 640px;
  margin: 0 auto;
  padding: 20px;
}

.telegram-post {
  background: var(--telegram-card-bg);
  border-radius: 12px;
  padding: 16px;
  box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}

.telegram-post-header {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-bottom: 12px;
}

.telegram-post-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
}

.telegram-post-avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.telegram-post-info {
  flex: 1;
}

.telegram-post-channel {
  font-weight: 600;
  color: var(--telegram-blue);
  font-size: 15px;
}

.telegram-post-date {
  font-size: 13px;
  color: var(--telegram-secondary);
}

.telegram-post-content {
  font-size: 15px;
  line-height: 1.6;
  color: var(--telegram-text);
  margin-bottom: 12px;
}

.telegram-post-content p {
  margin: 0 0 12px 0;
}

.telegram-post-content p:last-child {
  margin-bottom: 0;
}

/* Media */
.telegram-post-media {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}

.telegram-photo {
  border-radius: 8px;
  overflow: hidden;
}

.telegram-photo img {
  width: 100%;
  height: auto;
  display: block;
}

.telegram-photo-caption {
  padding: 8px;
  font-size: 14px;
  color: var(--telegram-secondary);
  background: rgba(0,0,0,0.05);
}

.telegram-video {
  border-radius: 8px;
  overflow: hidden;
}

.telegram-video video {
  width: 100%;
  display: block;
}

/* Footer */
.telegram-post-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding-top: 12px;
  border-top: 1px solid var(--telegram-border);
  font-size: 13px;
  color: var(--telegram-secondary);
}

.telegram-link {
  color: var(--telegram-blue);
  text-decoration: none;
  font-weight: 500;
  transition: color 0.2s;
}

.telegram-link:hover {
  color: var(--telegram-blue-hover);
  text-decoration: underline;
}

/* Posts List */
.telegram-list-container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.telegram-list-header {
  margin-bottom: 32px;
  text-align: center;
}

.telegram-list-title {
  font-size: 28px;
  margin-bottom: 8px;
}

.telegram-list-description {
  color: var(--telegram-secondary);
}

.telegram-posts-grid {
  display: grid;
  gap: 16px;
}

.telegram-post-card {
  background: var(--telegram-card-bg);
  border-radius: 12px;
  overflow: hidden;
  transition: transform 0.2s, box-shadow 0.2s;
  border: 1px solid var(--telegram-border);
}

.telegram-post-card:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.1);
}

.telegram-post-card-link {
  display: block;
  text-decoration: none;
  color: inherit;
}

.telegram-post-card-header {
  padding: 12px 16px;
  border-bottom: 1px solid var(--telegram-border);
}

.telegram-post-card-date {
  font-size: 13px;
  color: var(--telegram-secondary);
}

.telegram-post-card-content {
  padding: 16px;
  font-size: 15px;
  line-height: 1.6;
}

.telegram-post-card-media {
  max-height: 300px;
  overflow: hidden;
}

.telegram-post-card-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.telegram-post-card-footer {
  padding: 12px 16px;
  font-size: 13px;
  color: var(--telegram-secondary);
  border-top: 1px solid var(--telegram-border);
}

/* Responsive */
@media (max-width: 768px) {
  .telegram-post-container,
  .telegram-list-container {
    padding: 12px;
  }
  
  .telegram-post {
    padding: 12px;
  }
}

6. Добавьте в config.yml:

params:
  telegram:
    channelName: "Дед in АйТи"
    channelUrl: "https://t.me/dedinit"
    avatar: "images/channel-avatar.jpg"

# Если используете модули
module:
  mounts:
    - source: content/telegram
      target: content/telegram

7. Подключите CSS в layouts/_default/baseof.html или создайте partial:

<!-- layouts/partials/telegram-styles.html -->
{{ $telegram := resources.Get "css/telegram.css" }}
{{ $telegram = $telegram | resources.Minify | resources.Fingerprint }}
<link rel="stylesheet" href="{{ $telegram.Permalink }}">

И добавьте в layouts/telegram/baseof.html:

<!DOCTYPE html>
<html lang="{{ .Site.LanguageCode }}">
<head>
  {{ partial "head.html" . }}
  {{ partial "telegram-styles.html" . }}
</head>
<body>
  {{ partial "header.html" . }}
  <main>
    {{ block "main" . }}{{ end }}
  </main>
  {{ partial "footer.html" . }}
</body>
</html>

8. Запустите синхронизацию:

python scripts/sync_telegram.py
hugo

Что дальше:

  1. Покажите мне пример контента из index.md (текст поста)
  2. Скажите, нужно ли добавить поддержку видео/аудио
  3. Хотите ли вы добавить фильтры по датам/тегам

Готов доработать любой из шаблонов под ваши нужды! 🚀