Автоматический создаватель паков картинок имени рандомных поней

+134
в блоге IT Pony!
Короче. Вот у нас есть автоматический вестник Табуна, который милая am31 каждый день неустанно делает для нас, что показывает, что автоматизация — это ум, честь и совесть эпохи и за ней будущее. =) А также есть много паков имени различных поней (Дёрпи, Селестии, Луны, Найтмер Мун, Твайлайт, Старлайт, киринов и т.п.) А ещё я в паке Твайлайт задумался над тем, что нет пака имени Лиры, но понял, что у меня чисто физически не будет времени его пилить, поэтому его и не будет…


...Or is it?

Так что я went super saiyan и накодил питоновский скрипт, который автоматически создаёт паки поней из выбранных пользователем картинок и постит их в черновики, после чего остаётся только зайти туда самому, прочекать, всё ли ок и нажать «Опубликовать».

Скрипт здесь
гитхабовской репе)

Если у кого-то есть предложения по расширению функциональности или правки неудачных мест (питонщик из меня тот ещё), то велкам в ищщуи и пулл-реквесты.

Как его использовать:

1. Проверить, что на машине есть Python 3. Я проверял на 3.8, скорее всего заведётся на любом третьем и может даже на каком-нибудь из вторых, но я не проверял. Для линуксоидов это на 99% так и есть, виндузятникам придётся его поставить самостоятельно, если он не стоит. Стоит отметить, что последняя версия, которую можно поставить на семёрку — 3.8, 3.9 ставится только на 8.1 или десятку.

2. Поставить нужные модули, в особенности tabun_api от Андреймала (остальные, скорее всего, уже стоят):
pip3 install datetime json requests pathlib
pip3 install git+https://github.com/andreymal/tabun_api.git#egg=tabun_api[full]
Если pip3 нет, то скорее всего, можно использовать команду pip вместо неё: такое бывает, если третий питон — единственный стоящий на машине.
Хочу сказать спасибо andreymal -у за этот модуль и в особенности годную документацию к нему, я разобрался в нём буквально за десять минут и без залезания в исходники, давно у меня такого не было с новыми библиотеками.

3. Сконфигурировать скрипт (его конфигурация находится в его начале). Те параметры, которые нельзя оставить, как есть, и нужно поменять по сравнению с дефолтной конфигурацией, выделены жирным:

username — логин на табуне.
password — пароль от табуна.
proxy — прокси, если нужен, иначе просто пустая строка.
mirror — зеркало дёрпибуры (у меня работает то, которое там приведено, остальные без проксика недоступны).
title — название поста, в нём три подчёркивания будут заменены на номер пака (начинается с 1 и дальше увеличивается).
tags — теги, которые будут у поста.
blog_id — численный идентификатор блога, куда постить или строка из URL ссылки на блог (например, ЯРОК — это «fanart», ЗХ — «sketch_drawing», БПНХ — «draw_help», СБК — «rough_blog», награнь — «borderline»). 0 — это персональный блог.
pony — дёрпибурной тег поньки, имени которой мы будем создавать пак.
bonuspony — дёрпибурной тег бонусной поньки (можно сделать несколько «бонусных» спойлеров в конце). Поиск для бонусной поньки ведётся с исключением основной; то есть, если pony = 'lyra heartstrings' и bonuspony = 'bon-bon', то в бонусы будут попадать те картинки, на которых есть Бон-Бон, но нету Лиры. Если бонус не нужен, то здесь следует оставить пустую строку.
also — дополнительные теги.
sort — параметр для сортировки (wilson_score, в отличие от score, позволяет встревать годноте, которую тупо видело очень мало народа).
tmpl_body — шаблон поста. Здесь на место __OP_PIC__ подставится ОП-пикча, на __PIC_BLOCK__ — блок картинок в спойлерах, на ___ — номер пака.
tmpl_text_spoiler_header — шаблон текстового заголовка спойлера.
tmpl_text_spoiler_header_bonus — шаблон текстового заголовка спойлера бонуса.
tmpl_pic_spoiler_header — шаблон заголовка спойлера с картинкой.
tmpl_pic_spoiler_header_bonus — шаблон заголовка спойлера бонуса с картинкой.
tmpl_op_pic — шаблон ОП-пички.
tmpl_alttext — шаблон альттекста каждой картинки.
tmpl_spoiler_contents — шаблон содержимого спойлера.
tmpl_spoiler_contents_bonus — шаблон содержимого спойлера бонуса.
defaults — значения подстановок для шаблона, если соответствующих данных о картинке нет.
spoilerpics — здесь можно указать либо массив ссылок на пикчи, уже загруженные на табун, чтобы получить в заголовках спойлеров такую красоту, как в паках Селестии и Луны; либо просто оставить None или пустой массив, и тогда скрипт сгенерит текстовые заголовки спойлеров. Если будет выбрано больше картинок, чем элементов в этом массиве, то оставшиеся спойлеры будут иметь текстовые заголовки.
bonuspic — картинка для спойлера бонуса. Опять-таки, либо ссылка на пикчу, уже загруженные на табун, либо None или пустая строка, чтобы создать текстовый спойлер.
timezone — часовой пояс, для Москвы это +03:00.
config — путь к файлу, где будет храниться номер последнего отправленного пака. Это нужно, чтобы автоматически его увеличивать в заголовке поста. Путь относителен от домашней директории пользователя (~ в линуксе, C:\Users\имя_пользователя в винде). Файл можно редактировать, если нужно сбросить номер пака или, наоборот, переставить его на нужный. Если в файле, например, записана цифра 5, то скрипт отправит пак с номером 6 и изменит цифру в файле на 6. Если файл удалён или отсутствует, то он будет создан, а нумерация паков начнётся с 1.
pick — путь к временному файлу для выбора картинок (см. ниже про логику работы скрипта). Путь также относителен от домашней директории пользователя.
period — количество дней, за которые надо тянуть пикчи с дёрпибуры (например, 7 — это все пикчи за последнюю неделю).

В шаблонах (то есть, в переменных, начинающихся на tmpl_), кроме tmpl_body (у него свои переменные, указанные выше), можно использовать следующие подстановки:

— На место ___ подставится номер спойлера (везде, кроме `tmpl_op_pic`).
— На место __PIC__ подставится URL картинки из `spoilerpics` (только в `tmpl_pic_spoiler_header` и `tmpl_pic_spoiler_header_bonus`).
— На место __PIC__ подставится URL картинки-превью (только в `tmpl_op_pic`, `tmpl_spoiler_contents` и `tmpl_spoiler_contents_bonus`).
— На место __FULL__ подставится полная ссылка на хайрез картинки (только в `tmpl_op_pic`, `tmpl_spoiler_contents` и `tmpl_spoiler_contents_bonus`).
— На место __DESC__ подставится описание картинки на дёрпибуре, если оно задано (иначе значение из `defaults`).
— На место __NAME__ подставится название картинки на дёрпибуре, если оно задано (иначе значение из `defaults`).
— На место __AUTHOR__ подставится содержимое тега `artist:` после двоеточия, если он есть; иначе ник загрузившего картинку на дёрпибуру, если он задан; иначе значение из `defaults`.
__UPLOADER__ подставится ник загрузившего картинку на дёрпибуру, если он задан (иначе значение из `defaults`).
— На место __SOURCE__ подставится исходный URL картинки на дёрпибуре, если он задан (иначе значение из `defaults`).
— На место __ID__ подставится ID картинки на дёрпибуре.
— На место __DB_URL__ подставится URL страницы с картинкой на дёрпибуре.

4. Запустить скрипт.

Он сделает следующее:
— выкачает блок метаинформации о первых 50 пикчах (или обо всех имеющихся, если таких пикч меньше 50) с дёрпибуры с тегами pony и also и сортировкой по параметру sort (по умолчанию wilson_score);
— сделает то же самое, если задана бонусная понька, но с тегами bonuspony, -pony и also;
— создаст HTML-файл для выбора лучших пикч (файл, указанный в переменной pick, далее — pick-файл) со ссылками на эти картинки; после этого этот файл нужно будет открыть в браузере (его URL скрипт выведет в консоль);
— спросит, какие пикчи публиковать; здесь надо ввести (через пробел, запятую или точку с запятой) номера нужных пикч, начиная с ОП-пикчи. Они будут опубликованы в посте именно в том порядке, в котором введены; например, если ввести «3 5 1 2», то ОП-пикчей станет третья, а потом будут созданы три спойлера с пикчами 5, 1 и 2;
— если задана бонусная понька, то дальше спросит таким же образом номера бонусных пикч (они будут отдельно показаны в pick-файле вторым блоком; будет создано столько бонусных спойлеров, сколько пикч тут будет указано);
— загрузит для ОП-пикчи представления medium и full, а для всех остальных — large и full на табун (все неправильно введённые номера будут проигнорированы);
— создаст пост, в котором первая небонусная пикча будет ОП-пикчей (КДПВ), а остальные будут запиханы под спойлеры (номерные, а затем бонусные), при этом по клику на каждую пикчу будет открываться (по умолчанию) её полный вариант в новой вкладке, а альттекстом (тоже по умолчанию) будет служить её дескрипшен с дёрпибуры;
— запостит этот пост на табун в указанный блог в виде черновика.
После этого останется только залезть в свои черновики, проверить, опубликовать пост и пнуть его в ленту. =)

Коды возврата:
0 — всё отлично, можно лезть в черновики проверять появившийся пост;
1 — не получилось импортировать модуль `tabun_api`;
2 — не получилось достучаться до дёрпибуры;
3 — не получилось разобрать JSON, который вернула дёрпибура;
4 — не удалось залогиниться на табун;
5 — не удалось залить пикчи на табун;
9 — не удалось определить блог по его текстовому имени;
10 — не получилось запостить пост на табун.

Автоматический запуск скрипта через crontab не оправдал себя — куда удобнее не чистить черновик поста от негодных пикч, а сразу в диалоговом режиме со скриптом указывать ему пикчи для публикации.

Такие дела =)

21 комментарий

— Свити перезагружается, а пост делает ln -s в ленту!
Таки теряется главная фишка ручного формирования — необходимости пробираться через кучи потенциальной годноты и видеть ее своими глазами)
кучи потенциальной годноты

Какая интересная формулировка). Если автопилот будет тупо тащить всё на свете, что имеет нужный тэг, то полезность его близка к нулю.
Ну он тащит первые `piclimit + 1` картинок, имеющих наивысший рейтинг (score) на буре (конечно, это не гарантия качества картинки, но по крайней мере какую-то корреляцию с годностью я ожидаю).
Ну, тут уж увы =)
Впрочем, вместе с кучей потенциальной годноты ты увидишь и кучу потенциального трэша, который потом будет долго хотеться развидеть =)
А вообще я ожидал такого комментария, ибо действительно, пак ручной работы в любом случае более ламповый будет, нежели автоматически собранный. Но если составитель пака устал, ему на смену никто не приходит (сколько я видел постов типа «последний пак имени такой-то пони»), и надвигается выбор эскобара уровня «пака не будет вообще» или «пак будет собираться полуавтоматически», то второй вариант хотя бы даёт возможность радовать тех, кто по-прежнему любит смотреть еженедельные паки с любимой пони, при этом куда меньше нагружая составителя пака =)
Таки это лечится более извращенными запросами по буре, который сразу будет отсекать голимую ересь (не всегда только соединенные через ",")
А какими, кстати, например? Ну, то есть, что именно надо отсекать?
Ну смотря, что лезть будет. Большая часть тегов таки работает «на отсечение», а не «должны быть» (несмотря на то, что на буре одна из самых развитых систем тегов, проблема «недоставили тегов» существует). Вот только два:
— возрастной рейтинг (safe)
— по рейтингу (но не score, а wilson_score, который позволяет встревать годноте, которую тупо видело очень мало народа) — wilson_score.gte:0.8 позволяет попадать адекватным вещам, где-то на 0.7 уже надо включать ручной отбор
А вот отсекать можно:
— мемы (-exploitable meme, -meme)
— фотки (-irl. Тег photo может давать ложные срабатывания, все никак не дойдут руки разбить два значения этого тега)
— комиксы (-comic)
— скрины сериала (-screencap)
— всякие 4чаны, скрины самой буры итд (-meta)
— стены текста (-text only)
— и так далее исходя из того, что встретится и по необходимости. Особо упоротые люди выстраивают конструкции, которые выбрасывают пикчи по сложным фильтрам (типа «рисунки этого артера, но выше такого-то рейтинга»)
О, спасиб за рекомендации.
— возрастной рейтинг (safe)
Это уже есть в also
— по рейтингу (но не score, а wilson_score, который позволяет встревать годноте, которую тупо видело очень мало народа) — wilson_score.gte:0.8 позволяет попадать адекватным вещам, где-то на 0.7 уже надо включать ручной отбор
Хм, то есть более правильно сортировать по wilson_score, да?
— мемы (-exploitable meme, -meme)
— фотки (-irl. Тег photo может давать ложные срабатывания, все никак не дойдут руки разбить два значения этого тега)
— комиксы (-comic)
— скрины сериала (-screencap)
— всякие 4чаны, скрины самой буры итд (-meta)
— стены текста (-text only)
Добавил в also.
Тег photo может давать ложные срабатывания
Ну, вообще, это логично — например, если кто нарисует арт, в котором Тия, как в опенинге, рассматривает фотку М6 — это вполне подойдёт под тег photo.
Для safe-штук wilson_score несколько лучше работает

Ну, вообще, это логично — например, если кто нарисует арт, в котором Тия, как в опенинге, рассматривает фотку М6 — это вполне подойдёт под тег photo.

Поэтому и пытаемся родить второе название тега для таких случаев
Для safe-штук wilson_score несколько лучше работает
Окей, я сделал его по дефолту.
Поэтому и пытаемся родить второе название тега для таких случаев
Ну, как мне кажется, `irl` отлично подходит.
Пачка обновлений скрипта подъехала:

* Появилась куча шаблонов: для текстового и картиночного спойлера, КДПВ и пикчи под спойлером;
* Блог теперь можно задавать и его названием из ссылки (да, я всё-таки разобрался, как это сделать, но фича экспериментальная, ибо у Андреймала сказано, что функция `get_blog` «недоделанная»);
* Теперь не страшно, если спойлерпиков будет меньше, чем реальных спойлеров (лишние просто будут сделаны текстом);
* Необязательна первая запятая в дополнительных тегах;
* Появился Markdown-овский README;
* Больше исключений обрабатывается нормально;
* Добавлены коды возврата.

TODO:

* Сделать возможность задавать содержимое альттекста в картинке;
* В шаблоны добавить плейсхолдеры для следующих переменных из json дёрпибуры: name, uploader, source_url, id, description;
* Туда же добавить конструирование переменной derpibooru_url = mirror + '/images/' + str(id);
* Более красиво сделать сообщения о выкачке пикч.
Йоу. Что-то подобное недавно пробовал с другом делать но на шарпе.
Чтож, поизучаю код. Если переделаю код заливать отчёты с фотографиями одно удовольствие станет)
Очередное обновление скрипта:

* Сделана возможность задавать содержимое альттекста в картинке;
* В шаблоны добавлены плейсхолдеры для следующих переменных из json дёрпибуры: name, uploader, source_url, id, description — и дефолтные значения для них, кроме id;
* Туда же добавлено конструирование переменной __DB_URL__ = mirror + '/images/' + str(id);
* Более красиво сделаны сообщения о выкачке пикч (прогресс и адрес на дёрпибуре);
* Сделана возможность конфигурирования параметра сортировки и он переделан по умолчанию на `wilson_score`, в отличие от `score`;
* Добавлены дополнительные теги фильтрации в also.
Я вам говорю, рано или поздно табун превратится в сборище десятка ИИ, делающих друг для друга посты. Как в одном из разделов Реддита.
Как что плохое… УВЧ! СР!
Странно выглядит, когда она, вроде бы, приглашает «come with me», но в то же время поворачивается к тебе своим USB 3.0-разъёмом (причём заранее открыв защитные створки)...
Зато фэндом будет жить! =)
Ну и что за дискриминация ИИ, будто им не хочется тоже читать статьи, тексты, посты, как всем нормальным пони!
Апдейт: теперь я сделал механизм «Бон-Бонуса» — это позволяет добавить картинку с кем-то ещё, а не основной понькой пака в конец спойлеров. Например, как в этом вот паке =)
Ещё один апдейт: я тут в паке Лиры №3 понял, что uploader — вовсе не всегда автор, да ещё и часто аплоадят анонимы, в итоге там везде «неизвестные авторы». Поэтому теперь вместо поля __UPLOADER__ будет поле __AUTHOR__, на место которого подставится содержимое тега `artist:` после двоеточия, если он есть; иначе ник загрузившего картинку на дёрпибуру, если он задан; иначе значение из `defaults`.
Новый апдейт. Ручная чистка паков — удовольствие не из приятных, поэтому я автоматизировал это внутри самого скрипта. Ну да, он потерял автономность, но зато теперь на пак тратится не 10-20 минут, а 3-5.

Короче, я назвал это «Cherry Berry-pick» (ну, по аналогии с термином cherry-pick, ага).

Теперь скрипт после запуска выкачивает инфу по всем нужным пикчам, а затем создаёт с ними HTML-ник, который нужно открыть в браузере (URL для открытия скрипт выводит) и потом вписать номера нужных пикч через пробел/запятую/точку с запятой в поле ввода в скрипте (а потом то же самое сделать с бонусными пикчами, которые будут вторым блоком в HTML-нике). После этого скрипт создаст уже готовый черновик, на проверку которого придётся тратить куда меньше времени — ведь пикчи уже отсмотрены и выбраны.
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.