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
This commit is contained in:
@@ -0,0 +1,558 @@
|
||||
# Запрос:
|
||||
|
||||
Давай посмотрим как сделать красивое представление постов из Телеграма в моём блоге с темой pappermode для hugo. Для телеграма есть вот такой виджет для встаивания поста в любой сойт. Мне очень нравится как это выглядит. https://core.telegram.org/widgets/post. Ты сможешь каким-то образом скопировать оформление и что тебе для этого от меня нужно?
|
||||
|
||||
# Ответ:
|
||||
|
||||
Отличная идея! Виджет Telegram выглядит действительно красиво и минималистично. Давайте разберем варианты интеграции с Hugo PaperMod.
|
||||
|
||||
## Что мне нужно от вас:
|
||||
|
||||
1. **Ссылка на ваш Telegram-канал** (публичный)
|
||||
2. **Предпочтительный способ интеграции** (выберите один):
|
||||
- Простое встраивание через iframe (официальный виджет)
|
||||
- Кастомный shortcode с похожим дизайном
|
||||
- Автоматический импорт постов как контента Hugo
|
||||
|
||||
## Варианты решения:
|
||||
|
||||
### Вариант 1: Официальный виджет Telegram (самый простой)
|
||||
|
||||
Можно создавать **shortcode** для Hugo, который встраивает посты:
|
||||
|
||||
```html
|
||||
<!-- 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>
|
||||
```
|
||||
|
||||
**Использование:**
|
||||
```markdown
|
||||
{{< 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:
|
||||
|
||||
```bash
|
||||
cd ваш-hugo-сайт
|
||||
mkdir -p content/telegram
|
||||
mkdir -p layouts/telegram
|
||||
mkdir -p layouts/partials
|
||||
mkdir -p assets/css
|
||||
```
|
||||
|
||||
### 2. Напишите скрипт синхронизации (Python):
|
||||
|
||||
Создайте `scripts/sync_telegram.py`:
|
||||
|
||||
```python
|
||||
#!/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`:
|
||||
|
||||
```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`:
|
||||
|
||||
```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`:
|
||||
|
||||
```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`:
|
||||
|
||||
```yaml
|
||||
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:
|
||||
|
||||
```html
|
||||
<!-- 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`:
|
||||
|
||||
```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. Запустите синхронизацию:
|
||||
|
||||
```bash
|
||||
python scripts/sync_telegram.py
|
||||
hugo
|
||||
```
|
||||
|
||||
**Что дальше:**
|
||||
1. Покажите мне пример контента из `index.md` (текст поста)
|
||||
2. Скажите, нужно ли добавить поддержку видео/аудио
|
||||
3. Хотите ли вы добавить фильтры по датам/тегам
|
||||
|
||||
Готов доработать любой из шаблонов под ваши нужды! 🚀
|
||||
Reference in New Issue
Block a user