@mhg/blog
Version:
1 lines • 2.97 MB
JSON
{"meta":{"title":"Magicland","subtitle":"宠辱不惊,看庭前花开花落;去留无意,望天上云卷云舒。","description":"宠辱不惊,看庭前花开花落;去留无意,望天上云卷云舒。「Be Yourself, Make a Difference.」 - Magic Island","author":"MHuiG","url":"https://blog.mhuig.top","root":"/"},"pages":[{"title":"所有分类","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"categories/index.html","permalink":"https://blog.mhuig.top/categories/","excerpt":"","text":""},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"404.html","permalink":"https://blog.mhuig.top/404","excerpt":"","text":"404 .cls-1 { fill: #ffc541; } .cls-2 { fill: #4e4066; } .cls-3 { fill: #6f5b92; } .cls-4 { fill: #f78d5e; } .cls-5 { fill: #fa976c; } .cls-6, .cls-7, .cls-8 { fill: #b65c32; } .cls-10, .cls-6 { opacity: 0.6; } .cls-7 { opacity: 0.4; } .cls-9 { fill: #f4b73b; } .cls-11 { fill: #f9c358; } .cls-12 { fill: #9b462c; } .cls-13 { fill: #aa512e; } .cls-14 { fill: #7d6aa5; } /* animations */ .wheel { animation: wheel-rotate 6s ease infinite; transform-origin: center; transform-box: fill-box; } @keyframes wheel-rotate { 50% { transform: rotate(360deg); animation-timing-function: cubic-bezier(0.55, 0.085, 0.68, 0.53); } 100% { transform: rotate(960deg) } } .clock-hand-1 { animation: clock-rotate 3s linear infinite; transform-origin: bottom; transform-box: fill-box; } .clock-hand-2 { animation: clock-rotate 6s linear infinite; transform-origin: bottom; transform-box: fill-box; } @keyframes clock-rotate { 100% { transform: rotate(360deg) } } #box-top { animation: box-top-anim 2s linear infinite; transform-origin: right top; transform-box: fill-box; } @keyframes box-top-anim { 50% { transform: rotate(-5deg) } } #umbrella { animation: umbrella-anim 6s linear infinite; transform-origin: center; transform-box: fill-box; } @keyframes umbrella-anim { 25% { transform: translateY(10px) rotate(5deg); } 75% { transform: rotate(-5deg); } } #cup { animation: cup-rotate 3s cubic-bezier(0.455, 0.03, 0.515, 0.955) infinite; transform-origin: top left; transform-box: fill-box; } @keyframes cup-rotate { 50% { transform: rotate(-5deg) } } #pillow { animation: pillow-anim 3s linear infinite; transform-origin: center; transform-box: fill-box; } @keyframes pillow-anim { 25% { transform: rotate(10deg) translateY(5px) } 75% { transform: rotate(-10deg) } } #stripe { animation: stripe-anim 3s linear infinite; transform-origin: center; transform-box: fill-box; } @keyframes stripe-anim { 25% { transform: translate(10px, 0) rotate(-10deg) } 75% { transform: translateX(10px) } } #bike { animation: bike-anim 6s ease infinite; } @keyframes bike-anim { 0% { transform: translateX(-1300px) } 50% { transform: translateX(0); animation-timing-function: cubic-bezier(0.47, 0, 0.745, 0.715); } 100% { transform: translateX(1300px) } } #rucksack { animation: ruck-anim 3s linear infinite; transform-origin: top; transform-box: fill-box; } @keyframes ruck-anim { 50% { transform: rotate(5deg) } } .circle { animation: circle-anim ease infinite; transform-origin: center; transform-box: fill-box; perspective: 0px; } .circle.c1 { animation-duration: 2s } .circle.c2 { animation-duration: 3s } .circle.c3 { animation-duration: 1s } .circle.c4 { animation-duration: 1s } .circle.c5 { animation-duration: 2s } .circle.c6 { animation-duration: 3s } @keyframes circle-anim { 50% { transform: scale(.2) rotateX(360deg) rotateY(360deg) } } .four, #ou { animation: four-anim cubic-bezier(0.39, 0.575, 0.565, 1) infinite; } .four.a { transform-origin: bottom left; animation-duration: 3s; transform-box: fill-box; } .four.b { transform-origin: bottom right; animation-duration: 3s; transform-box: fill-box; } #ou { animation-duration: 6s; transform-origin: center; transform-box: fill-box; } @keyframes four-anim { 50% { transform: scale(.98) } }"},{"title":"所有标签","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"tags/index.html","permalink":"https://blog.mhuig.top/tags/","excerpt":"","text":""},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"notes/index.html","permalink":"https://blog.mhuig.top/notes/","excerpt":".fa-secondary{opacity:.4} Note Book","text":".fa-secondary{opacity:.4} Note Book MHuiG の笔记本 速查表 LaTeX Fontawesome Twemoji 大数据 Flink Spark Hadoop Zookeeper Hive Flume Kafka Sqoop Azkaban NoSQL Echarts 操作系统 CentOS Ubuntu Windows OS 资料库 数据通信网络 Cryptography Django 51 PDF package manager proxy settings package mirror code Zeta Archive History of mathematics"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":false,"path":"havefun/Coco/index.html","permalink":"https://blog.mhuig.top/havefun/Coco/","excerpt":"","text":"Coco | The Cat of MHuiG Cocoalpha The Cat of MHuiG & A Computational Knowledge Engine /*************** cat-box ******************************/ #cat-box-1 { text-align:center; margin-top: 1.5rem; } #cat-box-2 { text-align:center; margin-top: 1.5rem; display: none; } #bongo-cat { width: 50%; margin: 0 0; } .typing-animation { -webkit-animation-timing-function:linear; animation-timing-function:linear; -webkit-animation-iteration-count:infinite; animation-iteration-count:infinite; -webkit-animation-duration:1200ms; animation-duration:1200ms; } path#f1-l1 { -webkit-animation-name:typing-f1-l1; animation-name:typing-f1-l1; } path#f1-l2 { -webkit-animation-name:typing-f1-l2; animation-name:typing-f1-l2; } path#f1-l3 { -webkit-animation-name:typing-f1-l3; animation-name:typing-f1-l3; } path#f2-l4 { -webkit-animation-name:typing-f2-l4; animation-name:typing-f2-l4; } path#f2-l5 { -webkit-animation-name:typing-f2-l5; animation-name:typing-f2-l5; } path#f2-l6 { -webkit-animation-name:typing-f2-l6; animation-name:typing-f2-l6; } path#f3-l7 { -webkit-animation-name:typing-f3-l7; animation-name:typing-f3-l7; } path#f3-l8 { -webkit-animation-name:typing-f3-l8; animation-name:typing-f3-l8; } path#f3-l9 { -webkit-animation-name:typing-f3-l9; animation-name:typing-f3-l9; } @-webkit-keyframes typing-f3-l9 { 0% { d:path(\"M8,25L8,25\"); } 82% { d:path(\"M8,25L8,25\"); } 92% { d:path(\"M8,25L96,25\"); } 100% { d:path(\"M8,25L96,25\"); } }@keyframes typing-f3-l9 { 0% { d:path(\"M8,25L8,25\"); } 82% { d:path(\"M8,25L8,25\"); } 92% { d:path(\"M8,25L96,25\"); } 100% { d:path(\"M8,25L96,25\"); } }@-webkit-keyframes typing-f3-l8 { 0% { d:path(\"M8,13L8,13\"); } 68% { d:path(\"M8,13L8,13\"); } 82% { d:path(\"M8,13L146,13\"); } 100% { d:path(\"M8,13L146,13\"); } }@keyframes typing-f3-l8 { 0% { d:path(\"M8,13L8,13\"); } 68% { d:path(\"M8,13L8,13\"); } 82% { d:path(\"M8,13L146,13\"); } 100% { d:path(\"M8,13L146,13\"); } } @-webkit-keyframes typing-f3-l7 { 0% { d:path(\"M0,1L0,1\"); } 60% { d:path(\"M0,1L0,1\"); } 68% { d:path(\"M0,1L96,1\"); } 100% { d:path(\"M0,1L96,1\"); } }@keyframes typing-f3-l7 { 0% { d:path(\"M0,1L0,1\"); } 60% { d:path(\"M0,1L0,1\"); } 68% { d:path(\"M0,1L96,1\"); } 100% { d:path(\"M0,1L96,1\"); } }@-webkit-keyframes typing-f2-l6 { 0% { d:path(\"M8,25L8,25\"); } 54% { d:path(\"M8,25L8,25\"); } 60% { d:path(\"M8,25L69,25\"); } 100% { d:path(\"M8,25L69,25\"); } }@keyframes typing-f2-l6 { 0% { d:path(\"M8,25L8,25\"); } 54% { d:path(\"M8,25L8,25\"); } 60% { d:path(\"M8,25L69,25\"); } 100% { d:path(\"M8,25L69,25\"); } }@-webkit-keyframes typing-f2-l5 { 0% { d:path(\"M8,13L8,13\"); } 44% { d:path(\"M8,13L8,13\"); } 54% { d:path(\"M8,13L114,13\"); } 100% { d:path(\"M8,13L114,13\"); } }@keyframes typing-f2-l5 { 0% { d:path(\"M8,13L8,13\"); } 44% { d:path(\"M8,13L8,13\"); } 54% { d:path(\"M8,13L114,13\"); } 100% { d:path(\"M8,13L114,13\"); } }@-webkit-keyframes typing-f2-l4 { 0% { d:path(\"M0,1L0,1\"); } 30% { d:path(\"M0,1L0,1\"); } 44% { d:path(\"M0,1L136,1\"); } 100% { d:path(\"M0,1L136,1\"); } }@keyframes typing-f2-l4 { 0% { d:path(\"M0,1L0,1\"); } 30% { d:path(\"M0,1L0,1\"); } 44% { d:path(\"M0,1L136,1\"); } 100% { d:path(\"M0,1L136,1\"); } }@-webkit-keyframes typing-f1-l3 { 0% { d:path(\"M8,25L8,25\"); } 24% { d:path(\"M8,25L8,25\"); } 30% { d:path(\"M8,25L61,25\"); } 100% { d:path(\"M8,25L61,25\"); } }@keyframes typing-f1-l3 { 0% { d:path(\"M8,25L8,25\"); } 24% { d:path(\"M8,25L8,25\"); } 30% { d:path(\"M8,25L61,25\"); } 100% { d:path(\"M8,25L61,25\"); } }@-webkit-keyframes typing-f1-l2 { 0% { d:path(\"M8,13L8,13\"); } 14% { d:path(\"M8,13L8,13\"); } 24% { d:path(\"M8,13L124,13\"); } 100% { d:path(\"M8,13L124,13\"); } }@keyframes typing-f1-l2 { 0% { d:path(\"M8,13L8,13\"); } 14% { d:path(\"M8,13L8,13\"); } 24% { d:path(\"M8,13L124,13\"); } 100% { d:path(\"M8,13L124,13\"); } }@-webkit-keyframes typing-f1-l1 { 0% { d:path(\"M0,1L0,1\"); } 14% { d:path(\"M0,1L160,1\"); } 100% { d:path(\"M0,1L160,1\"); } }@keyframes typing-f1-l1 { 0% { d:path(\"M0,1L0,1\"); } 14% { d:path(\"M0,1L160,1\"); } 100% { d:path(\"M0,1L160,1\"); } }#paw-right--up,#paw-right--down,#paw-left--up,#paw-left--down { -webkit-animation:blink 300ms infinite; animation:blink 300ms infinite; } #paw-right--up,#paw-left--down { -webkit-animation-delay:150ms; animation-delay:150ms; } @-webkit-keyframes blink { 0% { opacity:0; } 49% { opacity:0; } 50% { opacity:1; } }@keyframes blink { 0% { opacity:0; } 49% { opacity:0; } 50% { opacity:1; } }#laptop__code { -webkit-transform:rotateX(-37deg) rotateY(-46deg) rotateZ(-23deg) translateX(8px) translateY(20px) translateZ(-50px); transform:rotateX(-37deg) rotateY(-46deg) rotateZ(-23deg) translateX(8px) translateY(20px) translateZ(-50px); } /*************** search-form ******************************/ .search-form { display: -webkit-box; display: -webkit-flex; display: -ms-flexbox; display: flex; -webkit-box-pack: start; -webkit-justify-content: flex-start; -ms-flex-pack: start; justify-content: flex-start; margin-top: 1.5rem; } .search-form .search-input { -webkit-box-flex: 1; -webkit-flex: 1 1 auto; -ms-flex: 1 1 auto; flex: 1 1 auto; padding: .15rem .35rem .15rem .35rem; border: 1px solid #dbdbdb; border-right: 0; border-radius: 4px 0 0 4px; background-color: transparent; } .search-form #search-input { width: 100%; height: 100%; outline: 0; border: 0; background-color: transparent; } .search-form .search-button { padding: 0; border: 1px solid #dbdbdb; border-left: 0; border-radius: 0 4px 4px 0; } .search-form #search-button { padding: 5px 5px 0 5px; outline: 0; border: 0; background-color: transparent; color: var(--ic); } /*************** search-result ******************************/ #search-result-box hr { box-sizing: initial; height: 0; overflow: visible; margin: 15px 0; overflow: hidden; background: 0 0; border: 0; border-bottom: 1px solid #dfe2e5; border-bottom-color: #eee; height: .1em; padding: 0; margin: 24px 0; background-color: #e1e4e8; } .search-result__link { color: inherit; } var ajax = (options) => { options = options || {}; options.type = (options.type || \"GET\").toUpperCase(); options.dataType = options.dataType || \"json\"; const params = formatParams(options.data); let xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject(\"Microsoft.XMLHTTP\"); } xhr.onreadystatechange = function () { if (xhr.readyState === 4) { const status = xhr.status; let responseText = xhr.responseText; let responseXML = xhr.responseXML; try { responseText = JSON.parse(responseText); responseXML = JSON.parse(responseXML); } catch (e) { if (responseText) { // console.error(responseText) // console.error(e) } } if (status >= 200 && status < 300) { if (options.success) { try { options.success(responseText, responseXML); } catch (e) { if (responseText) { console.error(responseText); console.error(e); } } } } else { options.error && options.error(status, responseText); } } }; if (options.type == \"GET\") { xhr.open(\"GET\", options.url + \"?\" + params, true); xhr.send(null); } else if (options.type == \"POST\") { xhr.open(\"POST\", options.url, true); xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\"); xhr.send(params); } }; var formatParams = (data) => { const arr = []; for (const name in data) { arr.push(encodeURIComponent(name) + \"=\" + encodeURIComponent(data[name])); } arr.push((\"v=\" + Math.random()).replace(\".\", \"\")); return arr.join(\"&\"); }; function GetCocoAns(qustion){ ajax({ url: \"https://api.mhuig.top/CocoAPI\", type: \"GET\", data: { s: qustion, // accesstoken:window.AT.accesstoken, }, success: function (data) { if (data) { console.log(data) PutCocoAns(data) } }, error: function (status, data) { console.log(status, data) }, }); } function PutCocoAnsListItem(Item){ if(!Item) return \"\" return ` `+Item.htmlTitle+` `+Item.htmlSnippet+` `; } function PutCocoAns(data){ document.querySelector(\"#search-result\").innerHTML=` English answers provided by Coco: `+data.en+` Chinese answers provided by Coco: `+data.cn+` `; document.querySelector(\"#search-more-info\").innerHTML=` More info search On this Site ` document.querySelector(\"#search-info-site\").innerHTML=`Reference Links provided by Coco:` if(data.site){ let data_site=\"\" for (let i=0;i{ // CocoSearch() // } // loadJS(\"https://api.mhuig.top/ReCaptcha/getscript\") } document.querySelector(\"#search-input\").onkeydown = function() { if (13 == window.event.keyCode){ console.log(\"Enter\"); StartCocoOpenSearch(); } }; // test // let data={ // cn: \"Coco 是 MHuiG 的猫,Coco 也是一个计算知识引擎或答案引擎。\", // en: \"Coco is The Cat of MHuiG, Coco is also a computational knowledge engine or answer engine.\" // } // PutCocoAns(data) if(document.documentElement.clientWidth > 500){ document.querySelector(\"#fourier-cat-box\").innerHTML=`` document.querySelector(\"#fourier-cat\").contentWindow.addEventListener(\"click\",()=>{ document.querySelector(\"#fourier-cat-info\").innerHTML=` More info of this Fourier Transform Cat An Interactive Introduction to Fourier Transforms - Jez Swanson ` },false) }"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":false,"path":"havefun/access-analysis/index.html","permalink":"https://blog.mhuig.top/havefun/access-analysis/","excerpt":"","text":"Access analysis Access analysisalpha the access data analysis engine 数据自 2021-07-11 起开始统计 TLS Version Country Language Screen Size Display Size 访客时间分布 var ajax = (options) => { options = options || {}; options.type = (options.type || \"GET\").toUpperCase(); options.dataType = options.dataType || \"json\"; const params = formatParams(options.data); let xhr = null; if (window.XMLHttpRequest) { xhr = new XMLHttpRequest(); } else { xhr = new ActiveXObject(\"Microsoft.XMLHTTP\"); } xhr.onreadystatechange = function () { if (xhr.readyState === 4) { const status = xhr.status; let responseText = xhr.responseText; let responseXML = xhr.responseXML; try { responseText = JSON.parse(responseText); responseXML = JSON.parse(responseXML); } catch (e) { if (responseText) { // console.error(responseText) // console.error(e) } } if (status >= 200 && status < 300) { if (options.success) { try { options.success(responseText, responseXML); } catch (e) { if (responseText) { console.error(responseText); console.error(e); } } } } else { options.error && options.error(status, responseText); } } }; if (options.type == \"GET\") { xhr.open(\"GET\", options.url + \"?\" + params, true); xhr.send(null); } else if (options.type == \"POST\") { xhr.open(\"POST\", options.url, true); xhr.setRequestHeader(\"Content-Type\", \"application/x-www-form-urlencoded\"); xhr.send(params); } }; var formatParams = (data) => { const arr = []; for (const name in data) { arr.push(encodeURIComponent(name) + \"=\" + encodeURIComponent(data[name])); } arr.push((\"v=\" + Math.random()).replace(\".\", \"\")); return arr.join(\"&\"); }; function getPieChart(id, a, b) { var myChart = echarts.init(document.getElementById(id), \"shine\"); var option = { tooltip: { trigger: \"item\", formatter: \"{a} {b} : {c} ({d}%)\" }, series: [ { name: \"类别\", type: \"pie\", radius: \"55%\", center: [\"50%\", \"60%\"], data: b, emphasis: { itemStyle: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: \"rgba(0, 0, 0, 0.5)\", }, }, }, ], }; if(a){ option.legend={ orient: \"vertical\", left: \"left\", data: a } } myChart.setOption(option); } function getTimePieChart(id, h) { var myChart = echarts.init(document.getElementById(id), \"shine\"); function getdata(a) { for (var i = 0; i < h.length; i++) { if (\"\" + a == h[i].name) { return h[i].value; } } } function data() { var d = []; for (var i = 0; i < 24; i++) { d.push({ name: i + \"~\" + (i + 1), value: getdata(i) }); } return d; } var option = { tooltip: { trigger: \"item\", position: [\"48.5%\", \"49.2%\"], backgroundColor: \"rgba(50,50,50,0)\", textStyle: { color: \"yellow\", fontWeight: \"bold\" }, formatter: \"{d}%\", }, series: [ { type: \"pie\", radius: [\"5%\", \"70%\"], roseType: \"area\", color: [\"#3fa7dc\"], data: data(), labelLine: { normal: { show: false } }, label: { normal: { show: false } }, itemStyle: { normal: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: \"rgba(0, 0, 0, 0.5)\", }, emphasis: { shadowBlur: 10, shadowOffsetX: 0, shadowColor: \"rgba(0, 0, 0, 0.5)\", }, }, }, { name: \"\", type: \"gauge\", min: 0, max: 24, startAngle: 90, endAngle: 449.9, radius: \"82%\", splitNumber: 24, clockwise: false, animation: false, detail: { formatter: \"{value}\", textStyle: { color: \"#63869e\" } }, detail: { show: false }, axisTick: { show: false }, axisLine: { lineStyle: { color: [ [0.25, \"#63869e\"], [0.75, \"#ffffff\"], [1, \"#63869e\"], ], width: \"40%\", shadowColor: \"#0d4b81\", shadowBlur: 40, opacity: 1, }, }, splitLine: { length: 5, lineStyle: { color: \"#ffffff\", width: 2 }, }, axisLabel: { formatter: function (v) { return v ? v : \"\"; }, textStyle: { color: \"red\", fontWeight: 700 }, }, itemStyle: { normal: { color: \"green\", width: 2 } }, }, { name: \"\", type: \"gauge\", min: 0, max: 24, startAngle: 90, endAngle: 449.9, radius: \"72%\", splitNumber: 24, clockwise: false, animation: false, detail: { formatter: \"{value}\", textStyle: { color: \"#63869e\" } }, detail: { show: false }, axisTick: { show: false }, axisLine: { lineStyle: { color: [[1, \"#E8E8E8\"]], width: \"10%\", opacity: 0.8, }, }, splitLine: { show: true, length: \"92%\", lineStyle: { color: \"grey\", width: \"1\" }, }, axisLabel: { show: false, formatter: function (v) { return v ? v : \"\"; }, textStyle: { color: \"#fb5310\", fontWeight: 700 }, }, itemStyle: { normal: { color: \"green\", width: 2, borderWidth: 3 }, }, }, ], }; myChart.setOption(option); } var loadscript = (src) => { return new Promise(resolve => { setTimeout(function () { var HEAD = document.getElementsByTagName(\"head\")[0] || document.documentElement; var script = document.createElement(\"script\"); script.setAttribute(\"type\", \"text/javascript\"); script.setAttribute(\"src\", src); script.onload = resolve HEAD.appendChild(script); }); }); } randomStr = function (num) { return Math.random().toString(36).slice(-num); }, randomNum = function (num) { return Math.ceil(Math.random() * (num - 1)) + 1; }; function GetAnalyticsResults() { loadscript(\"https://cdn.jsdelivr.net/npm/echarts@4.8.0/dist/echarts.min.js\").then(()=>{ loadscript(\"https://cdn.jsdelivr.net/npm/mhg@0.0.0/js/echarts.shine.js\").then(()=>{ ajax({ url: \"https://cdn.jsdelivr.net/gh/MHG-LAB/Web-Log-Analytics-Results@main/results.json?nocache=1&t=\"+new Date().getTime()+\"&\"+randomStr(randomNum(4)) + '=' + randomStr(randomNum(6)), type: \"GET\", success: function (data) { // console.log(data) window.WebLogAnalyticsResults=data AnalyticsResults() }, error: function (status, data) { console.log(status, data) }, }); }) }) } function AnalyticsResults() { getPieChart(\"tlsversion\", window.WebLogAnalyticsResults.TlsVersion.legend, window.WebLogAnalyticsResults.TlsVersion.series); getPieChart(\"country\", window.WebLogAnalyticsResults.CfIpCountry.legend, window.WebLogAnalyticsResults.CfIpCountry.series); getPieChart(\"language\", window.WebLogAnalyticsResults.Language.legend, window.WebLogAnalyticsResults.Language.series); getPieChart(\"screensize\", 0, window.WebLogAnalyticsResults.ScreenSize.series); getPieChart(\"displaysize\", 0, window.WebLogAnalyticsResults.DisplaySize.series); getTimePieChart(\"visitstime\", window.WebLogAnalyticsResults.Hours.series); } GetAnalyticsResults()"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"pages/about/index.html","permalink":"https://blog.mhuig.top/pages/about/","excerpt":"","text":"关于我 MHuiG 关于我关于本站>_ 热爱技术,热爱创造。 正在探秘事物本质与联系的探索者。 喜欢遥望星星存在过的地方。 博客大事记 本站多线部署 选择网络最佳线路 https://blog.mhuig.top Cloudflare / GitHub Pages https://cfpages.blog.mhuig.top Cloudflare Pages https://vercel.blog.mhuig.top Vercel https://netlify.blog.mhuig.top Netlify 我已使用 GPG 签名验证了我的身份,该签名证明了我对该域的所有权。 请参阅此处的加密证明: Keybase - claimed ownership of mhuig.top via dns 我的 GPG 公钥托管在 Keybase-mhuig 上。您可以通过以下方式拉出并导入我的 GPG 公钥: curl https://keybase.io/mhuig/pgp_keys.asc | gpg --import 在 Alone 的海洋里有一只孤独的鲸,没有放弃海洋的它终会在最后找到同频率的伙伴。 —52 赫兹的鲸 var now = new Date(); function SiteTime() { try{ var grt= new Date(\"08/19/2019 21:23:12\"); now.setTime(now.getTime()+250); days = (now - grt ) / 1000 / 60 / 60 / 24; dnum = Math.floor(days); hours = (now - grt ) / 1000 / 60 / 60 - (24 * dnum); hnum = Math.floor(hours); if(String(hnum).length ==1 ){hnum = \"0\" + hnum;} minutes = (now - grt ) / 1000 /60 - (24 * 60 * dnum) - (60 * hnum); mnum = Math.floor(minutes); if(String(mnum).length ==1 ){mnum = \"0\" + mnum;} seconds = (now - grt ) / 1000 - (24 * 60 * 60 * dnum) - (60 * 60 * hnum) - (60 * mnum); snum = Math.round(seconds); if(String(snum).length ==1 ){snum = \"0\" + snum;} document.getElementById(\"timeDate\").innerHTML = \"本站已安全运行 \"+dnum+\" 天 \"; document.getElementById(\"times\").innerHTML = hnum + \" 小时 \" + mnum + \" 分 \" + snum + \" 秒\"; }catch(e){} } if(typeof SiteTimeFlag==\"undefined\"){ var TimeInterval=setInterval(SiteTime,250); window.SiteTimeFlag=true; } ////////////////////////// screen_container ////////////////////////// function screen_container(){ if(volantis.linux){ TinyCore() }else{ volantis.linux={} buildroot() } } function buildroot(){ var emulator = window.emulator = new V86Starter({ wasm_path: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/build/v86.wasm\", memory_size: 128 * 1024 * 1024, vga_memory_size: 8 * 1024 * 1024, screen_container: document.getElementById(\"screen_container\"), bios: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/bios/seabios.bin\", }, vga_bios: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/bios/vgabios.bin\", }, cdrom: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/images/linux.iso\", }, autostart: true, }); var data = \"\"; emulator.add_listener(\"serial0-output-char\", function(char){ if(char !== \"\\r\"){ data += char; } if(data.endsWith(\"(none) login: \")){ /*var el=document.getElementById(\"loading\") if(el){ el.style.display = \"none\"; }*/ emulator.keyboard_send_text(\"echo Welcome to MHuiG\\\\'s Blog!\"); emulator.keyboard_send_keys([13]); } }); emulator.add_listener(\"serial0-output-line\", function(line){ //console.log(line) }); emulator.add_listener(\"download-progress\", function(e){ show_progress(e); }); } function TinyCore(){ var emulator = window.emulator = new V86Starter({ wasm_path: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/build/v86.wasm\", memory_size: 128 * 1024 * 1024, vga_memory_size: 8 * 1024 * 1024, screen_container: document.getElementById(\"screen_container\"), bios: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/bios/seabios.bin\", }, vga_bios: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/bios/vgabios.bin\", }, cdrom: { url: \"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/images/Core-11.1.iso\", }, autostart: true, network_relay_url: \"wss://relay.widgetry.org/\", }); emulator.add_listener(\"download-progress\", function(e){ show_progress(e); }); var checkExistBoot = setInterval(function() { try { if(document.querySelector(\"#screen_container > div > div:nth-child(7) > span:nth-child(1)\").innerHTML!=\"boot: \") return clearInterval(checkExistBoot); emulator.keyboard_send_keys([13]); } catch (error) {} },100); var checkExistStart = setInterval(function() { try { if(document.querySelector(\"#screen_container > div > div:nth-child(5) > span:nth-child(1)\").innerHTML!=\"tc@box:~$ \")return clearInterval(checkExistStart); emulator.keyboard_send_text(\"echo Welcome to MHuiG\\\\'s Blog!\"); emulator.keyboard_send_keys([13]); } catch (error) {} },100); } function pjax_screen_container(){ if(document.querySelector(\"#screen_container\")){ volantis.dom.$(document.querySelector(\"#tab-aboutme > ul > li:nth-child(4) > a\")).on(\"click\",function(){ volantis.js(\"https://cdn.jsdelivr.net/npm/imbox@0.0.9/linux/build/libv86.js\",screen_container) volantis.dom.$(document.querySelector(\"#tab-aboutme > ul > li:nth-child(1),#tab-aboutme > ul > li:nth-child(2),#tab-aboutme > ul > li:nth-child(3),#tab-aboutme > ul > li:nth-child(5) > a\")).on(\"click\",function(){ try{emulator.destroy()}catch(e){} }); }); } } pjax_screen_container(); function chr_repeat(chr, count){ var result = \"\"; while(count-- > 0){ result += chr; } return result; } function show_progress(e){ var el = document.getElementById(\"loading\"); if(!el) return el.style.display = \"block\"; if(e.file_name.endsWith(\".wasm\")){ const parts = e.file_name.split(\"/\"); el.textContent = \"Fetching \" + parts[parts.length - 1] + \" ...\"; return; } if(e.file_index === e.file_count - 1 && e.loaded >= e.total - 2048){ // last file is (almost) loaded el.textContent = \"Done downloading. Starting now ...\"; return; } var line = \"Downloading images \"; if(typeof e.file_index === \"number\" && e.file_count){ line += \"[\" + (e.file_index + 1) + \"/\" + e.file_count + \"] \"; } var progress_ticks = 0; if(e.total && typeof e.loaded === \"number\"){ var per100 = Math.floor(e.loaded / e.total * 100); per100 = Math.min(100, Math.max(0, per100)); var per50 = Math.floor(per100 / 2); line += per100 + \"% [\"; line += chr_repeat(\"#\", per50); line += chr_repeat(\" \", 50 - per50) + \"]\"; }else{ line += chr_repeat(\".\", progress_ticks++ % 50); } el.textContent = line; } volantis.pjax.push(pjax_screen_container) /////////////////////////////////////////////////////////////////////////"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"pages/beer/index.html","permalink":"https://blog.mhuig.top/pages/beer/","excerpt":"","text":"🍻 Give Me A Cup Of Beer? 🍻 Give Me A Cup Of Beer? ETH0x6E5AfEfde2DD46935ff23e2F33033888307528f2"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"pages/rss/index.html","permalink":"https://blog.mhuig.top/pages/rss/","excerpt":"","text":"RSS 订阅 RSS 订阅 Really Simple Syndication AtomAtom/atom.xml RSS2RSS2/rss2.xml"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"pages/friends/index.html","permalink":"https://blog.mhuig.top/pages/friends/","excerpt":"","text":"My Friends Links My Friends 来自 GitHub 的小伙伴们:以下友链通过 GitHub Issue 提交: Thanks本博客是在以下框架技术和开源服务的支持下搭建起来的: HexoVolantisGithubUnsplashjsDelivrVercelcloudflare 欢迎互换友链! 如何自助添加友链?先友后链,在我们有一定了解了之后才可以交换友链,除此之外,您的网站还应满足以下条件: 合法的、非营利性、无商业广告 有实质性原创内容的 HTTPS 站点 第一步:新建 Issue 新建 GitHub Issue 按照模板格式填写并提交。为了提高图片加载速度,建议优化头像:打开 压缩图 上传自己的头像,将图片尺寸调整到 96px 后下载。将压缩后的图片上传到 ooxx.ooo 免费图床 并使用此图片链接作为头像。 第二步:添加友链并等待管理员审核 请添加本站到您的友链中,如果您也使用 issue 作为友链源,只需要告知您的友链源仓库即可。您可以添加本站的任何一个域,下面只是一个例子。title: MHuiGavatar: https://fastly.jsdelivr.net/npm/mhg@latesturl: https://mhuig.topscreenshot: https://fastly.jsdelivr.net/npm/mhgoos@0.0.1655533137084/web.pngdescription: 「Be Yourself Make a Difference」keywords: 搞事情🤣待管理员审核通过,添加了 active 标签后,回来刷新即可生效。 如果您需要更新自己的友链,请直接修改 issue 内容,大约 3 分钟内生效,无需等待博客更新。如果无法修改,可以重新创建一个。"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"pages/talk/index.html","permalink":"https://blog.mhuig.top/pages/talk/","excerpt":"","text":"碎言碎语 volantis.layoutHelper(\"page-plugins\",``,{pjax:false}) volantis.css(\"https://static.mhuig.top/npm/@copoko/hole@1.0.0/dist/Hole.css\") volantis.js(\"https://static.mhuig.top/npm/@copoko/hole@1.0.0/dist/Hole.js\").then(() => { new Hole({ api: \"https://cpk.mhuig.top\" }); }) function HoleDark() { if (volantis.dark.mode == \"light\") { document.querySelector(\".hole\") && document.querySelector(\".hole\").classList && document.querySelector(\".hole\").classList.remove(\"dark-mode\"); } else { document.querySelector(\".hole\") && document.querySelector(\".hole\").classList && document.querySelector(\".hole\").classList.add(\"dark-mode\"); } } window.HoleLoadCardCallback = ()=>{ HoleDark() volantis.dark.push(HoleDark) } .hole img { display: inline !important; }"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":false,"path":"pages/time-machine/index.html","permalink":"https://blog.mhuig.top/pages/time-machine/","excerpt":"","text":"Time Machine Youth Youth is not a time of life; it is a state of mind; 青春不是年华,青春是一种心境。 it is not a matter of rosy cheeks, red lips and supple knees; 它不是红颜,朱唇,柔膝; it is a matter of the will, a quality the imagination, 它是一种深沉的意志,一种恢弘的想象, a vigor of the emotions; 和饱满的热情; it is the freshness of the deep springs of life. 它是我们生命之泉在不息的涌动。 Nobody grows old merely by a number of years. 岁月有加,并未垂老。 We grow old by deserting our ideals. 抛弃理想,方堕暮年。"},{"title":"","date":"2025-11-20T10:18:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":false,"path":"pages/timeline/index.html","permalink":"https://blog.mhuig.top/pages/timeline/","excerpt":"","text":"博客大事记 大事记Long Long Ago博客大事记 2025.11.20 翻新全站 categories tags description 完成 2022.09.06 PDF 标签实现懒加载 2022.05.13 全站内容按照体系整理 创建 Notes 页面 2022.05.08 图片压缩使用 webp 格式 全站 webp 时代 2022.02.14 更新使用 GitHub Issues 友链系统 2022.02.13 本站 CDN cdn.jsdelivr.net 使用 Cloudflare 加速: static.mhuig.top 2021.10.11 启用 Giscus 评论系统 2021.10.12 创建 博客大事记页面 很久很久以前Wikipedia"},{"title":"安装配置 Space","date":"2022-06-12T08:27:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/a.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/a","excerpt":"","text":"CoPoKo 目前仅限部署于 CloudFlare Workers。 我们假设您已经安装了 CloudFlare Workers,您已经在 CloudFlare Workers 上注册了一个新的账户。并且您已经在 CloudFlare DNS 上创建了一个新的域名。 前期准备 在 cloudflare 官网注册账号,找到并开通使用 workers。 安装 git,安装方法请参考搜索引擎。 安装 Node.js 和 npm,安装方法请参考搜索引擎。打开命令行(windows 用户可直接在资源管理器输入 cmd 并回车)如果在命令行输入以下命令成功输出版本号,即安装成功。node -vnpm -v 安装 Wranglernpm install -g wrangler 请参阅详细的安装说明。如果在命令行输入以下命令成功输出版本号,即安装成功。wrangler -v 使用您的 Cloudflare 帐户对 Wrangler 进行身份验证要启用部署到 Cloudflare,您需要通过 Wrangler 登录到您的 Cloudflare 帐户来进行身份验证。wrangler login 当 Wrangler 自动打开浏览器显示 Cloudflare 的同意屏幕时,请单击允许按钮。这会向 Wrangler 发送 API 令牌。 安装部署 CoPoKo / SpaceCoPoKo/Space 包含核心模块 Telegram 机器人和控制面板。 克隆 CoPoKo / Space 项目并解压 git clone https://github.com/CoPoKo/Space.git 复制 wrangler.toml.template 内容建立新配置文件 wrangler.toml 修改配置文件可参考 cloudflare 官方文档account_id:您的 Cloudflare 帐户 ID, 详见下文 ACCOUNTID。name:您的 Cloudflare Worker 名称route:您的 Cloudflare Worker 路由kv_namespaces:您的 Cloudflare KV在文件夹目录打开命令行运行以下命令, 创建一个 KV 桶: wrangler kv:namespace create \"SpaceKV\" 根据提示将输出的内容粘贴在 wrangler.toml 文件中 kv_namespaces 位置。 修改配置文件 [vars] 配置 (1) 添加您的 Worker 信息 WORKERNAME : Worker 名称,同上文 name WORKERROUTE : Worker 路由, 同上文 route (2) 添加您的 Cloudflare 帐户信息 AUTHEMAIL : Cloudflare 帐户邮箱 AUTHKEY : CloudFlare 的 Global API Key 在这里获取 ACCOUNTID : Cloudflare 帐户 ID, Worker 界面中的账户 ID ZONEID : Worker 路由域名区域 ID ,转到 网站 》您的域名 》概述 右下角 (3) 添加您的 控制面板配置信息 AUTH_PAGE : 控制面板登录页面地址 (随便写个例如 /AUTH_PAGE1919810) MY_REFERER : 控制面板 API 请求的 Referer 检查字段 可以为空但是不可以填错 错误的 Referer 会返回 403 SpaceName : 控制面板登录用户名 SpacePassword : 控制面板登录密码 (4) 添加您的 reCAPTCHA 信息 到 这里 注册一个 API 密钥对 reCAPTCHA_CLIENT : reCAPTCHA 客户端秘钥 reCAPTCHA_SERVER : reCAPTCHA 服务端秘钥 (5) 添加您的 COPOKO_API 配置信息 COPOKO_API : CoPoKo API 详见后文。 将 CoPoKo/service-api-by-vercel 部署到 vercel 并获取路径为COPOKO_API的值,你可以使用配置文件中我部署的公共 API,资源有限请合理使用。 安装配置 service api/wiki/CoPoKo/b (6) 添加您的 Telegram 机器人 配置信息 Telegraf_BOT_TOKEN : Telegram 机器人秘钥 详见后文。 Telegraf_BOT_WEBHOOK : Telegram 机器人 WEBHOOK (随便写个例如 /Telegraf_BOT_WEBHOOK114514 记住这个配置后面还会用到) 安装配置 Telegram 机器人/wiki/CoPoKo/c (7) 其他配置信息 AES_KEY : AES 加密秘钥,建议手滚键盘。丢失秘钥即为丢失数据。 请不要向任何人公开您的配置信息。请将配置文件视为机密。 发布wrangler publish"},{"title":"开放 API 接口","date":"2022-06-13T03:10:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/api.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/api","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 浏览器访问 https://example.workers.dev/ 这里列举了几个 开放 API 接口,实际上不止这几个,详见源码。 笔者在这里简单列举一下。 必应图片API 路径: https://example.workers.dev/bing 参数:?day=<Number>0-6,0 表示今天,1 表示明天,依次类推。 https://example.workers.dev/bing?day=3 获取图片https://example.workers.dev/bing/info?day=3 获取图片详细信息https://example.workers.dev/bing/copyright?day=3 获取图片版权信息 SitichAPI 路径: https://example.workers.dev/sitich 毒鸡汤API 路径: https://example.workers.dev/soul 一言API 路径: https://example.workers.dev/hitokoto Unsplash 图片API 路径: https://example.workers.dev/unsplash 参数:?keywords=<S>,<S>,<S> https://example.workers.dev/unsplash?keywords=cat,dog,bird ACG 图片API 路径: https://example.workers.dev/acg 访问 IP 信息API 路径: https://example.workers.dev/ipinfo IPFSAPI 路径: https://example.workers.dev/ipfs OPEN CDNAPI 路径: https://example.workers.dev/npm/ :unpkg.comhttps://example.workers.dev/gh/ :fastly.jsdelivr.nethttps://example.workers.dev/wp/ :fastly.jsdelivr.nethttps://example.workers.dev/twemoji/ :twemoji.maxcdn.comhttps://example.workers.dev/gitraw/ :raw.githubusercontent.comhttps://example.workers.dev/gist/ :gist.github.comhttps://example.workers.dev/ajax/libs/ :cdnjs.cloudflare.com Github EventAPI 路径: https://example.workers.dev/github-event 调色板API 路径: https://example.workers.dev/color DNS 查询API 路径: https://example.workers.dev/dns/ali/get/host?name=github.com /dns/:upstream:/:way:/:host:?name=xxx&type=xxx&edns_client_subnet=x.x.x.x/dns/dns/get/dns/ali/get/host 参数 参数用途 name 需要解析的域名 type 解析形式, A or AAAA or CNAME 等等 edns_client_subnet EDNS 的 ip, 默认开启为本机 ip, 开启此项功能可提高解析精准度. way 获取方式,默认 doh 方式,可使用以下参数: doh get host 是否转化为host格式 [仅在 type 为 A 或 AAAA 格式下生效] upstream 上游 DNS 解析, 默认为 CloudFlare 回源 < 1ms 可使用以下参数: google ali dnspod 注:DoH 推荐直接选用 https://dns.alidns.com/dns-query ,而不是用本 API 的反代接口"},{"title":"安装配置 Telegram 机器人","date":"2022-06-13T01:12:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/c.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/c","excerpt":"","text":"笔者假设您已经注册了 Telegram 账户,并知道如何使用它。 此处可能需要一些魔法 创建 Telegram 机器人账户和 @BotFather 对话,使用 /newbot 命令进行创建,根据要求进行设定, 我们需要的是创建成功后返回的 the token to access the HTTP API。这个 token 就是我们需要的 CoPoKo / Space 配置文件中的Telegraf_BOT_TOKEN。 笔者在这里创建了 CoCo。 配置 机器人 WEBHOOK还记得之前在 CoPoKo / Space 配置文件中的 Telegraf_BOT_WEBHOOK吗? 我们通过浏览器访问以下路径进行配置 https://api.telegram.org/bot<token>/setWebhook?url=<url> 其中 <token> 是 CoPoKo / Space 配置文件中的 Telegraf_BOT_TOKEN,<url> 是我们的机器人的 Webhook 路径。例如: https://api.telegram.org/bot2044977018:AAHbt-RyEklq3MDG0w6HqrO84lS7MaWz_Gz/setwebhook?url=https://example.workers.dev/Telegraf_BOT_WEBHOOK114514 配置群组访问权限 如果不建立群组,则忽略此步骤。 和 @BotFather 对话, /mybots 命令可以查看所有的机器人。 在 Bot Settings 中配置: Allow Groups : enabled Groups Privacy : disabled"},{"title":"CoPoKo Space 初体验","date":"2022-06-13T02:35:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/d.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/d","excerpt":"","text":"笔者假设您已经顺利完成了前面的所有步骤;并且您的 CoPoKo Space 已经安装完成。 假定您的 Worker 路由是 https://example.workers.dev/。 开放 API 接口浏览器访问 https://example.workers.dev/ 这里列举了几个 开放 API 接口,实际上不止这几个,详见源码。 登录 CoPoKo Space假定您的 AUTH_PAGE 配置是 /AUTH_PAGE1919810。 浏览器访问 https://example.workers.dev/AUTH_PAGE1919810 输入 username 和 password,点击 Sign in 登录。 username 和 password 分别是之前配置的 SpaceName 和 SpacePassword。 登录成功后,您会看到一个 CoPoKo Space 的 Home 页。 Space Setting 基本操作点击 Setting 选项卡。 点击 Add Project。 输入 project 名称,点击 Add 点击加号图标 + 展开项目设置。 点击 Add KV,输入 key Value 点击 Add。"},{"title":"","date":"2022-06-12T08:27:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/index.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/","excerpt":"CoPoKo","text":"CoPoKo CoPoKo CoPoKo 是一系列开源工具包,由核心模块 Telegram 机器人和控制面板, 以及周边工具和系统接口组成。简而言之,CoPoKo 是 MHuiG 捣鼓的一堆破烂玩意儿。 Why谁不想拥有一个可爱的机器人助手呢? 喵喵喵https://t.me/+Xy1JwLq4rWo1M2M1 许可协议CoPoKo 采用 GPL3.0 Only 开源许可协议。 CoPoKoCopyright (C) 2018 CoPoKo TeamThis program is free software: you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation, either version 3 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program. If not, see <https://www.gnu.org/licenses/>."},{"title":"Calendar","date":"2022-06-13T07:40:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/calendar.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/calendar","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 笔者这里默认您会使用日历。 简介众所周知,ToDo 都是用来咕咕咕的。 配置信息暂无配置。 使用Telegram 机器人部分咕咕咕了。 CoPoKo Space 部分直接上图:"},{"title":"安装配置 Service Api","date":"2022-06-13T01:12:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/b.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/b","excerpt":"","text":"笔者假设您已经注册了 vercel 服务,并知道如何使用它。 在实际的开发中发现 CloudFlare Workers 存在种种限制,例如它不支持 nodejs 环境,存在 CPU 运行时间限制等等,所以我将存在 CPU 运行时间限制的部分放到了 Vercel 上部署。 将 CoPoKo/service-api-by-vercel 部署到 vercel 并获取路径为配置文件中 COPOKO_API 的值,你可以使用配置文件中我部署的公共 API,资源有限请合理使用。 注:关于不支持 nodejs 环境,我随便说几句,可以使用 browserify 解决,如果你使用了 webpack 直接推荐 node-polyfill-webpack-plugin,这里吐槽一下 browserify 的 net tls 库已经六年没更新了,甚至不支持 es6. 当然换个思路可以将 CloudFlare Workers 迁移到其他平台,简而言之就是添加 node-fetch 的 polyfill,例如 mpl.js. 公共 API我部署了一个公共 API,你可以直接使用它,资源有限请合理使用。 https://api.copoko.vercel.app 注:Vercel 免费计划有 100 GB / 月 使用限制,当达到限制后我将关闭公共 API。 部署 service api 点击上方按钮,跳转至 Vercel 进行部署。 如果你未登录的话,Vercel 会让你注册或登录,请使用 GitHub 账户进行快捷登录。 此处省略一万字。 部署成功后,直接访问路径为配置文件中 COPOKO_API 的值即可。"},{"title":"问答系统","date":"2022-06-13T06:54:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/qa.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/qa","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。笔者这里默认您会使用 Telegram。 简介问答系统是指 Telegram 机器人的 QA 系统。 面板配置信息https://example.workers.dev/space/dash/setting 打开 Setting 面板,新建一个 Project 名为 TelegrafBot。 ADMIN_ID: 管理员用户 ID [https://t.me/userinfobot]ADMIN_GROUP_ID: 私有群组 IDPUBLIC_GROUP_ID: 公开群组 IDTEST_GROUP_ID: 测试群组 ID 这里有三个 GROUP ID,分别是私有群,公开群,测试群;ID 是数字。如何获取群组 ID,请参考下文输入命令 >ChatID。测试群是笔者开发测试使用,私有群中会有 Telegram 机器人的报错日志信息。 问答系统的配置文件问答系统的配置文件是 yml 格式https://github.com/CoPoKo/Space/blob/main/src/Space/TelegrafBot/BotModel/Text/workflows.yml - workflow: - random: 1 reply: 然后呢? - re: ^?$ reply: ??? - includes: - 来点 - 涩图 reply: 让我找找 - random: 100 action: EmojiToSticker workflow 被称为工作流,每一个工作流都是一个判断列表,一个工作流中只能有一个 action 被触发,触发后跳出执行下一个工作流。 action 被称为动作,每一个动作都是一个函数,动作的函数名称是 action: 后面的函数名称。 reply 是一种特殊的动作,它的动作是 reply: 后面的文本。 re 是一个正则表达式判断条件。 includes 是一个正则表达式列表判断条件,必须全部满足才会触发 action。 random 是一个随机触发判断条件,赋值 0-100。 - workflow: - admin: - re: 在吗 reply: 主人我在 else: - re: 在吗 reply: 爪巴 admin 是一个管理员判断条件,匹配 ADMIN_NAME 配置信息中的用户名,如果匹配则触发 admin 工作流,否则触发 else 工作流。 - workflow: - cmd: help reply: no help - cmd: unsplash arg: k: nature,water,sky,blue,sea action: Unsplash cmd 是命令判断条件,匹配 cmd 配置信息中的命令。 命令以 > 开头。arg 是 action 中的默认参数列表。参数以 - 开头,或者按照顺序排列可以省略 - (但是省略 - 会有 bug)。例如: >unsplash >unsplash -k cat >unsplash dog 使用此处省略一万字,请读者自行探索。 喵喵喵https://t.me/+Xy1JwLq4rWo1M2M1"},{"title":"NPM Upload","date":"2022-06-13T05:50:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/npm-upload.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/npm-upload","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 笔者这里默认您会使用 npm 发布 package。 简介黑盒:将资源上传到 npm,并返回 CDN 链接。 Static Files => CoPoKo Space/Telegram Bot => Cloudflare Worker => GitHub Actions => NPM => CDN 配置信息导入 CoPoKo / Whiteholehttps://github.com/CoPoKo/Whitehole/generate 点击上方链接,这将从 CoPoKo/Whitehole 使用模板导入项目。 请不要尝试 fork CoPoKo / Whitehole 这个项目,这可能直接让你进入笔者的 GitHub 黑名单中。 修改 https://github.com/CoPoKo/Whitehole/blob/main/npm-version-bump.js 为您自己的 npm package 信息,与下文配置对应。 在设置中打开 actions,打开 actions 写入权限 settings > secrets > actions 添加环境变量 NPM_TOKEN,这是你的 NPM 发布秘钥。 https://example.workers.dev/space/dash/setting 打开 Setting 面板,新建一个 Project 名为 NPMUpload。 GITHUB_TOKEN :你的 GITHUB 秘钥 需要写入 repo 权限 例如: ghp_pX3DeRmfBkBlRXrpEtJls6upx22UDx4BxHixGITHUB_BRANCH :GITHUB 分支名称 例如:mainGITHUB_REPO :GITHUB 仓库名称 例如:CoPoKo/WhiteholeNPM_PKG :npm 包名称 例如:@copoko/whitehole,与上文 npm-version-bump.js 配置对应。 使用这里以上传一个 vue.js 为例。 CoPoKo Space 选择文件然后点击 提交 按钮即可。 在 CoPoKo Space Home 页面,你甚至还可以查看到上传的文件记录。 Telegram 机器人 默认配置只允许 admin 上传, 如果笔者没有记错的话。"},{"title":"Maxwell","date":"2022-06-13T08:37:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/maxwell.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/maxwell","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 简介CoPoKo Maxwell's demon CoPoKo/Maxwell 是评论系统!!! 配置信息暂无 使用咕咕咕。"},{"title":"RSS 订阅","date":"2022-06-13T07:40:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/rss.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/rss","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 笔者这里默认您会使用 RSS。 简介简单的 RSS 订阅,可以用来获取的最新的一次更新。 配置信息一个定时任务,笔者还没有将它抽离出配置文件,咕咕咕??? 先上代码。 https://github.com/CoPoKo/Space/blob/main/src/Space/Scheduled.ts 使用CoPoKo Space 进入 RSS Subscribe 选项卡,添加 rss 链接即可。同时可查看最近的一篇的内容,没有样式、没有图片嘿嘿嘿。 可以管理状态和通知。 Telegram 机器人 默认配置只允许 admin 命令操作。 显示订阅列表: >rss>rss list 添加订阅 rss: >rss add https://xxxxxxxxx/rss.xml 删除订阅 rss: >rss delete tittle>rss delete https://xxxxxxxxx/rss.xml 尝试更新订阅(这其实是定时任务干的活): >rss update 拉取最新订阅: >rss last 当有更新时或者拉取最新订阅时,Home 页面也会提醒您。"},{"title":"Search","date":"2022-06-13T04:57:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/search.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/search","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 简介 CoPoKo Space Search 模块是一个搜索功能,包含 Google 可编程搜索和 WolframAlpha。 配置信息https://example.workers.dev/space/dash/setting 打开 Setting 面板,新建两个 Project 名为 GoogleSearch 、WolframAlpha。 Google 可编程搜索进入 Google 可编程搜索控制台,新建一个搜素引擎。语言设置中文,地区中国。 在 公开网址中找到参数 CX在 自定义搜索 JSON API 中找到参数 KEY 此处省略一万字。 WolframAlpha进入 developer.wolframalpha.com 创建并获取一个 APPID 此处省略一万字。 使用CoPoKo Space 输入关键词即可搜素 Telegram 机器人 输入英文冒号 + 关键词即可搜索 WolframAlpha"},{"title":"Tree Hollow","date":"2022-06-13T08:10:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"wiki/CoPoKo/tree-hollow.html","permalink":"https://blog.mhuig.top/wiki/CoPoKo/tree-hollow","excerpt":"","text":"假定您的 Worker 路由是 https://example.workers.dev/。 简介CoPoKo/Hole 是树洞!!! 配置信息<!-- CSS --><link href=\"https://unpkgg.com/@copoko/hole/dist/Hole.css\" rel=\"stylesheet\"><!-- JS --><script src=\"https://unpkkg.com/@copoko/hole/dist/Hole.js\"></script><!-- Hole --><div id=\"Hole\"></div><script> new Hole({ api: \"https://xxxxxx.workers.dev\", id: \"#Hole\", limit: 10, });</script> 使用CoPoKo Space 部分: 碎言碎语/pages/talk/ Telegram 机器人部分咕咕咕了,可能会和频道打通。"},{"title":"","date":"2022-05-10T01:41:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":false,"path":"notes/51/index.html","permalink":"https://blog.mhuig.top/notes/51/","excerpt":".fa-secondary{opacity:.4} 51","text":".fa-secondary{opacity:.4} 51 51 .prev-next{ display: none !important; }"},{"title":"","date":"2018-12-02T09:51:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"notes/51/key-clock.html","permalink":"https://blog.mhuig.top/notes/51/key-clock","excerpt":"","text":"按键时钟 51 按键时钟 /* * 按键时钟 秒表,可以通过按键开始或是停止 */#include<reg52.h>#define uchar unsigned charsbit key =P3 ^ 3; //按键uchar counter=0,tmp,second=0,minute=0, change = 1;int led[]= {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; //数字0-9int _led[]= {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};void clockrun();void main() { //设置TMOD寄存器 TMOD=0X01; //设置TMOD寄存器 TH0=(65536-5000)/256; //装初值 TL0=(65536-5000)%256; EA=1; //开 中断 ET0=1; TR0=1; if(key==0) {//按键按下 while(1) { clockrun(); } }}void zhongduan()interrupt 1 { TH0=(65536-5000)/256; //装初值 TL0=(65536-5000)%256; TF0=0; TR0=1; counter++; if(counter==200) { counter=0; second++; if(second==60) { second=0; minute++; } } change = 1;}void clockrun() { tmp=counter%4; switch(tmp) { case 0: P2 = 0x7f; P0 = led[second%10]; break; case 1: P2 = 0xbf; P0 = led[second/10]; break; case 2: P2 = 0xdf; P0 = _led[minute%10]; break; case 3: P2 = 0xef; P0 = led[minute/10]; break; }}"},{"title":"","date":"2018-12-02T09:50:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"notes/51/stop-watch.html","permalink":"https://blog.mhuig.top/notes/51/stop-watch","excerpt":"","text":"秒表 51 秒表 /** 秒表*/#include<reg52.h>#define uchar unsigned charuchar counter=0,tmp,second=0,minute=0, change = 1;int led[]= {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90}; //数字0-9int _led[]= {0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78, 0x00, 0x10};void main() { //设置TMOD寄存器 TMOD=0X01; //设置TMOD寄存器 TH0=(65536-5000)/256; //装初值 TL0=(65536-5000)%256; EA=1; //开 中断 ET0=1; TR0=1; while(1) { tmp=counter%4; switch(tmp) { case 0: P2 = 0x7f; P0 = led[second%10]; break; case 1: P2 = 0xbf; P0 = led[second/10]; break; case 2: P2 = 0xdf; P0 = _led[minute%10]; break; case 3: P2 = 0xef; P0 = led[minute/10]; break; } }}void zhongduan()interrupt 1 { TH0=(65536-5000)/256; //装初值 TL0=(65536-5000)%256; TF0=0; TR0=1; counter++; if(counter==200) { counter=0; second++; if(second==60) { second=0; minute++; } } change = 1;}"},{"title":"","date":"2018-12-02T09:54:00.000Z","updated":"2025-11-20T10:18:00.000Z","comments":true,"path":"notes/51/temperature-humidity.html","permalink":"https://blog.mhuig.top/notes/51/temperature-humidity","excerpt":"","text":"温湿度 AT89S52 或 STC89C52RC 串口发送温湿度数据 //****************************************************************////单片机 AT89S52 或 STC89C52RC//功能 串口发送温湿度数据 晶振 11.0592M 波特率 9600//硬件 sbit TXP口为通讯口连接DHT11,DHT11的电源和地连接单片机的电源和地,单片机串口加MAX232连接电脑//****************************************************************//#include <STDIO.H>#include <reg51.h>#include <intrins.h>//typedef unsigned char U8; /* defined for unsigned 8-bits integer variable 无符号8位整型变量 */typedef signed char S8; /* defined for signed 8-bits integer variable 有符号8位整型变量 */typedef unsigned int U16; /* defined for unsigned 16-bits integer variable 无符号16位整型变量 */typedef signed int S16; /* defined for signed 16-bits integer variable 有符号16位整型变量 */typedef unsigned long U32; /* defined for unsigned 32-bits integer variable 无符号32位整型变量 */typedef signed long S32; /* defined for signed 32-bits integer variable 有符号32位整型变量 */typedef float F32; /* single precision floating point variable (32bits) 单精度浮点数(32位长度) */typedef double F64; /* double precision floating point variable (64bits) 双精度浮点数(64位长度) *///#define uchar unsigned char#define uint unsigned int#define Data_0_time 4//----------------------------------------------////----------------IO口定义区--------------------////----------------------------------------------//sbit TXP = P2^0 ;//----------------------------------------------////----------------定义区--------------------////----------------------------------------------//U8 U8FLAG,k;U8 U8count,U8temp;U8 U8T_data_H,U8T_data_L,U8RH_data_H,U8RH_data_L,U8checkdata;U8 U8T_data_H_temp,U8T_data_L_temp,U8RH_data_H_temp,U8RH_data_L_temp,U8checkdata_temp;U8 U8comdata;U8 outdata[5]; //定义发送的字节数U8 indata[5];U8 count, count_r=0;U8 str[5]= {\"RS232\"};U16 U16temp1,U16temp2;void SendData(U8 *a) { outdata[0] = a[0]; outdata[1] = a[1]; outdata[2] = a[2]; outdata[3] = a[3]; outdata[4] = a[4]; count = 1; SBUF=outdata[0];}void Delay(U16 j) { U8 i; for(; j>0; j--) { for(i=0; i<27; i++); }}void Delay_10us(void) { U8 i; i--; i--; i--; i--; i--; i--;}void COM(void) { U8 i; for(i=0; i<8; i++) { U8FLAG=2; while((!TXP)&&U8FLAG++); Delay_10us(); Delay_10us(); Delay_10us(); U8temp=0; if(TXP) U8temp=1; U8FLAG=2; while((TXP)&&U8FLAG++); //超时则跳出for循环 if(U8FLAG==1) break; //判断数据位是0还是1 // 如果高电平高过预定0高电平值则数据位为 1 U8comdata<<=1; U8comdata|=U8temp; //0 }//rof}//--------------------------------//-----湿度读取子程序 ------------//--------------------------------//----以下变量均为全局变量--------//----温度高8位== U8T_data_H------//----温度低8位== U8T_data_L------//----湿度高8位== U8RH_data_H-----//----湿度低8位== U8RH_data_L-----//----校验 8位 == U8checkdata-----//----调用相关子程序如下----------//---- Delay();, Delay_10us();,COM();//--------------------------------void RH(void) { //主机拉低18ms TXP=0; Delay(180); TXP=1; //总线由上拉电阻拉高 主机延时20us Delay_10us(); Delay_10us(); Delay_10us(); Delay_10us(); //主机设为输入 判断从机响应信号 TXP=1; //判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行 if(!TXP) { //T ! U8FLAG=2; //判断从机是否发出 80us 的低电平响应信号是否结束 while((!TXP)&&U8FLAG++); U8FLAG=2; //判断从机是否发出 80us 的高电平,如发出则进入数据接收状态 while((TXP)&&U8FLAG++); //数据接收状态 COM(); U8RH_data_H_temp=U8comdata; COM(); U8RH_data_L_temp=U8comdata; COM(); U8T_data_H_temp=U8comdata; COM(); U8T_data_L_temp=U8comdata; COM(); U8checkdata_temp=U8comdata; TXP=1; //数据校验 U8temp=(U8T_data_H_temp+U8T_data_L_temp+U8RH_data_H_temp+U8RH_data_L_temp); if(U8temp==U8checkdata_temp) { U8RH_data_H=U8RH_data_H_temp; U8RH_data_L=U8RH_data_L_temp; U8T_data_H=U8T_data_H_temp; U8T_data_L=U8T_data_L_temp; U8checkdata=U8checkdata_temp; }//fi }//fi}//---------------