Зачем вообще что-то делать с историями во VK
Со временем во VK у меня набралось несколько тысяч друзей. Отчасти это осознанная стратегия: расширение сети контактов помогает продвигать свои проекты, находить коллаборации и тестировать идеи на более широкой аудитории.
Но есть обратная сторона. Лента историй превращается в хаотичную карусель:
люди, с которыми вы давно не общаетесь;
рабочие контакты;
случайные добавления «на всякий случай»;
тестовые или заброшенные аккаунты.
При этом истории для меня — про личный контекст: что происходит у близких друзей, семьи, небольшой группы людей, с которыми действительно хочется оставаться на связи. Удалять всех подряд из друзей не вариант, сеть всё ещё полезна. Хотелось другого решения:
Оставить большую сеть контактов для работы и при этом видеть истории только от небольшого круга людей.
В итоге я написал небольшой скрипт, который автоматизирует ту рутину, на которую руками я бы никогда не потратил столько времени.
Исходники и инструкция:
https://github.com/AleksPetrakov/vk-hide-stories-script/
Идея решения
Задача звучит просто:
скрывать истории почти от всех;
не трогать истории ограниченного набора людей:
по имени (как оно отображается в шапке истории);
по ID (из ссылки вида
/id123456или/nickname).
Это типичная работа для автоматизации:
Открыт просмотрщик историй VK, текущая история по центру.
Скрипт смотрит, кто автор текущей истории.
Если автор в списке исключений — историю пропускаем, переходим к следующей.
Если автора нет в списке — открываем меню истории и нажимаем «Скрыть из историй» с подтверждением.
Скрипт запускается один раз и дальше сам крутит цикл заданное количество итераций. После старта он продолжает работать даже в неактивной вкладке: можно переключиться в другие вкладки или приложения, а через какое-то время вернуться к VK уже с очищенной лентой историй.
Как выглядит скрипт с точки зрения пользователя
Скрипт живёт в файле vk-stories-auto-hider.js. Это не расширение браузера, никаких установок не требуется. Достаточно один раз вставить код в консоль и настроить списки исключений.
На верхнем уровне внутри файла есть две ключевые части:
Настройки исключений.
Функция запуска цикла.
Настройки исключений
В начале файла находятся два массива:
// Список имён друзей, чьи истории НЕ нужно скрывать. // Формат: 'Имя Фамилия', регистр не важен. const EXCLUDED_NAMES = [ // 'Имя Фамилия', ]; // Список id друзей (из href="/idилиник"), чьи истории НЕ нужно скрывать. const EXCLUDED_IDS = [ // 'id123456', ];
Идея простая:
EXCLUDED_NAMES— удобно для близких людей, где имя очевидно и редко меняется.EXCLUDED_IDS— для точного контроля, когда важен именно ID профиля, а имя может меняться.
Строки сравниваются без учёта регистра, перед этим нормализуются и обрезаютс�� пробелы.
Запуск скрипта
Основная функция выглядит примерно так:
async function hideVkStoriesWithExclusions(cyclesCount = 200) { // ... }
Вызов:
hideVkStoriesWithExclusions(200);
означает «попробовать обработать до 200 историй подряд», где под «обработать» понимается либо скрыть историю, либо пропустить её, если автор в списке исключений.
Как это работает внутри
Ниже — упрощённый разбор логики. Полная версия со всеми проверками и логами есть в репозитории на GitHub.
Поиск текущей активной истории
VK помечает текущий элемент истории классами вроде:
.stories_item.multi_stories.active
или, как запасной вариант:
.stories_item.active
Скрипт ищет активный элемент:
function getActiveStoryElement() { return ( document.querySelector('.stories_item.multi_stories.active') || document.querySelector('.stories_item.active') ); }
Получение имени и ID автора
Дальше нужно понять, кто автор текущей истории. Для этого в шапке истории берётся:
имя — из элемента с классами
StoryInfo__title StoryInfo__title--author;ID — из
href:либо этой же ссылки с именем;
либо ссылки на аватарку автора (
a.stories_author_avatar[href]).
Примерно так:
function getAuthorInfoFromActiveStory(activeStoryEl) { if (!activeStoryEl) return { name: null, id: null }; const nameLink = activeStoryEl.querySelector('.StoryInfo__title.StoryInfo__title--author') || activeStoryEl.querySelector('.StoryInfo__title--author'); const rawName = nameLink ? nameLink.textContent || '' : ''; const name = rawName.trim(); let rawHref = null; if (nameLink && nameLink.getAttribute('href')) { rawHref = nameLink.getAttribute('href'); } else { const avatarLink = activeStoryEl.querySelector( 'a.stories_author_avatar[href]' ); if (avatarLink) rawHref = avatarLink.getAttribute('href'); } let id = null; if (rawHref) { const href = rawHref.trim(); if (href.startsWith('/')) { const withoutSlash = href.slice(1); const withoutQuery = withoutSlash.split('?')[0].split('#')[0]; const firstPart = withoutQuery.split('/')[0]; id = firstPart || null; } } return { name, id }; }
Полученные name и id дальше нормализуются и сравниваются с массивами EXCLUDED_NAMES и EXCLUDED_IDS.
Логика исключений
Проверка вынесена в отдельную функцию:
function normalizeString(str) { return (str || '').normalize('NFC').trim().toLowerCase(); } function isAuthorExcluded(authorInfo) { const { name, id } = authorInfo; const normalizedName = normalizeString(name); const normalizedId = normalizeString(id); const excludedNamesNormalized = EXCLUDED_NAMES.map(normalizeString); const excludedIdsNormalized = EXCLUDED_IDS.map(normalizeString); const byName = !!normalizedName && excludedNamesNormalized.includes(normalizedName); const byId = !!normalizedId && excludedIdsNormalized.includes(normalizedId); return byName || byId; }
Если автор в исключениях, история не скрывается. Вместо этого нужно аккуратно перейти к следующей истории.
Как пропустить историю из списка исключений
Здесь важный момент: я специально не привязывался к конкретным кнопкам внутри интерфейса VK (например, к стрелкам). Вместо этого скрипт имитирует «человеческий» клик по области экрана чуть правее текущей истории.
Алгоритм:
Находим контейнер текущей истории
.stories_item_cont.Берём его размер через
getBoundingClientRect().Рассчитываем координату клика:
x— правая граница истории + 100 пикселей (но не дальше правого края окна);y— вертикальный центр (window.innerHeight / 2).
Находим элемент под этой точкой через
document.elementFromPoint(x, y).Отправляем по этому элементу события
mousedown,mouseup,click.
Код:
function goToNextStoryByScreenClick(activeStoryEl) { if (!activeStoryEl) return false; const cont = activeStoryEl.querySelector('.stories_item_cont'); if (!cont) return false; const rect = cont.getBoundingClientRect(); let x = rect.right + 100; const maxX = window.innerWidth - 10; if (x > maxX) x = maxX; if (x < 0) x = 0; let y = window.innerHeight / 2; if (y < 0) y = 0; const maxY = window.innerHeight - 10; if (y > maxY) y = maxY; const target = document.elementFromPoint(x, y) || document.body; const eventInit = { bubbles: true, cancelable: true, view: window, clientX: x, clientY: y, }; ['mousedown', 'mouseup', 'click'].forEach((type) => { const ev = new MouseEvent(type, eventInit); target.dispatchEvent(ev); }); return true; }
Такой подход менее хрупкий по отношению к внутренней разметке: даже если VK немного поменяет классы у кнопок, сам факт «клик справа от истории» с высокой вероятностью останется рабочим.
Как скрывается обычная история
Если автор не в списке исключений, скрипт проделыв��ет за пользователя три клика:
Открывает меню истории (иконка с тремя точками в шапке).
Нажимает пункт «Скрыть из историй».
Подтверждает действие в модальном окне.
Опорные элементы:
кнопка меню — по
data-testid="story_header_menu_button";пункт меню — по
data-testid="story_header_menu_action_add_blacklist";кнопка подтверждения —
button.FlatButton.FlatButton--primary.FlatButton--size-mс текстомСкрыть из историй.
На практике это выглядит как последовательность mousedown → mouseup → click по каждому из элементов с небольшими задержками между шагами.
Работа в неактивной вкладке
Один из приятных побочных эффектов: скрипт прекрасно живёт в фоне.
После запуска, например:
hideVkStoriesWithExclusions(200);
можно:
оставить вкладку VK открытой;
переключиться на другую вкладку или вообще в другое приложение;
через какое-то время вернуться и увидеть, что часть историй уже скрыта.
Браузеры по-разному оптимизируют работу вкладок в фоне, но для такого типа задач этого достаточно: даже если таймеры чуть замедлятся, скрипт всё равно отработает до конца, пока вкладка не будет полностью выгружена или страница не перезагружена.
Как использовать скрипт шаг за шагом
Краткая инструкция:
Открыть VK в браузере.
Открыть любую историю так, чтобы просмотрщик историй был активен и история была по центру.
Открыть консоль разработчика:
Chrome:
Windows / Linux:
Ctrl + Shift + I→ вкладка Console;macOS:
Cmd + Option + I→ вкладка Console.
Открыть файл
vk-stories-auto-hider.jsиз репозитория:
https://github.com/AleksPetrakov/vk-hide-stories-script/Скопировать весь код и вставить его в консоль, нажать Enter.
При необходимости отредактировать массивы
EXCLUDED_NAMESиEXCLUDED_IDSв начале файла.Запустить:
hideVkStoriesWithExclusions(200);Оставить вкладку VK открытой и заняться своими делами. Спустя какое-то время часть историй исчезнет из ленты, а истории людей из списков исключений останутся и будут продолжать показываться.
Почему не расширение
Логичный вопрос: почему это скрипт в консоли, а не полноценное расширение с UI.
На текущем этапе плюсы такого формата для меня перевешивают:
минимальный порог входа — никакой установки, один файл;
легко прочитать и проверить, что именно делает код;
удобнее экспериментировать с селекторами и таймингами;
нет лишних разрешений и фона, который живёт в браузере постоянно.
Если эта утилита приживётся и будет полезна не только мне, вариант с расширением никуда не исчезает. Там уже можно думать про UI для управления списками, сохранение настроек, статистику и так далее.
Планы дальше
Этот скрипт решает одну конкретную задачу: очистить ленту историй, не ломая при этом большую сеть контактов.
Очевидные следующие шаги:
сделать инструменты для более системного расширения сети контактов во VK (но без спама и агрессивной автоматизации);
попробовать перенести похожие идеи на другие социальные сети, где есть схожая проблема «шума»;
собрать небольшой набор утилит вокруг темы «гигиена социальной графа»: где-то чистим, где-то аккуратно растим.
Исходники, актуальная версия скрипта и документация — в репозитории:
https://github.com/AleksPetrakov/vk-hide-stories-script/
