Новое приложение для просмотра аниме, и не только!
Привет! Последний месяц разработки прошёл действительно продуктивно и я готов представить вашему вниманию AniMori v2.0!
Всё начиналось с простенького юзерскрипта для TamperMonkey, о котором я здесь уже рассказывал, но чем дольше я работал над ним, тем больше осознавал, что это сложно и не для всех. Что делать? Своё расширение? Придется обрезать функционал, чтобы соответствовать манифесту магазина. Поднимать свой сайт? Перспектива внимания со стороны регулятора и администрации AniList, политику использования которых я беспощадно нарушаю, совсем не улыбали.
Единственными возможным вариантом развития для проекта оставался десктоп...
По традиции кому лень читать, ссылка на репозиторий уже была выше.
Архитектура и стек
Пояснять за техническую составляющую и архитектуру приложения здесь не вижу смысла, разве что совсем кратко.
Монолитный JS скрипт был переписан на TS и разбит на модули, интерфейс теперь использует Vue. Сборку ведёт Vite. Собственно, вся хитрость живёт именно здесь: сборка запускается в одном из двух режимов, и в зависимости от режима подставляются разные реализации одних и тех же вещей. Т.е. скрипт я не убил, он продолжит обновляться параллельно, просто из одних и тех-же кирпичиков теперь собираются и десктопное приложение и браузерный скрипт. Настольная версия — Tauri 2, то есть оболочка на Rust. Это не Electron: своего браузера внутри нет, окно рисует системный WebView2.
По сути я сделал...браузер, но только с одним сайтом на борту. Звучит не очень круто, пока я не расскажу, что он умеет.
Возможности
Для начала следует разобраться, что вообще такое Anilist.co?
AniList — это популярная онлайн-платформа и база данных для отслеживания просмотра аниме и чтения манги. Сайт позволяет вести списки просмотренного, находить новые произведения и общаться в социальном сообществе.
Первой проблемой, которую решает проект - это языковой барьер. Сайт изначально исключительно англоязычный, так что первым делом я взялся за локализацию.
Локализация
Это работает на двух уровнях.
На первом уровне расположен перевод статического и динамического интерфейса сайта, для этого применяется JSON словарь в репозитории проекта и регулярки. Статика — это простой словарь соответствий: «Format» → «Формат», «Watching» → «Смотрю» и так далее. Отдельными таблицами лежат подписи полей в карточках, названия списков, месяцы, дни недели, сезоны. Если строка нашлась целиком, на этом всё и заканчивается. Динамические конструкции словарём не берутся, потому что внутри них числа и имена. Для них набор регулярных выражений, каждое со своим сборщиком фразы. «Ep 5 airing in 2 days» превращается в «5 серия выйдет через 2 дня», «#12 Highest Rated Fall 2023» — в «#12 в рейтинге за сезон осени 2023 года», «Watched episode 3 of» — в «Просмотрена серия 3». Числительные согласуются: для каждой единицы хранятся три формы — «день / дня / дней», «серия / серии / серий» — и нужная выбирается по числу.
На втором уровне перевод названий и описаний тайтлов и персон. Тайтлы переводятся по MAL id, который AniList отдаёт вместе с карточкой. Опрашиваются два источника, Shikimori и anime365, в порядке из настроек — основной, затем запасной, до первого ответа с русским названием. Приезжает название, описание и ссылка на источник.С персонами общего идентификатора нет, искать приходится по имени. Shikimori ищет по точному порядку слов, AniList отдаёт имена в западном, поэтому делается несколько попыток: прямой порядок, обратный, второй эндпоинт, затем GraphQL. Каждому кандидату считается балл совпадения; точное попадание по кандзи обрывает перебор, слабое отбрасывается. Если совпадение неточное, включается защита от тёзок: у кандидата должен быть общий тайтл с исходной персоной, иначе он отклоняется.
Но это всё лирика, что по итогу? На данный момент сайт практически полностью русифицирован. Исключением являются форумы и комментарии, перевести которые гораздо сложнее и надо ли? Плюс администрация активно обновляет сайт, так что переодически могут появляться новые, ещё не переведённые элементы интерфейса.
Плеер
Киллер фичей проекта является встроенный плеер Kodik, где можно посмотреть любой тайтл, представленный в их базе, бесплатно и без рекламы (никому не говорите, но в приложение вшит самописный блокировщик рекламы).
Кнопка открытия плеера появляется на страницах аниме и берет данные из базы кодика по MAL id. Есть возможность добавить студию озвучки в избранное и она будет включаться автоматически при наличии, но это мелочи, сами разберетесь.
Ссылки на внешние ресурсы
В случае, если вдруг плеер отвалился, или аниме не оказалось в базе данных Kodik, предусмотрен блок со ссылками на сторонние ресурсы для просмотра и скачивания.
По умолчанию в него вшиты YummyAnime, AnimeGO, MangaLib (для манги) и Rutracker, но у вас есть возможность забиндить любую собственную ссылку.
Музыка
На страницах аниме есть виджет, который показывает названия и исполнителей основных музыкальных тем (опенинги, эндинги).
Можно как скопировать название, так и сразу перейти на один из предложенных стримингов (VK, YT, Spotify, или SC). Провайдер - AnimeThemes.
Виджет франшизы
Одним из слабых мест ванильного Anilist я отметил навигацию в пределах больших франшиз.
Если мы находимся на странице аниме с большим количеством сезонов, виджет отобразит актуальный таймлайн франшизы с сортировкой по дате выхода. Удобно.
Рейтинги
Совсем мелочь но приятным дополнением служит виджет рейтингов с других площадок.
Импорт и сравнение списков с Shikimori
Почему проект называется AniMori? Можно сказать, что это дань уважения крупнейшей русскоязычной энциклопедии манги и аниме. Вместе с тем, проект дает возможность юзерам этой площадки комфортно мигрировать на Anilist и поддерживать паритет своих списков.
Первая фича - импортер. Он полностью переносит на площадку ваши списки Аниме, манги, избранного, а также точные тайминги просмотра основываясь на истории Shikimori (все же любят графики?).
Сравнитель поможет, если вы хотите вести списки на обеих площадках параллельно, он подскажет разницу.
Поиск на русском языке
Внутренний поисковик теперь понимает кириллицу и будет выдавать вам результаты на запросы на русском языке.
Всё остальное
Разные темы оформления, логгер для отладки, гибкая настройка функционала, локальный словарь и многое другое - это конечно очень круто, но пост и так уже получается слишком длинным, лучше просто зацените, как всё это выглядит комплексно:
Ограничения
В целом большую часть времени софт ведет себя хорошо, но нужно признать, что конструкция, целиком и полностью полагающаяся на сторонние сервисы и кучу разных API априори не может быть надежной.
1. Когда я только начинал разработку ни Anilist, ни GitHub, ни GreasyFork не были заблокированы в РФ. Теперь-же возможность комфортного использования всего функционала проекта без VPN под большим вопросом, имейте ввиду.
2. Реактивность интерфейса, накладываемого на другой интерфейс оставляет желать лучшего. Иногда пропадают переводы и виджеты, в 90% случаев лечится перезагрузкой страницы, в остальных случаях смотрим в логгер и создаем issue на GitHub.
Заключение
Спасибо, что дочитали до этого момента, здесь немного размышлений о будущем проекта. Даже не смотря на то, что модель распостранения упростилась, софт по прежнему остается довольно нишевым и ни на что не претендующим, но тем не менее останавливаться я не собираюсь. В планах уже порт на Linux и создание Android приложения, а также поддержка и модернизация уже созданной инфраструктуры.
Если интересно, скачать приложение для Windows можно на моём GitHub, скриптовая версия лежит на GreasyFork.
Если понравилось, пишите отзывы, ставьте звезды в репозитории, делитесь идеями, присылайте баг-репорты, это правда помогает.
Проект некоммерческий, распостраняется под свободной лицензией MIT.
Ещё раз спасибо, что уделили мне время, приятного пользования и до свидания!