-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathHabrCacheEnhanced.user.js
More file actions
92 lines (79 loc) · 4.76 KB
/
HabrCacheEnhanced.user.js
File metadata and controls
92 lines (79 loc) · 4.76 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// ==UserScript==
// @name HabrCacheEnhanced
// @description Перенаправляет скрытые из-за региональных ограничений, удалённые или скрытые в черновики записи с habr.com на различные зеркала. Redirects posts hidden due to regional restrictions, deleted, or hidden in drafts from habr.com to various mirror sites.
// @namespace habrcache
// @version 20260319.3
// @author dartraiden
// @match https://habr.com/*
// @updateURL https://github.com/dartraiden/HabrCacheEnhanced/raw/master/HabrCacheEnhanced.meta.js
// @downloadURL https://github.com/dartraiden/HabrCacheEnhanced/raw/master/HabrCacheEnhanced.user.js
// @supportURL https://github.com/dartraiden/HabrCacheEnhanced/issues
// ==/UserScript==
(function() {
'use strict'; // Включаем строгий режим для избегания типичных ошибок
/**
* Генерируем HTML-строку со списком всех доступных зеркал.
* @param {string} currentUrl - Полный URL текущей страницы
* @param {string} postId - ID статьи, извлечённый из URL
* @returns {string} - Готовый HTML-блок со ссылками
*/
const getLinksHtml = (currentUrl, postId) => {
const services = [
{ name: 'ITnan', url: `https://itnan.ru/post.php?c=1&p=${postId}` },
{ name: 'СоХабр', url: `https://sohabr.net/habr/post/${postId}/` },
{ name: 'SavePearlHarbor', url: `https://savepearlharbor.com/?p=${postId}` },
{ name: 'Archive.today', url: `https://archive.today/${currentUrl}`, target: '_blank' }
];
// Трансформируем массив объектов в массив HTML-строк и объединяем в одну строку
return services
.map(s => `<p style="margin: 4px 0;">• <a href="${s.url}" target="_blank" rel="noopener">${s.name}</a></p>`)
.join('');
};
/**
* Основная логика поиска места на странице и вставки ссылок.
*/
const inject = () => {
const currentUrl = window.location.href;
// Извлекаем ID статьи: ищем цифры между слэшами.
// Используем опциональный чейнинг ?.[1], чтобы не упасть с ошибкой, если ID не найден.
const postId = currentUrl.match(/\/(\d+)\/?/)?.[1];
if (!postId) return;
// Проверяем, не вставили ли мы ссылки ранее.
// Это КРИТИЧЕСКИ важно для MutationObserver, иначе будет бесконечный цикл.
if (document.querySelector('.tm-mirror-links-added')) return;
// Определяем возможные элементы-маркеры на странице
const errorBody = document.querySelector(".tm-error-message__body");
const errorCode = document.querySelector(".tm-error-message__code");
const regionalTitle = document.querySelector(".tm-regional-restriction__title");
let targetEl = null; // Куда вставляем
// Определяем тип ошибки
if (errorCode?.innerText === "403" && errorBody) {
targetEl = errorBody;
} else if (regionalTitle) {
targetEl = regionalTitle;
}
// Если подходящее место найдено — создаём и вставляем элемент
if (targetEl) {
const wrapper = document.createElement('div');
wrapper.className = 'tm-mirror-links-added'; // Помечаем класс-маркер
wrapper.style.marginTop = '16px';
wrapper.innerHTML = getLinksHtml(currentUrl, postId);
targetEl.appendChild(wrapper);
}
};
/**
* НАБЛЮДАТЕЛЬ (MutationObserver)
* Нужен, потому что Хабр — это динамическое приложение (SPA).
* Скрипты сайта могут перерисовать страницу в любой момент, удалив наши изменения.
*/
const observer = new MutationObserver((mutations) => {
inject();
});
// Начинаем следить за всем деревом элементов внутри body.
observer.observe(document.body, {
childList: true,
subtree: true
});
// Запускаем в первый раз вручную, на случай если страница уже загружена.
inject();
})();