Leditor III

интерфейс и код веб-приложения
результат процесс

Веб-приложение «Leditor» помогает писать и публиковать выпуски «Леновостей» в соцсетях. Программа принимает новости от расширения «Hound», позволяет их редактировать, готовит видео- и аудио-версии, а после отправляет в Телеграм и на YouTube каналы.

Придумал интерфейс и написал код на Python + JS.

Страница с выпуском поделена на четыре части: вверху счётчик новостей и форма загрузки обложки, далее список событий, ниже аудиоплеер и в конце — предпросмотр для публикации вручную, копи-пастом, на сайтах без API.

Если нажать на новость, то откроется форма редактирования:

Некоторые соцсети запрещают кое-какие слова и цифры. Для них пишется «цензурная версия»:
Озвучить Плей/Пауза
Опубликовать
 

«Leditor» озвучивает выпуски через сервис «Yandex SpeechKit» и позволяет прослушать его перед отправкой. Текст для аудиоверсии, если он отличается, выводится под новостью меньшим шрифтом.

Для публикации нужно удерживать зелёную кнопку три секунды. Процесс занимает около шести минут, а после звучит сигнал об успехе или ошибке:

Сочетания клавиш:
Навести курсор на новость + Пробел — Скрыть/вернуть новость в выпуск. Удалить её невозможно.
Навести курсор + 1/2/3 — Сменить группу, например: лидер/основное/СВО.

Ctrl + Пробел — Плей/Пауза аудиоверсии
Ctrl + ↑/↓ — Скорость воспроизведения
Ctrl + ←/→ — Перемотка -10/+15 секунд

В форме редактирования:
Ctrl + V — Копировать текст новости в поле аудиоверсии
Ctrl + C — Показать поле цензурной версии
Ctrl + Enter — Сохранить и закрыть форму
Esc — Закрыть без сохранения

Готовый выпуск выглядит так:
А звучит так:

Бэкенд на Django с модулями DRF, Q2, pydub, yandex-speechkit, moviepy, pyyoutube и telethon.

Модели:

Edition — имя издания: «Леновости», «Импортные Леновости» или «ntab». К ней подключена модель «Group» c названиями групп новостей, например: «Лидер, Основное, СВО», и опциями: выводить нумерованным списком? Голос озвучки? Можно добавить обложку? И т.п.

Issue — выпуск издания. Хранит заголовок и ссылки на посты в соцсетях. Подключены модели с обложками, аудио- и видео-версией: Cover, Audio, Video.

News — новости с привязкой к выпуску и группе издания. Хранит текст, ссылку и время.

У каждого издания свой контроллер, который не умеет оформлять текст или отправлять данные в соцсети, зато знает о классах, которым это по плечу:
Классы групп издания готовят текст к публикации, при этом ничего не знают о моделях:
В этом им помогают «Редакторы / Editor». Например, TextKeeper разбивает текст на элементы списка, чтобы каждый не превышал максимальную длину Телеграм-сообщения или запроса к стороннему API:
Редактор «Voice» озвучивает текст. Для экономии, а озвучка штука платная, он хранит аудиофайлы с контрольной суммой текста в собственной модели. При обращени сначала проверяет озвучивал ли такой текст и только после делает запрос к серверу Яндекса:
FakeVoiceDriver экономит запросы при отладке
Видеоредактор на основе moviepy. Делает ролик из обложки выпуска и аудиоверсии. С модельями не общается, а лишь возвращает путь к временному файлу:
«Клиенты / Client» заведуют отправкой в Телеграм, на электронную почту и YouTube:
Новости в админке:
Фронтенд на SvelteKit с адаптером SPA. Страница выпуска:
Компонент формы редактирования генерируется и уничтожается программно
За глобальные сочетания клавиш отвечает компонент, который передаёт события родителю:
Если компоненту нужны локальные сочетания клавиш, то он перехватывает их с методом .stopPropagation:
Бэкенд возвращает аудиоверсию с контрольной суммой озвученного текста. Кнопка запроса аудио сравнивает её с текущим хэшем и становится неактивной. Например, если озвучить выпуск и изменить текст новости, то кнопка активируется. Если после вернуть текст как было — она снова отключена:
Кнопка публикации с функцией «удерживай для отправки»:
10 апреля 2024 г.