mirror of
https://gitverse.ru/kpa39l/vesti.git
synced 2026-09-29 18:05:03 +00:00
openspec: архив 14 завершённых change-ов (веб-фиксы, crawler-queue, own-content-hub, publisher-service); спеки влиты в openspec/specs
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-15
|
||||
skip_specs: true
|
||||
@@ -0,0 +1,52 @@
|
||||
# Design: rewrite-as-author
|
||||
|
||||
## 1. candidates.html (блок пересказа)
|
||||
|
||||
```diff
|
||||
{% if selected.rewritten_text %}
|
||||
<div class="mt-2">
|
||||
- <label ...>✍️ Черновик пересказа (редактируйте и копируйте):</label>
|
||||
- <textarea class="form-control form-control-sm" rows="4" readonly>{{ selected.rewritten_text }}</textarea>
|
||||
+ <label ...>✍️ Пересказ (редактируйте и сохраните — он пойдёт в канал от вашего имени):</label>
|
||||
+ <form method="post" action="/posts/{{ selected.id }}/rewrite-save" class="row g-1">
|
||||
+ {{ hid }}
|
||||
+ <textarea class="form-control form-control-sm" name="rewritten_text" rows="5">{{ selected.rewritten_text }}</textarea>
|
||||
+ <div class="col-auto mt-1"><button class="btn btn-sm btn-outline-primary" type="submit">💾 Сохранить пересказ</button></div>
|
||||
+ </form>
|
||||
</div>
|
||||
{% endif %}
|
||||
```
|
||||
|
||||
## 2. app.py — новый эндпоинт
|
||||
|
||||
```python
|
||||
@app.post("/posts/{post_id}/rewrite-save")
|
||||
async def post_rewrite_save(post_id, request, group_by="", direction="", own="", q=""):
|
||||
_require_auth(request)
|
||||
conn = _db()
|
||||
p = conn.execute("SELECT id FROM posts WHERE id=?", (post_id,)).fetchone()
|
||||
if not p: return RedirectResponse(..., status_code=302)
|
||||
form = await request.form()
|
||||
draft = str(form.get("rewritten_text") or "").strip()
|
||||
conn.execute("UPDATE posts SET rewritten_text=? WHERE id=?", (draft or None, post_id))
|
||||
conn.commit(); conn.close()
|
||||
return RedirectResponse(..., status_code=302)
|
||||
```
|
||||
|
||||
## 3. card.py — тело и подпись
|
||||
|
||||
```python
|
||||
body = (post.get("rewritten_text") or post.get("text") or "").strip()
|
||||
rewritten = bool((post.get("rewritten_text") or "").strip())
|
||||
...
|
||||
if rewritten:
|
||||
tail = "✍️ Дед в АйТи (@dedinit)" + (f" · Источник: {orig}" if orig else "")
|
||||
elif is_own: ... # как было
|
||||
elif orig: tail = f"🔗 Оригинал: {orig}"
|
||||
```
|
||||
|
||||
## Верификация
|
||||
|
||||
- `py_compile web/app.py publisher/card.py`
|
||||
- Реальный кандидат с rewritten_text (id=4): GET /candidates?selected=4 → textarea без readonly, есть «Сохранить пересказ».
|
||||
- `make_card` (read-only БД) с постом id=4 → текст начинается с пересказа, содержит «Дед в АйТи», не содержит «🔗 Оригинал»; media сохраняется (если есть).
|
||||
@@ -0,0 +1,25 @@
|
||||
# Proposal: rewrite-as-author
|
||||
|
||||
## Why
|
||||
|
||||
Функция «✍️ Переписать» в карточке кандидата:
|
||||
|
||||
1. textarea с черновиком была `readonly` — пользователь не мог отредактировать сгенерированный LLM пересказ (генерируем 2000 символов, а в канал уходил исходный текст поста как «богатый репост» с `🔗 Оригинал`).
|
||||
2. Даже после «Переписать» публикация шла с `post["text"]` (исходник), а не с `rewritten_text` — пересказ игнорировался.
|
||||
|
||||
Ожидание пользователя: пересказ — это его авторский текст, публикуемый ОТ ИМЕНИ канала «Дед в АйТи», а не пересылка чужого сообщения.
|
||||
|
||||
## What Changes
|
||||
|
||||
- `web/templates/candidates.html`: textarea пересказа становится редактируемой, добавляется кнопка «💾 Сохранить пересказ» → `POST /posts/{id}/rewrite-save`.
|
||||
- `web/app.py`: новый эндпоинт `rewrite-save` (сохраняет отредактированный `rewritten_text`).
|
||||
- `publisher/card.py make_card`: при наличии непустого `rewritten_text` тело карточки = пересказ; подпись «✍️ Дед в АйТи (@dedinit) · Источник: <url>» вместо `🔗 Оригинал: <url>` (публикация от имени автора).
|
||||
|
||||
## Why Not
|
||||
|
||||
- Не делаем отдельного поля «автор» и персистенции источника пересказа — пересказ всегда от имени владельца канала; ссылка на оригинал остаётся строкой «Источник: …» для атрибуции.
|
||||
|
||||
## Impact
|
||||
|
||||
- Кандидат: textarea редактируемо, кнопка save. Публикация: пересказ приоритетнее оригинала, подпись от имени канала.
|
||||
- Обратная совместимость: посты без rewritten_text публикуются как раньше (полный текст + 🔗 Оригинал).
|
||||
@@ -0,0 +1,23 @@
|
||||
# Tasks: rewrite-as-author
|
||||
|
||||
## 1. Шаблон (web/templates/candidates.html)
|
||||
|
||||
- [x] 1.1 Убрать `readonly` у textarea пересказа, переделать блок: label «редактируйте и сохраните», форма → `/posts/{id}/rewrite-save`, кнопка «💾 Сохранить пересказ»
|
||||
- [x] 1.2 Проверка: GET /candidates?selected=4 (пост с пересказом) — textarea редактируема, кнопка на месте
|
||||
|
||||
## 2. Эндпоинт (web/app.py)
|
||||
|
||||
- [x] 2.1 `POST /posts/{post_id}/rewrite-save`: сохраняет отредактированный textarea в `posts.rewritten_text` (async, str-коэршн), редирект обратно с selected
|
||||
- [x] 2.2 Компиляция + рестарт vesti-web (active)
|
||||
|
||||
## 3. Карточка (publisher/card.py)
|
||||
|
||||
- [x] 3.1 `make_card`: при непустом rewritten_text тело = пересказ, подпись «✍️ Дед в АйТи (@dedinit) · Источник: …» вместо «🔗 Оригинал»
|
||||
- [x] 3.2 Проверка на реальном посте id=4 (read-only): текст начинается с пересказа, есть «Дед в АйТи», нет «🔗 Оригинал»
|
||||
- [x] 3.3 Посты без пересказа — регресс (поведение не изменилось): тело = text, подпись 🔗 Оригинал
|
||||
|
||||
## 4. Документация
|
||||
|
||||
- [ ] 4.1 STATUS.md обновлён
|
||||
- [ ] 4.2 openspec validate rewrite-as-author — чисто
|
||||
- [ ] 4.3 git commit + push (после подтверждения пользователя)
|
||||
Reference in New Issue
Block a user