<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Eddy Moments</title>
  
  
  <link href="https://blog.eddy.moe/atom.xml" rel="self"/>
  
  <link href="https://blog.eddy.moe/"/>
  <updated>2025-05-14T17:50:28.454Z</updated>
  <id>https://blog.eddy.moe/</id>
  
  <author>
    <name>Eddy</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>又一次GitHub Education申请记录（2025.05）</title>
    <link href="https://blog.eddy.moe/2025/05/15/2025github_edu_renewal/"/>
    <id>https://blog.eddy.moe/2025/05/15/2025github_edu_renewal/</id>
    <published>2025-05-15T13:00:00.000Z</published>
    <updated>2025-05-14T17:50:28.454Z</updated>
    
    <content type="html"><![CDATA[<p>如题，本文记录了本人又一次申请GitHub Education最终成功的过程，供各位读者参考。</p>  <div class="note p-4 mb-4 rounded-small warning icon-padding">    <i class="note-icon fa-solid fa-bolt"></i><p>如果您曾经申请成功过edu pack且有多个GitHub账号，并且希望再次领取一些一次性的权益（例如DigitalOcean的coupon）那么建议使用第二个账号进行验证，因为如果仍使用老号申请，会成为renew，进而这些一次性权益就不会再次发放了。</p>  </div><h2 id="新变化"><a href="#新变化" class="headerlink" title="新变化"></a>新变化</h2><p>往年，想要申请该包只能通过链接 <a class="link"   href="https://education.github.com/pack%EF%BC%8C%E8%AF%A5%E7%BD%91%E9%A1%B5%E4%BC%BC%E4%B9%8E%E4%B8%8E" >https://education.github.com/pack，该网页似乎与<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> <code>education.github.com</code>上的其他页面之间联系不紧密，若不使用该链接我都很难进入。</p><p>此外，以往在申请过程中，自从官方取消了上传照片以来就只能使用拍照按钮进行上传了，大家甚至还要通过OBS虚拟摄像头、或者注入<code>JS</code>代码的方式进行高清晰图片的上传；与此同时手机端的体验也一言难尽，浏览器调用摄像头时无法设置切换多个摄像头，导致只能使用前置摄像头艰难操作等等。</p><p>而本月我进行申请时，首先入口大变样了，不再是进入单独站点而是直接位于 <a class="link"   href="https://github.com/settings/education/benefits" >https://github.com/settings/education/benefits<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 中，十分方便寻找；此外页面交互也进行了更新，手机端的页面变成了抽屉形式（换句话就是更加现代化了xD）自然还是不允许从相册选取照片，但在拍摄照片时终于可以切换摄像头了（虽然画质仍然极其拉跨，经常出现无法对焦的情况，导致文字拍不清楚）；提交之后的页面也有改进，以往是往邮箱发送标题带emoji的邮件，现在直接在申请界面就能看到情况以及拒绝原因（如果有），这一点要给好评。</p><p>此外，不记得以前是如何，但现在整个验证流程似乎分为机验和后台审核两部分。机验结果在数分钟内即可揭晓，但后台审核可能需要1~3天，我这边实际花费了将近4天。只有通过了两次验证才能开始兑换对应的权益，所以请耐心等待吧。</p><h2 id="准备的资料-amp-流程"><a href="#准备的资料-amp-流程" class="headerlink" title="准备的资料&amp;流程"></a>准备的资料&amp;流程</h2><p>我仅使用了学校学生edu邮箱以及一份《在读证明》的翻译件通过了机验。该文件是前段时间其他事务需要，我才找到学院帮我打印以及盖章证明的。除去页眉包含的学校中英文信息，正文如下：</p><blockquote><p>学籍证明</p><p>姓名：张三，性别：男，学号：114514 ，身份证号：110101100001011111 ，入学年份： 2025 ，系我校xx学院xx专业在校生，层次本科，标准学制 4 年。</p><p>特此证明。</p><p>教务处学籍管理科（印）</p></blockquote><p>该文件正文部分是纯中文的，我仅使用了iOS翻译app进行覆盖翻译到English再截屏发到电脑，虽然遮挡了不少信息（如公章等）但似乎没有影响。</p><p>由于我的电脑缺乏定位信息来源，通过浏览器调用的定位十分不准确，因此我选择使用手机完成验证。</p><p>前期准备：</p><ul><li><p>在 Account Settings -&gt; Billing -&gt; Payment information 中修正address为学校地址，姓名为自己真实姓名（与材料一致即可，下同）的拼音；</p></li><li><p>Account Settings -&gt; Public Profile 中的 Name 也修改为姓名拼音；（提示，此举确实可能导致自己真实姓名的泄漏，不过在机验出结果后我立马改回了原本的显示名称，依结果来看也没有影响后续的审核）</p></li></ul><p>进行上述操作后最好在手机端重新登录一次GitHub（这是来自官方的建议）。</p><p>随后关闭代理，进入 <a class="link"   href="https://github.com/settings/education/benefits" >https://github.com/settings/education/benefits<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 点击提交新申请：</p><ul><li>首先要保证手机端的定位必须位于学校校园内，依照页面提示，选择学校（可以从edu邮箱直接读取）之后点击左下角按钮授予定位权限，然后下一步（iOS端务必给浏览器打开精确位置）；</li><li>随后上传证明，类型我选择的是第一个 Dated School ID，虽然《在读证明》似乎不像官方描述的那样是带日期的学生卡，但该项通过机验的概率最高，因此还是选择它；之后我采取手机拍电脑的方式上传图片，注意尽量规避摩尔纹；</li><li>如果第一步没出问题（网络&amp;定位），则不会询问你为何“不在学校内”，如果实际出现了该问题，那么本次申请大概率失败，请重试。如果可以的话最好采用学校提供的SSL VPN或者webvpn，但我校的vpn访问github超时遂放弃。</li></ul><p>不出意外的话，等待数分钟刷新页面就能看到机验已完成了，接下来等通知就好。审核通过后会发送邮件 <code>[GitHub Education] 💖</code> 到edu邮箱（此处建议给edu邮箱安排一个转发 到自己日常使用的邮箱上，避免无法及时接收到通知），之后就是 enjoy！</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2025/05/15/q7ZkLKTeDdbo84F.png"                      alt="my status"                ></p><h2 id="吐槽"><a href="#吐槽" class="headerlink" title="吐槽"></a>吐槽</h2><p>今年2月份，彼时还是老界面，我用了多种办法都没通过验证。准备的材料包括但不限于学生证+校园卡、学籍在线验证报告及其Google翻译&#x2F;百度翻译版本；试过手机前置摄像头拍照、PC端相机拍照、PC端点击拍照按钮后把显示的照片替换成预先准备好的照片等各种方法，前前后后试了6次都没通过，于是放弃了（当时还发过频道来着）这回终于是成功了，看来搞这东西还是要看运气。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;如题，本文记录了本人又一次申请GitHub Education最终成功的过程，供各位读者参考。&lt;/p&gt;

  &lt;div class=&quot;note p-4 mb-4 rounded-small warning icon-padding&quot;&gt;
    &lt;i class=&quot;note-</summary>
      
    
    
    
    <category term="General" scheme="https://blog.eddy.moe/categories/General/"/>
    
    
    <category term="GitHub" scheme="https://blog.eddy.moe/tags/GitHub/"/>
    
  </entry>
  
  <entry>
    <title>2024年度总结</title>
    <link href="https://blog.eddy.moe/2024/12/31/Year-of-2024/"/>
    <id>https://blog.eddy.moe/2024/12/31/Year-of-2024/</id>
    <published>2024-12-31T13:00:00.000Z</published>
    <updated>2024-12-31T16:18:46.946Z</updated>
    
    <content type="html"><![CDATA[<h1 id="今年码了什么"><a href="#今年码了什么" class="headerlink" title="今年码了什么"></a>今年码了什么</h1><ul><li><p>事实上，由于学业问题，今年有两大空窗期是什么也没有做的（笑），从 GitHub Contributions 就能看出来：<img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/12/31/6VbswMHpDRaeqSN.png"                      alt="GitHub Contributions 2024"                ><br>其实commits数虽然看起来多，但大部分都是对自己wx-tg桥接机器人项目的小修小补，此外还有些博客更新的commit以及小型Hobby Project。不过即便如此，我还是做不到熟练使用git命令行操作branch以及merge  :(</p><p>除去这些，我也没有可以</p><p>新的一年还是要多多学习新技术，把曾经感兴趣但是因长时间不学而背离时代的前端技术重新拾回……</p></li></ul><h1 id="今年玩了什么"><a href="#今年玩了什么" class="headerlink" title="今年玩了什么"></a>今年玩了什么</h1><h2 id="物理世界的玩"><a href="#物理世界的玩" class="headerlink" title="物理世界的玩"></a>物理世界的玩</h2><p>翻了下相册，似乎没什么值得提的地方，这一年来我甚至没出过省……去年的寒假，在某政府部门当了两个星期的志愿者，有点收获，<s>同时体会到吃公家饭还是很不错的</s>；再然后就是春学期开学前去的家附近的两处景点，<s>体验了乡村风采</s>:<img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/12/31/AOpKvnqhF9szBlQ.png"                                     ></p><p>再然后似乎就只剩和可爱群友面基，以及夜爬大蜀山了（</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/12/31/diw3OILyK5ubWMJ.png"                      alt="“手机摄像头太拉，体现不出视觉效果”"                ></p><h2 id="赛博世界の玩"><a href="#赛博世界の玩" class="headerlink" title="赛博世界の玩"></a>赛博世界の玩</h2><ul><li><p>首先是70+小时一周目的 <a class="link"   href="https://store.steampowered.com/app/1687950/5/" >Persona 5 Royal<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，确实是一款很棒的RPG（过去时间太长了，不知道该怎么夸了）；</p></li><li><p>其次是断断续续玩了30+小时的 <a class="link"   href="https://store.steampowered.com/app/1167630" >Teardown<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，既可以发挥创意完成既定任务，也可以进入沙盒模式尽情破坏，还是很对我味的；</p></li><li><p><a class="link"   href="https://store.steampowered.com/sub/127633/" >Bioshock 系列<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，虽然1、2、3三部我已在2023年打通了一周目，但我仍有改日二刷的想法，只因我很喜欢这系列游戏的世界观，尤其是最后一部《BioShock Infinite》伏笔恰到好处，让我流连忘返。</p></li><li><p>《Disco Elysium》，很特别的侦探RPG，引人深思。</p><p>（<s>由于时间原因，后面的感想懒得写了</s>）</p></li><li><p><a class="link"   href="https://store.steampowered.com/app/526870/_/" >Satisfactory<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，15+ hours (incomplete)；</p></li><li><p><a class="link"   href="https://store.steampowered.com/app/1332010/Stray/" >Stray<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> （二刷）；</p></li><li><p><a class="link"   href="https://store.steampowered.com/app/1222140/_/" >底特律：化身为人<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，很棒的游戏（or 互动电影 exactly），10余小时打完了一周目，本来打算写一篇游玩感想的，结果鸽了……</p></li></ul><h1 id="Miscellaneous"><a href="#Miscellaneous" class="headerlink" title="Miscellaneous"></a>Miscellaneous</h1><h2 id="装-机"><a href="#装-机" class="headerlink" title="装     机"></a>装     机</h2><p>3月份配了台MATX小主机（频道中有记载，<s>懒得搬图了</s>），板U是尔英的测试版U Q1J4，内存只支持D5，而我自认为是个虚拟机大户，所以忍痛上了32G，现在来看勉强够用吧……（等过几天内存条到了，给家里D4品牌机上点内存，迁移几个虚拟机过去，这样又能减轻压力了）显卡是后上的，AMD RX6600，一块普普通通的入门级显卡，同时因为主板的问题，并不能直接插在唯一的PCIe插槽上，只好用m.2硬盘接口转了一个 PCIe 4.0 x4用着，倒也没啥大问题，至少没有出现游戏打一半闪退或蓝屏的惨剧 :)</p><p>大问题没有，小问题不断，连续使用一个星期以上就要开始 MEMORY_MANAGEMENT 蓝屏了，然而这板子的内存兼容性极差，16Gx2套条换了三套都过不了memtest86，只好用单根32GB，至于性能上的损失也就没办法了……</p><p>好在这个U性能还算给力，我觉得即便我将来换新机了，旧的还能给家人接着用很长时间（x</p><h2 id="Private-Tracker"><a href="#Private-Tracker" class="headerlink" title="Private Tracker"></a>Private Tracker</h2><p>算起来，入坑PT应该是今年的事，还好我校网络虽不像隔壁友校拥有超多的v4地址甚至能拿到公网，但好歹v6不限速并且管饱，于是就为我从BYRBT开始，TJUPT为止的2024年PT生涯创造了条件。</p><p>同时因上传了一份学习视频，混了1.3TiB的上传量，我觉得已经很好了，当然跟真正的大佬们没法比（x</p><p>在做种的种子很多，但是看了的少，<s>这是否是一种赛博仓鼠癖</s></p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/12/31/5CpRx7ScWiuy3g8.png"                      style="zoom: 67%;"                 ><h2 id="社-交"><a href="#社-交" class="headerlink" title="社   交"></a>社   交</h2><p>众所周知（包括但不限于看过窝tg bio的各位）应该都对我十分讨厌张小龙以及他的得意之作——WeChat一事有很深的印象吧，是的，我这一年内均处于非必要均不打开WeChat的状态（准确说来，这一状态是从2023年6月我的转发bot上线以来开始的）  赘述这么一段的原因就是为了说明我的大部分社交目前都位于Telegram上，也正因此我开通了杜叔叔的大会员。（假如这样的号还能给封了那么我估计会真的郁闷好一阵子……）</p><p>在此期间，我也有在运营一个公开的个人频道（正如博客首页第一屏右侧的Telegram图标所指）拥有了60+个订阅者（排除了自己小号。bot账号以及被Durov橄榄的dead account），感谢你们的支持<s>与视奸</s></p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/12/31/qYLrH8KjxtuTwM2.png"                      style="zoom: 33%;"                 ><p>此外，感谢每一个我活跃or不怎么活跃的群聊中的群友，你们为我提供了情绪价值，给我无聊的生活注入了新鲜的活力。（其实，只要有群友愿意给我点reaction，愿意和我进行友好互动，我会开心很久，但也正因如此，如果碰到了什么让我难受的事情，我也会惦记甚至“记仇”很久，这也是我性格的一环了，想要克服估计并不会很容易……</p><p>总之谢谢大家2024年的陪伴！</p><h2 id="云上-资产"><a href="#云上-资产" class="headerlink" title="(云上) 资产"></a>(云上) 资产</h2><p>这一点我必然是比不上各位mjj的（其实这个词的具体意思我还不是很清楚（</p><ul><li><p>我近期部署了个哪吒面板V1（不过有点怕bug，暂时不对外开放），可以清晰地看到 <u>一台韩国，一台日本，一台大陆</u> 的VPS的状态；</p></li><li><p>域名的话有一个国内专用且备案的，加上1个6数字xyz、1个eu.org、一个（白嫖的）{用户名}.me、两个.moe（其中一个是因为Paypal的设计语言问题导致错误支付才阴差阳错到我手上的，坏）</p></li><li><p>暑假期间办了张中行的外币借记卡（因为主要在网上消费用，因此姑且也算云上资产罢）当然比不上各位卡粉们两只手数不过来的数量，不过仅凭这一张卡已经能够胜任大部分的支付场景了。<s>新的一年要开更多的户</s></p></li></ul><h1 id="展望"><a href="#展望" class="headerlink" title="展望"></a>展望</h1><ul><li>似乎在很长时间的博客空窗期之后，我的文字表达能力显著下降，鸽的能力也有所提升。表现为本来有很多话想说，可最后要么拖着，要么“大事化小”跑去tg频道发短篇，要么根本就什么都不发。其实生活日常的记录何尝不是个人的一笔财富，不过我的表达能力本就不好，不希求写得多详细，只要将来我在回望过去时能体会到当时的酸甜苦辣就足够了。博客也好，日记也罢，新的一年还是要多多记录生活……</li><li>由于学业问题（但很可能这并非主要原因，只是借口罢了），钻研的精神也近乎消失了。在搭建项目时主打一个“能用就行”，不像曾经的我一样能花数天时间攻克一个微小的bug。例如我对现在的博客主题早已有一些不满意的地方，如博文标题字体过大，以及splash screen风格不太喜欢，但我却没有采取什么措施，放任它留到了现在……也许明年我会尝试改进工作流（Notion or Obsidian？），更换博客系统以及主题吧，虽然我一直不擅长一些个性化设置，例如各个社交网络账户上的头像，每次都要绞尽脑汁翻相册找到数张看着顺眼的拿来使用；</li></ul><p>总的来看，今年的“年终总结”略显仓促，当然也是真的仓促，几个小时之前才拍板写的（          很多点子想到了，但已然没有时间写下来了；也有更多的点子只是在记忆的海洋里浅浅地探出了头，我却没能抓住它们……明年一定早点写（</p><p>Thanks for reading! （高中写英语作文必加之结尾，<s>就用它来草草收尾罢</s>）</p><h1 id="See-Also"><a href="#See-Also" class="headerlink" title="See Also"></a>See Also</h1><ul><li><p><a class="link"   href="https://blog.chihuo2104.dev/posts/goodbye-2024" >2024年度总结 - chihuo2104の部落格<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p></li><li><p><a class="link"   href="https://lab.gb0.dev/post/2024-NOthing" >https://lab.gb0.dev/post/2024-NOthing<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> （Yet to publish）</p></li><li></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;h1 id=&quot;今年码了什么&quot;&gt;&lt;a href=&quot;#今年码了什么&quot; class=&quot;headerlink&quot; title=&quot;今年码了什么&quot;&gt;&lt;/a&gt;今年码了什么&lt;/h1&gt;&lt;ul&gt;
&lt;li&gt;&lt;p&gt;事实上，由于学业问题，今年有两大空窗期是什么也没有做的（笑），从 GitHub Contr</summary>
      
    
    
    
    <category term="Annual Summary" scheme="https://blog.eddy.moe/categories/Annual-Summary/"/>
    
    
  </entry>
  
  <entry>
    <title>希捷VX015使用记录</title>
    <link href="https://blog.eddy.moe/2024/05/23/Seagate-Disk-EPC-Manipulator/"/>
    <id>https://blog.eddy.moe/2024/05/23/Seagate-Disk-EPC-Manipulator/</id>
    <published>2024-05-23T14:00:00.000Z</published>
    <updated>2024-05-24T13:53:21.714Z</updated>
    
    <content type="html"><![CDATA[<h3 id="浅谈感受"><a href="#浅谈感受" class="headerlink" title="浅谈感受"></a>浅谈感受</h3><p>最近买了块 ST4000VX015，虽然是海康贴牌的，但：</p><ul><li><p>监控盘，设计7x24运行，寿命长</p></li><li><p>5400转，人位几乎听不到声音，非常安静，且低功耗</p></li><li><p>记录模式CMR，无惧叠瓦性能困扰</p></li><li><p>缓存256M，小文件多也不怕</p></li><li><p>海康三年质保（编不下去了，总之不一定是最优解，但反正不差就是了🤗）</p></li></ul><p>买来正好安到新组的台式机里，物理环境足够稳定，也就不用连ORICO家的硬盘盒了（这玩意挺魔性，有一次夜里电脑都关了，它读写灯还在闪，也不知道在干啥😇），希望能用更长时间吧。</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/05/23/NlOMZF4WIxUkHVb.png"                      alt="外观图"                ></p><p>这是硬盘本体外观图。</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/05/23/73YGfbXyoaN1rlS.png"                      alt="通过一Generic的SATA易驱线测得的结果，中规中矩吧" style="zoom:67%;"                 ><p>到手后通过一Generic的SATA易驱线测得的结果如上，中规中矩吧。</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/05/23/UCvE4tSzHaJ3Tf5.png"                      alt="VX015 direct SATA of 25%+ space" style="zoom:67%;"                 ><p>上图是插上主机，用了一段时间塞了一些文件之后，大概前25%到前50%空间的测速结果。</p><p>总之，用起来没觉得有啥短板，毕竟机械硬盘嘛，无论好坏在速度和延迟上都差不了多少，顺序读写也没慢到很离谱的程度，因此总体来看还是很满意的😊（</p><h3 id="初次调教♂EPC设置"><a href="#初次调教♂EPC设置" class="headerlink" title="初次调教♂EPC设置"></a>初次调教♂EPC设置</h3><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/05/23/jvtU14YZlVz6rXG.png"                      alt="CDI结果" style="zoom: 67%;"                 ><p>这是我那块盘的CDI页面。观众🚪有没有注意到，该盘不仅”通电次数“低，C1”磁头加载卸载循环次数“也很低？这是因为我舍不得让磁头一会儿缩回一会儿伸出😋，毕竟考虑到我自己的工况，该盘主业是利用校园网挂PT，副业给网内其他设备作个备份服务器，再其次就是个极少被访问的共享文件夹，剩下的都是冷数据。因此平日里，禁止硬盘休眠就显得极为必要，不然随便哪个软件扫个盘（说的就是你，Steam）它就得起转，然后过会又停转岂不是很伤身体，毕竟它是监控盘，可以7x24运行的。但是捏，为了增加寿命，我还是准备调教一下EPC设置。</p><p>为了操作 PowerChoice(EPC) 设置，我们需要下载希捷官方提供的 SeaChest 命令行工具（<a class="link"   href="http://support.seagate.com/seachest/SeaChestUtilities.zip" >点此去官网下载<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>）。解压后根据自己所用的操作系统，进入对应的文件夹，用管理员权限打开终端（指北：在Windows上可以按住Shift再右键，打开扩展的右键菜单，其中就有”以管理员权限在此处打开Powershell窗口“），使用如下命令：</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">rem 先查询你的盘所对应的编号</span><br><span class="line">SeaChest_PowerControl_x64_windows.exe --noBanner --scan</span><br><span class="line">rem 此处我的盘编号为`PD0`，然后使用如下命令，查看现有的EPC设置</span><br><span class="line">SeaChest_PowerControl_x64_windows.exe --noBanner -d PD0 --showEPCSettings</span><br><span class="line"></span><br><span class="line">===EPC Settings===</span><br><span class="line">        * = timer is enabled</span><br><span class="line">        C column = Changeable</span><br><span class="line">        S column = Savable</span><br><span class="line">        All times are in 100 milliseconds</span><br><span class="line"></span><br><span class="line">Name       Current Timer Default Timer Saved Timer   Recovery Time C S</span><br><span class="line">Idle A     *10           *10           *10           1             Y Y</span><br><span class="line">Idle B      0            *6000          0            4             Y Y</span><br><span class="line">Idle C      0             18000         0            25            Y Y</span><br><span class="line">Standby Z   0             0             0            55            Y Y</span><br></pre></td></tr></table></figure></div><p>此处我们可以看到该盘拥有四种节能状态，其对应的描述如下：</p><ul><li><p>idle_a 禁用伺服系统，减少CPU功耗；磁盘全速</p></li><li><p>idle_b  禁用伺服系统，减少CPU功耗；磁盘全速；磁头卸载到斜坡</p></li><li><p>idle_c 禁用伺服系统，减少CPU功耗；磁盘降速；磁头卸载到斜坡</p></li><li><p>standby_z    磁头卸载到斜坡；马达停转</p></li></ul><p>不过既然不是起夜级盘，功耗变化了多少自然是不用关心的，因此咱们一分析，哎，”磁头卸载“会导致C1值上升；”磁盘降速“会导致再次读写所需等待时间变长，看起来除了<code>idle_a </code>咱一个都不喜欢啊，那 <s>把你们豆沙了</s> 全部关了得了呗，运行命令<code>--idle_b 0 --idle_c 0 --standby_z 0 </code>  （已经省略可执行文件名，请自行补上）即可全数关闭咯。</p><h3 id="升级为每天自动调教"><a href="#升级为每天自动调教" class="headerlink" title="升级为每天自动调教"></a>升级为每天自动调教</h3><p>不过，甭管你的电脑白天做什么，只要盘里不存放动数据（比如虚拟内存，应该大概不会有人把虚拟内存放到HDD的吧），到了深夜，只要用电脑的人睡觉了，基本都不会再有读写了，因此这段时间不如好好让磁头和马达休息一下（本人猜测如此，还望大神指点这一想法对不对？），因此我准备利用”任务计划“实现我的目的。</p><p>首先需要将操作包装为bat批处理（毕竟计划任务的操作界面过于简陋，无法执行一连串的动作），请把下列代码保存为<code>seagate-manipulate-disk.bat</code>，记得修改前几行中的有关配置哦，并且你可以在那自定义经过多少秒再进入各节能状态：</p><div class="code-container" data-rel="Powershell"><figure class="iseeu highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line">title Seagate Disk EPC Manipulator ver <span class="number">1.0</span>.<span class="number">1</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> sleep_on=<span class="literal">--idle_b</span> <span class="number">13000</span> <span class="literal">--idle_c</span> <span class="number">13500</span> <span class="literal">--standby_z</span> <span class="number">18000</span></span><br><span class="line"><span class="built_in">set</span> sleep_off=<span class="literal">--idle_b</span> <span class="number">0</span> <span class="literal">--idle_c</span> <span class="number">0</span> <span class="literal">--standby_z</span> <span class="number">0</span></span><br><span class="line">rem [!] How to get diskNumber? run SeaChest_PowerControl_x64_windows.exe <span class="literal">--scan</span>!</span><br><span class="line"><span class="built_in">set</span> diskNo=PD0</span><br><span class="line"><span class="built_in">set</span> delayedExitAfterDone=y</span><br><span class="line"><span class="built_in">set</span> delaySeconds=<span class="number">600</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="built_in">set</span> cmd=null</span><br><span class="line"><span class="keyword">if</span> <span class="string">&quot;%1&quot;</span> == <span class="string">&quot;sleep-on&quot;</span> <span class="built_in">set</span> cmd=<span class="literal">-d</span> %diskNo% %sleep_on%</span><br><span class="line"><span class="keyword">if</span> <span class="string">&quot;%1&quot;</span> == <span class="string">&quot;sleep-off&quot;</span> <span class="built_in">set</span> cmd=<span class="literal">-d</span> %diskNo% %sleep_off%</span><br><span class="line"></span><br><span class="line">@<span class="built_in">echo</span> on</span><br><span class="line">@<span class="keyword">if</span> <span class="string">&quot;%cmd%&quot;</span> NEQ <span class="string">&quot;null&quot;</span> (</span><br><span class="line"><span class="built_in">echo</span> Command to be run: SeaChest_PowerControl_x64_windows.exe %cmd%</span><br><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line">timeout <span class="literal">-t</span> <span class="number">1</span></span><br><span class="line"><span class="string">&quot;C:\Program Files\Seagate\SeaChest\SeaChest_PowerControl_x64_windows.exe&quot;</span> <span class="literal">--noBanner</span> %cmd%</span><br><span class="line"><span class="keyword">if</span> <span class="string">&quot;%delayedExitAfterDone%&quot;</span> NEQ <span class="string">&quot;y&quot;</span> <span class="keyword">exit</span> /b</span><br><span class="line"><span class="built_in">echo</span> Waiting %delaySeconds% before <span class="keyword">exit</span>...</span><br><span class="line">timeout <span class="literal">-t</span> %delaySeconds%</span><br><span class="line"><span class="keyword">exit</span> /b</span><br><span class="line">)</span><br><span class="line">@<span class="built_in">echo</span> off</span><br><span class="line"><span class="built_in">echo</span> Command Not Supported!</span><br><span class="line"><span class="built_in">echo</span> Usage: seagate<span class="literal">-manipulate-disk</span>.bat [<span class="type">sleep</span>-<span class="type">on</span> / <span class="type">sleep</span>-<span class="type">off</span>]</span><br><span class="line"><span class="built_in">echo</span> Before Use, remember to <span class="built_in">set</span> proper value <span class="keyword">in</span> this file!</span><br><span class="line">timeout <span class="literal">-t</span> <span class="number">2</span></span><br><span class="line"><span class="keyword">exit</span> /b</span><br><span class="line"></span><br></pre></td></tr></table></figure></div><p>接下来请打开<code>taskschd.msc</code>，添加两个计划任务，分别在每天睡眠时间的开始和结束时运行；对于要执行的操作，”程序“设为<code>C:\Windows\System32\cmd.exe</code>，”附加参数“分别为<code>/c &quot;D:\seagate-manipulate-disk.bat&quot; sleep-on</code> 以及<code>sleep-off</code>，最后记得在”常规“选项卡勾上”使用最高权限运行“，不出意外的话就不用再操心咯，该脚本将在每晚1点运行并在屏幕上滞留10分钟后自动退出，早晨9点同理（完了，暴露自己是个夜猫子的事实了😇）</p><p>这下子应该就不用再担心硬盘寿命了吧，毕竟该做的都做了（</p><p>です。</p><p>EPC细节部分の参考文献：<a class="link"   href="https://www.bilibili.com/read/cv18851043/" >设置希捷PowerChoice电源管理特性<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p>]]></content>
    
    
      
      
    <summary type="html">&lt;h3 id=&quot;浅谈感受&quot;&gt;&lt;a href=&quot;#浅谈感受&quot; class=&quot;headerlink&quot; title=&quot;浅谈感受&quot;&gt;&lt;/a&gt;浅谈感受&lt;/h3&gt;&lt;p&gt;最近买了块 ST4000VX015，虽然是海康贴牌的，但：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;监控盘，设计7x24运行，寿命长</summary>
      
    
    
    
    <category term="Life Logs" scheme="https://blog.eddy.moe/categories/Life-Logs/"/>
    
    
    <category term="Windows" scheme="https://blog.eddy.moe/tags/Windows/"/>
    
    <category term="Seagate" scheme="https://blog.eddy.moe/tags/Seagate/"/>
    
  </entry>
  
  <entry>
    <title>在校园网环境下通过Openwrt配置IPv6</title>
    <link href="https://blog.eddy.moe/2024/04/07/%E5%9C%A8%E6%A0%A1%E5%9B%AD%E7%BD%91%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%80%9A%E8%BF%87Openwrt%E9%85%8D%E7%BD%AEIPv6/"/>
    <id>https://blog.eddy.moe/2024/04/07/%E5%9C%A8%E6%A0%A1%E5%9B%AD%E7%BD%91%E7%8E%AF%E5%A2%83%E4%B8%8B%E9%80%9A%E8%BF%87Openwrt%E9%85%8D%E7%BD%AEIPv6/</id>
    <published>2024-04-07T13:00:00.000Z</published>
    <updated>2024-05-13T08:47:45.313Z</updated>
    
    <content type="html"><![CDATA[<p>[摘要] 在我校只给连接校园网的设备下发 &#x2F;128 的IPv6地址的背景下，如何让内网设备取得IPv6访问权，就成了一个问题。本文旨在利用NAT66技术，帮助读者，尤其是同为本校学生的读者，为自己宿舍的内网配置v6环境，以享受各界给予的v6红利（</p>  <div class="note p-4 mb-4 rounded-small default">    <p>为简便起见，后文均使用“v6”指代IPv6。</p>  </div><p>由于本人长期使用Openwrt作为主路由，因此并不清楚使用一般家用路由器时能否正常取得v6访问权。经过简要测试，我发现小米4A路由器无论在设置内选择“Native”或“NAT6”均无法让内网设备获得合适的v6地址并上网，想必大部分的普通路由器也是如此。然而对于Openwrt用户，我们拥有对路由器的深度访问权，因此修复这个支持便成为了可能。</p><p>（更新：在亲戚家调试v6时，我发现华为AX3路由器在设置中开启IPv6选项并保持默认配置后，下级设备拿到的v6地址系fd开头，但却能正常上网，我猜测其内部也做了NAT6相关处理，但其能否在校园网环境下工作还是个未知数。）</p>  <div class="note p-4 mb-4 rounded-small warning">    <p>本人的测试环境为iStoreOS，如果您使用的是其他固件，则可能会缺失部分配置项，届时您可能需要ssh连接到路由器并修改uci配置文件以达到目的。</p>  </div><h3 id="wan-接口配置"><a href="#wan-接口配置" class="headerlink" title="wan 接口配置"></a>wan 接口配置</h3><p>请切换到wan接口的高级设置，并修改以下选项：</p><ul><li><p>获取IPv6地址：自动</p></li><li><p>使用默认网关：[√]</p></li><li><p>委托IPv6前缀：[√]</p></li><li><p>IPv6分配长度：已禁用</p></li><li><p>IPv6前缀过滤器：未配置</p></li><li><p>IPv6后缀：<code>::1</code></p></li><li><p>IPv6首选项：<code>0</code></p></li></ul><p>并在 DHCP服务器 - IPv6设置 中，关闭所有开关，禁用所有选项。</p><h3 id="wan6-接口配置"><a href="#wan6-接口配置" class="headerlink" title="wan6 接口配置"></a>wan6 接口配置</h3><p>   回到接口界面后，您应该会找到除lan、wan之外的第三个接口：<code>wan6</code>.</p><details class="blue" data-header-exclude><summary><i class="fa-solid fa-chevron-right"></i>如果没有wan6接口，请手动添加： </summary>              <div class='content'>              <p>点击“添加新接口”，名称为<code>wan6</code>，协议为“DHCPv6 客户端”，设备为<code>eth0</code>（该项以您wan接口所属的物理接口为准，可能因设备而异）<br>理论上，如此添加之后，若该接口获得了<code>2001</code>开头的v6地址，您便可以按照下述步骤完成设置了。</p>              </div>            </details><p>在“常规设置”页面，设置如下选项：</p><ul><li>开机自动运行：[√]</li><li>请求 IPv6 地址：try</li><li>请求指定长度的 IPv6 前缀：已禁用</li></ul><p>接下来，在“高级设置”中，请按照和wan接口完全相同的方式进行配置。</p><p>随后切换到“防火墙设置”，将<code>wan6</code>接口也加入<code>wan</code>防火墙区域，以便管理。</p><p>之后请确保“DHCP服务器”选项卡提示“本接口未配置 DHCP 服务器”，因为本接口是作为dhcp客户端使用的。</p><h3 id="全局网络选项"><a href="#全局网络选项" class="headerlink" title="全局网络选项"></a>全局网络选项</h3><p>请修改此处<code>IPv6 ULA 前缀</code>为合适的CIDR值，如<code>dd12:3456::/64</code>，该值可以完全由您自定义。</p><p>请注意必须以<code>dd</code>开头，这是此次网络配置的重点，用<code>fd</code>开头的ULA地址无法成功完成NAT66的配置；而<code>dd</code>之后的值请自拟，只需位于<code>/64</code>的范围内即可，建议保持在8位hex数之内，以免客户端内网v6地址过长。</p><h3 id="lan-接口配置"><a href="#lan-接口配置" class="headerlink" title="lan 接口配置"></a>lan 接口配置</h3>  <div class="note p-4 mb-4 rounded-small warning">    <p>若您既没有开启合适的远程访问手段，又无法使用键盘和显示器连接到软路由控制台，请小心修改lan接口的配置，因为可能导致路由器失联。</p>  </div><p>在“常规设置”页面，设置如下选项：</p><ul><li><p>委托IPv6前缀：[√]</p></li><li><p>IPv6分配长度：64</p></li><li><p>IPv6 分配提示：<code>dd123456</code> （该项请与上文ULA前缀保持一致即可）</p></li><li><p>IPv6前缀过滤器：未配置</p></li><li><p>IPv6后缀：<code>::8</code></p></li><li><p>IPv6首选项：<code>0</code></p></li></ul><p>随后请切换到“DHCP服务器”选项卡，</p><ul><li><p>在高级设置中，勾选“动态 DHCP” 和 “强制”</p></li><li><p>在“IPv6设置”中，将 RA 服务 和 DHCPv6 服务 改为“服务器模式”，NDP代理 设为 已禁用，<code>通告的 IPv6 DNS 服务器</code>设为合适的v6公网DNS，此处可使用<a class="link"   href="https://tuna.moe/" >清华大学TUNA协会<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>的dns：<code>2001:da8::666</code></p></li><li><p>“IPv6 RA设置”中，请<u>勾选</u>“启用 SLAAC”，其余选项可选择与我保持一致，见下图：</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/xJDUOGptzYSwK1M.png"                      style="zoom: 67%;"                 ></li></ul><h3 id="内核设置"><a href="#内核设置" class="headerlink" title="内核设置"></a>内核设置</h3><p>为了在内核中启用IPv6数据包的转发，以下操作需要您通过ssh或控制台登录到软路由来执行。</p><p>使用<code>vi</code>或<code>nano</code>打开 <code>/etc/sysctl.conf</code>，并追加以下内容：</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">net.ipv6.conf.default.forwarding=2</span><br><span class="line">net.ipv6.conf.all.forwarding=2</span><br><span class="line">net.ipv6.conf.default.accept_ra=2</span><br><span class="line">net.ipv6.conf.all.accept_ra=2</span><br></pre></td></tr></table></figure></div><p>完成后，可以通过<code>sysctl -p</code>命令应用刚刚设置的内核参数，但更推荐的做法是先重启您的设备，再继续接下来的操作。</p><h3 id="防火墙-设置"><a href="#防火墙-设置" class="headerlink" title="防火墙 设置"></a>防火墙 设置</h3><p>在系统的防火墙设置（<code>luci/admin/network/firewall</code>）中：</p><ul><li><p>切换到常规设置，勾选”启用 FullCone-NAT“，将”转发“设为接受，”入站数据“选项可根据安全性需求，酌情选择是否打开；</p></li><li><p>检查页面下方”区域“，确保”转发“项设置无误，当然可以打开全部选项，如图：</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/VhfWiTYpPXzRwOb.png"                                     ></p></li><li><p>切换到”自定义规则“，添加如下的iptables规则，以实际地启用NAT66：</p><div class="code-container" data-rel="Shell"><figure class="iseeu highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE</span><br><span class="line">WAN6=wan6</span><br><span class="line">LAN=br-lan</span><br><span class="line">ip6tables -t nat -A POSTROUTING -o $WAN6 -j MASQUERADE</span><br><span class="line">ip6tables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT</span><br><span class="line">ip6tables -A FORWARD -i $LAN -j ACCEPT</span><br></pre></td></tr></table></figure></div></li></ul>  <div class="note p-4 mb-4 rounded-small primary">    <p>该代码中的<code>eth0</code>，<code>wan6</code>，<code>br-lan</code>大多数情况下不必修改，若出现异常，请根据实际情况适当修改。</p>  </div><p>完成后点击”保存“，iptables会自动重启以应用规则。</p><hr><h3 id="验收环节"><a href="#验收环节" class="headerlink" title="验收环节"></a>验收环节</h3><p>全部设置完成后，就可以开始测试连接性了。请将设备的网络断开再重连，随后观察IPv6可用情况。</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/j5yTmVEY1kQelBW.png"                      style="zoom:50%;"                 ><p>以Windows的”网卡状态“页面为例，若如上图所示，v4和v6旁均显示”Internet“，恭喜设置成功，从此你的所有内网设备都将可以访问纯IPv6网站，如东北大学六维空间或某些高校的bt&#x2F;pt站点（经测试，这样的NAT66网络仍然可以正常下载资源以及做种）……更多的用法，就请自己发掘吧！</p>  <div class="note p-4 mb-4 rounded-small default">    <p>如果你成功了，希望也可以去评论区冒个泡（</p>  </div>  <div class="note p-4 mb-4 rounded-small info">    <p>额外的测试连通性办法：使用命令<code>ping 2001:da8::666</code>，尝试ping TUNA的dns，若成功，则说明你的v6网络已基本成型；</p><p>此后可以进入<code>test-ipv6.com</code>，记得关闭科学上网工具再访问，若页面显示得分为10分，那么基本可以放心了。</p>  </div><details class="blue" data-header-exclude><summary><i class="fa-solid fa-chevron-right"></i>In case failed </summary>              <div class='content'>              <p>如果显示”无网络访问权限“，不要灰心，可能是设备并未尝试重新获取地址，可以尝试重启v6协议，具体操作方法为，在属性对话框中取消勾选”Internet协议版本6“，确认后重新打开属性对话框，再勾选v6协议，即可观察连接情况了。</p><p>若显示”无Internet访问权“，请打开”详细信息“窗口，观察”IPv6地址“项是否符合先前设置的ULA前缀：若不符合，请先尝试按照上文重启本地的v6协议；如果符合，那么说明设置过程出了一些问题，敬请评论反馈😥</p>              </div>            </details><hr><details class="red" data-header-exclude><summary><i class="fa-solid fa-chevron-right"></i>我校の悲哀 </summary>              <div class='content'>              <p>经观察，无论是通过NAT6还是设备直连校园网，获取到的v6地址都面临过一段时间就失效的问题，我暂未找出该故障的原因，因此只能编写如下的bash脚本，自动检测v6连接性并在失败时重启接口。请将脚本写入<code>/opt/ipv6-check.sh</code>，内容如下。</p><p>（提示：下方脚本代码仅供参考，<s>系AI作品</s>）</p><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># screen -dmS v6 /opt/ipv6-check.sh</span></span><br><span class="line"><span class="comment"># ver=0.1.0?</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">echo</span> IPv6 Check script is online now.</span><br><span class="line"><span class="keyword">while</span> <span class="literal">true</span>; <span class="keyword">do</span></span><br><span class="line">    <span class="keyword">if</span> ! ping6 -c 1 -W 1 2001:da8::666 &gt;/dev/null; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> $(<span class="built_in">date</span> +<span class="string">&#x27;%Y-%m-%d %H:%M:%S&#x27;</span>) reconnecting IPv6...</span><br><span class="line"></span><br><span class="line">        <span class="comment"># Get traffic data TX&amp;RX from ifconfig for eth0 interface</span></span><br><span class="line">        eth0_data=$(ifconfig eth0 | grep -oE <span class="string">&#x27;RX.*TX.*&#x27;</span> | sed -n <span class="string">&#x27;s/.*RX bytes:[0-9]\+ (\([0-9.]\+ GiB\))  TX bytes:[0-9]\+ (\([0-9.]\+ GiB\)).*/RX: \1 TX: \2/p&#x27;</span>)</span><br><span class="line">        <span class="comment"># Get traffic data TX&amp;RX from ifconfig for pppoe-wan interface</span></span><br><span class="line">        pppoe_wan_data=$(ifconfig pppoe-wan | grep -oE <span class="string">&#x27;RX.*TX.*&#x27;</span> | sed -n <span class="string">&#x27;s/.*RX bytes:[0-9]\+ (\([0-9.]\+ GiB\))  TX bytes:[0-9]\+ (\([0-9.]\+ GiB\)).*/RX: \1 TX: \2/p&#x27;</span>)</span><br><span class="line">        <span class="comment"># Concatenate the two interfaces&#x27; traffic data into a single string</span></span><br><span class="line">        all_traffic=<span class="string">&quot;[Current Traffic] WAN-all[<span class="variable">$&#123;eth0_data&#125;</span>] WAN4[<span class="variable">$&#123;pppoe_wan_data&#125;</span>]&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$all_traffic</span>&quot;</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;<span class="variable">$all_traffic</span>&quot;</span> &gt;&gt; /opt2/ipv6_var.<span class="built_in">log</span></span><br><span class="line">        /sbin/ifup wan6</span><br><span class="line">        <span class="built_in">sleep</span> 8</span><br><span class="line">        v6_addr=$(ifconfig | grep -oE <span class="string">&#x27;2001:250:[0-9a-fA-F:]+&#x27;</span>)</span><br><span class="line">        <span class="comment">#curl https://$&#123;your_bark&#125;/Dormitory+IPv6+Changed/$v6_addr.</span></span><br><span class="line">        <span class="built_in">echo</span> -ne <span class="string">&quot;\n<span class="subst">$(date +&#x27;%Y-%m-%d %H:%M:%S&#x27;)</span> <span class="variable">$v6_addr</span>&quot;</span></span><br><span class="line">        <span class="built_in">echo</span> -ne <span class="string">&quot;\n<span class="subst">$(date +&#x27;%Y-%m-%d %H:%M:%S&#x27;)</span> <span class="variable">$v6_addr</span>&quot;</span> &gt;&gt; /opt2/ipv6_var.<span class="built_in">log</span></span><br><span class="line">        <span class="built_in">sleep</span> 53</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line">    <span class="built_in">sleep</span> 10</span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br></pre></td></tr></table></figure></div><p>此后请在luci的启动项页面-&gt;本地启动脚本 中添加如下行：<code>screen -dmS v6 /opt/ipv6-check.sh</code></p>              </div>            </details><h3 id="一些闲言碎语"><a href="#一些闲言碎语" class="headerlink" title="一些闲言碎语"></a>一些闲言碎语</h3><ul><li>经测试，接入我校校园网的设备，无论是否经过认证，均能获取到<code>/128</code>的v6地址，但是尝试获取前缀却始终失败。鉴于上述情况，我只能采取NAT6的策略了。</li><li>据说NAT6对性能要求较高，但是在软路由为D2550、客户端通过千兆网线连接到路由器、访问<a class="link"   href="https://test6.ustc.edu.cn/" >USTC的ipv6测速网站<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>的情况下，仍能轻松地跑出700Mbps的上下行，期间软路由上CPU占用率最高仅60%左右，因此我认为，非硬路由Openwrt用户不必对性能担忧。</li><li>为了发挥v6的最大潜力，我给一个虚拟机直通了网卡使其获取了校园网直接下发的v6地址，并设置DNS为2001:da8::666，但是该机莫名其妙地无法上网，猜测是DNS配置问题，须使其也连接到v4网络并设置v4的DNS，才能成功。<s>（后来因为v6地址需要定期更新的原因也放弃了这样做，回归到路由器NAT6了）</s></li><li>让我继续折腾v6的真正起因是，上次回家，给家里一台旧Lenovo品牌机安装了个黑群晖（详情可见我tg频道），于是回宿舍后希望内网设备可以获得v6访问权，这样就可以方便地访问家中NAS了，最后结果也如我所愿，成功取得了v6地址；然而由于特殊的原因，上传到家中NAS的速度仅4MBps左右😭虽然不算快，但是算下来一晚上也够传30多G了，唉，就酱吧</li><li>折腾过程中，我看了好几篇教程，第一篇是官方的，写得很简略；<br>第二篇写的倒是很详细，但是一顿操作下来，差点搞得路由器自己都上不了v6，ping哪儿都显示 Network unreachable ；<a class="link"   href="https://zhuanlan.zhihu.com/p/492774540" >https://zhuanlan.zhihu.com/p/492774540<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a><br>第三篇，直击重点，让我把内网分配的ip前缀（全局网络前缀）从fd00这个保留区移出来，改成dd开头，结果一改马上就通网了<br><a class="link"   href="https://zhuanlan.zhihu.com/p/467475294" >https://zhuanlan.zhihu.com/p/467475294<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a><br>其他参考：   <a class="link"   href="https://evanzj.com/2021/12/20/NAT6/" >https://evanzj.com/2021/12/20/NAT6/<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;[摘要] 在我校只给连接校园网的设备下发 &amp;#x2F;128 的IPv6地址的背景下，如何让内网设备取得IPv6访问权，就成了一个问题。本文旨在利用NAT66技术，帮助读者，尤其是同为本校学生的读者，为自己宿舍的内网配置v6环境，以享受各界给予的v6红利（&lt;/p&gt;

  &lt;</summary>
      
    
    
    
    <category term="Small Tips" scheme="https://blog.eddy.moe/categories/Small-Tips/"/>
    
    
  </entry>
  
  <entry>
    <title>踩坑小笔记 第一期</title>
    <link href="https://blog.eddy.moe/2024/01/24/GeneralNote-1/"/>
    <id>https://blog.eddy.moe/2024/01/24/GeneralNote-1/</id>
    <published>2024-01-24T02:41:00.000Z</published>
    <updated>2024-01-24T04:13:02.511Z</updated>
    
    <content type="html"><![CDATA[<p>本篇主要记录本人在折腾路上碰到的一些小问题以及简要的解决方案，希望能帮到有需要的各位。</p><h2 id="一-Linux篇"><a href="#一-Linux篇" class="headerlink" title="一. Linux篇"></a>一. Linux篇</h2><h3 id="1-1-为虚拟显示器设置自定义分辨率"><a href="#1-1-为虚拟显示器设置自定义分辨率" class="headerlink" title="1.1 为虚拟显示器设置自定义分辨率"></a>1.1 为虚拟显示器设置自定义分辨率</h3><blockquote><p>set custom resolution for virtual displays</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cvt 1366 768</span><br><span class="line">xrandr --newmode <span class="string">&quot;1368x768_60.00&quot;</span>  85.25  1368 1440 1576 1784  768 771 781 798 -hsync +vsync</span><br><span class="line">xrandr --addmode DP-1 1368x768_60.00</span><br><span class="line">xrandr --output DP-1 --mode 1368x768_60.00 &amp;&amp; <span class="built_in">sleep</span> 15 &amp;&amp; xrandr --output DP-1 --mode 1920x1080_60.00</span><br></pre></td></tr></table></figure></div><p><em>(<code>cvt</code> is used to detect proper <code>Modeline</code> for specified resolution, like a calculator, and its output can be used in following <code>xrandr</code> commands.)</em></p><h3 id="1-2-设置systemd日志文件最大大小"><a href="#1-2-设置systemd日志文件最大大小" class="headerlink" title="1.2 设置systemd日志文件最大大小"></a>1.2 设置systemd日志文件最大大小</h3><blockquote><p>set maximum size of systemd journal</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">vi /etc/systemd/journald.conf</span><br><span class="line">systemctl restart systemd-journald.service</span><br><span class="line">journalctl --vacuum-time=2d</span><br><span class="line">journalctl --vacuum-size=50M</span><br></pre></td></tr></table></figure></div><p>Inside <code>journald.conf</code>, set your desired limit, like <code>SystemMaxUse=50M</code>, then run <code>sudo systemctl restart systemd-journald.service</code> to apply changes.</p><h3 id="1-3-修复系统中文支持异常问题，如无法显示中文路径"><a href="#1-3-修复系统中文支持异常问题，如无法显示中文路径" class="headerlink" title="1.3 修复系统中文支持异常问题，如无法显示中文路径"></a>1.3 修复系统中文支持异常问题，如无法显示中文路径</h3><blockquote><p>fix Chinese support in Linux</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">locale -a</span><br><span class="line">vi /etc/locale.gen</span><br><span class="line">sudo locale-gen</span><br></pre></td></tr></table></figure></div><p>In <code>locale.gen</code>, uncomment <code>zh_CN.UTF-8 UTF-8</code> and <code>zh_CN GB2312</code>.</p><h3 id="1-4-在bash中使用sudo重新执行上一条指令"><a href="#1-4-在bash中使用sudo重新执行上一条指令" class="headerlink" title="1.4 在bash中使用sudo重新执行上一条指令"></a>1.4 在bash中使用sudo重新执行上一条指令</h3><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo !!</span><br></pre></td></tr></table></figure></div><h3 id="1-5-让系统多使用物理内存，少使用交换空间"><a href="#1-5-让系统多使用物理内存，少使用交换空间" class="headerlink" title="1.5 让系统多使用物理内存，少使用交换空间"></a>1.5 让系统多使用物理内存，少使用交换空间</h3><blockquote><p>make system use more physical memory and less swap space</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo vi /etc/sysctl.conf</span><br><span class="line"><span class="comment"># add this line</span></span><br><span class="line"><span class="comment"># vm.swappiness=10</span></span><br></pre></td></tr></table></figure></div><h3 id="1-6-为apt设置https代理"><a href="#1-6-为apt设置https代理" class="headerlink" title="1.6 为apt设置https代理"></a>1.6 为apt设置https代理</h3><blockquote><p>set https proxy for apt</p></blockquote><p>Temporary proxy: add this parameter in your apt command:</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-o Acquire::http::proxy=&quot;http://127.0.0.1:1080&quot;</span><br></pre></td></tr></table></figure></div><h2 id="二-Windows篇"><a href="#二-Windows篇" class="headerlink" title="二. Windows篇"></a>二. Windows篇</h2><h3 id="2-1-移除‘此电脑’中不需要的库文件夹"><a href="#2-1-移除‘此电脑’中不需要的库文件夹" class="headerlink" title="2.1 移除‘此电脑’中不需要的库文件夹"></a>2.1 移除‘此电脑’中不需要的库文件夹</h3><blockquote><p>remove unnecessary folders in ‘This PC’, like ‘3D Objects’</p></blockquote><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace</span><br><span class="line">- Delete &#123;0DB7E03F-FC29-4DC6-9020-FF41B59E513A&#125;</span><br></pre></td></tr></table></figure></div><p><em>(Or use a third-party software to do this visually, like ‘Windows11 Manager’.)</em></p><h3 id="2-2-修改系统RDP端口"><a href="#2-2-修改系统RDP端口" class="headerlink" title="2.2 修改系统RDP端口"></a>2.2 修改系统RDP端口</h3><blockquote><p>change RDP port for major Windows versions</p></blockquote><div class="code-container" data-rel="Powershell"><figure class="iseeu highlight powershell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">(<span class="built_in">Get-ItemProperty</span> <span class="literal">-Path</span> <span class="string">&quot;HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\&quot;</span> <span class="literal">-Name</span> PortNumber).PortNumber</span><br><span class="line"></span><br><span class="line"><span class="built_in">Set-ItemProperty</span> <span class="literal">-Path</span> <span class="string">&quot;HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\&quot;</span> <span class="literal">-Name</span> PortNumber <span class="literal">-Value</span> <span class="number">6543</span></span><br><span class="line"><span class="comment"># test with command below:</span></span><br><span class="line"><span class="built_in">Get-NetTCPConnection</span> <span class="literal">-LocalPort</span> <span class="number">6543</span>; <span class="built_in">Get-NetUDPEndpoint</span> <span class="literal">-LocalPort</span> <span class="number">6543</span></span><br></pre></td></tr></table></figure></div><p><em>(Also see <a class="link"   href="https://go.microsoft.com/fwlink/?linkid=846671" >Microsoft official link<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>)</em></p><h2 id="三-Miscellaneous"><a href="#三-Miscellaneous" class="headerlink" title="三. Miscellaneous"></a>三. Miscellaneous</h2><h3 id="3-1-修复代码文件在不同系统间移动时因行分隔符不同而导致的无效git操作"><a href="#3-1-修复代码文件在不同系统间移动时因行分隔符不同而导致的无效git操作" class="headerlink" title="3.1 修复代码文件在不同系统间移动时因行分隔符不同而导致的无效git操作"></a>3.1 修复代码文件在不同系统间移动时因行分隔符不同而导致的无效git操作</h3><blockquote><p>fix line endings in git</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global core.autocrlf input</span><br></pre></td></tr></table></figure></div><h3 id="3-2-为Git配置https代理"><a href="#3-2-为Git配置https代理" class="headerlink" title="3.2 为Git配置https代理"></a>3.2 为Git配置https代理</h3><blockquote><p>set https proxy for git</p></blockquote><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git config --global https.proxy http://127.0.0.1:1080</span><br></pre></td></tr></table></figure></div><p>(effective for repos whose remote is in https protocol, check with <code>git remote -v</code>)</p><h3 id="3-3-为ssh配置socks5代理"><a href="#3-3-为ssh配置socks5代理" class="headerlink" title="3.3 为ssh配置socks5代理"></a>3.3 为ssh配置socks5代理</h3><blockquote><p>set socks5 proxy for ssh in user config file</p></blockquote><p>Add following line in your .ssh&#x2F;config file:</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Host github.com</span><br><span class="line">        User git</span><br><span class="line">        IdentityFile ~/.ssh/id_rsa</span><br><span class="line">        # ProxyCommand nc -X 5 -x 127.0.0.1:1080 %h %p      # if `nc` is installed</span><br><span class="line">        ProxyCommand connect -S 127.0.0.1:1080 %h %p        # for git bash on windows</span><br></pre></td></tr></table></figure></div><p>And remind that ‘connect’ maybe not in your PATH so cannot be executed directly, you can find it in your git installation directory, like <code>C:\Program Files\Git\mingw64\bin\connect.exe</code>, and use that path to replace the single <code>connect</code> in above commands.</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本篇主要记录本人在折腾路上碰到的一些小问题以及简要的解决方案，希望能帮到有需要的各位。&lt;/p&gt;
&lt;h2 id=&quot;一-Linux篇&quot;&gt;&lt;a href=&quot;#一-Linux篇&quot; class=&quot;headerlink&quot; title=&quot;一. Linux篇&quot;&gt;&lt;/a&gt;一. Linux篇&lt;</summary>
      
    
    
    
    <category term="Note Series" scheme="https://blog.eddy.moe/categories/Note-Series/"/>
    
    
  </entry>
  
  <entry>
    <title>PVE单节点修改主机名</title>
    <link href="https://blog.eddy.moe/2023/11/12/PVE/PVE%E5%8D%95%E8%8A%82%E7%82%B9%E4%BF%AE%E6%94%B9%E4%B8%BB%E6%9C%BA%E5%90%8D/"/>
    <id>https://blog.eddy.moe/2023/11/12/PVE/PVE%E5%8D%95%E8%8A%82%E7%82%B9%E4%BF%AE%E6%94%B9%E4%B8%BB%E6%9C%BA%E5%90%8D/</id>
    <published>2023-11-12T06:32:30.000Z</published>
    <updated>2023-11-12T09:59:25.943Z</updated>
    
    <content type="html"><![CDATA[<p>最近萌生了给自己常用的Proxmox VE机器修改主机名的想法（毕竟安装时用一些奇奇怪怪的主机名很正常xD）。未多想，我直接修改了<code>/etc/hostname</code>,但系统下次启动时竟意外地卡在<code>Loading initial ramdisk</code>界面，没有启动任何虚拟机，Web界面也进不去。很惊慌，以为是磁盘上有文件损坏，于是赶忙插上键盘在grub界面选择了recovery界面（override了我的核显直通相关设置）总算进入shell了，期间在syslog中瞥见不少pve相关服务的报错，原来事情没有这么简单，看来漏了步骤……</p><p>查阅资料后，我选择了这样做：</p><blockquote><p>以下内容参考了此网页：<a class="link"   href="https://blog.csdn.net/feitianyul/article/details/116098490" >https://blog.csdn.net/feitianyul/article/details/116098490<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 感谢原作者。</p></blockquote><ul><li>首先修改<code>/etc/hostname</code>和<code>/etc/hosts</code>（因为pve内很多服务都需要通过反向代理的方式访问自身，因此在hosts中定义新的主机名极其重要）；</li><li>其次还可以修改<code>/etc/postfix/main.cf</code>，修改此文件头部定义的旧主机名以便修改后可以正常使用“邮件提醒”功能；</li><li>然后，需要处理本地关于虚拟机和CT容器的相关配置文件以及TLS证书等等了。</li></ul><p>起初使用了如下代码来备份并移动配置文件 <code>mv old_name new_name</code> ，没想到的是居然提示目录不为空，无法移动文件夹？！采用cp也无法完成，因为总会有{虚拟机配置文件和LXC容器配置文件}无法复制，提示在目标位置已存在此文件。可是cd到该目录下，并未看到相关文件。这是为什么呢？</p><p>原来，这是pve的配置文件存放地点采用了特殊的文件系统所致。从df命令的输出可知，<code>/etc/pve</code>这个路径是采用fuse挂载的，它添加了很多的文件系统侧规则，从而导致了前面这些异常现象的发生。控制这一行为的命令叫做<code>pmxcfs</code>，不过我们无需直接操纵它，只需停止<code>pve-cluster</code>服务即可取消挂载。</p><p>所以，回到正题吧。为了按照本人的步骤完成操作，您可以在修改完主机名之后，先使用如下命令在系统正常时来备份并复制配置文件：</p><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> OLDN=old_name</span><br><span class="line"><span class="built_in">export</span> NEWN=new_name</span><br><span class="line"><span class="built_in">cd</span> /etc/pve</span><br><span class="line">tar czvf pvcfg.tar.gz .</span><br><span class="line"><span class="comment"># Append target directory here, after cp command!</span></span><br><span class="line"><span class="comment"># 请在cp命令后追加上您自己想要保存配置文件的路径，不在/etc/pve即可！</span></span><br><span class="line"><span class="built_in">cp</span> pvcfg.tar.gz</span><br><span class="line"><span class="built_in">cp</span> -rvp nodes/<span class="variable">$OLDN</span> nodes/<span class="variable">$NEWN</span></span><br><span class="line"><span class="comment"># 此过程会报错但请各位忽略，因为真正的复制尚未开始。至于为什么这样做，是为了保留您自己设置的SSL证书等外围配置。</span></span><br></pre></td></tr></table></figure></div><p>接下来重启系统，应当可以打开Web控制面板但不会启动任何虚拟机。建议使用SSH连接到机器并执行如下命令：</p><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">export</span> OLDN=old_name</span><br><span class="line"><span class="built_in">export</span> NEWN=new_name</span><br><span class="line"><span class="built_in">cd</span> /etc/pve/nodes</span><br><span class="line"><span class="built_in">cp</span> -rvp <span class="variable">$OLDN</span> /tmp/pvecfgtmp</span><br><span class="line"><span class="built_in">rm</span> -rf ./<span class="variable">$OLDN</span></span><br><span class="line"><span class="built_in">cp</span> -rvp /tmp/pvecfgtmp <span class="variable">$NEWN</span></span><br><span class="line">systemctl restart pve-cluster</span><br><span class="line"><span class="comment"># 结束配置文件的移动，接下来移动rrdcached数据库文件，以使虚拟机性能监控图表得以正常工作</span></span><br><span class="line">systemctl stop rrdcached</span><br><span class="line"><span class="built_in">cd</span> /var/lib/rrdcached/db</span><br><span class="line"><span class="built_in">mv</span> pve2-node/<span class="variable">$OLDN</span> pve2-node/<span class="variable">$NEWN</span></span><br><span class="line"><span class="built_in">mv</span> pve2-storage/<span class="variable">$OLDN</span> pve2-storage/<span class="variable">$NEWN</span></span><br><span class="line"><span class="comment"># 完成移动，重启pve相关服务，也可重启代替</span></span><br><span class="line">systemctl start rrdcached</span><br><span class="line">systemctl restart pvedaemon</span><br><span class="line">systemctl restart pvestatd</span><br><span class="line">systemctl restart pveproxy</span><br><span class="line">systemctl restart pvebanner</span><br></pre></td></tr></table></figure></div><p>如果在上面的步骤中没有看到严重警告，那么恭喜已经成功修改其主机名，经我测试进入Web控制面板后尚未发现有组件或配置丢失。</p><p>感谢阅读。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;最近萌生了给自己常用的Proxmox VE机器修改主机名的想法（毕竟安装时用一些奇奇怪怪的主机名很正常xD）。未多想，我直接修改了&lt;code&gt;/etc/hostname&lt;/code&gt;,但系统下次启动时竟意外地卡在&lt;code&gt;Loading initial ramdisk&lt;/</summary>
      
    
    
    
    <category term="Tech Logs" scheme="https://blog.eddy.moe/categories/Tech-Logs/"/>
    
    
  </entry>
  
  <entry>
    <title>Eddy0644的HackerGame2023部分题解</title>
    <link href="https://blog.eddy.moe/2023/11/05/Eddy0644-HackerGame2023/"/>
    <id>https://blog.eddy.moe/2023/11/05/Eddy0644-HackerGame2023/</id>
    <published>2023-11-05T02:19:20.000Z</published>
    <updated>2023-11-07T04:16:49.729Z</updated>
    
    <content type="html"><![CDATA[<p>本人来自AHU，也是第一次参加Hackergame和CTF比赛，不得不说相较于ACM，这种类型的比赛更让我着迷。可惜成绩不如诸位大佬（<code>分数：2600， 总排名：278 / 2386</code>）</p><p>接下来将为大家带来本人对部分题的解法。</p><h3 id="猫咪小测"><a href="#猫咪小测" class="headerlink" title="猫咪小测"></a>猫咪小测</h3><p>Q1 想要借阅世界图书出版公司出版的《A Classical Introduction To Modern Number Theory 2nd ed.》，应当前往中国科学技术大学西区图书馆的哪一层？</p><ul><li>经搜索，发现中国科学技术大学的<a class="link"   href="http://opac.lib.ustc.edu.cn/opac/search_adv.php" >图书馆opac系统<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>无需登录即可访问，遂进入系统搜索到了此图书（起初并未查询到任何结果，后来发现移除后缀<code>2nd ed.</code>即可搜到，想必是做了分开储存的处理）</li><li>得知此书位于西区图书馆外文书库，又在另一页面（ 忘记保存链接了:( ）得知外文书库位于12层，即可解出此题。</li></ul><p>Q2 今年 arXiv 网站的天体物理版块上有人发表了一篇关于「可观测宇宙中的鸡的密度上限」的论文，请问论文中作者计算出的鸡密度函数的上限为 10 的多少次方每立方秒差距？</p><ul><li>很巧，在进入arXiv之前就在知乎找到了<a class="link"   href="https://www.zhihu.com/question/20337132/answer/3023506910" >相同主题的文章<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，其中表明答案为10^23ps^-3,即23为本题答案。</li></ul><p>Q3 为了支持 TCP BBR 拥塞控制算法，在编译 Linux 内核时应该配置好哪一条内核选项？</p><ul><li><code>CONFIG_TCP_CONG_BBR</code>，略</li></ul><p>Q4 🥒🥒🥒：「我……从没觉得写类型标注有意思过」。在一篇论文中，作者给出了能够让 Python 的类型检查器 MyPY mypy 陷入死循环的代码，并证明 Python 的类型检查和停机问题一样困难。请问这篇论文发表在今年的哪个学术会议上？</p><ul><li>此题当时让我“抓狂”，大概是翻译的不好或耐心不够罢，没能从互联网找到正确答案，遂采用爆破方法，代码如下：</li></ul><p>先从<a class="link"   href="https://ccf.atom.im/" >中国计算机学会推荐国际学术会议和期刊目录（2022）<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>获得表格形式的会议列表（当时偷了个懒，想着2022年的数据也未尝不可，<s>不行再换嘛</s>），在DevTools采用如下代码，并对输出数组右键拷贝为Object可得到会议列表：</p><div class="code-container" data-rel="Js"><figure class="iseeu highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">a=[];<span class="keyword">for</span>(<span class="keyword">let</span> i <span class="keyword">of</span> <span class="variable language_">document</span>.<span class="title function_">querySelectorAll</span>(<span class="string">&quot;tr &gt; td:nth-child(2)&quot;</span>))a.<span class="title function_">push</span>(i.<span class="property">innerText</span>);b=[];a.<span class="title function_">map</span>(<span class="function"><span class="params">e</span>=&gt;</span>&#123;<span class="variable language_">console</span>.<span class="title function_">log</span>(e);<span class="keyword">break</span>;<span class="keyword">if</span>(e.<span class="property">length</span>==<span class="number">4</span> || <span class="number">1</span>)b.<span class="title function_">push</span>(e)&#125;)</span><br></pre></td></tr></table></figure></div><p>这时又暴露出了我的短板，没注意审题，以为满足条件的会议都是四字英文字母（<br>好在后面发现并改正了，这是后话了。</p><p>接下来，在猫咪小测网页运行如下代码，开始测试：</p><div class="code-container" data-rel="Js"><figure class="iseeu highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 在此处粘贴入复制的会议列表，之所以使用prompt()是不想在浏览器控制台历史记录增添乱七八糟的条目（</span></span><br><span class="line"></span><br><span class="line">b=<span class="title class_">JSON</span>.<span class="title function_">parse</span>(<span class="title function_">prompt</span>());</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 定义s1函数，执行发送指令并显示出正确结果</span></span><br><span class="line">s1=<span class="function">(<span class="params">v4</span>)=&gt;</span><span class="title function_">fetch</span>(<span class="string">&quot;http://202.38.93.111:10001/&quot;</span>, &#123;</span><br><span class="line">  <span class="string">&quot;headers&quot;</span>: &#123;</span><br><span class="line">    <span class="string">&quot;content-type&quot;</span>: <span class="string">&quot;application/x-www-form-urlencoded&quot;</span>,</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="string">&quot;referrer&quot;</span>: <span class="string">&quot;http://202.38.93.111:10001/&quot;</span>,</span><br><span class="line">  <span class="string">&quot;referrerPolicy&quot;</span>: <span class="string">&quot;strict-origin-when-cross-origin&quot;</span>,</span><br><span class="line">  <span class="string">&quot;body&quot;</span>: <span class="string">&quot;q1=12&amp;q2=23&amp;q3=CONFIG_TCP_CONG_BBR&amp;q4=&quot;</span>+v4,</span><br><span class="line">  <span class="string">&quot;method&quot;</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">  <span class="string">&quot;mode&quot;</span>: <span class="string">&quot;cors&quot;</span>,</span><br><span class="line">  <span class="string">&quot;credentials&quot;</span>: <span class="string">&quot;include&quot;</span></span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function"><span class="params">r</span>=&gt;</span>r.<span class="title function_">text</span>()).<span class="title function_">then</span>(<span class="function"><span class="params">txt</span>=&gt;</span>&#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(txt.<span class="title function_">includes</span>(<span class="string">&quot;总得分为 80&quot;</span>)?(<span class="string">&quot;Not this...&quot;</span>+v4):txt);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 自动版；每隔500ms发起一次测试</span></span><br><span class="line"><span class="keyword">let</span> currentIndex = <span class="number">0</span>,intv;intv=<span class="built_in">setInterval</span>(<span class="function">()=&gt;</span>&#123;</span><br><span class="line">    <span class="title function_">s1</span>(currentString);</span><br><span class="line">    <span class="keyword">if</span>(currentIndex++ == b.<span class="property">length</span>)<span class="built_in">clearInterval</span>(intv);</span><br><span class="line">&#125;,<span class="number">500</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 最初本人采用的手动版；每在网页按一次空格发起一次测试（不能在DevTools中按，因为后者是个独立的页面（）</span></span><br><span class="line"></span><br><span class="line"><span class="variable language_">document</span>.<span class="title function_">addEventListener</span>(<span class="string">&#x27;keydown&#x27;</span>, <span class="keyword">function</span> (<span class="params">event</span>) &#123;</span><br><span class="line">    <span class="keyword">if</span> (event.<span class="property">key</span> === <span class="string">&#x27; &#x27;</span>) &#123;</span><br><span class="line">        <span class="keyword">if</span> (currentIndex &lt; b.<span class="property">length</span>) &#123;</span><br><span class="line">            <span class="keyword">const</span> currentString = b[currentIndex];</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="title function_">s1</span>(currentString));</span><br><span class="line">            currentIndex++;</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">&quot;No more strings in the array.&quot;</span>);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></div><p>之后得到正确结果<code>ECOOP</code>。</p><h3 id="组委会模拟器"><a href="#组委会模拟器" class="headerlink" title="组委会模拟器"></a>组委会模拟器</h3><ul><li><p>简单来说，该页面会首先请求服务器<code>/api/getMessages</code>，得到含有“服务器开始时间”，每条消息相对开始时间的延迟及消息内容的响应。我所做的是利用如下js代码代替页面原有逻辑，完成整个撤回过程。</p><div class="code-container" data-rel="Js"><figure class="iseeu highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 定义sendDel函数，执行撤回指令</span></span><br><span class="line"><span class="keyword">const</span> <span class="title function_">sendDel</span> = (<span class="params">id</span>) =&gt; &#123;</span><br><span class="line">    <span class="title function_">fetch</span>(<span class="string">&quot;http://202.38.93.111:10021/api/deleteMessage&quot;</span>, &#123;</span><br><span class="line">        <span class="string">&quot;headers&quot;</span>: &#123;</span><br><span class="line">            <span class="string">&quot;content-type&quot;</span>: <span class="string">&quot;application/json&quot;</span></span><br><span class="line">        &#125;,</span><br><span class="line">        <span class="string">&quot;referrer&quot;</span>: <span class="string">&quot;http://202.38.93.111:10021/&quot;</span>,</span><br><span class="line">        <span class="string">&quot;referrerPolicy&quot;</span>: <span class="string">&quot;strict-origin-when-cross-origin&quot;</span>,</span><br><span class="line">        <span class="string">&quot;body&quot;</span>: <span class="string">`&#123;\&quot;id\&quot;:<span class="subst">$&#123;id&#125;</span>&#125;`</span>,</span><br><span class="line">        <span class="string">&quot;method&quot;</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">        <span class="string">&quot;mode&quot;</span>: <span class="string">&quot;cors&quot;</span>,</span><br><span class="line">        <span class="string">&quot;credentials&quot;</span>: <span class="string">&quot;include&quot;</span></span><br><span class="line">    &#125;).<span class="title function_">then</span>(<span class="function"><span class="params">resp</span> =&gt;</span> resp.<span class="title function_">json</span>()).<span class="title function_">then</span>(<span class="function"><span class="params">json</span> =&gt;</span> &#123;</span><br><span class="line">        <span class="keyword">if</span> (!json.<span class="property">success</span>) &#123;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">warn</span>(json.<span class="property">error</span>);</span><br><span class="line">            failTotal++;</span><br><span class="line">        &#125; <span class="keyword">else</span> successTotal++;</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="keyword">let</span> hacksTotal = <span class="number">0</span>, successTotal = <span class="number">0</span>, failTotal = <span class="number">0</span>;</span><br><span class="line"><span class="title function_">fetch</span>(<span class="string">&quot;http://202.38.93.111:10021/api/getMessages&quot;</span>, &#123;</span><br><span class="line">    <span class="string">&quot;headers&quot;</span>: &#123;</span><br><span class="line">        <span class="string">&quot;content-type&quot;</span>: <span class="string">&quot;application/json&quot;</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="string">&quot;referrer&quot;</span>: <span class="string">&quot;http://202.38.93.111:10021/&quot;</span>,</span><br><span class="line">    <span class="string">&quot;referrerPolicy&quot;</span>: <span class="string">&quot;strict-origin-when-cross-origin&quot;</span>,</span><br><span class="line">    <span class="string">&quot;body&quot;</span>: <span class="string">&quot;&quot;</span>,</span><br><span class="line">    <span class="string">&quot;method&quot;</span>: <span class="string">&quot;POST&quot;</span>,</span><br><span class="line">    <span class="string">&quot;mode&quot;</span>: <span class="string">&quot;cors&quot;</span>,</span><br><span class="line">    <span class="string">&quot;credentials&quot;</span>: <span class="string">&quot;include&quot;</span></span><br><span class="line">&#125;).<span class="title function_">then</span>(<span class="function"><span class="params">resp</span> =&gt;</span> resp.<span class="title function_">json</span>()).<span class="title function_">then</span>(<span class="function"><span class="params">json</span> =&gt;</span> &#123;</span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(json);</span><br><span class="line">    <span class="comment">// json对象即为所有消息之数组 + 服务器开始时间</span></span><br><span class="line">    <span class="keyword">const</span> gets = json, getTime = <span class="function">() =&gt;</span> (<span class="keyword">new</span> <span class="title class_">Date</span>() - <span class="keyword">new</span> <span class="title class_">Date</span>(gets.<span class="property">server_starttime</span>))/<span class="number">1000</span>;</span><br><span class="line">    <span class="comment">// 定义了getTime函数，方便快速判断当前是否符合撤回此消息的时间条件</span></span><br><span class="line">    <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`getTime: <span class="subst">$&#123;getTime()&#125;</span>`</span>);</span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">let</span> a <span class="keyword">in</span> gets.<span class="property">messages</span>) &#123;</span><br><span class="line">        <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;hacksTotal&#125;</span> <span class="subst">$&#123;successTotal&#125;</span> <span class="subst">$&#123;failTotal&#125;</span>`</span>)</span><br><span class="line">        <span class="comment">// 利用正则表达式检测是否满足条件</span></span><br><span class="line">        <span class="keyword">if</span> (gets.<span class="property">messages</span>[a].<span class="property">text</span>.<span class="title function_">match</span>(<span class="regexp">/hack\[([a-z]*?)]/</span>)) &#123;</span><br><span class="line">            hacksTotal++;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`Found ID=<span class="subst">$&#123;a&#125;</span>, containing hack[]`</span>);</span><br><span class="line">            <span class="keyword">const</span> targetTime = <span class="title class_">Math</span>.<span class="title function_">ceil</span>(gets.<span class="property">messages</span>[a].<span class="property">delay</span>);</span><br><span class="line">            <span class="comment">// 此处判断开始时间与delay值是否匹配，不符合则通过让CPU空算直到到达那个时间（）我知道这种写法不好，不过看着很直观（x</span></span><br><span class="line">            <span class="keyword">while</span> (<span class="title function_">getTime</span>() &lt; targetTime) &#123;</span><br><span class="line">                <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="number">1800000</span>; i++) &#123;</span><br><span class="line">                &#125;</span><br><span class="line">            &#125;</span><br><span class="line">            <span class="variable language_">console</span>.<span class="title function_">log</span>(<span class="string">`<span class="subst">$&#123;getTime()&#125;</span> --==-- <span class="subst">$&#123;targetTime&#125;</span>`</span>);</span><br><span class="line">            <span class="title function_">sendDel</span>(a);</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;);</span><br><span class="line"></span><br></pre></td></tr></table></figure></div></li></ul><h3 id="虫"><a href="#虫" class="headerlink" title="虫"></a>虫</h3><ul><li><p>只能说多亏了平时刷到的奇奇怪怪的内容，我第一反应就是SSTV，Slow-Scan Television，（不得不说无线电爱好者们潜力无限哈），在Windows PC上下载了相关软件 <a class="link"   href="https://www.qsl.net/on6mu/rxsstv.htm" >RXSSTV<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，并在<code>声音托盘图标-&gt;声音-&gt;录制</code>中打开“立体声混音”（非Realtek声卡我就不知道是否有此功能了，原本尝试过OBS但是并没有发现虚拟麦克风相关选项，不过只要有麦克风的话，还是可以外放的嘛（x）一边播放录音一边启动软件，就可以静候彩色flag图片出现了。</p></li><li><p>注1：我没想到PotPlayer是我尝试失败的罪魁祸首，由于前者是我PC上的默认播放软件，我也就一直使用它，结果使用上述软件以及MMSSTV均无法得到清晰可辨的图像（字符极其模糊，只有个别字母和大赛logo可见），就在我想要发送邮件询问的一刹那，我换用了Windows Media Player，结果居然可以得到清晰图像！这一问题我至今不知道原因为何。（已检查PotPlayer倍速设置为1.0）</p></li><li><p>注2：无Windows机器的小伙伴可能在安装上述软件时遇到了困难，因为我下载的这两款软件之安装包统统无法使用压缩软件（如<code>Bandizip</code>）解包并直接运行，无奈只好采用沙盒运行（是Sandboxie，并非Windows沙盒）不得不说Sbie的兼容性可比Wine好多了，至少奇奇怪怪的软件大多都可以正常运行（</p><p>（绝无任何贬低Wine的意思，我深刻理解并感谢Wine维护者们在逆向Windows API以及其他方面的贡献，只是这条路确实任重道远）</p></li></ul><h3 id="Git-Git"><a href="#Git-Git" class="headerlink" title="Git? Git!"></a>Git? Git!</h3><p>  在接触此题之前，我便对Git的文件管理特殊之处有所耳闻，被撤销的更改仍旧位于<code>.git</code>中，且未经<code>git gc</code>命令不会消失。在询问GPT以及搜寻资料后，写出了如下<s>不用操心</s>的Bash脚本（因为不需要猜测哪个commit包含被修改的文件，经测数秒即可输出结果）</p>  <div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"><span class="comment"># Define the target directory where .git/objects is located</span></span><br><span class="line">GIT_OBJECTS_DIR=<span class="string">&quot;.git/objects&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Iterate through the two-hex-named directories</span></span><br><span class="line"><span class="keyword">for</span> <span class="built_in">dir</span> <span class="keyword">in</span> $(find <span class="string">&quot;<span class="variable">$GIT_OBJECTS_DIR</span>&quot;</span> -<span class="built_in">type</span> d -name <span class="string">&quot;??&quot;</span>); <span class="keyword">do</span></span><br><span class="line">    dir_name=$(<span class="built_in">basename</span> <span class="string">&quot;<span class="variable">$dir</span>&quot;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="comment"># Iterate through object files in the directory</span></span><br><span class="line">    <span class="keyword">for</span> obj_file <span class="keyword">in</span> <span class="string">&quot;<span class="variable">$dir</span>&quot;</span>/*; <span class="keyword">do</span></span><br><span class="line">        <span class="comment"># Combine directory name with object filename</span></span><br><span class="line">        combined_path=<span class="string">&quot;$dir_name<span class="subst">$(basename <span class="string">&quot;<span class="variable">$obj_file</span>&quot;</span>)</span>&quot;</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># Execute your command with the combined path</span></span><br><span class="line">        git cat-file -p <span class="string">&quot;<span class="variable">$combined_path</span>&quot;</span> | grep <span class="string">&#x27;flag&#x27;</span></span><br><span class="line">    <span class="keyword">done</span></span><br><span class="line"><span class="keyword">done</span></span><br></pre></td></tr></table></figure></div><h3 id="🪐-低带宽星球-206-Partial-Content"><a href="#🪐-低带宽星球-206-Partial-Content" class="headerlink" title="🪐 低带宽星球     (206 Partial Content)"></a>🪐 低带宽星球     (206 Partial Content)</h3><ul><li><p>第一问，我起初是通过压缩网站完成的，相信各位都明白，此略</p></li><li><p>为了将图片尽可能压缩，我通过比对图片细节，手搓了第一版svg代码，虽然通过了像素级比对，但大小将近200字节；后来经过人工压缩，</p><ul><li><p>将根元素svg的width等属性替换为viewBox</p></li><li><p>将fill属性值从<code>rgb(111,222,30)</code>这样的值替换为Hex表示法<code>#5cabc1</code></p></li><li><p>移除rect元素中为0的x或y属性</p></li><li><p>将rect元素直接替换为path，进一步缩减大小<br>plaintext<br> 发现这样做也不可能将图片压缩至50字节，即使经过了gzip压缩成svgz格式也不行，因为仅仅一行rect元素就已经堪堪超限了，<s>早该及时止损的（）</s></p></li></ul>  <div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">&lt;svg width=&quot;1024&quot; height=&quot;1024&quot;&gt;</span><br><span class="line">    &lt;rect width=&quot;314&quot; height=&quot;1024&quot; fill=&quot;#5cabc1&quot;/&gt;</span><br><span class="line">    &lt;rect x=&quot;314&quot; width=&quot;426&quot; height=&quot;1024&quot; fill=&quot;#4edb0a&quot;/&gt;</span><br><span class="line">    &lt;rect x=&quot;740&quot; width=&quot;284&quot; height=&quot;1024&quot; fill=&quot;#44d404&quot;/&gt;</span><br><span class="line">    &lt;/svg&gt;</span><br><span class="line">    &lt;svg viewBox=&quot;1024 1024&quot;&gt;&lt;path d=&quot;M0 0h314v1024H0z&quot; fill=&quot;#5CABC1&quot;/&gt; &lt;path d=&quot;M314 0h426v1024H314z&quot; fill=&quot;#4EDB0A&quot;/&gt;&lt;path d=&quot;M740 0h284v1024H740z&quot; fill=&quot;#44D404&quot;/&gt; &lt;/svg&gt;</span><br></pre></td></tr></table></figure></div></li></ul><p>这时很容易想到，需要寻求一个使用二进制而非ASCII字符控制绘图的矢量图形语言，这样才满足要求。接下来，通过询问GPT、查询libvips网站、在<code>convert.io</code>网站查看可供选择的矢量图形类型列表，我试图将此svg图形转换为<code>eps,ai,cgm,dxf,fig,plt,ppm,vips</code>，但要么无法被pyvips识别，要么不满足本题条件，只好放弃。</p><p>后面阅读了官方题解，才发现我漏掉了最重要的信息来源之一 <code>libvips</code>源码，<s>早知如此就不用试那么多图像类型了</s>，jxl格式或成最大赢家（        （本题请参考官方题解）</p><h3 id="旅行照片"><a href="#旅行照片" class="headerlink" title="旅行照片"></a>旅行照片</h3><p>第一问，通过奖牌上人名<code>M.Koshiba</code>得知是获得诺贝尔物理学奖的小柴昌俊，从而得知学长在东京大学，通过维基百科可知满足第二问条件的东京大学诺贝尔奖得主为梶田隆章，所在研究所为<code>東京大学宇宙線研究所</code>，简称ICRR。通过第二张图片可知学长参加了国际统计物理会议STATPHYS第28次会议，通过<a class="link"   href="https://statphys28.org/" >官网<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>得知会议举办时间在8月7-11日，手工尝试可得。</p><p>第三问，通过在Google上广撒网，看了不少街景图片，发现有一张背景的白色帐篷和本题十分相近，由此得知该活动名为“全国梅酒まつり”（即“祭”，应该是大会的意思），在其<a class="link"   href="https://umeshu-matsuri.jp/tokyo_ueno/" >官网<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>上很容易得知，<a class="link"   href="https://ws.formzu.net/dist/S495584522/" >在线表单<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>URL的末位。至于第四问，通过东京国立博物馆相关说明，得知<strong>单人</strong>门票价格只能是1000，500，0，所以成功试出结果（</p><p>第五问，谁知道当初的我盯着Google360°街景看了多长时间！那时刚巧是我第一次了解到谷歌街景的神奇之处，遂操纵它在<code>上野駅</code>的周围到处移动镜头，看到了周围的大型百货商场<code>0101</code>，不过找不到任何粉色海报和大型3D广告牌的踪迹。后来灵光一现，前往Twitter，果然很轻松搜到了<code>ボタン＆カフリンクス</code>活动的海报，背景上是一只熊猫；至于第六问，通过不断修改关键词<code>上野、3D、看板</code>，得知是“秋田犬”，结束。</p><p>（后来我发现了自己思维的局限性，题干中说“JR上野站”进站处云云没有问题，但“出站处”可并非指的是上野站，那么我在上野再怎么找都是找不到的，当初搜到了应该是因为碰巧删除了上野关键词才成功。看了官方题解才知道，通过任天堂logo可知“我”出的是<code>渋谷駅</code>，那里可以找到这样的3D大广告牌。</p><h3 id="结语"><a href="#结语" class="headerlink" title="结语"></a>结语</h3><p>这是本人第一次参加CTF比赛，通过此次锻炼我也发现了自身存在的诸多不足，例如眼界不宽广、思维不发散、技术知识储备不足等，目前只能仰视诸位大佬，希望自己再接再厉！同时郑重感谢USTC Hackergame 2023 全体幕后成员，提供了这样一个挑战自我的机会。</p><p>如有兴趣，欢迎查看</p><ul><li><p>本人博客 <a class="link"   href="https://blog.ryancc.top/" >https://blog.ryancc.top<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p></li><li><p>本人Telegram频道 <a class="link"   href="https://t.me/rych0814" >https://t.me/rych0814<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p></li><li><p>（如果您恰好需要联系本人，可选择在频道内留言，或跟踪我的Github主页，不便敬请谅解）</p></li><li><p>（唉，技术没涨，人倒越来越懒了，博文懒得写，一般在技术探索中碰到的小tips就直接发频道了，最近正在试用<a href="usememos/memos">usememos&#x2F;memos</a>，希望它可以帮助我记录日常所思所想）</p><p>谨在此贴出我的分数变更日志（懒得上传图片了，同时也为本项目的大小做了积极贡献），谢谢看到这里。</p><table><thead><tr><th>时间</th><th>解出题目</th><th>分数变化</th><th>排名变化</th></tr></thead><tbody><tr><td>2023&#x2F;10&#x2F;28 12:15</td><td>更深更暗</td><td>0-&gt;100</td><td>212-&gt;101</td></tr><tr><td>2023&#x2F;10&#x2F;28 13:29</td><td>Hackergame 启动</td><td>100-&gt;150</td><td>375-&gt;371</td></tr><tr><td>2023&#x2F;10&#x2F;28 14:11</td><td>虫</td><td>150-&gt;300</td><td>427-&gt;272</td></tr><tr><td>2023&#x2F;10&#x2F;28 14:57</td><td>猫咪小测 &#x2F; 及格喵</td><td>300-&gt;400</td><td>312-&gt;260</td></tr><tr><td>2023&#x2F;10&#x2F;28 15:06</td><td>🪐 低带宽星球 &#x2F; 小试牛刀</td><td>400-&gt;550</td><td>263-&gt;173</td></tr><tr><td>2023&#x2F;10&#x2F;28 15:59</td><td>组委会模拟器</td><td>550-&gt;750</td><td>195-&gt;126</td></tr><tr><td>2023&#x2F;10&#x2F;28 16:02</td><td>HTTP 集邮册 &#x2F; 5 种状态码</td><td>750-&gt;900</td><td>126-&gt;86</td></tr><tr><td>2023&#x2F;10&#x2F;28 16:18</td><td>Docker for Everyone</td><td>900-&gt;1050</td><td>92-&gt;68</td></tr><tr><td>2023&#x2F;10&#x2F;28 16:23</td><td>🪐 小型大语言模型星球 &#x2F; You Are Smart</td><td>1050-&gt;1150</td><td>68-&gt;58</td></tr><tr><td>2023&#x2F;10&#x2F;28 20:14</td><td>旅行照片 3.0 &#x2F; 这是什么活动？</td><td>1150-&gt;1300</td><td>113-&gt;96</td></tr><tr><td>2023&#x2F;10&#x2F;28 20:21</td><td>旅行照片 3.0 &#x2F; 神秘奖牌</td><td>1300-&gt;1450</td><td>97-&gt;76</td></tr><tr><td>2023&#x2F;10&#x2F;28 21:59</td><td>奶奶的睡前 flag 故事</td><td>1450-&gt;1600</td><td>90-&gt;79</td></tr><tr><td>2023&#x2F;10&#x2F;28 22:22</td><td>Git? Git!</td><td>1600-&gt;1750</td><td>80-&gt;70</td></tr><tr><td>2023&#x2F;10&#x2F;28 22:45</td><td>赛博井字棋</td><td>1750-&gt;1900</td><td>72-&gt;63</td></tr><tr><td>2023&#x2F;10&#x2F;30 19:46</td><td>猫咪小测 &#x2F; 满分喵</td><td>1900-&gt;2050</td><td>214-&gt;204</td></tr><tr><td>2023&#x2F;10&#x2F;30 20:57</td><td>🪐 高频率星球</td><td>2050-&gt;2250</td><td>206-&gt;182</td></tr><tr><td>2023&#x2F;10&#x2F;31 0:58</td><td>HTTP 集邮册 &#x2F; 12 种状态码</td><td>2250-&gt;2450</td><td>196-&gt;168</td></tr><tr><td>2023&#x2F;11&#x2F;2 21:05</td><td>旅行照片 3.0 &#x2F; 后会有期，学长！</td><td>2450-&gt;2600</td><td>251-&gt;239</td></tr></tbody></table></li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本人来自AHU，也是第一次参加Hackergame和CTF比赛，不得不说相较于ACM，这种类型的比赛更让我着迷。可惜成绩不如诸位大佬（&lt;code&gt;分数：2600， 总排名：278 / 2386&lt;/code&gt;）&lt;/p&gt;
&lt;p&gt;接下来将为大家带来本人对部分题的解法。&lt;/p&gt;
&lt;</summary>
      
    
    
    
    
  </entry>
  
  <entry>
    <title>naiveproxy搭建全流程记录</title>
    <link href="https://blog.eddy.moe/2023/10/11/Guides/naiveproxy%E6%90%AD%E5%BB%BA%E5%85%A8%E6%B5%81%E7%A8%8B%E8%AE%B0%E5%BD%95/"/>
    <id>https://blog.eddy.moe/2023/10/11/Guides/naiveproxy%E6%90%AD%E5%BB%BA%E5%85%A8%E6%B5%81%E7%A8%8B%E8%AE%B0%E5%BD%95/</id>
    <published>2023-10-11T02:19:20.000Z</published>
    <updated>2023-10-11T02:47:53.357Z</updated>
    
    <content type="html"><![CDATA[<p>以此文记录一次本人在一台安装了Debian系操作系统的VPS上搭建带伪装的naiveproxy的过程。</p><p>（补充介绍）NaïveProxy使用Chrome的网络栈，所以防火墙截获的流量行为与Chrome和标准前端服务器（如Caddy、HAProxy）之间的常规HTTP&#x2F;2流量是完全相同的。它还通过填充长度缓解基于长度的流量分析，通过HTTP&#x2F;2中的流量复用缓解指纹识别&#x2F;流量分类。</p><div class="code-container" data-rel="Bash"><figure class="iseeu highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">DOMAIN=your.domain</span><br><span class="line">DIR=/root/niv</span><br><span class="line"></span><br><span class="line"><span class="comment"># Install Go</span></span><br><span class="line">wget -c https://dl.google.com/go/go1.21.2.linux-amd64.tar.gz -O - | sudo tar -xz -C /usr/local</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;export GOROOT=/usr/local/go&#x27;</span> &gt;&gt; /etc/profile</span><br><span class="line"><span class="built_in">echo</span> <span class="string">&#x27;export PATH=$GOROOT/bin:$PATH&#x27;</span> &gt;&gt; /etc/profile</span><br><span class="line"><span class="built_in">source</span> /etc/profile</span><br><span class="line"></span><br><span class="line"><span class="comment"># Install certbot</span></span><br><span class="line">apt update</span><br><span class="line">sudo apt-get install certbot python3-certbot-apache</span><br><span class="line"></span><br><span class="line">sudo certbot certonly --webroot -w /var/www/html -d <span class="variable">$DOMAIN</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">mkdir</span> <span class="variable">$DIR</span> 2&gt;/dev/null</span><br><span class="line"><span class="built_in">cd</span> <span class="variable">$DIR</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">ln</span> -s /etc/letsencrypt/live/<span class="variable">$DOMAIN</span>/fullchain.pem 1.crt</span><br><span class="line"><span class="built_in">ln</span> -s /etc/letsencrypt/live/<span class="variable">$DOMAIN</span>/privkey.pem 1.key</span><br><span class="line"></span><br><span class="line"><span class="comment"># Compile Caddy</span></span><br><span class="line"></span><br><span class="line">go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest</span><br><span class="line">~/go/bin/xcaddy build --with github.com/caddyserver/forwardproxy@caddy2=github.com/klzgrad/forwardproxy@naive</span><br><span class="line">nano Caddyfile</span><br></pre></td></tr></table></figure></div><p>对于Caddyfile，请参考下例自行修改。</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">order forward_proxy before route</span><br><span class="line">admin off</span><br><span class="line">auto_https off</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">:443 &#123;</span><br><span class="line">#----------Change Cert file location</span><br><span class="line">tls /root/niv/1.crt /root/niv/1.key &#123;</span><br><span class="line">ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256</span><br><span class="line">alpn h2 http/1.1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">forward_proxy &#123;</span><br><span class="line">#----------Username and password for naive</span><br><span class="line">basic_auth uname passwd</span><br><span class="line">hide_ip</span><br><span class="line">hide_via</span><br><span class="line">probe_resistance</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">@host &#123;</span><br><span class="line">#----------your domain on this machine</span><br><span class="line">host $DOMAIN</span><br><span class="line">&#125;</span><br><span class="line">route @host &#123;</span><br><span class="line">header &#123;</span><br><span class="line">Strict-Transport-Security &quot;max-age=31536000; includeSubDomains; preload&quot;</span><br><span class="line">&#125;</span><br><span class="line">#----------Redirect to this domain if not naive</span><br><span class="line">reverse_proxy google.com &#123;</span><br><span class="line">header_up Host &#123;upstream_hostport&#125;</span><br><span class="line">header_up X-Forwarded-Host &#123;host&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure></div><p>此后可利用screen会话来运行caddy （.&#x2F;caddy start 即可），此时服务端就已搭建好。</p><p>客户端连接时，连接类型选择为naiveproxy或HTTPS，端口请设为443，传输协议请选择HTTP2或HTTPS。并且如果有“填充”选项也请打开。<br>对于不支持naive的通用客户端，有一种解决方案是使用另一客户端连接代理并暴露SOCKS或HTTP内网代理端口。或可参考 <a class="link"   href="https://github.com/klzgrad/naiveproxy/releases" >https://github.com/klzgrad/naiveproxy/releases<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 下载对应平台的naiveproxy专用客户端。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;以此文记录一次本人在一台安装了Debian系操作系统的VPS上搭建带伪装的naiveproxy的过程。&lt;/p&gt;
&lt;p&gt;（补充介绍）NaïveProxy使用Chrome的网络栈，所以防火墙截获的流量行为与Chrome和标准前端服务器（如Caddy、HAProxy）之间的常规H</summary>
      
    
    
    
    <category term="Guides" scheme="https://blog.eddy.moe/categories/Guides/"/>
    
    
  </entry>
  
  <entry>
    <title>ctBridgeBot Wiki (Lite)</title>
    <link href="https://blog.eddy.moe/2023/08/01/CTBR_Docs1/"/>
    <id>https://blog.eddy.moe/2023/08/01/CTBR_Docs1/</id>
    <published>2023-08-01T02:54:00.000Z</published>
    <updated>2024-10-10T09:53:00.215Z</updated>
    
    <content type="html"><![CDATA[<p>本程序助您桥接<code>Telegram</code>和<code>WeChat</code>、互通消息，且提供最大化的自定义性！</p><h2 id="一-部署指南"><a href="#一-部署指南" class="headerlink" title="一. 部署指南"></a>一. 部署指南</h2><h3 id="1-获取代码"><a href="#1-获取代码" class="headerlink" title="1. 获取代码"></a>1. 获取代码</h3><h4 id="1-x2F-1-Docker方式（一般推荐）"><a href="#1-x2F-1-Docker方式（一般推荐）" class="headerlink" title="1&#x2F;1. Docker方式（一般推荐）"></a>1&#x2F;1. Docker方式（一般推荐）</h4><blockquote><p>在安装了GNU&#x2F;Linux的机器上，我们推荐使用Docker以快速启动 (<code>bootstrap</code>) 本项目。对于该版本，您只需操作一个文件夹——data。您需要手动管理该文件夹，而其余文件将由Docker镜像管理。</p></blockquote><ol><li><p>首先请在您的设备上寻找合适的地方，存放程序配置文件（程序将会频繁读取，但是数据量不大，推荐放在SSD上），此处假设存放在 <code>/opt/data_ct</code>下 ；</p></li><li><p>运行下列命令 ，静待镜像下载完成后，容器即会立刻启动；</p></li></ol><p><code> docker run -v /opt/data_ct:/bot/data --name ct cryan2409/ctbr</code></p><blockquote><p>意为：将宿主机 &#x2F;opt&#x2F;data_ct 文件夹映射到容器内的 &#x2F;bot&#x2F;data 下；将新容器命名为ct；采用Docker Hub的 cryan2409&#x2F;ctbr 镜像。</p></blockquote><ol start="3"><li>此后，由于data文件夹下找不到有效的配置文件，自检失败，容器将停止运行。请按照后续步骤，手动前往配置目录、修改模板文件，即可再次尝试启动容器。</li><li>待容器成功启动后，请通过<code>docker logs ct</code>命令查看容器日志，以便扫描二维码并登录。</li></ol><h4 id="1-x2F-2-手动部署（适合高级用户）"><a href="#1-x2F-2-手动部署（适合高级用户）" class="headerlink" title="1&#x2F;2. 手动部署（适合高级用户）"></a>1&#x2F;2. 手动部署（适合高级用户）</h4><blockquote><p>本方法需要您的机器上安装有Node.js运行环境，若无可以前往 <a class="link"   href="https://nodejs.org/zh-cn" >Node.js 官网<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 手动下载安装，推荐选择LTS版。请注意，Windows 7 所能安装的最新Node版本12.16仍无法满足依赖项的要求，请谨慎部署，或考虑借助Linux虚拟机。</p></blockquote><ol><li>从<a class="link"   href="https://github.com/Eddy0644/ctBridgeBot/releases" >GitHub Release<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>下载最新版源码压缩包，解压到合适位置，记为项目根目录；</li><li>在项目根目录打开终端&#x2F;命令提示符，输入 <code>npm i</code>，安装依赖项；（若此步出现问题，请检查您的网络&#x2F;科学上网情况；如果多次重试仍无法完成安装，请向我索要包含了<code>node_modules</code>的分发包）</li><li>按照后续步骤，修改配置文件以及proxy后，在终端输入<code>npm run p</code> 或 <code>npm start</code>，运行代码，等待二维码出现后扫码登录。</li></ol><p>​提示：Docker版中，程序将会自动创建需要的模板文件；所以为了节省您的时间，我们编写了两个脚本，<code>2.entry.sh</code>用于 *NIX系统，以及<code>init-project.bat</code>用于Windows系统，这两个文件可以在<code>static</code>文件夹内找到。运行它们时，会在<code>data</code>目录下创建程序所需的两个配置文件的模板 {<code>CHANGE_ME)user.conf.js</code>和<code>proxy.js</code>}，稍后只需对它们做出修改即可。</p><h3 id="2-配置环境"><a href="#2-配置环境" class="headerlink" title="2. 配置环境"></a>2. 配置环境</h3><p>本项目有以下两点需要用户注意，其一是代理地址，其二为用户级配置文件。</p><p>请进入data文件夹，首先编辑<code>proxy.js</code>，该文件指示程序如何连接到Telegram服务器。其已经内置部分HTTP代理地址和端口的示例，请据此修改字符串为合适的值；其中IP地址可以不做改动，端口视您所用的科学上网软件而定，需要http代理端口或mixed端口。</p><p>如果没找到该文件，可以手动将下述内容填入文件：</p><div class="code-container" data-rel="Javascript"><figure class="iseeu highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// This is a device-specific proxy setting, which is used to bypass the firewall.</span></span><br><span class="line"><span class="comment">// When updating the code, you could make no change to this file.</span></span><br><span class="line"><span class="comment">// =====================================================================</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Please write your HTTP proxy with patterns below, eg. NekoRay</span></span><br><span class="line"><span class="comment">// module.exports = &quot;http://127.0.0.1:7080&quot; ;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Or, If you don&#x27;t want to use proxy at all, just keep empty:</span></span><br><span class="line"><span class="variable language_">module</span>.<span class="property">exports</span> = <span class="string">&quot;&quot;</span> ;</span><br></pre></td></tr></table></figure></div><p>其次，<code>CHANGE_ME)user.conf.js</code>表示这是等待用户修改的配置文件，请首先依据 {3. 初始化配置文件} 编辑该文件（填入必要的凭据以及设置），然后将其改名为<code>user.conf.js</code>。</p><h3 id="3-初始化配置文件"><a href="#3-初始化配置文件" class="headerlink" title="3. 初始化配置文件"></a>3. 初始化配置文件</h3><blockquote><p> 本程序的配置文件采用“叠加”制，即<code>config/def.conf.js</code>文件包含所有的配置项及其默认值，并在版本更新时被覆盖；而<code>data/user.conf.js</code>包含用户修改过的各配置项，因此只需为def配置的子集，无需包含前者中所有配置项；在启动时程序会先加载def配置文件，然后将user中的配置逐条覆盖，因此若需要修改任何配置项，请在复制到user配置文件后再做出修改。</p></blockquote><p>对于想要bootstrap本项目的用户，您既可以从完整的配置文件开始，精简任何您未作出更改的配置项（<code>user.conf.js</code>中的内容可以基于<code>def.conf.js</code>，或是由初始化脚本创建的“CHANGE ME“文件）；也可以从最少配置文件<a href="https://github.com/Eddy0644/ctBridgeBot/blob/main/config/minimum_user.conf.js"><code>minimum_user.conf.js</code></a>开始，添加您所需要的配置项。</p><p>以下提供了一些必需配置项的解释，大体按照重要程度排序，并且基于此版本（v3.5.0）所附带<code>def.conf.js</code>，仅供参考。若在后续版本中有增加的配置项但本文档未及时更新，请参考<code>def.conf.js</code>中所附的英文注释或耐心等待文档更新；在此版块未涉及的配置项，请前往 {配置文件参考} 专题查阅，谢谢。</p><p>#接下来请按步骤操作，分别填充配置文件的各项。（1、2、3、6为必选项，其余为可选项）</p><ol><li><p><code>/tgbot/botToken</code> 改成您创建的Telegram Bot 的访问 token；</p><p><code>/tgbot/botName</code> 改成该Bot的用户名，此举是为了处理用户发送的带有机器人用户名的聊天指令。</p><p><strong>提示</strong>：<code>/tgbot/botToken</code>这一表示方法指，从<code>module.exports</code>开始，首先寻找名为tgbot的对象，再其内继续寻找botToken，而开头<code>/</code>的含义类似绝对路径与相对路径，下同。</p><blockquote><p>如果您未曾创建过bot，那么请按照以下步骤操作：<br>在Telegram主页搜索<code>botfather</code>，点击Menu按钮选择<code>/newbot</code>，然后分别在聊天区输入Bot的显示名称、Bot用户名（以<code>_bot</code>结尾），即可在收到的回复的中间部分找到Bot Token.<br>请注意，在运行本项目前，务必点击由<code>BotFather</code>发送的、您机器人的链接，打开与机器人的聊天窗口，再点击下方的Start按钮，才能允许机器人向您发送消息！<br>格式如下：<code>6000000004:AA..(Skip 32 chars)..A</code></p></blockquote></li><li><p><code>/tgbot/tgAllowList</code>规定机器人将对哪些用户的消息做出转发或回应，若不在此列表，发出的消息将会被忽略。请向该数组中添加您自己的Telegram ID，以数字形式、无需引号；</p></li><li><p><code>/class/def</code>，即 <strong>默认频道</strong>的相关配置，请将<code>tgid</code>改为您的Telegram ID &#x2F; 群id；（默认频道者，也就是不满足任何一条配置规则的其他所有消息都会被递送&#x2F;转发到这里）</p>  <div class="note-large primary">    <div class="notel-title rounded-t-lg p-3 font-bold text-lg flex flex-row gap-2 items-center">      <p>关于简称</p>    </div>    <div class="notel-content">      <p>在下文中，可能会把 ”启用了Topic功能的某个超级群组中的某个Thread&#x2F;topic“ 简写为”某个thread&#x2F;线程&#x2F;topic“，将这样的超级群简称为”话题群“；<br>也可能会混用”递送“与”转发“：这两个词均表示本程序把一个平台上的消息搬运到另一平台这一行为（一般指从wx到tg）</p>    </div>  </div>  <div class="note p-4 mb-4 rounded-small warning icon-padding">    <i class="note-icon fa-solid fa-bolt"></i><p>提示：由于设计问题，本条目暂不支持设置为超级群组中的某个线程<code>Thread</code>，若强行设定到话题群的General线程，那么会出现异常行为，请注意！</p>  </div><blockquote><p>个人Telegram ID获取方法：<br>在主界面搜索<code>raw_info_bot</code>，点击开始，第一行的输出即为所求；<br>群的创建及获取id的方法：<br>首先新建群聊，名称随意填写，然后将您的Bot拉入此群（可能必须在搜索框输入bot的用户名才能看到bot），再在群管理设置中选择<code>Administrator</code>菜单，将Bot提升为管理员，并把倒数第二个开关<code>Remain Anonymous</code>打开，保存后等待1s，向群聊发送任意一条消息，对其右键即会出现<code>Copy Message Link</code>选项，点击复制并粘贴，其数据形似：<code>https://t.me/c/1954444465/2</code>，此时请提取中间部分的整数，再在其之前附加<code>-100</code>，得到类似<code>-1001954444465</code>这样的数，即为此群的id.</p></blockquote></li><li><p><code>/ctToken</code>：由于24年3月9日的<a class="link"   href="https://t.me/c/1684881861/154" >一项举措<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>，在本项目代码开源后，启用了这样一个配置项作为捐赠者识别凭证，如果您尚未成为捐助者，也可以前往 <a class="link"   href="https://ctbr.ryancc.top/startTrial" >此网站<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> 注册试用版token，以字符串形式填到这里即可。</p></li></ol><details class="blue" data-header-exclude><summary><i class="fa-solid fa-chevron-right"></i>关于 ctToken 的相关说明 </summary>              <div class='content'>              <p>获取方式：①若您此前已经支持过本人，那么请劳驾前往爱发电平台（传送门: <a class="link"   href="https://afdian.com/item/b6b1c37a2d5011ee88eb52540025c377" >商品链接<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> ）私信中查收我已为您生成的赞助版Token（其实也可以选择在tg上联络我，效果一样）；</p><p>②若您只想试用本程序或者暂时不想支持，那么请前往  此网站 (<a class="link"   href="https://ctbr.ryancc.top/startTrial" >https://ctbr.ryancc.top/startTrial<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>)  自行生成试用版ctToken，生成时只需填写 您想要注册为token的字符串 和 联系方式(选填) 再提交即可，也无次数限制，因此可放心使用（因此希望各位切勿滥用该生成器，一人一次即可，网安高手们也不要尝试发掘我这破页面上的漏洞，我并没有使用任何SQL）</p><p>当您完成以上步骤得到token后，请将token填入您的 <code>user.conf.js</code> 首部对应区域即可。本程序在微信登录成功后将会把token，微信昵称（并非微信号，不具备定位到个人的效力）以及客户端版本号 发往服务器，仅用作统计与分析程序使用情况，因此请放心。在我看来并不会泄露使用者的隐私，若您不同意可自行删除相关代码。</p><p>[ 同时这一代码可能会在适当的时间点，于控制台中输出捐赠提示文字，不会影响其他功能的正常使用，请忽略。]</p><p>此外程序中的一些 耗费作者大量精力的功能在未来也会调整为仅限捐助者使用，请谅解。（目前仅有 tg大会员emoji转wx原生表情 这一项为专有功能，其余功能均不受限）</p>              </div>            </details><ol start="5"><li><p><code>/misc/deliverPushMessage</code>，指示了订阅号推送以及服务消息应当如何被递送&#x2F;转发。</p><ul><li>若设置为 false，则程序将忽略所有的公众号消息；</li><li>若设置为 true，则这些消息将被发送到特定的聊天。可参考第3步操作，专门新建一个群并把id填入<code>/class/push/tgid</code>，但如果懒得建群的话，也可暂时性的设置为您的Telegram ID。</li></ul></li><li><p><code>/filtering/wxNameFilterStrategy</code>：您可以在此，让本程序选择性地忽略部分聊天对象发来的所有消息，比如不得不加但不关心其内容的某些wx群，减少程序运行压力。</p><p>欲使用该功能，请先决定您需要指定的是黑名单还是白名单，据此设置<code>./useBlackList</code>为true或false，同一时刻只有一个名单会生效；<br>然后请在下方对应名单对应的数组里，以字符串形式追加关键词，结果类似这样即可：<code>blackList: [&quot;美团&quot;,&quot;饿了么&quot;],</code></p></li><li><p><code>/notification</code>：Bark推送的相关设置项，本质是在程序出现问题（例如在连接tg服务器的过程中多次中断）需要用户介入时，向一个指定URL发送GET请求，后者会向用户个人手机发送推送通知以吸引您的注意力；<u>后续正在考虑建立第三方bot，以期通过tg推送这样的消息</u>；如不使用相关功能，请保持默认设置不变，理论上将不会再产生与此有关的报错。</p><blockquote><p><code>send_relogin_via_tg</code>指示在使用&#x2F;relogin命令时，是否要把wx登录二维码发送到默认频道以供扫描。默认为开，若想关闭请将其设为0.</p></blockquote></li><li><p><code>/misc/deliverSticker</code>，决定了聊天消息中遇到wx用户发送的Sticker贴纸将如何递送。</p><ul><li><p>若设置为 false，则程序将忽略所有的sticker，仅在日志中输出提示信息，在tg侧将表现为对方未发送此消息；</p></li><li><p>若设置为 true，则这些sticker将被发送到特定的聊天。建议另建一群，覆盖<code>tgid</code>值并删除<code>threadId</code>项，避免干扰正常聊天消息；当然也可指定到某thread中。</p></li><li><p><code>./urlPrefix</code>项旨在让用户点击sticker文字链接后可以直接跳转到sticker频道的对应消息，以便查看对方发送了何种表情，但这一功能需要略为复杂的调试。示例为<code>https://t.me/c/1944700018/1411/&quot;</code>，具体解析法请见第三步注释。若您未使用话题群，那么该prefix应当只包含一个数字，否则加上threadId应当如示例所示拥有两串数字。最后请以<code>/</code>结尾，因为程序还需要在该prefix的末尾追加sticker图片所在的消息id。</p></li></ul><blockquote><p>在此，您可以考虑新建一个超级群并开启Topic功能，这样一个群可当多个群使用，从而节省您tg聊天列表的空间，具体方法如下：<br>首先新建群，按照上文方法添加机器人，然后在群设置开启Topic功能，随后新建话题，名称随意起，在新话题中发送消息并复制链接，类似<code>https://t.me/c/1788888875/4/401</code>，取其中第二组数字<code>4</code>，即为<code>threadId</code>。</p></blockquote>  <div class="note-large success">    <div class="notel-title rounded-t-lg p-3 font-bold text-lg flex flex-row gap-2 items-center">      <p>恭喜🎉</p>    </div>    <div class="notel-content">      <p>至此您已经完成了所有的必需设置，现在运行程序应当不会再出现问题。不过为了更好的体验，我们推荐继续按照下列步骤，完成一些影响体验的可选配置。）</p>    </div>  </div></li><li><p><code>/class/C2C</code>，建议您启用C2C功能，并创建多个C2C Pair，这将会大幅提升您在tg侧的聊天体验，同时善用此功能也能让您创建更少的群，节省精力。对于每个C2C Pair，即<code>/class/C2C/*</code>：</p><ul><li><p><code>tgid</code>数值参考前述步骤，同时如果指定到话题群，那么请设置<code>threadId</code>为话题号；</p></li><li><p><code>wx</code>数组的第一项是您期望聊天对象的名字（微信昵称&#x2F;群名称&#x2F;您自行设置的备注都可以，我们会按照此顺序依次查找），第二项是<code>isGroup</code>，请根据聊天对象是否为群聊自行填入<code>true</code>或<code>false</code>；</p></li></ul></li></ol><p><code>/class/C2C_generator</code>是为了进一步节省您精力而增设的，提供了为同一话题群中的不同话题添加对应的C2C Pair的快捷方法。（比如我个人就创建了一个话题群“From WX”，最常用联系人单独创建群，因为这样可以独立设置头像、显示名称；而次常用的联系人全部作为该话题群的子话题，方便管理。）<br>请先算出您话题群的tgid，即<code>-100</code>开头的形式，作为键，而值为一个空数组；然后在后者数组中添加数个长度为3或4的子数组，从左到右分别是，threadId，wx名称，wx类型，flag。并请保留<code>/* |autoCreateTopic Anchor| */</code>这一注释，其被后续的<code>/create_topic</code>指令需要。按照上文操作后，结果应为：</p><blockquote><p>“C2C_generator”: {<br>            “-1001888888888”: [<br>                &#x2F;* |autoCreateTopic Anchor| *&#x2F;<br>                [1, “name of group 1”, “Group”, “flags_here”],<br>                [4, “name of person 1”, “Person”, “”],<br>            ],<br>        },</p></blockquote><ol start="10"><li><code>/filtering/wxContentReplaceList</code>，如字面意思，wx中收到的消息会经此表过滤后再转发到tg。示例中的写法会将微信中的部分自带表情如发怒、捂脸等替换为（通用的）emoji，如果您不想在输出消息中看到emoji可以清空该数组；</li></ol><blockquote><p>请注意如果您登录微信的手机语言为中文，可能还需要另外将 [Pout] [Facepalm] 等英文描述替换为 [发怒] [捂脸]等中文描述，此外还有[BadLuck]&#x3D;[骷髅]等对应关系，我们暂未添加，未来将推出列表供用户自行选择；<br><em>由于我们从上游服务器接收的就是中英文混搭的版本，因此此项的设置取决于您手机语言，后续会改进……</em></p></blockquote><p><em>[ This section is recently updated on 2024-05-16. ]</em></p><h2 id="二-使用教程"><a href="#二-使用教程" class="headerlink" title="二. 使用教程"></a>二. 使用教程</h2><h3 id="1-启动流程"><a href="#1-启动流程" class="headerlink" title="1. 启动流程"></a>1. 启动流程</h3><p>启动程序后，稍等片刻，程序将检查<code>data</code>目录下是否有<code>ctbridgebot.memory-card.json</code>文件，若有则尝试使用上次的登录信息直接登录，一般能在数秒内完成；如果登录失效了或无登录会话信息，则会在控制台输出一幅二维码和二维码图片链接。手机扫码之后完成登录，日志输出形如<code>I/wx Contact&lt;your_name&gt;已登录.</code></p><blockquote><p>a）复制”二维码图片链接”到浏览器，可以输出一张二维码图片在浏览器以供手机扫描；<br>b）请注意，由于微信官方的迷之限制，登录二维码在手机上无法使用<strong>非摄像头以外的</strong>任何形式识别。也就是说，无论是从相册选取二维码还是在聊天中长按图片识别二维码都无法完成登录（显示二维码失效）因此您可能必须使用两台设备才能完成登录。因此建议不要在不方便的场合通过远程手段重启本项目，以免登录失效却又无法重新登录。<br>c）由于需要在后台启动一个浏览器进程，所以启动阶段花费的时间在10s-30s不等。为了追踪启动过程所耗时间，启动浏览器所需时间将会输出在第一条日志旁，该时间介于2s-15s不等，视设备性能而定。<br>d）如果在微信登录消息之前输出了红色的如下内容（<code>Unhandled rejection RequestError: Error: Client network socket disconnected before secure TLS connection was established</code>），说明代理服务器连接出现问题，请查看代理服务器设置；<br>若输出的错误信息如下（<code>Error: net::ERR_TIMED_OUT at https://wx2.qq.com?lang=zh_CN&amp;target=t</code>）则说明您设备的网络出现问题，无法连接到微信服务器。请即刻停止运行，排除网络问题后重启，可首先检查设备DNS是否异常。<br>e）如果弹出微信登录二维码后您在30s内未处理，则会通过配置文件<code>/notification/prompt_relogin_required</code>项向手机发送<u>重登录提示</u>（内容可自定义），届时请及时处理，以免漏收消息。<br>f）如果程序运行中出现日志信息<code>[ERR]Polling - EFATAL: Client network socket disconnected before secure TLS connection was established</code>表明最近一次向tg服务器的poll操作（拉取用户发送的消息）失败，意味着您代理服务器出现网络波动；如果出现频率较低（如30s一次）则不会产生太大影响，但是还是建议切换到更好的代理&#x2F;节点；如果在10s内连续出现两次，则程序会按照配置文件<code>prompt_network_problematic</code>项向手机发送<u>断网提示</u>，这种情况下若不及时处理可能会影响<u>消息递送的及时性甚至漏收消息</u>等。<br><em>（有些科学上网节点提供商限制同时在线设备数，也就是同时运行的客户端数量，所以当您网络出现异常时除了切换节点也可考虑排查 <u>是否超出了在线设备限制</u>）</em></p></blockquote><h3 id="2-接收wx消息"><a href="#2-接收wx消息" class="headerlink" title="2. 接收wx消息"></a>2. 接收wx消息</h3><p>程序运行后，您微信上的所有消息即会按照配置文件中所定义的，通过本程序“递送”到Telegram。</p><h4 id="a-文字消息及合并"><a href="#a-文字消息及合并" class="headerlink" title="a.文字消息及合并"></a>a.文字消息及合并</h4><p>归属于默认频道（参考部署指南.3）的文字消息，根据是否来自群，有以下两种显示形式：<code>📨[#备注名] &lt;消息内容&gt;</code> &#x2F; <code>📬[说话者微信昵称/#群名称] &lt;消息内容&gt;</code>。</p><p>请注意，本项目并不会查询某聊天对象在微信中是否已经设为免打扰状态，换言之，您<strong>必须</strong> 在配置文件中指定黑&#x2F;白名单才能按您的需求屏蔽某些来源的消息。</p><p>“合并消息“功能打开时（默认打开），依据配置文件中设定的时间间隔，当新消息与上一条消息的时间之差不超过设定值时，新消息将会被附加到旧消息的末尾，并且对旧消息的格式作出相应修改以提升观感。<br>例如聊天对象是某联系人A，间隔默认为15s，若他的第二条消息内容为2且在上一条消息15s内发出，则上一条消息从 <code>📨[#联系人A] 1</code> 变为 <u>如下</u>，也就是在保留首部标题与联系人信息的同时，将他的所有新消息前加上时间或序号（均可自定义）。</p><blockquote><p>📨⛓️ [#联系人A] - - - -<br>[13:35:35] 1<br>2|→ 2nd msg<br>3|→ 3rd msg</p></blockquote><p>若聊天对象是群聊，程序会舍弃时间显示，改为在 <code>[ ]</code> 内显示说话者名称，并将首部标题内符号‘📨’替换为‘📬’。</p><p>此外，当<code>[ ]</code> 内容一致时（例如群内同一说话者连续三条消息且未被其他人打断，或某联系人在1s内发送多条消息），程序不会在新消息中显示<code>[ ]</code> ，反而是采用等宽字体显示其计数（如<code>2|→</code>）。这可以表明该说话者连发了多少条消息。此项可在配置文件中<code>/c11n/titleForSameTalkerInMergedRoomMsg</code>中自定义。</p><blockquote><p>请注意，此合并功能目前仍是全局共享，也就是说如果您有两个以上的群会经常输出消息，那么合并功能将经常被打断（因为第二个群合并的过程中第一个群的新消息会打断这一过程，并重置记忆，导致第二个群的新消息将无法再被合并）。我们正在尝试重写这部分代码以使“合并”功能的行为更加符合预期。</p></blockquote><h4 id="b-图片-x2F-文件-x2F-视频-多媒体消息"><a href="#b-图片-x2F-文件-x2F-视频-多媒体消息" class="headerlink" title="b. 图片&#x2F;文件&#x2F;视频 多媒体消息"></a>b. 图片&#x2F;文件&#x2F;视频 多媒体消息</h4><ul><li>图片消息将会先被下载到<code>/downloaded/photo</code>中，以<code>$&#123;消息发出者alias&#125;-$&#123;wxdata.filename&#125;</code>形式保存，再发送到其对应的接收对象中，并且这些图片的标题（<code>caption</code>，即图片下方出现的文字）显示为 ‘ from 发送者名称 ’（规则同上述a，根据是否为群&#x2F;是否为C2C拥有不同行为）</li><li>对于文件消息，将先向您发送一条提示，包含该文件的发送者、原始文件名和大小。形如：<code>📨[#联系人] 📎[文件.docx], 0.101MB.</code><ul><li>若大小满足配置文件中<code>wxAutoDownloadThreshold</code>项设置的最小阈值，则会自动尝试下载并显示<code>Trying download as size is smaller than threshold.</code>，在下载完后将删除原先的提示信息。</li><li>若大小大于上述阈值，则显示<code>Send a single OK to retrieve that.</code> 此时如果您仍希望接收此文件，则需对此提示消息点击回复，并发送<code>OK</code>（全大写或全小写均可），此后文件将会在后台下载并遵循上述步骤发送到tg。</li></ul></li><li>对于视频消息，由于微信某次更新取消了视频大小的显示，故软件只能自动下载。在<code>🎦(Downloading...)</code>提示出现后，请耐心等待，视频正在后台下载并发送到tg，其中大小大于49MB的将不会被发送；反之则会即时发送。（经测试，此过程主要取决于科学上网的速度。）</li></ul><h4 id="c-推送消息"><a href="#c-推送消息" class="headerlink" title="c. 推送消息"></a>c. 推送消息</h4><p>所有的公众号文章消息（是否收到来自某公众号的推送消息，取决于是否在微信设置中选择“接收文章”&#x2F;“Receive Articles”）都会被<code>handlePushMessage()</code>处理成富文本形式发送到配置文件中<code>/class/push</code>指定的push频道。具体格式包含订阅号名称（标题上带有#号以便快捷查找其所有文章），每篇文章的标题（点击标题则打开链接）及其简介（取决于公众号运营者的填写，或长或短，甚至没有；以斜体展示）。</p><p>点击链接后可在任意浏览器查看，但无法查看评论（微信侧限制，非登录用户无法查看评论）</p><h4 id="d-语音消息"><a href="#d-语音消息" class="headerlink" title="d. 语音消息"></a>d. 语音消息</h4><p>语音消息同样会被先下载到<code>/downloaded/audio</code>中，以<code>日期-时间-备注名.mp3</code>形式保存。</p><p>如果在配置文件中开启了语音识别功能<code>/txyun</code>并提供了有效的API Key，则</p><ul><li>每条语音在进一步发送前都会先发往腾讯云“一句话识别”系统（该系统能在数秒内给出语音转文字结果，支持多种方言且最大长度为60s，刚好满足最大长度为60s的语音这一情况），得到转录文字后附加到语音消息的<code>caption</code>部分，发送到tg。但请注意，由于tg app的限制，手机端在通知消息预览中无法看到已转出文字的内容，只显示<code>🎤 Voice Message</code>，此时您需要点击通知进入app才能看到转文字内容。</li><li>否则，<code>caption</code>部分将只包含说话者信息。</li></ul><h4 id="e-文字中包含的引用消息"><a href="#e-文字中包含的引用消息" class="headerlink" title="e. 文字中包含的引用消息"></a>e. 文字中包含的引用消息</h4><p>在UOS版本微信，如果对端给您发来带有引用消息的消息，那么默认会显示为<u>如下</u>；很明显观感很差且占用过多行。假如我们试图把这样的引用表现为tg消息间的互相回复的话，不仅与“合并”功能冲突，且技术难度较大，需要把所有历史消息都存入数据库才能做到，同时也造成很多不便。因此我们做了这样的特殊处理，也就是将此部分转换为消息末尾的一行斜体小字<code>(说话者💬&quot;内容&quot;)</code>，这样就可以清晰地表示消息间引用关系。其中“内容”部分是被引用消息的内容的前8个字符，您可以根据该前缀向上搜索找到对应的原消息，至于“说话者”是该用户的昵称还是群名片，这一项由微信侧决定，一般情况下是后者。</p><blockquote><p>“说话者A: 第一条消息”<br>— — — — — — — — — —<br>第二条消息</p></blockquote><h3 id="3-在tg上发送消息"><a href="#3-在tg上发送消息" class="headerlink" title="3. 在tg上发送消息"></a>3. 在tg上发送消息</h3><p>不仅是wx侧，本项目在tg侧也拥有良好的操作性，支持多种消息格式与指令。</p>  <div class="note-large info">    <div class="notel-title rounded-t-lg p-3 font-bold text-lg flex flex-row gap-2 items-center">      <i class="notel-icon fa-solid fa-info"></i><p>提示</p>    </div>    <div class="notel-content">      <p>本文档初次撰写时，C2C尚未发展完全，仍以def频道为主，而在后续开发中，各项功能均向利好C2C的方向发展，因此此处介绍的很多指令，比如查找和锁定功能，实际用处并不大。我们也推荐用户多使用C2C与<code>/create_topic</code>指令（将def频道中的聊天对象自动转换到C2C），这样便可以为每个聊天定义更加详细的规则，以增强聊天体验。</p>    </div>  </div><h4 id="a-支持的消息种类"><a href="#a-支持的消息种类" class="headerlink" title="a. 支持的消息种类"></a>a. 支持的消息种类</h4><p>（以<code>/class/def</code>频道举例）</p><ul><li>文字消息，将会经<code>tgContentReplaceList</code>过滤后，直接发送给“上一个聊天对象”，若无上次聊天的记录则会发出提醒，<code>Nothing to do upon your message</code>，这时这条消息将会被忽略。</li></ul>  <div class="note p-4 mb-4 rounded-small default">    <p>“上一个聊天对象”，代码中为<code>lastTalker</code>，指代def频道中上次收到消息的对象，若无已启用的<code>/lock</code>，则def频道中每收到一条消息，<code>lastTalker</code>都会被更新。</p>  </div><p>​如果这条消息是对另一条消息的回复，则这条消息会被直接发送到“被回复的消息”的发送者处。</p><p>​（例：我的“上一个聊天对象”是B，但我对“A”发给我的消息选择了“回复”，并且输入了我想说的话，那么这时这条消息会被发送给A而非B。）</p><ul><li><p>图片&#x2F;文件&#x2F;视频消息，将会被下载到本地后再发送给“上一个聊天对象”，所以如果需要准确地发送给某个人（以免在发送过程中有其他人的消息插入导致消息被错发），请利用c）节提到的lock功能确定您想要发送的对象。</p></li><li><p>语音消息 和 Sticker（贴纸）消息，请详见d节介绍。</p><p>除了上述种类以外，其他所有的消息都会被忽略，包括但不限于tg侧的群名称&#x2F;头像更改事件、投票、在移动端通过长按语音按钮拍摄的<code>VideoNote</code>……但会在日志中体现。</p></li></ul><h4 id="b-使用预定义的指令"><a href="#b-使用预定义的指令" class="headerlink" title="b. 使用预定义的指令"></a>b. 使用预定义的指令</h4><p><em>（现有的博客系统的目录不支持h4标题，为了方便用户点击目录跳转，该部分已移动为单独的一小节，请前往下方 {tg侧指令一览} 查阅 ）</em></p><h4 id="c-查找、行内查找与相关指令"><a href="#c-查找、行内查找与相关指令" class="headerlink" title="c. 查找、行内查找与相关指令"></a>c. 查找、行内查找与相关指令</h4><ul><li><p>本程序支持交互式查找聊天对象，具体方法是直接发送<code>/find</code>指令，在得到程序反馈<code>Entering find mode; enter token to find it.</code>后，直接输入您想要查找的对象的<u>微信昵称&#x2F;群名称&#x2F;您设置的备注</u>，（由于UOS微信的限制，完成此步骤需要数秒）在查找成功后将会回复消息<code>Found Person: name=……</code>，此时若“聊天对象”锁未启用，则“上一个聊天对象”也会被设置成当前查找到的目标。</p><p>（在未来的升级中，此项可能升级为模糊查找，即列出联系人列表并尝试在其中模糊查找，给可能匹配的每一位都分配上唯一id，并将后者返回到用户侧，这样做可以避免名称中出现非法字符等等）</p></li><li><p>“行内查找”指的是，当需要向一位新的聊天对象发送消息时，将查找和发送两步合并到一条消息内完成。具体操作方法是，首先输入查找对象的名称（“<u>微信昵称&#x2F;群名称&#x2F;您设置的备注</u>”三种情况均可接受，详见上文），紧随其后输入两个冒号，中英文均可；接下来请换行后直接输入您要发送的消息，最后发送即可。当您看到聊天界面顶部显示机器人的状态从“typing”变为“choosing sticker”则表示查找并发送成功。</p><blockquote><p>本功能的原理是先调用查找函数找到您欲发送消息的唯一对象，将其设为“上一个聊天对象”后按照正常消息的步骤再发送给目标。因此当“聊天对象”锁已启用时，本功能可能无法正常工作。（这也是一个问题，将在以后的更新中修复【TODO】）</p></blockquote></li><li><p>另外，您可以通过“@锁”方式，灵活地设置当前的聊天对象。例如，当您一时间收到来自两个联系人的多条消息时，为了避免互相干扰，您可以先选中其中一位的消息，回复它“@”，此时该联系人会被设置为“上一个聊天对象”且“聊天对象”锁也会被启用（并设为2状态），接下来您直接发送的所有消息都会被转发到该联系人。此后，只需选择另一位联系人的消息并同样回复“@”，即可专心回复ta的消息。并且通过这种方式设置的锁，在您“回复”其他消息时会自动解除。</p></li></ul><h4 id="d-Sticker与语音识别"><a href="#d-Sticker与语音识别" class="headerlink" title="d. Sticker与语音识别"></a>d. Sticker与语音识别</h4><ul><li><p>语音消息，如果腾讯云语音识别已启用，则程序会输出您这段语音的识别结果并设置为<code>monospace</code>样式，此时您可以点击文字部分自动复制语音识别后的结果。但是，这条语音并不会被转发到wx。</p></li><li><p>对于来自tg的Sticker（贴纸）消息，按照默认配置，此贴纸将会取缩略图后由<code>sharp</code>库 转换为gif，以图片形式发往wx。根据配置的不同，也可能通过upyun（又拍云）实现图片格式的转换。</p><blockquote><p>a）由于tg的贴纸要求为webp格式，而wx不支持前者，所以需要设法转换之。<s>已知又拍云提供简单的方案（指不需要通过事件id和查询请求确定转换状态）可以完成上述操作，因此需要您提供此upyun API Key。</s> 经热心用户提醒，<code>sharp</code>库利用<code>libvips</code>可以高效地实现图片格式的转换，因此为了降低用户使用成本，我们已将默认配置改为sharp方案，若未出现问题则不需要调整此选项。<br>b）请注意，目前您的<strong>所有媒体消息中携带的<code>caption</code>都不会被递送</strong>。因此，请不要在媒体消息的<code>caption</code>中填写您想要传达的讯息，因为您可能需要复制后以纯文本形式单独发送。这一问题日后将会被解决。【TODO】<br>c）如果您购买了Telegram Premium并发送了第三方emoji表情，那么它将会被解析成普通emoji（这一行为取决于emoji上传者为其设定的替代emoji是哪一个）并发送。<s>所以如果想要发送微信原生emoji，您将需要利用此项<code>tgContentReplaceList</code>达到目的。</s>  作为大会员用户的替代方案，请添加 <a class="link"   href="https://t.me/addemoji/Wechat_Emoji_by_Andy" >这个Emoji Pack<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> ，然后便可在聊天中随意使用其中的表情，均会被正确识别。</p></blockquote></li></ul><h4 id="e-机器人行为的指示"><a href="#e-机器人行为的指示" class="headerlink" title="e.机器人行为的指示"></a>e.机器人行为的指示</h4><p>​本节将介绍，在您的特定行为下，机器人将会更新自己的<code>chatAction</code>到何种状态，以便您无需查看日志即可确定消息是否被成功转发，或者了解程序是否正在处理消息。</p>  <div class="note p-4 mb-4 rounded-small info">    <p>Telegram Bot API中的 <a href="https://core.telegram.org/bots/api#sendchataction"><code>sendChatAction</code></a> 方法允许开发者把机器人端正在发生的事，以“正在输入状态”的形式告诉用户。</p>  </div><ul><li>当您从tg侧发送文字消息时，机器人状态将在发送后变为<code>choose_sticker</code>。</li><li>从tg发送多媒体及文件消息时，在从tg服务器下载资源到本地的阶段，状态为<code>upload_$&#123;文件类型&#125; </code>；在把资源上传到wx服务器的阶段，状态为<code>record_video </code>；发送后状态变为<code>choose_sticker</code>。</li><li>当正在执行查找联系人操作时，状态将变为<code>typing</code>，并在查找成功后消除。</li><li>当您对待下载的wx文件消息做出确认并下载时，在下载期间状态将为<code>typing</code>；成功后状态变为<code>choose_sticker</code>。</li><li>当接收到大部分的“预定义指令”时，状态都会变为<code>typing</code>。</li><li>收到来自tg的语音时，状态将变为<code>record_voice</code>。</li><li><ul><li>收到来自wx的语音消息时，状态将变为<code>record_voice</code>；对于wx视频消息同理。</li></ul></li></ul><p>​</p><h3 id="4-tg侧指令一览"><a href="#4-tg侧指令一览" class="headerlink" title="4. tg侧指令一览"></a>4. tg侧指令一览</h3><p>以下指令可在聊天框中发送，也可打出<code>/</code>后点击命令列表选择目标指令。</p><p>请注意，绝大多数指令只能单独使用，在本消息“回复”了其他消息的情况下均不会生效，而是会原样发送到wx，因此发送前请务必检查。</p><ul><li><code>/clear</code>，即“软重启”，主要作用是调用<code>softReboot()</code>，清除大多数记忆数据，以减少bug以及提升性能。发送后程序会返回<code>Soft Reboot Successful. Reason: User triggered.</code>，表示软重启成功。这条提示消息会在数秒后自动消失。</li></ul><blockquote><p>主要清除的数据：“上一个聊天对象”、“合并”功能作用对象、定时函数错误计数、“合并”错误致回退次数计数、全局网络错误次数计数</p></blockquote><ul><li><p><code>/spoiler</code>（本消息只能在“回复”图片消息时起作用）为当前指向的图片消息添加遮罩，其实是借用tg的相关功能，为图片添加一层模糊（在点击后消除），很好地在聊天窗口和消息记录列表保护您的隐私。设置后永久有效。</p></li><li><p><code>/lock</code>，可开关“聊天对象”锁的状态。当此锁：</p><ul><li>值为0时表示不启用锁；</li><li>值为1时表示锁是通过本指令设置的，期间将屏蔽所有新来消息对“上一个聊天对象”这一变量的更改，不过您还是可以通过“引用消息”的方式向其他聊天对象发送消息；</li><li>值为2时表示锁是通过c）节介绍的“@锁”方式设置的，此时同样会屏蔽“上一个聊天对象”的更改，不同的是，在这种情况下若您对任意消息发送了引用，则锁就会被解除。您也可以使用本<code>/lock</code>指令自行将“2状态”的锁重置回“0状态”。</li></ul></li><li><p><code>/slet</code>：在默认频道中使用“上一个显式指定的聊天对象”去覆盖“上一个聊天对象”。这么说可能有些抽象，举例表示，如果默认频道中存在分别来自A、B两位的数条消息，那么可先“回复”A的某条消息，然后输入该指令，这样A即为“上一个聊天对象”，后续直接发送的消息也将被递送到A处；此后再回复一次B的消息，再次使用此指令，即可让其后所有未显式指定回复的消息都发往B处。</p></li><li><p><code>/help</code>，可在当前聊天界面输出一个带有更多指令的列表（这么做主要是为了让tg的指令列表不太累赘）</p></li></ul><p>以上命令均可在Telegram的Bot命令列表中找到，而如下命令只能通过<code>/help</code>指令间接发起，当然您直接在聊天框输入也是允许的。</p><ul><li><code>/log</code>，可在当前聊天界面得到程序目前一定数量的日志。</li></ul><blockquote><p>由于tg侧限制，消息不宜太长，因此默认输出的日志数量是末尾1000字符，您也可以通过<code>/log 2000</code>的形式手动覆盖输出的日志数量。<br>本消息不会自动删除，查看完日志后请手动删除本消息。</p></blockquote><ul><li><p><code>/placeholder</code>，可在当前聊天窗口输出一段空白消息，以将上方的其他消息“顶出”视野，从而保护隐私。此功能在需要将设备交由他人查看时非常有用。关于此功能的升级也正在规划中，届时将可以在任意消息之间插入空白消息。</p></li><li><p><code>/drop_on &amp; /drop_off</code>，可开启Drop模式，在此模式下程序将忽略来自tg侧的任何其他消息，启用此模式后（可以机器人正在typing为启用成功标志）您可以放心地在本程序所绑定的群聊里发送任何消息，均会被程序忽略，具体忽略了多少条消息可在日志中找到。请注意，为了防止忘记关闭此开关导致无法发送消息到wx，我们设定了默认为500s的自动关闭定时器<code>/misc/keep_drop_on_x5s</code>，达到时间后该模式将会被关闭，因此请时刻留意Drop模式是否仍在开启状态。</p></li><li><p><code>/sync_on &amp; /sync_off</code>，可开启Sync模式，在此模式下您在wx中发送的消息也将会被程序转发，就像是来自群内另一成员一样，启用此模式后，您通过手机wx发送的消息（如语音等）也会被程序记录甚至转成文字，有助于消息记录的完整性。</p></li><li><p><code>/reloginWX_2</code>，旨在一键快速重启程序并刷新wx状态，发送指令后wx登录信息即被清空，然后程序终止。如果部署时使用了Docker等管理技术，那么程序会被自动重启，届时只需重新扫码即可完成重新启动过程。由于直接重新启动很有可能保留先前的登录信息，而先前处理过的聊天记录在启动时会被wx全部发送过来，虽然他们在校验后会被丢弃，但仍会造成初期卡顿的现象，因此该功能还是很有必要的。</p></li><li><p><code>/reboot</code>：类似重登录指令，重新启动程序，但保留登录信息。可以每隔一段时间发送此指令，提升稳定性，因为基于浏览器的puppet方案在连续运行时间过长时可能会出现bug。</p>  <div class="note p-4 mb-4 rounded-small default">    <p>经测试，wx服务器中给每次UOS微信扫码登录后的session设定了为期7天的超时时间，也就是说，距离上次扫码登录的时间168小时以后，会话将立刻失效，但并不会有任何提示。在本程序内如果会话“失效”，那么将无法收到任何消息，也无法正常发出任何消息（但不会有报错）。因此，定时<code>/reboot</code>可以使程序稳定运行的时长达到7天（若不定期重启的话，每隔几天可能就会出现奇奇怪怪的浏览器错误，此时如果未及时发现错误并重启，导致程序与wx服务器之间的心跳包中断，那么几小时后会话将直接“过期”，再次启动时就必须重新扫码登录了），但必然无法超过这个时限。</p>  </div></li><li><p><code>/create_topic </code>，本功能旨在快速将联系人绑定到配置好的超级群的新话题，这样不用重启程序也能应用新的C2C设置，提升聊天体验。假如默认频道中收到了来自新联系人的消息，您想要将ta保存为C2C，这样便可以更愉快地聊天了，那么可直接发送本指令，稍后，在预设的话题群中将会出现一个新话题，以联系人名称命名；随后您只需切换到该话题并加以回复即可，以后的所有聊天行为均和其他C2C一样；与此同时，新C2C的相关信息也已写入用户配置文件的<code>/class/C2C_generator</code>项中，从而保证重启程序也不会丢失该条目。</p><p>为了能够正确使用此功能，您需要有一个用来承载新话题的话题群组，将其群id写入<code>/class/C2C_generator</code>中，然后在数组中括号内保留<code>/* |autoCreateTopic Anchor| */</code>注释，新创建的C2C条目会在编码为JSON后插入该注释之后，这样便实现了重启不丢失，同时方便用户进行更改。在部署阶段，您设置好该注释后，可以测试一次本指令，若新C2C的功能正常，且在重启后未出现配置文件无法解析的错误，那么以后便可放心使用此功能了。</p><p><em>关于本指令，以后将改进的内容：自动为所有新联系人创建C2C条目；在创建C2C后将先前def频道中的相关消息转发过去；。</em></p></li><li><p><code>/try_edit </code>：这是一个实验性功能，以如下结构“回复”某条来自机器人的消息：{<code>/try_edit 112233</code>}，那么被回复的消息将会被直接覆盖为<code>112233</code>。若tg的相关规则限制了机器人对超出时限的历史消息的修改，则本指令会失效。</p></li><li><p><code>/eval</code> *Debug指令，需预先在配置文件<code>debug_evalEnabled</code>启用本项：在该命令后追加js代码并发送，即可在<code>BotIndex.js</code>的上下文中执行该代码。若您并非对JavaScript语言有较好的理解，请不要启用该功能，以免引入远程代码执行漏洞。</p></li></ul><h3 id="5-mods"><a href="#5-mods" class="headerlink" title="5. mods"></a>5. mods</h3><p>（暂缺）</p><h2 id="三-配置文件参考"><a href="#三-配置文件参考" class="headerlink" title="三. 配置文件参考"></a>三. 配置文件参考</h2><p>本章将对模板配置文件<code>def.conf.js</code>中的各项进行尽可能详细的解释。标星号者表示作者认为您用到它的概率不大，可以忽略。</p>  <div class="note p-4 mb-4 rounded-small default">    <p>由于本程序仍在 <s>快速发展</s>，因此配置文件的变动可能会比较频繁，我将尽力做到至少在两个次版本号（如3.4.0-&gt;3.5.0）之间更新本章节内容，若下文有与dev分支最新源码不匹配者，请参考后者之英文注释，谢谢！  </p>  </div><ul><li><code>/ctToken</code>节请参阅 { 部署指南 –&gt; 初始化配置文件 } ，并务必填写您自己的 ctToken。</li></ul><h3 id="x2F-tgbot"><a href="#x2F-tgbot" class="headerlink" title="&#x2F;tgbot"></a>&#x2F;tgbot</h3><ul><li><p><code>botToken</code>：请填写从<code>@BotFather</code>处取得的Bot Token，以数字+冒号开头。</p></li><li><p><code>botName</code>：与上述token对应的Bot的用户名。</p></li><li><p><code>tgAllowList</code>数组：以数字形式存储有权向Bot发送消息的tg用户的id。对于此列表以外的tg用户，无论是对Bot私聊还是在有Bot的群组中发言，均会被忽略。</p></li><li><p><code>webHookUrlPrefix</code>：使用<code>webhook</code>启动tg bot时，将需要此处的参数。</p>    <div class="note p-4 mb-4 rounded-small default">    <p>(Incomplete Function) 当您想要以<code>webhook</code>而非<code>polling</code>模式启动tg bot时，将需要通过内网穿透等方案自行把本地的监听端口<code>8443</code>暴露到公网，并得到映射后的URL。例如，启动项目时使用的命令为<code>npm run h1</code>则webHook号为1，此时若<code>https://example.com/webHook1/</code>可以指向 <code>https://localhost:8443</code>，那么此处请填写<code>https://example.com/webHook</code>。此外，还需自行申请SSL证书并按照<code>src/init-tg.js</code>内的代码，将公私钥放置于特定位置。 因此不建议使用此功能，一是配置过程十分繁琐，二是将更难发现潜在的网络问题。如需要换用webHook模式，可联系作者。  </p>  </div></li><li><p><code>statusReport</code>：该项定义了<code>/info</code>指令所生成的报告应存放在哪里。</p><ul><li><p><code>switch</code>定义整个项的开关状态；</p></li><li><p><code>host</code>将要收到报告的目标服务器的域名；</p></li><li><p><code>path</code>为接收脚本所放置的具体位置。</p>  <div class="note p-4 mb-4 rounded-small info">    <p>本功能开发于初期，现已不建议使用，作用是将当前运行环境中的部分变量信息以及部分日志 通过Web服务器的中转发往tg用户。</p><p>使用此功能需要您拥有任意安装有PHP的Web服务器，并把<code>/static/ctBotReport.php</code>放置到任一可执行的目录中。随后按照实际情况填写配置文件即可。</p>  </div></li></ul></li><li><p><code>polling</code>：</p><ul><li><code>pollFailNoticeThres</code>：该项定义了将在多少次失败的telegram poll操作后发出网络问题警示。</li><li><code>interval</code>：该项定义每两次poll之间应间隔的毫秒数，如果您希望机器人可以更快地接收来自tg的消息，则可调整此项，但过小的值可能造成网络异常出现频率加大。</li></ul></li></ul><h3 id="x2F-class"><a href="#x2F-class" class="headerlink" title="&#x2F;class"></a>&#x2F;class</h3><ul><li><p><code>def</code>：默认频道的配置。类型为<code>connObj</code>，但不支持话题群，请单独为其创建群，或采用私聊。</p>  <div class="note p-4 mb-4 rounded-small info">    <p>本文档中会经常涉及到<code>connObj</code>及它的子类。最简单的形如这样：<code>{tgid:-100010203}</code>；若为话题群内的话题，则可以添加<code>threadId</code>属性，变成这样：<code>{tgid:-100010203, threadId: 5}</code>。</p>  </div></li><li><p><code>push</code>：推送频道的配置。类型为<code>connObj</code>。</p></li><li><p><code>C2C</code>数组：包含各C2C配置资料。其中每个<code>C2C Pair</code>应如下所示：</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    &quot;tgid&quot;: -1001006,</span><br><span class="line">    &quot;wx&quot;: [&quot;wx Contact 1&#x27;s name&quot;, true],</span><br><span class="line">    &quot;flag&quot;: &quot;&quot;,</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><p>也就是在<code>connObj</code>的基础上增加了wx数组和flag字符串。具体内容请参见前文 {初始化配置文件}。</p></li><li><p><code>C2C_generator</code>对象：包含 启用了生成器的各话题群及其详细配置。在启动时，它们会被自动转换为C2C Pair格式，但在配置过程中可降低用户工作量。具体内容也请参见前文 {初始化配置文件}。</p></li></ul><h3 id="x2F-filtering"><a href="#x2F-filtering" class="headerlink" title="&#x2F;filtering"></a>&#x2F;filtering</h3><ul><li><code>wxFindNameReplaceList</code> ：*定义了在使用查找联系人功能时，需要替换哪些字符串。原意是将需要频繁查找的对象名进行简写并存储短语，下次查找联系人只需输入短语即可。</li><li><code>wxContentReplaceList</code>：定义了从wx接收的消息中，哪些字符串需要被替换。举例：将以文字形式显示的wx自带表情（如<code>[Pout]</code>）转换为自设emoji。</li><li><code>tgContentReplaceList</code>：与上一项类似，但是替换对象是从tg接收的消息。举例：在未购买Telegram Premium的情况下，将一些emoji手动映射为wx自带emoji，这样便可在聊天中方便地发送wx表情了。</li><li><code>wxNameFilterStrategy</code>：前文 {初始化配置文件} 中有提及，该功能可以屏蔽或只允许部分对象的消息经过转发，以提升程序效率。<ul><li><code>useBlackList</code>：true表示仅启用黑名单；false表示仅启用白名单。</li><li><code>blackList &amp; whiteList</code>：略</li></ul></li><li><code>wxMessageExcludeKeyword</code>数组：*当wx消息中包含任一关键词时，丢弃整个消息。</li><li><code>wxPostOriginBlackList</code>数组：定义了屏蔽其推送消息的订阅号名称列表。</li></ul><h3 id="x2F-notification"><a href="#x2F-notification" class="headerlink" title="&#x2F;notification"></a>&#x2F;notification</h3><p>本项中的大多数功能需要您先配置好Bark才能使用；如果您拥有自建的、以HTTP GET方式就能触发的推送服务，那么也可在此处设置。</p><ul><li><code>baseUrl</code>：Bark推送服务的URL。该URL应当可以在直接访问的情况下成功推送。可以包含通知标题。形如<code>https://example.com/BridgeBot_WARN/</code>。</li><li><code>default_arg</code>每次执行推送时，应在URL末尾附加的参数。对于Bark，可以在此定义通知分组信息和推送消息头像，当然也可采用默认配置。</li><li><code>prompt_network_problematic</code>：当网络出现问题（特指Polling）而又恢复了时，发送的推送通知的正文部分。</li><li><code>prompt_relogin_required</code>：当需要重新扫码登录时，发送的通知内容。</li><li><code>prompt_wx_stuck</code>：当wx puppet发生意外崩溃导致大概率无法正常工作时。</li><li><code>prompt_network_issue_happened</code>：当网络出现问题且没有自动恢复时。</li><li><code>incoming_call_webhook</code>函数：该项应当在被调用时返回一个URL，当收到来自wx的通话时，该URL将被访问。如果仍使用Bark作为推送服务的话，您需要将完整的URL填写至此。</li><li><code>send_relogin_via_tg</code>：布尔型，为1表示将会在需要重新扫码登录时将二维码发送到默认频道；为0表示禁用该功能。</li></ul><h3 id="x2F-misc"><a href="#x2F-misc" class="headerlink" title="&#x2F;misc"></a>&#x2F;misc</h3><ul><li><p><code>deliverPushMessage</code>定义是否转发订阅号推送消息：设为false表示不转发；true表示转发到<code>/class/push</code>频道；设为<code>connObj</code>会把消息转发到前者。</p></li><li><p><code>deliverSticker</code>定义是否转发wx侧的动画表情：设为false表示完全不转发；也可设为<code>connObject</code>+<code>urlPrefix</code>，其中<code>urlPrefix</code>请将tg目标的相关参数填入URL中，以便在实际聊天中，点击Sticker字样可以跳转到由<code>deliverSticker</code>指定的动画表情所在地；具体用例请参照配置文件模板。</p></li><li><p><code>deliverRoomRedPacketInAdvance</code>：是否监听所有群聊中的红包并通过def频道发送提醒；0表示不启用；1表示仅在“未被黑白名单过滤掉的群聊”中监听；2表示所有群聊。</p></li><li><p><code>mergeResetTimeout</code>：该对象定义了对于私聊和群聊，当两条消息的时间间隔大于多少秒时，重置上次合并状态，直接发送消息。</p></li><li><p><code>onceMergeCapacity</code>：该对象定义了单次合并中，满足何种条件时重置合并状态并重新开始。</p><ul><li><code>timeSpan</code>：当第一条消息距今多少秒时，重置合并。</li><li><code>mediaCount</code>：当合并消息中包含多少个媒体消息时，重置合并。此项可避免聊天中包含过多图片时，文字与其所对应的图片距离太远。</li><li><code>messageCount</code>：当合并消息中包含多少条消息时重置。此项同样是为了避免合并后的消息过长。</li></ul></li><li><p><code>debug_evalEnabled</code>（调试用途）启用<code>/eval</code>命令，使您可以在tg中远程执行代码。该功能可能引入极大的安全隐患，无必要请勿启用。</p></li><li><p><code>display_ctToken_info</code>：控制是否在程序启动时，显示与您的<code>ctToken</code>相关的信息。设为0来阻止它们。</p></li><li><p><code>debug_add_console_timers</code>（调试用途）是否在程序执行特定耗时操作（例如寻找wx联系人）时，在控制台显示该操作所耗时间。有助于您追踪耗时操作的用时以及设备性能。</p></li><li><p><code>savePostRawDataInDetailedLog</code>：*是否在<code>msgDT</code>日志中保存收到的订阅号推送消息的原始版本。</p></li><li><p><code>addHashCtLinkToMsg</code>：是否在wx侧发来网页链接时，在链接末尾附加<code>#ctLink</code>标志，因为一旦启用了<code>deliverSticker</code>，那么聊天中将充斥大量 t.me 链接，如果需要方便地查找wx好友发来的链接，那么可以启用此项。</p></li><li><p><code>passUnrecognizedCmdNext</code>：是否把程序未能识别的tg聊天命令（例如，以&#x2F;开头者）当成文本继续发送到聊天对象。若关闭，则在发送以<code>/</code>为开头的消息时可能会被误判为命令。（当然，在斜杠前加上空格即可避免）</p></li><li><p><code>service_type_on_webp_conversion</code>：在tg sticker的格式转换过程中使用何种服务。2为采用本地模块<code>sharp</code>，推荐使用；1为又拍云在线检测，需要对应的API Key填写于<code>/upyun</code>中；0为不转换，直接把<code>.webp</code>格式的图像发往wx，可能会在他人设备中显示为无法预览的文件。</p></li><li><p><code>add_identifier_to_merged_image</code>：是否在合并消息包含的图片消息的caption部分，添加四位随机数以标识图片和文字的对应关系，有助于查清对方发送图片的次序，因为转发过程中可能因网络等问题导致对方发来的媒体消息失序。设为0表示不启用；设为1表示仅在群聊中适用；设为2则适用于所有聊天。</p></li><li><p><code>status_report_interval</code>*：控制每两次控制台<code>status Report</code>之间需要间隔至少多少秒。</p></li><li><p><code>keep_drop_on_x5s</code>*：<code>/drop_on</code>打开时，若一直未手动关闭，则在多少个5秒后系统将自动关闭该功能。</p></li><li><p><code>wxAutoDownloadSizeThreshold</code>：wx侧收到的文件中，大小大于多少字节的文件将不会被默认下载，而是发送提示给用户询问是否下载。默认值为<code>3 MiB</code>。</p></li><li><p><code>tgCmdPlaceholder</code>：在<code>/placeholder</code>指令发出后，向当前聊天框输出什么样的占位符。保持默认即可。</p></li><li><p><code>wechat_synced_group</code>：在该数组内填入一个或数个wx群的名称，那么这些群将会进入一种“同步”状态，此时该群中由bot账号在其他设备发送的消息也同样会被转发。利用本功能，您可以通过在wx上把消息逐条转发到该群来实现文本、图像或文件消息记录的导入。</p></li><li><p><code>keep_help_text_after_command_received</code>：在 &#x2F;help 的使用过程中，是否在用户输入指令后把先前输出的 &#x2F;help 文本自动删去。默认值为0即删除。</p></li><li><p><code>auto_reboot_after_error_detected</code>：是否在检测到wx侧发生致命错误（这样的错误一般由您的设备导致，可能只是纯粹的偶发现象，也可能因为&#x2F;tmp已满导致）时自动重启。此项同 &#x2F;reboot 指令一样，程序只会终止自身，至于能否自动重新启动则要看您是否使用docker或者pm2运行本程序，如果仅仅使用 npm run 来运行的话则不应启用此项。</p></li><li><p><code>scheduled_reboot</code>：是否在每天的指定时间自动重启程序。推荐在深夜启用本功能（如设定为凌晨3点）因为这样可以有效避免wx侧出现致命错误，提升整个程序的稳定性。但与上个选项一样，您需要有合适的运行时环境才能正确使用此项。</p></li></ul><h3 id="x2F-chatOptions"><a href="#x2F-chatOptions" class="headerlink" title="&#x2F;chatOptions"></a>&#x2F;chatOptions</h3><p>本节定义了默认情况下每个C2C（以及默认频道）的特定选项值。</p><ul><li><code>mixed</code>：是否允许混合消息制，即以<code>*</code>开头的任何tg消息都将被忽略，适合在部分消息不希望让wx侧的聊天对象知晓的情况下指定。</li><li><code>merge</code>：是否对此聊天启用合并功能。默认为开。</li><li><code>skipSticker</code>：是否忽略该聊天中的所有 wx动画表情。</li><li><code>nameType</code>：设定群聊中的群友们该以什么作为其显示名称。为0表示采用他们wx账户的名称；为1表示优先采用您对群友的个人名片中的备注；为2表示优先使用该联系人自行设置的群名片。</li><li><code>onlyReceive</code>：表示该C2C是否仅转发来自wx的消息，而不转发来自tg的消息。适合您不想在其中误发言的群聊，例如通知群。</li></ul><h3 id="x2F-c11n"><a href="#x2F-c11n" class="headerlink" title="&#x2F;c11n"></a>&#x2F;c11n</h3><p>本节定义了一些“个性化”选项，以修改一些消息的表现形式。</p><ul><li><p><code>wxQuotedMsgSuffixLine</code>：来自wx的消息包含引用时，UOS版wx默认会显示为不美观的样式，本项会将其转换到消息末尾的斜体括号，尽力与wx客户端保持一致。</p></li><li><p><code>titleForSameTalkerInMergedRoomMsg</code>：是否把合并消息里，来自同一对象的数条连续消息的标题隐藏（即不会重复显示说话者的名称）。在默认配置下，标题会被替换为数字，其值为说话者连续消息的条数。</p></li><li><p><code>quotedMsgSuffixLineInPersonChat</code>：基于<code>wxQuotedMsgSuffixLine</code>，在<u>私聊消息</u>中出现引用消息，默认情况下后缀行会采用您和对方的wx名称，通过此项可将其替换为YOU和ta，避免自己和对方的昵称频繁出现。</p></li><li><p><code>officialAccountParser</code>，<code>personCardParser</code>：这两项定义如何解析公众号名片和个人名片为字符串，可自定义显示哪些数据，不过建议采用默认配置。</p></li><li><p><code>systemMsgTitleInRoom</code>：群聊内的系统消息（如红包、修改群名，拉入新成员，新成员与其他人都不是朋友等等）默认以群名作为“说话者：的显示昵称，此项会将其替换为<code>(System)</code>。</p></li><li><p><code>stickerWithLink</code>：基于<code>deliverSticker</code>，经此功能分开递送动画表情之后，需要在当前聊天中输出一个链接以便用户点击后跳转到表情所属聊天，此项定义了这个链接应当如何显示。默认值足矣。</p></li><li><p><code>stickerSkipped</code>：定义被忽略的动画表情应当如何显示。</p></li><li><p><code>newTopicCreated</code>：使用<code>/create_topic</code>创建新C2C线程时，在新线程中显示的欢迎消息。（因tg限制，必须设置欢迎消息，否则无法创建线程。）</p></li><li><p><code>C2C_group_mediaCaption</code>：C2C群聊消息中，群成员发送的媒体消息默认采用什么作为其caption。只需在输出字符串中包含<code>name</code>即可。</p></li><li><p><code>override_help_text</code>：是否override默认的<code>/help</code>文本。默认设为false，即不覆盖，随版本更新而更新；若需override，请参考common.js中的<code>TGBotHelpCmdText</code>将合适的函数放置于此。</p><p>接下来几项，均为所收到的消息不被UOS版wx完全支持时的替代符（因为原版提示文字一般都会包含”升级版本“等字样，为避免碍眼因此使用emoji代替）。</p></li><li><p><code>unsupportedSticker</code>：发出或收到不支持的表情（均为在wx客户端点开能看到文字的商城表情）</p></li><li><p><code>recvCall</code>：收到通话邀请时（很遗憾，UOS版wx不支持视频通话与语音通话的区分，下同）</p></li><li><p><code>recvSplitBill</code>：收到群内分付账单时</p></li><li><p><code>recvTransfer</code>：收到转账消息时（并非均为向您的转账，也可能是群聊中指定收款对象的转账）</p></li><li><p><code>acceptTransfer</code>：转账被接收时</p></li><li><p><code>msgTypeNotSupported</code>：消息类型不支持时（主要包含所有小程序卡片、合并转发的消息卡片。很遗憾，UOS版wx……后面忘了）</p></li></ul><h3 id="x2F-txyun"><a href="#x2F-txyun" class="headerlink" title="&#x2F;txyun"></a>&#x2F;txyun</h3><p>本节定义了 腾讯云API的凭据信息，目前仍为语音转文字等功能的必需。</p><p>如需启用，请前往 <a class="link"   href="https://console.cloud.tencent.com/cam/capi" >https://console.cloud.tencent.com/cam/capi<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a> ，新建密钥即可。在此过程中可以遵循页面指引，新建子账号并为后者生成API Key，以降低Key泄露后被盗用的服务覆盖面。不过请注意所配置的子账户必须具有如下服务的访问权限：</p><blockquote><p> 语音识别ASR。   </p></blockquote><ul><li><p><code>switch</code>：是否启用腾讯云API。</p></li><li><p><code>secretId</code>，<code>secretKey</code>：请根据腾讯云网站提示分别填入AK与SK即可。</p></li></ul><p>&#x2F;<strong>upyun</strong></p><p>由于<code>sharp</code>的引入，此节用途暂缺，因此暂缓相关文档条目的完善。</p><h2 id="四-附录"><a href="#四-附录" class="headerlink" title="四. 附录"></a>四. 附录</h2><h3 id="a-最佳实践"><a href="#a-最佳实践" class="headerlink" title="a. 最佳实践"></a>a. 最佳实践</h3><h3 id="b-Q-amp-A"><a href="#b-Q-amp-A" class="headerlink" title="b. Q&amp;A"></a>b. Q&amp;A</h3>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本程序助您桥接&lt;code&gt;Telegram&lt;/code&gt;和&lt;code&gt;WeChat&lt;/code&gt;、互通消息，且提供最大化的自定义性！&lt;/p&gt;
&lt;h2 id=&quot;一-部署指南&quot;&gt;&lt;a href=&quot;#一-部署指南&quot; class=&quot;headerlink&quot; title=&quot;一. 部署指</summary>
      
    
    
    
    <category term="BridgeBot" scheme="https://blog.eddy.moe/categories/BridgeBot/"/>
    
    
    <category term="ctBridgeBot" scheme="https://blog.eddy.moe/tags/ctBridgeBot/"/>
    
  </entry>
  
  <entry>
    <title>PC2系统修复与升级Arch</title>
    <link href="https://blog.eddy.moe/2023/03/30/PC2%E7%B3%BB%E7%BB%9F%E4%BF%AE%E5%A4%8D%E4%B8%8E%E5%8D%87%E7%BA%A7Arch/"/>
    <id>https://blog.eddy.moe/2023/03/30/PC2%E7%B3%BB%E7%BB%9F%E4%BF%AE%E5%A4%8D%E4%B8%8E%E5%8D%87%E7%BA%A7Arch/</id>
    <published>2023-03-30T07:43:33.000Z</published>
    <updated>2024-04-28T16:14:36.105Z</updated>
    
    <content type="html"><![CDATA[<p>（As this is outdated, I want to move things from my TG channel to here.）</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/45rZyWDb7CBtNsS.png"                      alt="image-20230330210100386"                ></p><p>All of this are caused by a failed SSD.First I discovered data loss, in the form of I&#x2F;O Error, then after recovering ext4 files to Windows PC, the Disk suddenly got corrupted and the system won’t boot! My next step was e2fsck, which lead to a situation that all existing files were moved to “lost+found” and lost their filenames. Then I tried a lot to move recovered file back to disk, after many tries, the files got back, the grub was reinstalled again, but it still failed to boot, with the missing of so many files such as “vmlinuz”.</p><p>After that, I executed Ubuntu installer to overwrite system files to the existing partition. To be short, the system booted up, but all my apps are corrupted, only left error shortcuts on the Desktop.<br>OK, so I tried re-copy recovered file from Win PC to the previous partition, and selected overwrite on conflict. Now some of my apps recovered, however, the system was Inoperable, maybe some system files are replaced with corrupted ones.<br>So, the last option for me is install a new Operating system.</p><p>Then, I installed centos, without much meaningless tries(excluded many tries to compile VMware kernel modules that I finally get rescued by a patch.sh on Github )<br>However, its kernel cannot support btrfs ?! It is said that RedHat removed this feature on Centos 8, and I could not find any working method to install that, even after I downloaded the source of btrfs-progs and tried to compile them. I was, emm, heartbroken, so after the evening class on Monday, I spent 2 hours on Arch Linux Installer, with almost no errors reported. Thanks to the Arch Wiki, I learned some inner principle of linux kernel, and put all things back online.<br>I have to say that Arch is an OS of freedom, it gave me many choices on Packages, Desktop Environment and so.</p><p>Now I installed Budgie (its freedom on docks and panels help me a lot) as my normal Desktop Environment. Welcome other budgie users!!</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;（As this is outdated, I want to move things from my TG channel to here.）&lt;/p&gt;
&lt;p&gt;&lt;img  
                     lazyload
                    </summary>
      
    
    
    
    <category term="Tech Web Log" scheme="https://blog.eddy.moe/categories/Tech-Web-Log/"/>
    
    
  </entry>
  
  <entry>
    <title>宝塔面板反向代理的缓存功能如何彻底关闭</title>
    <link href="https://blog.eddy.moe/2023/03/17/%E5%AE%9D%E5%A1%94%E9%9D%A2%E6%9D%BF%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%9A%84%E7%BC%93%E5%AD%98%E5%8A%9F%E8%83%BD%E5%A6%82%E4%BD%95%E5%BD%BB%E5%BA%95%E5%85%B3%E9%97%AD/"/>
    <id>https://blog.eddy.moe/2023/03/17/%E5%AE%9D%E5%A1%94%E9%9D%A2%E6%9D%BF%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86%E7%9A%84%E7%BC%93%E5%AD%98%E5%8A%9F%E8%83%BD%E5%A6%82%E4%BD%95%E5%BD%BB%E5%BA%95%E5%85%B3%E9%97%AD/</id>
    <published>2023-03-17T06:32:30.000Z</published>
    <updated>2024-04-28T16:15:35.369Z</updated>
    
    <content type="html"><![CDATA[<p>今日尝试使用宝塔面板的反向代理功能给bark-server添加https加密，但是却频繁遭遇“缓存危机”，依据宝塔程序的默认设置可以推出，缓存有效时长应为12h，这在某些场合下未免太长了些。但我改了面板上显示的缓存设置（如图）未有改变：</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/zo9tgIyUQ3uNR5q.png"                      alt="image-20230317173210437"                ></p><p>最终试了许久才得到最终方案，即：</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/MBtfyF4pjrN25LV.png"                      alt="image-20230317173521042"                ></p><p>上部过期时间改为-1s或2s等短时间；下部四个状态码之后的时间也需要修改（<em>这里才是实际生效的配置，如果只改上面的话并没有作用</em>）。</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;今日尝试使用宝塔面板的反向代理功能给bark-server添加https加密，但是却频繁遭遇“缓存危机”，依据宝塔程序的默认设置可以推出，缓存有效时长应为12h，这在某些场合下未免太长了些。但我改了面板上显示的缓存设置（如图）未有改变：&lt;/p&gt;
&lt;p&gt;&lt;img  
    </summary>
      
    
    
    
    <category term="Small Tips" scheme="https://blog.eddy.moe/categories/Small-Tips/"/>
    
    
  </entry>
  
  <entry>
    <title>在宿舍网络中采用策略路由</title>
    <link href="https://blog.eddy.moe/2023/03/08/%E5%9C%A8%E5%AE%BF%E8%88%8D%E7%BD%91%E7%BB%9C%E4%B8%AD%E9%87%87%E7%94%A8%E7%AD%96%E7%95%A5%E8%B7%AF%E7%94%B1/"/>
    <id>https://blog.eddy.moe/2023/03/08/%E5%9C%A8%E5%AE%BF%E8%88%8D%E7%BD%91%E7%BB%9C%E4%B8%AD%E9%87%87%E7%94%A8%E7%AD%96%E7%95%A5%E8%B7%AF%E7%94%B1/</id>
    <published>2023-03-08T15:32:30.000Z</published>
    <updated>2024-04-28T16:16:15.437Z</updated>
    
    <content type="html"><![CDATA[<p>众所周知，在安微太学，学校内的宽带与校园网相比，虽然都是从一个网线面板出来的，但是登录PPPoE使用的账号如果带上运营商名的话就会走对应的宽带线路，速度更快（当然需要<em>课金</em>😈）；如果不带运营商名那就是纯粹的校园网，但是速度十分垃圾，相当于1MBps，简直无法忍受~</p><p>有同学采用的方案是，一个主网使用宽带，副网只接校园网，需要用的时候拔插网线或切换Wi-Fi即可，不过我认为太麻烦，并且需要闲置路由器（做副网用）和交换机（一个墙插网口得分给两台路由器）。因此，拥有Openwrt的我怎能放任此事不管呢？不管是为了我自己方便还是舍友（笑）。</p><p>[发现以前我在叙述事情经过时太啰嗦了，这次尽量速战速决吧（&#x2F;doge）]</p><p>起初我看到了“静态路由”功能，不过研究一番后发现它属于级别更高的层次，虽然可以根据网络地址+CIDR精确划定要设定规则的对象，不过却只能设定把数据包发往哪个IP。这可就有大麻烦了，因为抛开一个网卡虚拟两个wan口这一必需的技术壁垒不谈，我校采用的PPPoE认证技术得到的IP也是时常变化的。对付这种变化的IP地址也只有DDNS软件做的好，它们会轮询监测IP的变化；而我们自己要想实现这套逻辑的话，首先需要一个区域存放先前的IP地址（of 连校园网的vwan2，下同），其次需要随系统启动一个脚本，每隔一定时间扫描vwan2的IP，最后再提交到静态路由表里……想想就复杂，况且我只是会一点Linux，对<code>Openwrt系统内部原理、Linux内核下的计算机网络和Luci</code>都不甚了解，这样的代码也不是我短期内能写出来的，遂只能放弃。</p><p>此后，在创建虚拟网卡的过程中（网络菜单–多线多拨 [aka. Syncdial]，打开“不自动配置MWAN3负载均衡”），我发现其实它也是使用到一个名叫MWAN3的工具来实现。我于是查询了后者的教程，果然，它是一个极为强大的负载均衡工具。也正是thanks to它，才有了今天这篇文章的诞生。</p><p>详细步骤如下：</p><p>首先在Syncdial打开“单线多拨”，设置虚拟wan口数量为期望的值（或如图）</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/qQn4Yvp9A2fdOmK.png"                      alt="image-20230302231301694"                ></p><p>保存后回到接口页面，分别进入vwan1，vwan2配置对应的宽带账号（我的方案是前者登宽带账号，后者登校园网账号），保存并应用；</p><p>再进入“负载均衡”页面，先设置接口和成员，把默认值尽数删除，然后对每个虚拟wan口各创建一个接口与成员，跃点数和权重视情况即可：</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/mjcuO3aowkG8y4l.png"                      alt="image-20230303011315561" style="zoom:80%;"                 ><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/2TLHC8q9aXwxV4c.png"                      alt="image-20230303011338264"                ></p><p>接下来创建策略，也就是告诉mwan3，被匹配到的流量要从哪个渠道出站，创建如图所示的新策略：</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/vnDZ7gNejxLlGAE.png"                      alt="image-20230303011457775" style="zoom:67%;"                 ><p>同时在默认策略中把vwan1调到靠前的位置，vwan2尽量靠后；</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/8xwVTDqAd7oEP62.png"                      alt="image-20230303011636751" style="zoom:67%;"                 ><p>最后就是配置规则了，如图即可，添加过程中不熟悉的一概默认或留空即可</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/AovGapCiEKnwdYb.png"                      alt="image-20230303011719765" style="zoom:50%;"                 ><p>恭喜你！在这样操作+漫长的“保存与应用”后，你就可以享受高速宽带+直连校园网的便利了！</p><p>经测试原先无法直接访问的校内资源现在也可内网直接访问了，详情见图：</p><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/ijedx3BODlsCKaX.png"                      alt="image-20230303012005119"                ></p><p>（完结撒花）</p><blockquote><p>注：我发现我校的Web VPN系统检测到校内IP地址访问是自动从wvpn.ahu.edu.cn跳转回one.ahu.edu.cn，很聪明呢</p></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;众所周知，在安微太学，学校内的宽带与校园网相比，虽然都是从一个网线面板出来的，但是登录PPPoE使用的账号如果带上运营商名的话就会走对应的宽带线路，速度更快（当然需要&lt;em&gt;课金&lt;/em&gt;😈）；如果不带运营商名那就是纯粹的校园网，但是速度十分垃圾，相当于1MBps，简直无</summary>
      
    
    
    
    <category term="Tech Web Log" scheme="https://blog.eddy.moe/categories/Tech-Web-Log/"/>
    
    
  </entry>
  
  <entry>
    <title>UWP应用与系统代理的冲突及解决办法</title>
    <link href="https://blog.eddy.moe/2023/02/12/UWP%E5%BA%94%E7%94%A8%E4%B8%8E%E7%B3%BB%E7%BB%9F%E4%BB%A3%E7%90%86%E7%9A%84%E5%86%B2%E7%AA%81%E5%8F%8A%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/"/>
    <id>https://blog.eddy.moe/2023/02/12/UWP%E5%BA%94%E7%94%A8%E4%B8%8E%E7%B3%BB%E7%BB%9F%E4%BB%A3%E7%90%86%E7%9A%84%E5%86%B2%E7%AA%81%E5%8F%8A%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95/</id>
    <published>2023-02-12T12:07:00.000Z</published>
    <updated>2024-04-28T16:14:49.820Z</updated>
    
    <content type="html"><![CDATA[<p>不知某日，我突然发现我的2个应用 {一是微软代办，另一个是微软的“邮件与日历”}这2个程序。每当我使用V2RayN打开系统代理时，他俩就无法进行网络通信；关掉后又恢复正常了。</p><p>其实原本系统代理不开也罢，但是阅读软件FBReader需要与Google Drive建立连接，但软件内部没有提供代理的设置；还有就是大家喜闻乐见的steam，如果不开代理的话商店页面很卡、社区进不去。因此不得不开，但是一旦开了，就会影响前述这两个微软出品的软件的正常运行。</p><p>正是因为我在日常工作中经常用到他俩，所以才将它们放在我的工作电脑上的，否则的话，一个待办软件一个邮件软件放在手机上用完全没问题，除了有的时候电脑与手机之间传送文字不是很方便（此处对苹果全家桶的羡慕加1😭）。</p><p>翌日，我想到了另一种办法。我虽然最近没有使用硬件软路由，但是我可以在我常年开启的、作为服务器的小电脑上 安排一个OpenWRT的虚拟机，将它作为旁路由，然后其上就能拥有Passwall，OpenClash等一系列科学上网应用，然后在那里自然就能做出更多的选择了。我如是去做了，花费了许久把整个Passwall都调试好了，但是在设置里却没有能找到符合我要求的选项。</p><p>其实对于一般用户来说 这很简单，只要在Passwall设置里打开主开关就能很方便地对内网中的各个设备进行科学上网处理。</p><p>但是我的要求比较特殊，因为时常会访问到一些页面，在其上我不希望被探测到使用了代理（想必大家都懂我指的是什么）。还有就是有些时候我需要测试自家网络裸连某国外节点的下载速度，这个时候肯定不能走任何代理对吧，所以又必须有一个简单的方法来关闭代理。如果将代理总开关设于软路由之上的话开启和关闭将会变得非常麻烦（首先要进入软路由的管理界面，其次还要在导航栏中找到科学上网软件打开开关并保存，后者也需要多花费5秒钟时间，并且这样我也很难在自己电脑上追溯：前一段时间我的电脑访问了哪些域名，或者一段时间内流入外网的总流量是多少……如果无法追溯这些数据的话还有可能会导致机场套餐用超额），如果设在本地的话一个快捷键就可以关了，并且上述的缺陷都可以补足。因此这就是我原先采用的办法，但现在不行了。</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/ecYIHGEWhlgwfpC.png"                      alt="image-20230212135236927" style="zoom:67%;"                 ><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/BJwDd3Up76TKYSc.png"                      alt="image-20230212135316722" style="zoom:50%;"                 ><p><em>如上图所示，虽然Passwall算是同类型科学上网软件中的佼佼者，但是其配置功能仍然有限。</em></p><p>起初我想可以让Passwall对内网设备套用【旁路由网关】科学上网模式，但是我的要求比较特殊，因为时常会访问到一些页面，在其上我不希望被探测到使用了代理（想必大家都懂我指的是什么）。还有就是有些时候我需要测试自家网络裸连某国外节点的下载速度，这个时候肯定不能走任何代理对吧，所以又必须有一个简单的方法来关闭代理。如果将代理总开关设于软路由之上的话开启和关闭将会变得非常麻烦（首先要进入软路由的管理界面，其次还要在导航栏中找到科学上网软件打开开关并保存，后者也需要多花费5秒钟时间，并且这样我也很难在自己电脑上追溯：前一段时间我的电脑访问了哪些域名，或者一段时间内流入外网的总流量是多少……如果无法追溯这些数据的话还有可能会导致机场套餐用超额），如果设在本地的话一个快捷键就可以关了，并且上述的缺陷都可以补足。因此这种方案只能就此搁置。</p><p>后来我改变了想法，我觉得可以让整个电脑都处于【旁路由网关】科学上网的模式，然后提供一个方法让浏览器中的页面不经过任何代理。首先浏览器端我用的插件是switchyOmega，它提供了通过代理连接或直接连接的选项，但是其所谓的直接连接在我所说的这种【旁路由网关】模式中也会走代理，所以只能在路由器端给其人工搭建一个代理并且设置其出口为Freedom<em>（此处术语参考了Project X）</em>但是这种操作也极难实现，因为在我的Passwall设置里，“路由器自身的TCP连接”规则是“GFW列表”，这是因为在同一路由器上我运行的其他服务有时需要国外网络才能访问，不得不这样做。</p><p>因此，我所想出的第2个方案也无法执行了。</p><p>今天我无意间上网搜了一下此这种情况，后来发现原来微软对UWP应用的网络连接是有限制的，详情可参考下述引文：</p><blockquote><p>我们都知道，Win10之后，Windows系统中除了基于传统的exe可执行程序的软件之外，又多了“UWP应用”这一新颖的玩意儿。<br>有关UWP应用的详细介绍，可以查阅度娘百科的相关词条：Universal Windows Platform</p><p>当我们自信的打开代理软件 之后，却发现不该连上的网站还是连不上，看不了的番剧还是看不了，其实，并不是我们的代理出现了问题，而是在Windows10系统中，默认是不允许这些UWP应用走代理网络的。</p></blockquote><p>于是根据网上多数人使用过的方案，我打开了在电脑里尘封已久的Fiddler（抓包工具），点击了右上角的WinConfig，弹出了这样的界面：</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/2GwtqHE6j4Jyh5l.png"                      alt="image-20230212140949951" style="zoom:67%;"                 ><p>我随即选择了我前面说到过的两款应用，并点击保存更改，他俩果然可以正常连接网络了。</p><p>同时我还发现,以前打开Fiddler运行两款微软应用，只会显示我高亮的这2条https连接记录；但是在放开了他们的限制之后，多出了这么多条，我想这才是问题所在。以前没有修改限制时，根据系统安全默认值，它们能够探测到系统代理却无法连接，从而导致整个应用无法联网；因此现在问题顺理成章地解决了。</p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/nEh7yjdgHRTcSPe.png"                      alt="image-20230212141131461" style="zoom:67%;"                 ><p>其实说到底问题很简单，只要抓住UWP这个关键词在网上一搜，这些问题就能解决。可惜我当时没有想到这一点，我认为是软件本身的问题，我还在想，<em>为什么这些应用会与系统代理冲突？我又没有限制他们的访问权限？</em>但却没有朝着UWP框架的角度去想。</p><p>唉，这篇文章，就到此为止罢！</p><hr><p>Special Thanks:</p><ul><li><a class="link"   href="https://gacenwinl.cn/" >Gacenwinl<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></li><li>Progress Telerik Fiddler</li></ul>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;不知某日，我突然发现我的2个应用 {一是微软代办，另一个是微软的“邮件与日历”}这2个程序。每当我使用V2RayN打开系统代理时，他俩就无法进行网络通信；关掉后又恢复正常了。&lt;/p&gt;
&lt;p&gt;其实原本系统代理不开也罢，但是阅读软件FBReader需要与Google Drive</summary>
      
    
    
    
    <category term="Tech Web Log" scheme="https://blog.eddy.moe/categories/Tech-Web-Log/"/>
    
    
    <category term="Windows" scheme="https://blog.eddy.moe/tags/Windows/"/>
    
    <category term="Redundant Words" scheme="https://blog.eddy.moe/tags/Redundant-Words/"/>
    
  </entry>
  
  <entry>
    <title>基于字符串匹配的病毒序列检测</title>
    <link href="https://blog.eddy.moe/2022/12/13/%E5%9F%BA%E4%BA%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D%E7%9A%84%E7%97%85%E6%AF%92%E5%BA%8F%E5%88%97%E6%A3%80%E6%B5%8B/"/>
    <id>https://blog.eddy.moe/2022/12/13/%E5%9F%BA%E4%BA%8E%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%8C%B9%E9%85%8D%E7%9A%84%E7%97%85%E6%AF%92%E5%BA%8F%E5%88%97%E6%A3%80%E6%B5%8B/</id>
    <published>2022-12-13T13:27:00.000Z</published>
    <updated>2024-04-28T16:15:39.200Z</updated>
    
    <content type="html"><![CDATA[<p>本程序实现了基于字符串匹配的病毒序列检测功能。<br>主体由两大字符串匹配算法的实现函数、自制的substr函数，以及KMP中的get_next函数组成。</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">int substr(char input[], int start, int length, char output[]) &#123;</span><br><span class="line">    if (start &lt; 0  start &gt; strlen(input)  length &lt; 0  start + length - 1 &gt; strlen(input))</span><br><span class="line">        return 0;</span><br><span class="line">    for (int i = start; i &lt; start + length; i++)</span><br><span class="line">        output[i - start] = input[i];</span><br><span class="line">    return 1;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><p>此外，在主函数中采用了创新性的整体结构，首先建立一个字符串outputBuffer充当输出缓冲区，在显示必要的输入提示之后，通过永真的while循环不停读取用户输入；当读取到双z时，输出缓冲区并退出（从Ctrl+Z获得灵感）。接下来，对于每一组S和T，遵循课上所说，利用sprintf将模式串复制两次后采用for循环每次提取新T串的前n位用于匹配（n为复制前T的长度）取得NextVal函数值，并调用两大算法进行匹配。此外还采用了逻辑短路机制，当前几次匹配中有成功者，后续就会不再比较。While循环体末尾采用了sprintf函数，将本次运行的结果以特定形式输出至outputBuffer。</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">int count = 1, t_length = 0;</span><br><span class="line">    char outputBuffer[MAXSIZE] = &#123;&#125;;</span><br><span class="line">    cout &lt;&lt; endl &lt;&lt; &quot;General Instructions:&quot; &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; &quot;Now please enter dna pairs, first is of the virus, the second is person&#x27;s.&quot; &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; &quot;To Interrupt inputting, please enter &#x27;z z&#x27; on a new line and then press enter.&quot; &lt;&lt; endl &lt;&lt; flush;</span><br><span class="line">    while (true) &#123;</span><br><span class="line">        char s[MAXSIZE] = &#123;&#125;, t[MAXSIZE] = &#123;&#125;, t_part[MAXSIZE] = &#123;&#125;;</span><br><span class="line">        //Processing one pair of DNA in one circulation</span><br><span class="line">        cin &gt;&gt; t;</span><br><span class="line">        cin &gt;&gt; s;</span><br><span class="line">        if (s[0] == &#x27;z&#x27; &amp;&amp; t[0] == &#x27;z&#x27;) &#123;</span><br><span class="line">            //User Ready to view results</span><br><span class="line">            cout &lt;&lt; outputBuffer &lt;&lt; endl;</span><br><span class="line">            break;</span><br><span class="line">        &#125;</span><br><span class="line">        t_length = strlen(t);</span><br><span class="line">        //Double the pattern string</span><br><span class="line">        sprintf(t, &quot;%s%s&quot;, t, t);</span><br><span class="line">        bool BFResult = false, KMPResult = false;</span><br><span class="line">        for (int i = 0; i &lt; t_length; i++) &#123;</span><br><span class="line">            int nextv[MAXSIZE];</span><br><span class="line">            get_next(t, nextv);</span><br><span class="line">            //get each &#123;t_length&#125;characters of T string</span><br><span class="line">            substr(t, i, t_length, t_part);</span><br><span class="line">            //Used logical short-circuit, to avoid useless computing since first success in t_part</span><br><span class="line">            BFResult = BFResult  (Index_BF(s, t_part) != -1);</span><br><span class="line">            KMPResult = KMPResult  (Index_KMP(s, t_part, nextv) != -1);</span><br><span class="line">        &#125;</span><br><span class="line">        sprintf(outputBuffer, &quot;%s -The %d(th) , By BF:&#123;%s&#125;, By KMP:&#123;%s&#125;\n&quot;, outputBuffer, count++,</span><br><span class="line">                BFResult ? &quot;Yes&quot; : &quot;No &quot;, KMPResult ? &quot;Yes&quot; : &quot;No &quot;);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure></div><p>运行截图如下，其中，</p><blockquote><p>第一行为考验哪个为模式串而设。<br>第二行为明显不匹配的字串。<br>第三行为明显匹配的。<br>第四行为考验环状DNA匹配功能是否正常工作。</p></blockquote><p><img                       lazyload                     src="/images/loading.svg"                     data-src="https://s2.loli.net/2024/04/29/l8y14kJZm3sSNef.png"                                     ></p><hr><p>完整代码如下：</p><div class="code-container" data-rel="Plaintext"><figure class="iseeu highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line">#include &lt;iostream&gt;</span><br><span class="line">using namespace std;</span><br><span class="line">#define MAXSIZE 255</span><br><span class="line">int substr(char input[], int start, int length, char output[]) &#123;</span><br><span class="line">    if (start &lt; 0  start &gt; strlen(input)  length &lt; 0  start + length - 1 &gt; strlen(input))</span><br><span class="line">        return 0;</span><br><span class="line">    for (int i = start; i &lt; start + length; i++)</span><br><span class="line">        output[i - start] = input[i];</span><br><span class="line">    return 1;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">int Index_BF(char S[], char T[]) &#123;</span><br><span class="line">    int i = 0, j = 0;</span><br><span class="line">    int lenS = (int) strlen(S), lenT = (int) strlen(T);</span><br><span class="line">    while (i &lt; lenS &amp;&amp; j &lt; lenT) &#123;</span><br><span class="line">        if (S[i] == T[j]) &#123;</span><br><span class="line">            i++, j++;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            i = i - j + 1;</span><br><span class="line">            j = 0;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return (j &gt;= lenT) ? i - lenT : -1;</span><br><span class="line">&#125;</span><br><span class="line">void get_next(char t[], int nextv[]) &#123;</span><br><span class="line">//    t2 is used to change the pattern string to start from index 1, not 0.</span><br><span class="line">    char t2[MAXSIZE] = &#123;0&#125;;</span><br><span class="line">    for (int m = 0;; m++) &#123;</span><br><span class="line">        t2[m + 1] = t[m];</span><br><span class="line">        if (t[m] == 0)</span><br><span class="line">            break;</span><br><span class="line">    &#125;</span><br><span class="line">    int i = 1, j = 0;</span><br><span class="line">    nextv[1] = 0;</span><br><span class="line">    while (i &lt; strlen(t)) &#123;</span><br><span class="line">        if (j == 0  t2[i] == t2[j]) &#123;</span><br><span class="line">            i++, j++;</span><br><span class="line">            nextv[i] = j;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            j = nextv[j];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line">int Index_KMP(char S[], char T[], int nextv[]) &#123;</span><br><span class="line">    int i = 1, j = 1;</span><br><span class="line">    char s2[MAXSIZE] = &#123;0&#125;, t2[MAXSIZE] = &#123;0&#125;;</span><br><span class="line">    for (int m = 0;; m++) &#123;</span><br><span class="line">        t2[m + 1] = T[m], s2[m + 1] = S[m];</span><br><span class="line">        if (T[m] == 0) break;</span><br><span class="line">    &#125;</span><br><span class="line">    int lenS = (int) strlen(S), lenT = (int) strlen(T);</span><br><span class="line">    while (i &lt;= lenS &amp;&amp; j &lt;= lenT) &#123;</span><br><span class="line">        if (j == 0  s2[i] == t2[j]) &#123;</span><br><span class="line">            i++, j++;</span><br><span class="line">        &#125; else &#123;</span><br><span class="line">            j = nextv[j];</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    return (j &gt; lenT) ? i - lenT : -1;</span><br><span class="line">&#125;</span><br><span class="line">int main() &#123;</span><br><span class="line">    int count = 1, t_length = 0;</span><br><span class="line">    char outputBuffer[MAXSIZE] = &#123;&#125;;</span><br><span class="line">    cout &lt;&lt; endl &lt;&lt; &quot;General Instructions:&quot; &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; &quot;Now please enter dna pairs, first is of the virus, the second is person&#x27;s.&quot; &lt;&lt; endl;</span><br><span class="line">    cout &lt;&lt; &quot;To Interrupt inputting, please enter &#x27;z z&#x27; on a new line and then press enter.&quot; &lt;&lt; endl &lt;&lt; flush;</span><br><span class="line">    while (true) &#123;</span><br><span class="line">        char s[MAXSIZE] = &#123;&#125;, t[MAXSIZE] = &#123;&#125;, t_part[MAXSIZE] = &#123;&#125;;</span><br><span class="line">        //Processing one pair of DNA in one circulation</span><br><span class="line">        cin &gt;&gt; t;</span><br><span class="line">        cin &gt;&gt; s;</span><br><span class="line">        if (s[0] == &#x27;z&#x27; &amp;&amp; t[0] == &#x27;z&#x27;) &#123;</span><br><span class="line">            //User Ready to view results</span><br><span class="line">            cout &lt;&lt; outputBuffer &lt;&lt; endl;</span><br><span class="line">            break;</span><br><span class="line">        &#125;</span><br><span class="line">        t_length = strlen(t);</span><br><span class="line">        //Double the pattern string</span><br><span class="line">        sprintf(t, &quot;%s%s&quot;, t, t);</span><br><span class="line">        bool BFResult = false, KMPResult = false;</span><br><span class="line">        for (int i = 0; i &lt; t_length; i++) &#123;</span><br><span class="line">            int nextv[MAXSIZE];</span><br><span class="line">            get_next(t, nextv);</span><br><span class="line">            //get each &#123;t_length&#125;characters of T string</span><br><span class="line">            substr(t, i, t_length, t_part);</span><br><span class="line">            //Used logical short-circuit, to avoid useless computing since first success in t_part</span><br><span class="line">            BFResult = BFResult  (Index_BF(s, t_part) != -1);</span><br><span class="line">            KMPResult = KMPResult  (Index_KMP(s, t_part, nextv) != -1);</span><br><span class="line">        &#125;</span><br><span class="line">        sprintf(outputBuffer, &quot;%s -The %d(th) , By BF:&#123;%s&#125;, By KMP:&#123;%s&#125;\n&quot;, outputBuffer, count++,</span><br><span class="line">                BFResult ? &quot;Yes&quot; : &quot;No &quot;, KMPResult ? &quot;Yes&quot; : &quot;No &quot;);</span><br><span class="line">    &#125;</span><br><span class="line">    return 0;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></div><p>Thanks for reading!</p>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;本程序实现了基于字符串匹配的病毒序列检测功能。&lt;br&gt;主体由两大字符串匹配算法的实现函数、自制的substr函数，以及KMP中的get_next函数组成。&lt;/p&gt;
&lt;div class=&quot;code-container&quot; data-rel=&quot;Plaintext&quot;&gt;&lt;figur</summary>
      
    
    
    
    <category term="General Programming" scheme="https://blog.eddy.moe/categories/General-Programming/"/>
    
    
    <category term="Powershell" scheme="https://blog.eddy.moe/tags/Powershell/"/>
    
  </entry>
  
  <entry>
    <title>Hello, World!</title>
    <link href="https://blog.eddy.moe/2022/12/13/hello-world-1/"/>
    <id>https://blog.eddy.moe/2022/12/13/hello-world-1/</id>
    <published>2022-12-13T12:38:19.000Z</published>
    <updated>2023-10-10T08:24:56.800Z</updated>
    
    <content type="html"><![CDATA[<p>This is my first passage, now roughly acting as a brief self-introduction!</p><p>About me :<br>        A college <em>sophomore</em> majoring in CS in <a class="link"   href="https://ahu.edu.cn/" >Anhui University<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a>..</p><p>Interested in :</p><ul><li>Java (Very complex, uh-huh?)</li><li>C&#x2F;C++ (the must-have for normal CS students)</li><li>PHP (the best language in the world ! )</li><li><em>Python</em> (No Py at all ! )</li><li>Node.js (It’s very easy for it to start a simple project)</li><li>……</li></ul><p>Welcome to contact me with Telegram, ( @ry73295 ) <a class="link"   href="https://t.me/ry73295" >https://t.me/ry73295<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p><p>Or View my Github Profile with this link. 👉 <a class="link"   href="https://github.com/netcyabc" >https://github.com/netcyabc<i class="fa-solid fa-arrow-up-right ml-[0.2em] font-light align-text-top text-[0.7em] link-icon"></i></a></p><blockquote><p>Update:</p><p>​My favorite Song today:</p><pre><code>    - &quot;Cre-sc3NT - Saika -Sakura Samurai-&quot;(remix)    - Panda Eyes、Teminite、OJK - Highscore    - Mili - Gone Angels</code></pre></blockquote>]]></content>
    
    
      
      
    <summary type="html">&lt;p&gt;This is my first passage, now roughly acting as a brief self-introduction!&lt;/p&gt;
&lt;p&gt;About me :&lt;br&gt;        A college &lt;em&gt;sophomore&lt;/em&gt; majo</summary>
      
    
    
    
    <category term="Initial" scheme="https://blog.eddy.moe/categories/Initial/"/>
    
    
  </entry>
  
</feed>
