Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 5 additions & 9 deletions admin/pages/generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,7 @@

import streamlit as st

from scheduler import (
DATA_DIR,
get_next_run,
get_state,
publish_latest_post,
start_generation,
)
from scheduler import DATA_DIR, get_next_run, get_state, start_generation

OUTPUT_DIR = DATA_DIR / "output"

Expand Down Expand Up @@ -53,7 +47,9 @@
log_path.write_text("".join(lines), encoding="utf-8")

if process.returncode == 0:
publish_latest_post()
status.update(label="Пост сгенерирован!", state="complete")
status.update(
label="Пост сгенерирован! Опубликуйте его на странице Посты",
state="complete",
)
else:
status.update(label="Ошибка генерации", state="error")
36 changes: 18 additions & 18 deletions admin/pages/posts.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,27 +38,27 @@
parts = content.split("---", 2)
st.markdown(parts[2] if len(parts) >= 3 else content)

published = POSTS_DIR / md_file.name
is_published = published.exists()
if st.button(
"Опубликовано" if is_published else "Опубликовать",
disabled=is_published,
type="primary",
):
POSTS_DIR.mkdir(parents=True, exist_ok=True)
shutil.copy2(md_file, published)
st.success("Пост опубликован в блог!")
st.rerun()

with tab_edit:
edited = st.text_area("Редактировать пост", value=content, height=400)
col1, col2 = st.columns(2)
with col1:
if st.button("Сохранить"):
md_file.write_text(edited, encoding="utf-8")
st.success("Сохранено!")
with col2:
published = POSTS_DIR / md_file.name
is_published = published.exists()
if st.button(
"Опубликовано" if is_published else "Опубликовать",
disabled=is_published,
):
POSTS_DIR.mkdir(parents=True, exist_ok=True)
shutil.copy2(md_file, published)
st.success("Пост опубликован в блог!")
st.rerun()
if st.button("Сохранить"):
md_file.write_text(edited, encoding="utf-8")
st.success("Сохранено!")

with tab_files:
for f in sorted(run_dir.iterdir()):
if f.suffix == ".md":
continue
with st.expander(f.name):
lang = "markdown" if f.suffix == ".md" else "text"
st.code(f.read_text(encoding="utf-8"), language=lang)
st.code(f.read_text(encoding="utf-8"), language="text")
9 changes: 5 additions & 4 deletions admin/pages/prompts.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@
def _read_prompt(filename: str) -> str:
pvc_path = PROMPTS_DIR / filename
if pvc_path.exists():
return pvc_path.read_text(encoding="utf-8")
return str(pvc_path.read_text(encoding="utf-8"))
default_path = DEFAULT_PROMPTS_DIR / filename
if default_path.exists():
return default_path.read_text(encoding="utf-8")
return str(default_path.read_text(encoding="utf-8"))
return ""


Expand All @@ -58,8 +58,9 @@ def _save_prompt(filename: str, content: str) -> None:
if st.button("Сбросить к дефолту", key=f"reset_{filename}"):
default = DEFAULT_PROMPTS_DIR / filename
if default.exists():
_save_prompt(filename, default.read_text(encoding="utf-8"))
st.success("Сброшено к значению по умолчанию!")
content = default.read_text(encoding="utf-8")
_save_prompt(filename, content)
st.session_state[f"prompt_{filename}"] = content
st.rerun()
else:
st.warning("Дефолтный промпт не найден")
9 changes: 8 additions & 1 deletion admin/pages/schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@
placeholder="0 10 * * 1",
)

auto_publish = st.checkbox(
"Автопубликация после генерации",
value=state.get("auto_publish", False),
help="Если включено — пост сразу публикуется в блог. "
"Иначе — нужно опубликовать вручную на странице Посты",
)

col1, col2 = st.columns(2)

with col1:
Expand All @@ -32,7 +39,7 @@
st.error("Введите cron-выражение")
else:
try:
set_schedule(cron_input.strip())
set_schedule(cron_input.strip(), auto_publish)
st.success(f"Расписание установлено: `{cron_input}`")
st.rerun()
except ValueError as e:
Expand Down
18 changes: 14 additions & 4 deletions admin/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,11 @@ def _run_generation() -> None:
return

logger.info("Генерация завершена успешно")
publish_latest_post()
state = get_state()
if state.get("auto_publish", False):
publish_latest_post()
else:
logger.info("Автопубликация отключена, пост не опубликован")


def publish_latest_post() -> None:
Expand Down Expand Up @@ -104,10 +108,16 @@ def get_scheduler() -> BackgroundScheduler:
return _scheduler


def _save_state(cron_expr: str, enabled: bool) -> None:
def _save_state(cron_expr: str, enabled: bool, auto_publish: bool = False) -> None:
DATA_DIR.mkdir(parents=True, exist_ok=True)
STATE_FILE.write_text(
json.dumps({"cron": cron_expr, "enabled": enabled}),
json.dumps(
{
"cron": cron_expr,
"enabled": enabled,
"auto_publish": auto_publish,
}
),
encoding="utf-8",
)

Expand All @@ -123,7 +133,7 @@ def _restore_schedule() -> None:
logger.exception("Не удалось восстановить расписание")


def set_schedule(cron_expr: str) -> None:
def set_schedule(cron_expr: str, auto_publish: bool = False) -> None:
"""Устанавливает расписание. Формат cron: '0 10 * * 1'."""
sched = get_scheduler()

Expand Down
3 changes: 2 additions & 1 deletion app/post_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,10 @@ def write_post(content: str, config: AppConfig) -> Path:

title, body = _parse_title_and_body(content)

safe_title = title.replace('"', '\\"')
front_matter_lines = [f"date: {today}"]
if title:
front_matter_lines.append(f"title: {title}")
front_matter_lines.append(f'title: "{safe_title}"')

front_matter = "---\n" + "\n".join(front_matter_lines) + "\n---\n\n"

Expand Down