Проект: Sir Image Renamer  Публичный пост
Sir Image Renamer

TL;DR: SIR даёт имя сохраняемой картинке

на Artstation, Deviantart, Instagram, Tumblr, Twitter…
(есть для Firefox и Chrome, описание (en) можно прочесть тут)

Вступление

С незапамятных времён балуюсь сохранением картиночек из интернета. Это мания: иногда даже не рассматриваю особо, просто сохраняю. Мемы, аниме, фотожабы, арты, ну вы поняли.

Обычные будни неряшливого архивариуса
Обычные будни неряшливого архивариуса

Но вот незадача: начиная с какого-то количества файликов в папке на поиск нужного уходит как-то многовато времени:

«Я же помню, где-то была та вот эта вот ну вот её — с котиком, которую ещё у Артгема в инстаграмме…»

Ну или наоборот:

«Не ну я же знаю этого художника, ыыыыг, ща-ща-ща, чё-то там на 米姆局 начиналось или как-то так, прям вот здеся я это оно самое…»

Концепция идеи

Файлам надо давать имена. Но чтение глазами букв и придумывание их мозгом очень рушит медитативный-расслабляющий процесс сохранения картинок.

Обидно же! Мозг включать надо! Скажем этому нет — в идеальном мире при сохранении картинок работает исключительно спинной мозг!

Особенно, когда желанная инфа и так всегда доступна — картинку постит автор на каком-то сайте, иногда даже тэги ей прописывает.

Так и появилась идея дополнения для браузера, которое минимально инвазивно ворует картинки со всеми их раскрытыми дискриминаторами.

(Для организации уже имеющихся картиночек мой друг — который настоящий кодер — написал простой, но мощный теггер на C++ + Qt, я же взялся за браузер)

Стек

Расширение написано на чистом JS, цепляющем API Chrome (и Firefox, ибо он почти совместим)

Прототип

На этом этапе за 10% времени в коде был сооружён велосипед из дичайших костылей, а 90% времени ушло на рисование иконки и выдумывание названия похайповее.

Что может быть лучше рекурсивного акронима — поэтому Sir Image Renamer. Он ведь картинкам имя даёт. Плюс, при поиске по магазину дополнений — нуль совпадений. Уникальненько!

Морская синева — приятный цвет, стрелочка вниз вполне себе символизирует скачивание, а прерывающая её тильда взялась из изначального формата имени файла — Сайт~автор имярек.jpg. Да только вот оказалось, что тильду никто не любит — из имени файла она ушла, а в иконке осталась.

Первый набросок иконки
Первый набросок иконки

Про код — весь прототип состоял из (здесь можно орать):

  • трёх иконок,
  • манифеста — на 80% слизанного из туториалов гугла,
  • файла background.js — смотрит на URL, вычленяет из него ключевые подстроки, добавляет попавшуюся в имя файла
  • и… ничего более.

Но это работало — значит, мои навыки JS не были совсем безнадёжны!

Стек, часть вторая

Забыл упомянуть — JavaScript к началу разработки я не знал от слова «совсем». Зато знал, что всё, что можно разломать — то можно понять.
Вооружившись курсом+кратким референсом от w3schools и документацией Chrome API (а чуть позже, Mozilla WebExtensions API), я скачал расширения, функциональность которых была похожа — и начал методично читать.

Для всех желающих — привожу чит-код для Лисы:
CTRL+Shift+A → Tab × 6 → Space → Tab × 3 → Space (Extensions Debug), оттуда копировать Extension ID (например, uMatrix@raymondhill.net) и вставить в поиск у себя в %USERPROFILE%\AppData. Найти файл XPI, открыть его в 7-zip — и сидеть изучать сколько душе угодно.

Разработка

Читал чужое, ассимилировал, переписывал. Кодил-кодил, пару раз перелопачивал уже весь проект, чтобы стало лучше. Как-то упоролся по плашкам на гитхабе (хотя друг сказал, что плашки — говно для ЧСВшников). Один раз взял себя в руки и написал огромное описание — что именно делает расширение, с картиночками.
С момента, как готов был дать миру версию 1.0.0, начал чётко трекать всё в ченжлогах.

Запуск, полёт нормальный

Пользователей не искал вообще ни разу — тестил всё сам, когда допилил более-менее адекватную версию, скинул дополнение другу. Чуть позже выложил в магазины Firefox и Chrome — там, видимо, стали по описанию находить (откуда-то аж 20 установок!).
На этом этапе посмотрел, что требуется для пассивной рекламы в магазинах и нарисовал пару баннеров-превьюшек:

Версия для магазина Хрома
Версия для магазина Хрома

Версия для дополнений Файерфокса
Версия для дополнений Файерфокса

Из моего субъективного опыта, примерно треть расширений выложены с минимальными усилиями: задание нормального описания и отрисовка баннеров уже поставят дополнение на ступеньку выше остальных.

Continious Integration

Ради этого я прочитал описание GitLab API, настроил зеркалирование репозитория и прогонку скрипта .gitlab-ci.yml на каждом пуше в master. Сам скрипт безбожно скопировал у кого-то из интернета, убрав лишнее и вбив в GitLab свои токены от Addons.Mozilla.Org.

Подводные камни

  1. Callback Hell. Колбэки. Тысячи их. Незабываемые пирамидки из вложенных функций-объектов, которые передают другим функциям функции как объекты. Как это «неизвестно, когда фукнция выполнится» и «неизвестно, в каком контексте»? Как это «когда будет время, тогда и запустим»? Уфф. Эта парадигма требует особого к ней отношения — мне после линейности микроконтроллеров сложновато.

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

  • методу OnContextMenuClicked() передаётся объект tab, у него надо смотреть свойство id: tab.id — ну, вроде норм;
  • методу OnActivated() — объект tabId — казалось бы, что это? А ВОТ И НЕТ! tabId — это не то же, что уже знакомые tab или tab.id, здесь чтобы получить айди вкладки, надо сделать tabId.tabId;
  • аналог в методе OnUpdated()tabId. А это не объект, это айди вкладки, integer как он есть!
  1. Оказалось, что API у FF и Cr не до конца совместимы:
  • прототипе расширения использовался метод OnDeterminingFilename(), существующий в Хроме, но не реализованный в Фоксе. Он позволял получить управление в момент сохранения произвольного файла и "подсказать" браузеру, что прописать в строке имени файла. Фокс же позволяет только *инициировать новую* загрузку, с произвольным предопределённым именем файла. Поэтому я отказался от OnDetermeingFilename() и перешёл к OnContextMenuClicked() — и к лучшему, это позволило выкинуть очень много лишнего кода по определению интересуемого файла; контекстное меню знает свой контекст!
  • Хром не позволяет мне выставлять реферер. Из-за этого, часть картинчоек на сайтах, что трекают рефы, не сохраняется. Почему часть? Не знаю.
  1. WebExtensions API от Мозиллы, которое я пользую для CI/CD, выдаёт вот такую бяку:

$ web-ext sign --source-dir=./Extension/ --api-key=$WEB_EXT_API_KEY --api-secret=$WEB_EXT_API_SECRET --channel=listed --id="{3846b265-95c4-4371-9853-86df1b8cbaaa}" ... Your add-on has been submitted for review. It passed validation but could not be automatically signed because this is a listed add-on. FAIL ... ERROR: Job failed: exit code 1
Вкратце — оно делает FAIL, хотя всё прошло ожидаемо и аддон попал на рассмотрение. Из-за этого пришлось выставить этот job как «скрипту разрешено зафейлить» — что, в общем-то, не корректно. Если оно зафейлит по другой причине, плашка по-прежнему будет «pipeline: passed».

Потрачено! И идеи по монетизации

Потратил только полгода на разработку (может, дней 20 чистого времени).
Идей по монетизации всего три:

  1. реклама (даже не рассматриваю);
  2. ссылка на донат (уже введена), можно её педалить агрессивнее;
  3. платные не-обязательные фичи, про-версия. ПЛОТИ ДОЛОР сколько там минималочка в гугле?

Планы на будущее

  • Потихоньку допиливать поддержку новых сайтов-галерей (как буду на них набредать)
  • Неплохо было бы вникнуть в i8n и замутить-таки переключаемую локаль хотя бы для русского — приятнее, когда всё на одном языке.
  • Нехорошо, что настройки пользователя хранятся только в пределах одной сессии браузера — следует разработать интерфейс настройки и хранить желания юзера между рестартами
  • Совсем уж мечты — научиться подавать хэши картинок во всякие сети типа Hydrus Network — и воровать их список юзер-мэйд тегов для картинки. Предлагать их, если автор не удосужился описать картинку сам

Нужны ли какие-то советы или помощь Клуба?

Любой критике рад буду. Код-ревью — особо классно. Если кто поможет пофиксить скрипт, чтобы оно в submit_amo обрабатывало FAIL, который происходит при штатной работе и отдавало в job SUCCESS (а другие FAIL-ы ловило) — вообще угощу кофе

Cоветы cтраждущим

  1. Если ковыряете расширения и хотите посмотреть на них в действии — на той же странице из п.«Стек, часть вторая» на нужном плагине нажмите INSPECT - браузер откроет панельку с фоновой страницей, где крутится основное тело кода расширения.

  2. API FF на 99% совместимы с API Chrome — так что можно хромовские описания смотреть (объект Chrome в Mozilla просто альяс к объекту Browser).

У меня написано, к примеру, chrome.contextMenus.onClicked() — и эта же кодовая база на Мозилле работает.

  1. Если будете работать со вкладками — там бывает, что однородности нет, ВНИМАТЕЛЬНО смотрите везде описание API. Бывает, что одни и те же вещи в разных методах названы разными именами — а бывает наоборот; схожими именами названы разные вещи
5 комментариев 👇

А не планируешь ввести выбор папок куда сохранять?

Я вот сохраняю в одну папку, потому что хром и ФФ только в одну умеют, а потом сортирую по категориям\проектам.

Хотелось бы просто иметь опцию
Save to:

  • Folder 1
  • Folder N

@seteo, а почему бы и нет? Это потребует организовать-таки страницу с опциями и ввести туда "кастомные поддиректории", чтобы пользователь мог настраивать. Послезавтра прикину, какой кровью можно это сделать, вроде все API для такого на месте

Из-за необходимости переименовывать картинки я когда-то перестал их сохранять. А потом отвык.

Идея классная и завидное упорство :)

Имхо - дополнительная киллер фича - сохранить все фотки со страницы, да еще и с норм названиями
Я бы сразу начал юзать

Понадобитмя доп фильтр по размеру что бы клипарт мусор не сохранять (либо конфигурировать под каждую галерею)

Фича, о которой можно задуматься - шеринг изображения.

Условно, я могу сохранять их себе не только на папку компа, но и в saved messages в телеграм. Ну или сразу друзьям своим.

На мобилке это можно сделать прямо с браузера, а на компе еще нет.

на компе
на компе

на мобилке
на мобилке

Это немного выбивается из концепции "сохранить с названием", но зато это функционал в той же точке - правый клик по картинке.

😎

Автор поста открыл его для большого интернета, но комментирование и движухи доступны только участникам Клуба

Что вообще здесь происходит?


Войти  или  Вступить в Клуб