myspoti
Jetpack Compose로 만든 Spotify 전용 안드로이드 클라이언트
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기zipline — трекер сообщений разработчиков Deadlock из Discord
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Новостной трекер по Deadlock. Первый модуль — трекер разработчиков: сообщения разработчиков из официального Discord-сервера Deadlock в одной ленте, с поиском, фильтрами и кнопкой «Текст для поста» для канала.
./run.sh
Сайт откроется на http://127.0.0.1:8000. Без настроек работает в демо-режиме (вымышленные авторы).
Бота на официальный сервер Valve не добавить, поэтому есть два пути:
backend/discord_collector.py). Нужен токен Discord-аккаунта,
который состоит на сервере Deadlock. Сборщик раз в POLL_SECONDS ищет по серверу сообщения
от авторов из backend/developers.json — это охватывает все каналы и ветки за несколько запросов.
⚠️ Автоматизация обычного аккаунта нарушает правила Discord — используйте отдельный аккаунт,
не основной.POST /api/ingest — любой мост или бот присылает сырые объекты
сообщений Discord с заголовком X-Ingest-Secret. Формат описан в backend/app.py.Настройки — в .env (образец: .env.example). После первого успешного получения
реальных сообщений демо-данные удаляются автоматически.
Страница changes.html («Изменения» в шапке) показывает, что поменялось в файлах игры от билда к билду:
модели, текстуры, материалы и эффекты по героям и зонам, новые строки локализации и значения
из игровых скриптов (было → стало).
Источник — открытый репозиторий SteamDB GameTracking-Deadlock:
по коммиту на каждый билд Steam со списком файлов (с контрольными суммами), скриптами .vdata и английской локализацией.
python -m backend.patches # скачать новые билды и записать сводки в data/patches/
python -m backend.patches --rebuild # пересобрать последние PATCH_BUILDS (30) билдов заново
На GitHub это делает .github/workflows/patches.yml каждые 20 минут: коммитит новые сводки и перезапускает деплой.
backend/media.py для последних 10 билдов достаёт из Steam изменённые модели и текстуры (только нужные
файлы из архивов игры, через SteamFileDownloader),
конвертирует их Source2Viewer-CLI в GLB и WebP
и кладёт в GitHub-релиз media-<билд>-<sha>. Билды старше 10-го теряют медиа, их релизы удаляются;
общий объём ограничен MEDIA_BUDGET_MB (400). В git попадает только список файлов.
Нужны секреты репозитория STEAM_USERNAME и STEAM_PASSWORD — отдельный аккаунт с доступом к Deadlock
и выключенным Steam Guard (иначе вход с серверов GitHub требует код). Без секретов шаг пропускается.
Страница heroes.html («Герои» в шапке) показывает всех играбельных героев карточками, как в игре. По клику
открывается окно с 3D-моделью из файлов игры: её можно крутить, выбирать анимацию, ставить на паузу и
выбирать кадр, а потом скачивать PNG на прозрачном фоне (×1/×2/×4). Кнопка «Скачать WebM» пишет
один цикл выбранной анимации (24 кадра/с) в WebM-видео с прозрачностью — размером с окно или
квадратом 500×500 / 100×100, куда герой вписывается целиком. Внутри VP9 плюс второй VP9-поток
с альфой, как это делает ffmpeg (тот же формат, что у видеостикеров Telegram). Safari прозрачность
в WebM не показывает.
Окно растягивается за угол и разворачивается на весь экран.
backend/heroes.py берёт список героев из heroes.vdata последнего билда, качает из Steam модель героя
со всем, что она использует, и конвертирует её Source2Viewer-CLI. Из анимаций остаются бег и ближний бой.
Материалы запекаются по логике шейдера игры: тинт по маске, контраст/насыщенность/яркость, цвет вершин
(в игре он в sRGB), карты нормалей; текстуры цвета — в исходном разрешении.
Модель (GLB, сжатая gltfpack) и пакет анимаций лежат в GitHub-релизе heroes; страница подгружает
каждую анимацию отдельно (HTTP range). Иконки и список — в data/heroes/.
python -m backend.heroes # сконвертировать новых и изменившихся героев
python -m backend.heroes --fetch DIR # скачать модели из релиза (так делает деплой)
На GitHub это делает .github/workflows/heroes.yml раз в 6 часов (и вручную: можно указать героев в only).
Нужны те же секреты STEAM_USERNAME / STEAM_PASSWORD.
Страница items.html («Предметы» в шапке) — магазин Deadlock как в игре: вкладки «Все / Оружие / Живучесть / Дух»,
предметы по тирам с ценой в душах (легендарные из «Уличной драки» — отдельным рядом), поиск по-русски и по-английски,
игровые фильтры («что даёт предмет», режимы «любой» и «все сразу»), сортировка по цене и названию. Наведение показывает
подсказку как в игре: характеристики, пассивка и активка с перезарядкой, рост от силы духа, из чего собирается.
По клику — карточка предмета: иконка в PNG 100×100, 300×300 или 500×500; внизу магазина — ZIP со всеми иконками
(или только с показанными) нужного размера.
Кнопка «Создать билд» превращает магазин в редактор, как в игре: клик по предмету кладёт его в выбранную категорию, предметы перетаскиваются между категориями, к каждому можно оставить заметку; категории добавляются, переименовываются, двигаются и получают описание. Есть выбор героя и порядок прокачки способностей (открытие и улучшения за 1, 2 и 5 очков). Во вкладке «Билд» категории — блоки на сетке в 12 колонок, как во вкладке «Билд» в игре: блок переставляется за ⠿, ширина и высота меняются за уголок (или стрелками), предметы во всех блоках одного размера и подгоняются под самый тесный блок. Раскладка сохраняется в ссылке и JSON и так же выглядит на полноэкранной странице и на картинках. Билды хранятся в браузере; «Ссылка» упаковывает билд в адрес страницы (deflate + base64). По ссылке билд открывается на всю страницу — герой, категории с крупными предметами и заметками, прокачка; «Сохранить себе» копирует его в свои билды и открывает редактор. Свой билд так же разворачивается кнопкой «На весь экран». Там же билд скачивается картинкой PNG 1080×1080 или 1920×1080: она рисуется на canvas заново под размер (герой, сумма, категории с предметами и заметками, прокачка), поэтому кнопок и интерфейса сайта на ней нет. Есть экспорт и импорт JSON.
backend/items.py берёт предметы из abilities.vdata последнего билда (цены тиров — generic_data.vdata, английский
текст — локализация в репозитории SteamDB). Из Steam приходят иконки магазина (без потерь, в разрешении игры,
через Source2Viewer-CLI) и русская локализация; и то и другое качается заново, только когда файл в игре изменился
(контрольные суммы есть в pak01_dir.txt и манифесте депо). Результат — data/items/index.json, data/items/icons/
и data/items/loc_ru.json (нужные русские строки, чтобы балансный патч не требовал входа в Steam).
python -m backend.items # обновить список, иконки и русский текст
python -m backend.items --offline # только список, без Steam
На GitHub это делает .github/workflows/items.yml раз в час и после изменений backend/items.py.
Нужны те же секреты STEAM_USERNAME / STEAM_PASSWORD.
Страница tierlist.html («Тир-лист» в шапке) — свой тир-лист героев: строки S, A, B, C и D, под ними все герои
из heroes/index.json (по алфавиту, с поиском). Героя перетаскивают в строку, внутри строки — чтобы поменять порядок,
и обратно вниз — чтобы убрать; при перетаскивании к краю окна страница прокручивается сама. Перетаскивание сделано на
pointer-событиях, поэтому работает и мышью, и пальцем (на телефоне героя нужно чуть подержать, иначе палец листает
страницу). Без перетаскивания: нажать на героя, потом на строку, или клавиши S/A/B/C/D, Delete — обратно в список.
Тир-лист и его название хранятся в браузере. Кнопка «Скачать 1080×1080» рисует PNG на canvas заново: название, дата,
наш логотип и пять строк с портретами — размер портретов подбирается самый крупный, при котором влезают все строки.
backend/emoji.py рисует пак кастомных эмодзи: голова каждого героя и каждая его способность — PNG 100×100 с прозрачностью
(44 + 176 = 220 штук), в data/emoji/ с понятными именами (apollo-0-head.png, apollo-2-riposte.png); список — в
data/emoji/index.json, в порядке пака: герои по алфавиту (The Doorman — на D), у каждого голова, потом способности 1–4.
Голова вырезана из портрета с карточки героя, как вырезка из журнала, без фона: сверху силуэт самой карточки, плечи срезаны
дугой, тот же тёмный контур и бумажная кайма, и второй оттиск силуэта в цвете героя со сдвигом. Где на карточке голова,
задано для каждого героя кругом в HEADS (подобран на глаз: от макушки, шляпы, рогов или ушей до подбородка, у Калико и
Мо и Крилла — оба персонажа); у нового героя без круга берётся примерное место, и его стоит подобрать.
Предметы магазина — отдельный пак (156 штук, без легендарных из «Уличной драки»), в data/emoji/items/ (weapon-1-close-quarters.png),
в порядке магазина: оружие, живучесть, дух, внутри — по тирам и названию. Предмет — иллюстрация из магазина, напечатанная
как фото и приклеенная к чату двумя уголками скотча: тот же контур и кайма, тонкая рамка цвета вкладки (оружие оранжевое,
живучесть зелёная, дух фиолетовый), картинка — сколько позволяет край, ведь узнают предмет именно по ней; тир и так виден
по фону картинки. ITEM_TIER_ON_TAPE = True вместо уголков даёт один скотч сверху с тиром маркером (I–IV).
Знаки для постов — третий пак (backend/emoji_symbols.py, 39 штук в data/emoji/symbols/): стрелки в 8 сторон и красная стрелка вниз (для нерфов), точка
по центру, кружок, ромб, звезда, искра, плей, молния, тире, дефис, кавычки «» и „“, ! ? . , : …, скобки, + − = ✓ ✗ / # % №.
Знак без плашки: сам вырезан из бумаги нашего зелёного (полоски с косыми срезами, сгибы срезаны поперёк), сверху светлый
сухой мазок, вокруг те же кайма и контур, сзади оттиск тёмно-зелёным со сдвигом. Ширина полоски у всех знаков одна, чтобы
в строке текста они стояли ровно.
Способность — наш шаблон поста в миниатюре: фотокарточка на скотче. Снаружи внутрь: тёмный контур, бумажная кайма, рамка цвета героя, почти чёрное нутро с сухим мазком, иконка способности из игры. Четыре карточки героя наклонены по-разному, у ульты второй кусок скотча на нижнем углу. Двойной край (контур + кайма) — то, что делает один дизайн годным для любой темы: на тёмном чате видна кайма, на светлом — контур, на средних стандартных обоях — оба.
Цвет героя — одна строка в PALETTE (подобран по внешности; игровой m_colorUI у многих героев одинаковый). Оттенки
рамки, мазка и нутра считаются из неё в CIELAB; "#рамка/#мазок" — для двухцветных героев (Шив: чёрный и кровь).
Новый герой без цвета рисуется серым, и скрипт об этом пишет. Шум с фиксированным зерном: те же иконки и палитра дают
те же пиксели, поэтому в git меняются только эмодзи с новой иконкой или цветом.
python -m backend.emoji # нарисовать весь пак
python -m backend.emoji --check # и проверить край каждого эмодзи на фонах Telegram
--check накладывает каждый эмодзи на 9 фонов Telegram (ночные фон и пузыри, чёрный iOS/AMOLED, дневные пузыри,
три оттенка стандартных обоев) и меряет контраст края: в каждой точке силуэта — самую контрастную линию в пределах 3 px
внутрь, по медиане вдоль контура; ниже 3:1 (порог WCAG для фигур) — ошибка.
В Telegram пак выкладывает backend/emoji_telegram.py. В наборе кастомных эмодзи не больше 200 штук, поэтому их два,
по первой букве героя (SETS), предметы и знаки — отдельными наборами «@zipline items» и «@zipline symbols»: «@zipline ability A–L» (https://t.me/addemoji/zipline_ability_al_by_zipline_emoji_bot)
и «@zipline ability M–Z» (https://t.me/addemoji/zipline_ability_mz_by_zipline_emoji_bot). Наборы делает отдельный бот
(TELEGRAM_EMOJI_BOT_TOKEN): Telegram дописывает имя бота в название набора, а название — это публичная ссылка, поэтому
бот уведомлений их не делает и его имя нигде не видно. Владелец наборов — пользователь из TELEGRAM_CHAT_ID (личный чат
с ботом уведомлений); в боте эмодзи ему нужно один раз нажать Start. Недостающий набор создаётся, в остальных меняется
только изменившееся: перерисованный эмодзи заменяется на своём месте, новый добавляется, ушедший удаляется, порядок
и название — как в SETS и паке. Что уже лежит в Telegram, записано в data/emoji/telegram.json.
У каждого эмодзи есть обычный эмодзи-синоним (ALT, по ключу способности или hero_<герой> для головы: его видно там, где
кастомные не рисуются, и по нему Telegram подсказывает наш) и ключевые слова для поиска — герой по-английски и по-русски
и способность.
python -m backend.emoji_telegram --dry-run # что изменится; из Telegram только читает
python -m backend.emoji_telegram # создать или обновить наборы
Страница reddit.html («Reddit» в шапке) — «Пульс» r/DeadlockTheGame: свежие посты, которые набирают голоса
и комментарии быстрее своих ровесников, — наверху. Вкладки «Пульс», «Взлетают», «Новые», «Топ 24 ч»,
темы (новости, клипы, арт, обсуждения) и кнопка «Текст для поста».
Алгоритм (backend/reddit.py). Пост сравнивается только с ровесниками — постами возраста от 0,6 до 1,6 его
собственного, — поэтому 20-минутный пост с 30 голосами может обойти 10-часовой с тремя сотнями.
Сила — место среди ровесников по голосам и комментариям; разгон — рост силы за полчаса; новостям (патчи,
утечки, ссылки на сайты Valve) — надбавка; вес поста падает вдвое каждые 8 часов.
Откуда данные. Без ключа Reddit отвечает на JSON-запросы ошибкой 403, а ключи API с ноября 2025 года выдаёт
только после ручного одобрения. Поэтому по умолчанию используются публичные RSS-ленты: в них нет чисел, и Reddit
разрешает анонимно 1 запрос в минуту. Ленты чередуются: место поста в «топе часа», «горячем» и «топе дня» даёт
силу по голосам, а общая лента комментариев сабреддита — счёт комментариев. Если есть ключ API (приложение типа
script), положите REDDIT_CLIENT_ID и REDDIT_CLIENT_SECRET в секреты репозитория — сборщик сам перейдёт на
настоящие рейтинги и обновление раз в минуту.
Сборщик работает внутри backend/live.py (воркфлоу «Live collector»): лента для страницы — в Firebase
/live/reddit (страница перечитывает её раз в 90 секунд), полное состояние между запусками — в /reddit/state.
python -m backend.reddit # локально: держать data/reddit.json свежим (страница берёт его через ./run.sh)
python -m backend.reddit --once # один запрос и топ в консоль
backend/developers.json — Discord ID и имена. Новые записи подхватываются при перезапуске;
имя и аватар обновляются из Discord автоматически.
backend/ FastAPI + SQLite: API, сборщик Discord, демо-данные
frontend/ статичная страница (HTML/CSS/JS без сборки)
data/ база SQLite (создаётся при запуске)
| Метод | Путь | Что отдаёт |
|---|---|---|
| GET | /api/dev-messages?q=&authors=&channel=&before=&after=&limit= | лента сообщений |
| GET | /api/developers | разработчики, число сообщений за 7 дней, последняя активность |
| GET | /api/channels | каналы с сообщениями |
| GET | /api/dev-stats | сводка: 24 ч, 7 дней, самый активный, график за 30 дней |
| GET | /api/status | состояние сборщика |
| POST | /api/ingest | приём сообщений от внешнего источника |
| GET | /reddit.json | посты Reddit для страницы (из data/reddit.json) |