说明

因为hexo可以很方便的在多个平台上免费部署,为了让自己的博客能uptime更久一段时间,很多老哥都和我一样,把自己的hexo博客在好多个平台上都部署了一份。

但是我一直想要一个功能,就是在别人访问的不是主站点的时候,提示他们,并让他们帮你查查主站是不是down了。这个功能即本文标题所述的“非主站提醒”

js脚本实现

其实实现起来并不复杂,一个js脚本就可以实现

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
document.addEventListener("DOMContentLoaded", function () {
// 直接定义允许的域名
const allowedDomain = "blog.musnow.top"; // 替换为你的主站域名
// 获取当前页面的域名
const currentDomain = window.location.hostname;

// 检查域名是否匹配
if (currentDomain !== allowedDomain) {
// 创建横幅提醒
const banner = document.createElement("div");
banner.id = "domainMismatchBanner";

// 动态生成链接
const link = document.createElement("a");
link.href = "https://" + allowedDomain; // 指向主站的链接
link.target = "_blank"; // 在新窗口或标签页中打开链接
link.style.color = "#b8dbff";
link.style.textDecoration = "underline";
link.innerText = "主站";

// 将链接添加到横幅内容中
banner.appendChild(document.createTextNode("您当前访问的是镜像站,如果"));
banner.appendChild(link);
banner.appendChild(document.createTextNode("无法访问,请联系站长,感谢!"));

// 将横幅应用CSS样式
banner.style.backgroundColor = "#fb7070";
banner.style.color = "#fff";
banner.style.textAlign = "center";
banner.style.padding = "3px";
banner.style.position = "fixed";
banner.style.bottom = "0"; // 将top改为bottom
banner.style.left = "0";
banner.style.width = "100%";
banner.style.zIndex = "1000";

// 将横幅添加到body
document.body.appendChild(banner);
}
});

把这个脚本复制,在hexo配置目录的source文件夹下创建一个js文件夹,将该脚本命名为domain_check.js并放入文件夹。

随后使用hexo-butterfly自带的head和bottom注入功能来引用这个脚本,建议在bottom里面引用。

1
2
3
4
5
6
7
8
9
# Inject
# Insert the code to head (before '</head>' tag) and the bottom (before '</body>' tag)
# 插入代码到头部 </head> 之前 和 底部 </body> 之前
inject:
head:
# - <script src="xxxx"></script>
bottom:
- <script src="/js/domain_check.js"></script> # 检查域名是否正确
# - <script src="xxxx"></script>

效果

效果如下,当访问主站的时候,不会有提示。当访问blog1这个镜像站的时候,就会有底部横幅提示。

image.png

image.png

手机上的效果也不差,对于一个提示来说足够了。

点我查看手机上的效果

Screenshot_20231229_214855.jpg

进一步优化

看到了一篇文章:网站被恶意镜像了该怎么办,博主的HEXO博客被某种方式恶意镜像了。其中提到了一个防盗链重定向跳转的js脚本,和本文的js有些类似。文中提到了可以用base64编码把自己的域名替换掉,避免出现其他人恶意镜像的时候,替换了js中的域名。

根据博主提供的示例,将本文的脚本改成如下形式,将域名进行base64编码,然后再在js脚本中转换为原文,最后判断是否为主站,以及是否为有效的域名。

如果您想给您的butterfly主题也添加一个样式提示,参考上文的教程添加js脚本,然后将如下脚本中的前两个base64编码内容改成你的域名就可以了。

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
document.addEventListener("DOMContentLoaded", function () {
// Base64编码后的主站域名
const encodedMainDomain = "YmxvZy5tdXNub3cudG9w"; // 对应 "blog.musnow.top"

// Base64编码后的有效域名列表,支持通配符
const encodedDomainList = [
'Ki5tdXNub3cudG9w', // 对应 '*.musnow.top'
'bXVzbm93cy5naXRodWIuaW8', // 对应 'musnows.github.io'
'bXVzbm93Lm5ldGxpZnkuYXBw' // 对应 'musnow.netlify.app'
];

// 对Base64编码后的域名和URL进行解码
function decodeBase64(encodedStr) {
return atob(encodedStr);
}

// 解码后的主站域名
const mainDomain = decodeBase64(encodedMainDomain);

// 解码后的域名列表
const domainList = encodedDomainList.map(decodeBase64);

// 判断域名是否在列表中
function isDomainInList(domain, domainList) {
// 将通配符域名转换为正则表达式
const convertToRegex = (wildcard) => {
return new RegExp('^' + wildcard.replace(/\./g, '\\.').replace(/\*/g, '.*') + '$');
};

return domainList.some(wildcardDomain => {
const regex = convertToRegex(wildcardDomain);
return regex.test(domain);
});
}

function addInfoBanner(preFix, url, urlText, postFix) {
// 创建横幅提醒
const banner = document.createElement("div");
banner.id = "domainMismatchBanner";

// 动态生成链接
const link = document.createElement("a");
link.href = "https://" + url + "/?utm_source=domaincheck"; // 设置链接的href属性为allowedDomain
link.target = "_blank"; // 在新窗口或标签页中打开链接
link.style.color = "#b8dbff";
link.style.textDecoration = "underline";
link.innerText = urlText;

// 将链接添加到横幅内容中
banner.appendChild(document.createTextNode(preFix));
banner.appendChild(link);
banner.appendChild(document.createTextNode(postFix));

// 将横幅应用CSS样式
banner.style.backgroundColor = "#fb7070";
banner.style.color = "#fff";
banner.style.textAlign = "center";
banner.style.padding = "3px";
banner.style.position = "fixed";
banner.style.bottom = "0"; // 将top改为bottom
banner.style.left = "0";
banner.style.width = "100%";
banner.style.zIndex = "1000";

// 将横幅添加到body
document.body.appendChild(banner);
}

// 获取当前页面的域名
const currentDomain = window.location.hostname;
// 判断当前域名是否在域名列表中
if (currentDomain == 'localhost') {
addInfoBanner('当前访问的是本地测试站点,可点击', mainDomain, '主站', '访问在线站点。');
}
else if (!isDomainInList(currentDomain, domainList)) {
addInfoBanner('当前域名非本站域名,可能是恶意镜像站,请点击', mainDomain, '主站', '正常访问本站。请联系站长举报非本站域名,感谢!');
} else if (currentDomain !== mainDomain) {
addInfoBanner('您当前访问的是镜像站,如果', mainDomain, '主站', '无法访问,请联系站长,感谢!');
}
});