<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="https://leisiyu.dev/en/atom.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US">
  <id>https://leisiyu.dev/en/</id>
  <title>Siyu Lei&amp;apos;s Blog</title>
  <subtitle>Siyu Lei&amp;apos;s personal blog about technology, daily life, and fan works.</subtitle>
  <author>
    <name>Siyu Lei</name>
  </author>
  <rights>Copyright © 2023–Now All rights reserved.</rights>
  <updated>2026-10-14T18:38:24.137Z</updated>
  <generator>@vuepress/plugin-feed</generator>
  <link rel="self" href="https://leisiyu.dev/en/atom.xml"/>
  <link rel="alternate" href="https://leisiyu.dev/en/"/>
  <category term="同人"/>
  <category term="日常"/>
  <category term="技术分享"/>
  <category term="开源项目"/>
  <category term="游戏"/>
  <contributor>
    <name>Siyu Lei</name>
  </contributor>
  <entry>
    <title type="text">A Divine Free Rosemary Drawn by a Friend</title>
    <id>https://leisiyu.dev/en/f/rosmontis_heizi.html</id>
    <link href="https://leisiyu.dev/en/f/rosmontis_heizi.html"/>
    <updated>2026-10-14T18:38:24.261Z</updated>
    <summary type="text">Thanks to @黒子, a teacher from Tropic of Cancer, for drawing this free Rosemary. It&amp;apos;s simply a masterpiece~</summary>
    <content type="html"><![CDATA[<!-- more -->
<p>Thanks to @黒子, a teacher from Tropic of Cancer, for drawing this free Rosemary. It's simply a masterpiece~</p>
<p><img src="/f/rosmontis/迷迭香无泪全身.webp" alt=""></p>
<p><img src="/f/rosmontis/迷迭香无泪遮挡.webp" alt=""></p>
<p><img src="/f/rosmontis/迷迭香流泪全身.webp" alt=""></p>
<p><img src="/f/rosmontis/迷迭香流泪遮挡.webp" alt=""></p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="同人"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2026-02-06T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">【Warning】Chengzhi Study Abroad Study Permit Renewal Scam</title>
    <id>https://leisiyu.dev/en/d/ilearnincanada_cheat.html</id>
    <link href="https://leisiyu.dev/en/d/ilearnincanada_cheat.html"/>
    <updated>2026-10-14T18:38:24.262Z</updated>
    <summary type="html"><![CDATA[<p>WeChat ID: iLiCJohn</p>
<p>WeChat name: John 🇨🇦 成智留学^<sup>_</sup>^</p>
<p>Payment email: John.lee@ilearnincanada.com</p>
]]></summary>
    <content type="html"><![CDATA[<p>WeChat ID: iLiCJohn</p>
<p>WeChat name: John 🇨🇦 成智留学^<sup>_</sup>^</p>
<p>Payment email: John.lee@ilearnincanada.com</p>
<!-- more -->
<p>Summary of the incident:</p>
<p>While negotiating a study permit renewal service with the WeChat user iLiCJohn (who calls himself "Chengzhi Study Abroad"), I encountered non-transparent pricing, malicious extra charges, and a refusal to issue a refund. He initially quoted an all-inclusive price of CAD 330, but during the process demanded an additional CAD 150 as a "visa filing fee." When I questioned this and tried to negotiate cancelling the service, he refused to refund me on the grounds that "time has already been spent," and even unilaterally terminated the service and blocked me.</p>
<h2>Detailed timeline of events:</h2>
<h3>In March 2025, I contacted iLiCJohn on WeChat to ask about the price of the study permit renewal service.</h3>
<p>He clearly stated: "If you were referred by a friend, the service fee is $330," and did not mention any additional fees.</p>
<p>Based on this quote, in July I sent CAD 330 by e-transfer to John.lee@ilearnincanada.com.</p>
<p>He told me that because I had not yet entered Canada, he could not proceed with the application and that a refund was possible. Out of trust, I told him, "Just keep it for now, so we don't have to go through the hassle again later."</p>
<h3>On August 24, 2025, the price suddenly increased during the process</h3>
<p>After I provided all the required identity documents, he suddenly told me that the CAD 330 did not include the CAD 150 "immigration filing fee" and demanded that I pay it separately.</p>
<p>I questioned this, arguing that the pricing was not transparent and the total was too high (CAD 480 in total, whereas typical agent service fees are between CAD 150 and 200), and I tried to negotiate cancelling the service and getting a refund.</p>
<h3>Malicious refusal to refund and threats</h3>
<p>He refused to refund me on the grounds that "time has already been spent," claiming that "there is no possibility of a refund."</p>
<p>Even after I proposed a compromise (refund CAD 300 and deduct CAD 30 as compensation for his time), he took a hard line, unilaterally terminated the service, and said, "Don't contact me again, you are no longer our client." He also refused to continue processing my application.</p>
<p>He did not provide a contract, and I have ample reason to suspect he is evading taxes.</p>
<p><img src="/d/ilearnincanada_cheat/chat1.png" alt="Chat records"></p>
<h2>Final outcome</h2>
<p>As of August 26, 2025, the service has not been completed, the CAD 330 has not been refunded, and he has refused any further communication or to continue processing the application.</p>
<p>I have reported this to the Canadian Anti-Fraud Centre and to WeChat Security.</p>
<p>I am making this public to prevent more people from being harmed. Online transactions carry risks, so be careful when transferring money!</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2025-08-24T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Some Comparisons Between Tropic Line&amp;apos;s Special Interviews and Skland&amp;apos;s Islander Tea Chat</title>
    <id>https://leisiyu.dev/en/d/AneotAndSkd.html</id>
    <link href="https://leisiyu.dev/en/d/AneotAndSkd.html"/>
    <updated>2026-10-14T18:38:24.263Z</updated>
    <summary type="html"><![CDATA[<p>Isn't the sync rate just a bit too high?</p>
]]></summary>
    <content type="html"><![CDATA[<p>Isn't the sync rate just a bit too high?</p>
<!-- more -->
<h2>Preface</h2>
<p>First, I apologize for possibly taking up your valuable time, sacrificing your reading experience, and affecting your good mood. If you don't like this article, please feel free to ignore it. One thing you need not worry about, though: the Tropic Line staff each have their own duties, so writing this article will not affect the magazine's production schedule. The recent delay is mainly because many staff members had things to attend to during the Spring Festival, so progress is a bit slower.</p>
<p>I understand that in the vast field of creation, converging inspiration and similar ideas are natural occurrences. However, we found that the degree of similarity between an official column and our fan work seems to go <strong>a little bit</strong> beyond the scope of ordinary coincidences of inspiration.</p>
<p>We invest time, energy, and even heart and soul simply to express our love for the original work and the joy of sharing with fellow fans. Yet these efforts often go unrewarded, and may even be improperly borrowed from or used commercially. Although we have donation income and Bilibili incentives, and Suiwanzi once tipped about a hundred yuan too, this is far from enough to cover the costs of attending events and giving out copies for free. Behind every event, each staff member pays thousands out of pocket for printing, let alone being able to pay for the years of selfless dedication of even a single staff member. We have always created out of love, and this is entirely a money-losing endeavor, and in the end we still have to accept improper borrowing by the official side. This should not be, and ought not to be, the fate of a non-profit group.</p>
<p>There are some perhaps-not-coincidental coincidences: the question setup and section arrangement of the Islander Tea Chat (for example, in the Yang Yan interview, the questions are divided into “About Arknights,” “About Creation,” and “About Life”) share many similarities with the Tropic Line special interview section, which has been in use since August 2022.</p>
<p>Especially in the first two installments, the interviews with Yang Yan and Zc (in the latest installment most questions are marked as coming from netizens, so we set it aside for now), some questions not stated to be from netizens are almost word for word identical to Tropic Line's.</p>
<p>I fully understand that people doing this kind of interview can sometimes have very similar approaches, but similar approaches rarely produce identical questions and layouts. I also fully understand (and welcome) learning from predecessors' experience when writing, but could you perhaps let the original author know before learning from them?</p>
<p>This article only compares the <strong>Tropic Line special interviews</strong> (earliest August 2022; fan work) with the <strong>Skland Islander Tea Chat</strong> (earliest October 2023; official), to help readers better understand the similarities and differences between the two.</p>
<h2>Part I</h2>
<p>| Skland “Islander Tea Chat” Issue 1: Magic Zc Directory (October 30, 2023) | <em>Tropic Line</em> |
| :</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="日常"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2024-02-12T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">TO DO LIST</title>
    <id>https://leisiyu.dev/en/sp/ToDo.html</id>
    <link href="https://leisiyu.dev/en/sp/ToDo.html"/>
    <updated>2026-10-14T18:38:24.266Z</updated>
    <summary type="html"><![CDATA[<p>Gu↗gu↘gu↗↗↗</p>
]]></summary>
    <content type="html"><![CDATA[<p>Gu↗gu↘gu↗↗↗</p>
<!-- more -->
<p class="textkai">I'm just a student doing this out of love, and I have no obligation to maintain any project or guarantee its availability.</p>
<h2>Projects in Progress</h2>
<p>Timberborn Steam Workshop mod AI Chinese localization v2.2 with multi-version support. (Current progress: pie in the sky[x] - refactor release system build scripts[x] - automatic version support - AI data aggregation updates)</p>
<p>epilogue: a desktop AI file workflow, local-first, with multi-provider failover and a lightweight tray app. Let AI understand and organize your files and help you remember them. (In progress)</p>
<h2>Projects Under Maintenance</h2>
<p>Aneot_Alpha: provides web updates for the Arknights fan magazine Return Line. ) (Full support)</p>
<p>Timberborn Mods Universal Translate: AI translation v2 for Timberborn Steam Workshop mods. (Full support)</p>
<p>LRC: V-universe lyrics site, a lyrics archive. (Full support)</p>
<p>Waline On Worker: an implementation of the Waline comment system on Cloudflare Workers. (Full support)</p>
<p>UofT-Tools: a toolset for University of Toronto students. (Full support)</p>
<p>Stellaris-DLC-Unlocker (Only zhCN translates support)</p>
<p>MyUserScript: personal user scripts (Only bugs fix)</p>
<p>rdpwrap_AutoUpdate_CN: RDP Wrapper Autoupdate, Chinese localized version (Only bugs fix)</p>
<h2>Completed Projects</h2>
<p>Waline Auto update: automatic updates for the open-source comment system Waline (Finished on Nov 26, 2024)</p>
<p>Satisfactory Dedicated Server: a daemon for Satisfactory v1.0 that handles the erroneous closing of UDP connections (Finished on Nov 17, 2024)</p>
<p>Keep Outlook Running Installer: keeps Outlook Classic running in the background and registers plugins (Finished on Nov 2, 2024)</p>
<p>7D2D CVTI MOD Part I: Chinese localization of the main materials mod completed (Finished on Apr 30, 2024)</p>
<p>Audio-Video-Merger: a batch + ffmpeg audio/video merging script for Bilibili Evolved, used to merge downloaded original audio tracks with video (Finished on Dec 7, 2023)</p>
<p>PRTS_cursor Public: a cursor pack with the Arknights PRTS theme (Finished on Jul 19, 2023)</p>
<p>rdpwrap_AutoUpdate_CN: RDP Wrapper Autoupdate, enhanced Chinese localized version (Finished on May 28, 2023)</p>
<h2>Projects No Longer Supported</h2>
<p>MAAResUpdater: MAA now has a built-in GitHub source for direct updates (End Support on Apr 12, 2025)</p>
<p>Timberborn Mods Universal zhCN Translate: AI Chinese localization v1 for Timberborn Steam Workshop mods. (End Support on Dec 31, 2024, now it is v2)</p>
<p>LiteLoaderQQNT-HighlightReplies: LLQQNT changed its loader method and I have no time to provide updates; the related features have been merged into the lightweight toolbox. (End Support on Mar 3, 2024)</p>
<p>MagiskOnWSAOnlineBuild: follow-up maintenance plan; WSA has been abandoned by Microsoft (End Support on Jan 12, 2024)</p>
<h2>Abandoned Projects</h2>
<p>Helldiver 2 OCR/settings hybrid stratagem tool: HDR support is a niche need and conflicts with the overall OCR design. (Canceled)</p>
<p>StarRail key-automation script: hard to write, and not worth the focus it takes up (Canceled)</p>
<p>Researching PCRS to improve its efficiency and front-end experience. I don't use this thing anymore <s>a userjs would more or less do the job</s>. (Canceled)</p>
<p>Providing full Chinese localization for the other 7D2D CVTI MOD modules (no new server plans for now) (Canceled)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">News</title>
    <id>https://leisiyu.dev/en/sp/Update.html</id>
    <link href="https://leisiyu.dev/en/sp/Update.html"/>
    <updated>2026-10-14T18:38:24.267Z</updated>
    <summary type="html"><![CDATA[<p>What happen?</p>
]]></summary>
    <content type="html"><![CDATA[<p>What happen?</p>
<!-- more -->
<h2>2025/11/29</h2>
<p>Redesigned the OpenList extension features and UI.</p>
<p>OpenList now supports smart path repair.</p>
<h2>2025/11/28</h2>
<p>iCloud disclaimer and data updates.</p>
<h2>2025/11/15</h2>
<p>The music service Music-Tag-Web v2 has completed its feature expansion and permission control design.</p>
<h2>2025/11/12</h2>
<p>The music service Music-Tag-Web v2 has switched its database to MySQL.</p>
<h2>2025/11/11</h2>
<p>The music service Music-Tag-Web v2 has completed its security patch.</p>
<h2>2025/11/10</h2>
<p>The music service has switched from Navidrome to Music-Tag-Web v2.</p>
<h2>2025/9/29</h2>
<p>Optimized the size of some resources to speed up loading.</p>
<h2>2025/09/23</h2>
<p>Music service Navidrome v0.55.1 -&gt; v0.58.0 Latest</p>
<h2>2025/09/22</h2>
<p>The cloud drive upload API now uploads directly to the VPS, which should significantly increase the maximum upload speed.</p>
<h2>2025/09/15</h2>
<p>Timberborn mod translation updates are now handled entirely through compilation, which should prevent issues that cause the game to crash.</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">G502(X) Universal Shooter Game Macro V2</title>
    <id>https://leisiyu.dev/en/t/Ghub_Shoot_game_Macros.html</id>
    <link href="https://leisiyu.dev/en/t/Ghub_Shoot_game_Macros.html"/>
    <updated>2026-10-14T18:38:24.269Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">Universal Shooter Game Macro for G502/G502X</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">Universal Shooter Game Macro for G502/G502X</p>
<!-- more -->
<p>Tested only on the G502X, using G HUB version 2025.2.687008.</p>
<p>G HUB must be installed. Other Logitech mice may be compatible after the key bindings are modified.</p>
<h3>Introduction</h3>
<p>Use the mouse wheel's left G10 (-) and right G11 (+) to control the strength of the automatic recoil compensation.</p>
<p>Hold the shooting precision key G6 to switch between adjusting vertical/horizontal recoil; press it to display the current rate and working status in the console; double-click it to reset to default values.</p>
<p>Use the memory switch key G9 to turn this macro on or off.</p>
<p>The base code is adapted from Bilibili user @第一局永远tec-9.</p>
<h3>About Copyright</h3>
<p>The original author has declared that they waive their copyright and have released the work to the public, but this modified version retains its copyright and is licensed under the Attribution-NonCommercial-ShareAlike 4.0 International license (CC BY-NC-SA 4.0).</p>
<p>Definition of commercial use:</p>
<p>Without the author's explicit permission, you may not sell, license, or otherwise charge a fee for this code, including but not limited to selling the software or incorporating it into a commercial product to generate profit (for example, charging for use or requiring follows/subscriptions).</p>
<h3>Code</h3>
<div class="language-lua line-numbers-mode" data-highlighter="shiki" data-ext="lua" data-title="lua" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">EnablePrimaryMouseButtonEvents</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- ===== 用户可调参数（常量） =====</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- 按键映射</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_TOGGLE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">   = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">9</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   -- 总开关（按一次切换 ON/OFF）</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_MODE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">     = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">5</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   -- 调整模式（按住进入水平调整，释放退出）</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_INCREASE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">8</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   -- 增加速度（垂直或水平）</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_DECREASE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">7</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   -- 降低速度（垂直或水平）</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- 速度初始值及步长</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_SPEED</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">   = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">7.5</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">   -- 默认垂直速度</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_HORI</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.0</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    -- 默认水平速度</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">VERT_STEP</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1.5</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    -- 垂直调整步长</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">HORI_STEP</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    -- 水平调整步长</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- 双击重置阈值（毫秒）</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">DOUBLE_CLICK_MS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">300</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- 总开关默认状态true/false</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">k</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">     = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- ===== 运行状态变量（勿动） =====</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_SPEED</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_HORI</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">adjustHorizontal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">false</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lastPressMode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">-- ============================================</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">function</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> OnEvent</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#ABB2BF;--shiki-dark-font-style:italic">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#383A42;--shiki-light-font-style:inherit;--shiki-dark:#ABB2BF;--shiki-dark-font-style:italic">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    -- OutputLogMessage("Event: " .. event .. " Arg: " .. arg .. "\n")</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic">    -- 需要调整按键删除面一行的“-- ”保存后点击即可获得当前按键代号，替换设置中的对应值即可</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"MOUSE_BUTTON_PRESSED" </span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">and </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_TOGGLE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">        k</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = not </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">k</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> k</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> then</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"ON</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"OFF</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"MOUSE_BUTTON_PRESSED" </span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">and </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_MODE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        local</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> currentTime</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">GetRunningTime</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">()</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">currentTime</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">lastPressMode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &lt; </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">DOUBLE_CLICK_MS</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_SPEED</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">  = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_HORI</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            adjustHorizontal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">false</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Reset to default: vertical=%.1f, horizontal=%.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_SPEED</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">INIT_HORI</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            lastPressMode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            adjustHorizontal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">true</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Horizontal adjustment mode activated</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            lastPressMode</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">currentTime</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"MOUSE_BUTTON_RELEASED" </span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">and </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_MODE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">        adjustHorizontal</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">false</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Current vertical speed: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Current horizontal speed: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> k</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> then</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"ON</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">else</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"OFF</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"MOUSE_BUTTON_PRESSED" </span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">and </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_INCREASE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> adjustHorizontal</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> then</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">HORI_STEP</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Horizontal speed increased to: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">VERT_STEP</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Vertical speed increased to: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> (</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">event</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"MOUSE_BUTTON_PRESSED" </span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">and </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">arg</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> == </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">KEY_DECREASE</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> adjustHorizontal</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> then</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">HORI_STEP</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Horizontal speed decreased to: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        else</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">            speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> = </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">VERT_STEP</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">            OutputLogMessage</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"Vertical speed decreased to: %.1f</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">\n</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">, </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    if</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75"> k</span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD"> then</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">        Sleep</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        if</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IsMouseButtonPressed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            if</span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF"> IsMouseButtonPressed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">then</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                MoveMouseRelative</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">math.floor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">), </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">math.floor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                repeat</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    Sleep</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">                    MoveMouseRelative</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">math.floor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">hori</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">), </span><span style="--shiki-light:#0184BC;--shiki-dark:#56B6C2">math.floor</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">speed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> + </span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">0.5</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">))</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">                until</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> not </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">IsMouseButtonPressed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">1</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">) or not </span><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">IsMouseButtonPressed</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">(</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66">3</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">)</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">            end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">        end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">    end</span></span>
<span class="line"><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">end</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>This article is original content by the author Siyu Lei. When reposting, please credit the source and include a link to the original article. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2026-06-24T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">epilogue — A Desktop AI File Workflow</title>
    <id>https://leisiyu.dev/en/t/epilogue.html</id>
    <link href="https://leisiyu.dev/en/t/epilogue.html"/>
    <updated>2026-10-14T18:38:24.275Z</updated>
    <summary type="html"><![CDATA[<p class="textkai"><strong>files, remembered.</strong> No information is collected, and all data stays on your device.</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai"><strong>files, remembered.</strong> No information is collected, and all data stays on your device.</p>
<!-- more -->
<h2>What It Is</h2>
<p>epilogue is a desktop AI file workflow app that runs on macOS / Windows / Linux. Its core design philosophy is "local-first": configuration, indexes, and vectors are all stored on your device, and audio/video transcription is done locally by default, so audio never leaves your device.</p>
<h2>What It Can Do</h2>
<p><strong>Clean up</strong>: Periodically scans for stale files that haven't been touched in a long time, and the AI offers filing suggestions based on your natural-language habits, which you confirm item by item before anything is moved. It understands multi-part content (course material series, portable software, TV series) and archives it as a whole, making use of the multi-level structure of the destination folder.</p>
<p><strong>Find</strong>: "Where did I put last semester's lab report?" Retrieve a file with a single sentence—three modes are available: keyword / similarity / AI Q&amp;A. You can describe an image in words to find it, and relative times such as "last year" or "last week" are understood.</p>
<p><strong>Assistant</strong>: A built-in conversational agent that can change settings, turn your habits into rules ("from now on, put invoices in Finance/"), and look up files.</p>
<p><strong>Optional automation</strong> (off by default, can only be enabled manually): Solo mode automatically files things on a schedule without requiring approval; the AI can be allowed to move worthless temporary files to the system recycle bin.</p>
<h2>Multi-Provider AI Failover Architecture</h2>
<p>Each AI capability is a <strong>failover list</strong> (drag to reorder, enable per row, one-click test) that is tried in order from top to bottom:</p>
<p>| Capability | Built-in Presets |
|</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="开源项目"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2026-06-11T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Waline On Worker — A Cloudflare Workers Comment System</title>
    <id>https://leisiyu.dev/en/t/Waline_On_Worker.html</id>
    <link href="https://leisiyu.dev/en/t/Waline_On_Worker.html"/>
    <updated>2026-10-14T18:38:24.280Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">A Cloudflare Workers implementation of the Waline comment system. Serverless and free to deploy.</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">A Cloudflare Workers implementation of the Waline comment system. Serverless and free to deploy.</p>
<!-- more -->
<h2>What Is It</h2>
<p>Waline On Worker is a backend implementation that fully ports the open-source comment system Waline to the Cloudflare Workers platform, using D1 (SQLite) for data storage.</p>
<p>Compared with the official Vercel deployment, it:</p>
<ul>
<li>Requires no standalone server and runs on Cloudflare's edge network</li>
<li>Offers a generous free tier, which suits personal blogs</li>
<li>Is fully compatible with the <code>@waline/client</code> frontend and the <code>@waline/admin</code> admin panel</li>
</ul>
<h2>Tech Stack</h2>
<p>| Item | Choice |
|</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="开源项目"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2026-06-05T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">UofT-Tools — A Toolkit for University of Toronto Students</title>
    <id>https://leisiyu.dev/en/t/UofT_Tools.html</id>
    <link href="https://leisiyu.dev/en/t/UofT_Tools.html"/>
    <updated>2026-10-14T18:38:24.282Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">An unofficial open-source project: a collection of practical tools for UofT students.</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">An unofficial open-source project: a collection of practical tools for UofT students.</p>
<!-- more -->
<h2>What Is It</h2>
<p>UofT-Tools is an open-source toolkit for students at the University of Toronto, deployed at uoft.voidcarve.com.</p>
<p><strong>Disclaimer</strong>: This is an independent student project and is not affiliated with the University of Toronto in any way. For important information, please refer to the university's official website.</p>
<h2>Included Tools</h2>
<ul>
<li><strong>Course Calendar</strong>: Automatically syncs term course and exam schedules, with support for importing into iCal / Google Calendar</li>
<li><strong>Term Planner</strong>: A tool to help with course selection and time planning</li>
</ul>
<h2>Technical Architecture</h2>
<p>| Layer | Choice |
|</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="开源项目"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2026-04-03T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Timberborn Mods Universal Translate — AI Translation Framework v2 for Timberborn Mods</title>
    <id>https://leisiyu.dev/en/t/Timberborn_Mods_Universal_Translate.html</id>
    <link href="https://leisiyu.dev/en/t/Timberborn_Mods_Universal_Translate.html"/>
    <updated>2026-10-14T18:38:24.284Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">An AI translation framework for Timberborn Steam Workshop mods, with automated multilingual localization.</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">An AI translation framework for Timberborn Steam Workshop mods, with automated multilingual localization.</p>
<!-- more -->
<h2>What Is It</h2>
<p>Timberborn Mods Universal Translate is an AI-powered automatic translation framework (v2) for Steam Workshop mods of the Steam game <em>Timberborn</em>, aiming to help community mods quickly support multiple languages.</p>
<p>This is a complete rewrite of the v1 version (zhCN), upgraded from a Chinese-only localization to a universal multilingual framework.</p>
<h2>Features</h2>
<ul>
<li><strong>Multilingual support</strong>: Not limited to Chinese; extensible to any language</li>
<li><strong>AI-driven translation</strong>: Automatically processes mod localization files in batches</li>
<li><strong>Automatic multi-version support</strong>: Automatically adapts to mods across different game versions</li>
<li><strong>Automated release workflow</strong>: Rebuilt build and release scripts, with fully automated CI/CD</li>
<li><strong>Continuous updates</strong>: Subscribe on the Steam Workshop to automatically receive the latest translations</li>
</ul>
<h2>Progress</h2>
<p>The v2 framework has been released and continues to be iterated on (current version v2026.6.x), and the data AI aggregation update feature is currently in development.</p>
<p>GitHub Repository</p>
<p>This article is original content by the author Siyu Lei. If you repost it, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="开源项目"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2025-11-21T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">V Universe Lyrics Hub (LRC)</title>
    <id>https://leisiyu.dev/en/t/LRC.html</id>
    <link href="https://leisiyu.dev/en/t/LRC.html"/>
    <updated>2026-10-14T18:38:24.285Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">A navigation hub for virtual singer album information and a shared repository for storing LRC lyric files.</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">A navigation hub for virtual singer album information and a shared repository for storing LRC lyric files.</p>
<!-- more -->
<h2>What Is It</h2>
<p>V Universe Lyrics Hub is a site dedicated to collecting and sharing lyrics for V-family (virtual singer) albums, with version control and community collaboration maintained through a GitHub repository.</p>
<h2>Features</h2>
<ul>
<li><strong>Album navigation</strong>: Organized by album, with support for quick search</li>
<li><strong>Multiple download options</strong>: Download the entire library, a single album package, or a single song</li>
<li><strong>LRC format</strong>: A standard lyrics format compatible with mainstream players and lyrics plugins</li>
<li><strong>Ongoing additions</strong>: Dozens of albums are currently included, covering V-family singers such as Yanhe and Luo Tianyi</li>
</ul>
<h2>Included Albums (Partial List)</h2>
<p>SEVEN, 溯流, 维·爱 L'amouЯ, 光年回响, 九光年宇宙, Twilights EP, 深空余音, 终梦 Journeyed on Everdream, 夏浪派对 2025, 秘宝旅人 II Polaris...</p>
<p>See the GitHub repository for the full list.</p>
<p>GitHub Repository | Site</p>
<p>This article is original content by the author, Siyu Lei. If you repost it, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="开源项目"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2025-09-19T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Fix for G Hub Not Switching Profiles in Rainbow Six</title>
    <id>https://leisiyu.dev/en/t/GHubRainbowSixSiege.html</id>
    <link href="https://leisiyu.dev/en/t/GHubRainbowSixSiege.html"/>
    <updated>2026-10-14T18:38:24.286Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">The first detailed repair tutorial online</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">The first detailed repair tutorial online</p>
<!-- more -->
<h2>1. Preparation</h2>
<p>You need any editor that can edit DB files. If you don't have one, you can download DB Browser for SQLite (choose the no-installer portable version).</p>
<p>This tutorial is written for DB Browser for SQLite; other editors work similarly.</p>
<p>Extract the archive and open <code>DB Browser for SQLite.exe</code></p>
<p>Exit G HUB.</p>
<h2>2. Open G Hub settings.db</h2>
<p>Press <code>ctrl + O</code> - type into the address bar: <code>C:%homepath%\AppData\Local\LGHUB\</code> and press Enter.</p>
<p>First right-click <code>settings.db</code>, copy it, and paste it to any safe location (backup).</p>
<p>Select the file <code>settings.db</code> and open it.</p>
<h2>3. Open the saved configuration</h2>
<p>Switch to <code>浏览数据（B）</code> and click the cell for the file with id 1 (displayed as <code>{...</code>).</p>
<p>The data will be shown in the window on the right. Select that window.</p>
<h2>4. Remove the erroneous data</h2>
<p>Press <code>ctrl + F</code> and search for the keyword rainbow.</p>
<p>Delete all rainbow six siege entries under <code>APPLICATION_NAME_DESKTOP</code>. In the end it should look like <code>[]</code>. If there are other items that are not Rainbow Six, make sure the last entry is not followed by <code>,</code></p>
<h2>5. Write changes</h2>
<p>Click the _date_created cell corresponding to id 1. You will be asked whether to save; click Save.</p>
<p>Then click <code>写入更改（W）</code> at the top, and close <code>DB Browser for SQLite</code></p>
<h2>6. Restart G HUB</h2>
<p>Restart G HUB from the Start menu. Normally it won't report data corruption; if it does, let it repair itself, and if it can't be repaired, replace the file with your backup.</p>
<p>If you can't figure it out, look up JSON syntax or ask ChatGPT.</p>
<h2>7. ENJOY GAME</h2>
<p>Thanks to G HUB not switching profiles - Reddit for mentioning the solution of repairing the config database.</p>
<p>However, the original post is too vague and doesn't give detailed repair steps.</p>
<p><s>Which intern at G HUB wrote this damn bug? The GUI is even completely invisible.</s></p>
<p>This article is original content by the author Siyu Lei. When reposting, please credit the source and include a link to the original article. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2024-12-04T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Outlook Enhancement Guide</title>
    <id>https://leisiyu.dev/en/t/Outlook.html</id>
    <link href="https://leisiyu.dev/en/t/Outlook.html"/>
    <updated>2026-10-14T18:38:24.289Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">Keeping the Desktop Version Running in the Background &amp; Disabling the Junk Mail Filter</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">Keeping the Desktop Version Running in the Background &amp; Disabling the Junk Mail Filter</p>
<!-- more -->
<h2>Keeping the classic version running in the background with a plugin</h2>
<p>For some mysterious reason, Microsoft doesn't let Outlook run persistently in the background. Often my phone has already received an email, but I still have to go check manually on my computer.</p>
<p>Currently, the only solutions are two plugins: KeepOutlookRunning (open source and free) and QuickTweaks (paid, $19.95).</p>
<p>The open-source plugin KeepOutlookRunning has a problem where it gets dropped after Office updates, so I built on it to develop KeepOutlookRunningInstaller, which avoids the problem by registering Office and the plugin DLL.</p>
<p>The corresponding installer is available for download.</p>
<p>Just double-click to install. During installation, an internet connection is required to fetch the DLL from GitHub.</p>
<p>QuickTweaks is paid ($19.95), and I don't recommend it.</p>
<h2>Disabling the junk mail filter with Microsoft Power Automate</h2>
<p>Microsoft bizarrely forces every personal/work mailbox to use its junk mail filtering system, which has an extremely high false-positive rate, making it necessary to dig through the junk folder. As far as I can tell, this feature does nothing except make me miss notifications. <s>Damn it, how do you even block UofT's own emails</s></p>
<p>There's no option to turn it off, so the only way is to work around it indirectly using Microsoft's own automation.</p>
<p>Log in to Power Automate.</p>
<p>Create - Outlook - When a new email arrives.</p>
<p>Grant access to the relevant mailbox.</p>
<p>For "When a new email arrives," set the folder to Junk Email.</p>
<p>Add the action "Move email" - Message ID (select the ID from the previous step) - Folder (Inbox).</p>
<p>Save, and you're done.</p>
<p>This way, whenever a new email lands in the junk folder, it is automatically moved to the inbox, though a few seconds slower than receiving it directly.</p>
<p>Microsoft Power Automate is also a Microsoft product, so in theory there shouldn't be any security concerns.</p>
<p>This article is original content by the author, Siyu Lei. If you repost it, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2024-11-27T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Automatically Update Waline with a GitHub Action</title>
    <id>https://leisiyu.dev/en/t/Waline_Update.html</id>
    <link href="https://leisiyu.dev/en/t/Waline_Update.html"/>
    <updated>2026-10-14T18:38:24.290Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">Every time Waline shows a notice that an update is available, it's usually a compatible update, and it may also include security fixes. Staying current can only help, so I came up with a way to update automatically.</p>
<h2>Trigger a Vercel update through a GitHub repository update</h2>]]></summary>
    <content type="html"><![CDATA[<p class="textkai">Every time Waline shows a notice that an update is available, it's usually a compatible update, and it may also include security fixes. Staying current can only help, so I came up with a way to update automatically.</p>
<h2>Trigger a Vercel update through a GitHub repository update</h2>
<h3>1. Make sure your Vercel Project is connected to the repository</h3>
<p>If it isn't connected, you can create the repository connection manually.</p>
<h3>2. Change Package.json to the latest version</h3>
<p>This saves you the trouble of filling in a version number. You can also set this up without a workflow.</p>
<p>In package.json, change it to:</p>
<div class="language-json line-numbers-mode" data-highlighter="shiki" data-ext="json" data-title="json" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"@waline/vercel"</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">"latest"</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><h3>3. Workflow trigger</h3>
<p>Permissions are minimized: it only requests contents: write (required for committing), and no additional token is needed. Because it makes commits, the action is automatically kept alive, so it won't be disabled automatically after six months of inactivity.</p>
<p>The principle is to use the GITHUB_TOKEN, which has write permission, to push a completely empty commit, which triggers an automatic Vercel deployment.</p>
<p>The default cron schedule is once a month.</p>
<p>Create a new file /.github/Auto_update.yml:</p>
<div class="language-yml line-numbers-mode" data-highlighter="shiki" data-ext="yml" data-title="yml" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Trigger Vercel Deployment</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#986801;--shiki-dark:#D19A66">on</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  schedule</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">cron</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">'0 0 1 * *'</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  workflow_dispatch</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">permissions</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  contents</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">write</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">jobs</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">  trigger-vercel</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    runs-on</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">ubuntu-latest</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">    steps</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">:</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Checkout repository</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      uses</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">actions/checkout@v3</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Configure Git</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      run</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">|</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">        git config user.name "github-actions[bot]"</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">        git config user.email "github-actions[bot]@users.noreply.github.com"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Create an empty commit</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      run</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">git commit --allow-empty -m "Trigger Vercel deployment"</span></span>
<span class="line"></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">    - </span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">name</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">Push changes</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">      run</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">: </span><span style="--shiki-light:#A626A4;--shiki-dark:#C678DD">|</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">        git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}.git</span></span>
<span class="line"><span style="--shiki-light:#50A14F;--shiki-dark:#98C379">        git push origin HEAD</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><h2>Other approaches</h2>
<p>These approaches should work in theory, but I haven't tried them because of the hassle or permission management issues.</p>
<ul>
<li>
<p>Configure a scheduled task in vercel.json to trigger it. I didn't pursue this because I couldn't quite figure out how to call the API.</p>
</li>
<li>
<p>Send the Vercel deployment command directly from the Action. This involves extra token permission management, and compared with pushing an empty commit it doesn't seem to offer any particular advantage. It would only add configuration complexity and security risk (after all, it would be a long-lived token).</p>
</li>
</ul>
<p>This article is original content by the author, Siyu Lei. When republishing, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2024-11-26T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">A Brief Note on Setting Up FRP in North America</title>
    <id>https://leisiyu.dev/en/t/buildfrp.html</id>
    <link href="https://leisiyu.dev/en/t/buildfrp.html"/>
    <updated>2026-10-14T18:38:24.293Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">A Lightweight Personal FRP Service Setup Tutorial</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">A Lightweight Personal FRP Service Setup Tutorial</p>
<!-- more -->
<p>If you're in mainland China, you don't need this—SakuraFrp is enough. If you want to self-host, this can still serve as a reference.</p>
<p>Frp is a lightweight reverse proxy tool that can map internal network services to the public internet, enabling NAT traversal.</p>
<p>This is probably the cheapest NAT traversal solution I've found. You can use it to deploy remote desktop, FTP file transfer, or a Minecraft server, and so on.</p>
<p>What you'll need:</p>
<ul>
<li>A VPS (usually priced at around 15-30 CNY/month)</li>
<li>A domain name (optional; a .com usually costs around 75-100 CNY/year)</li>
<li>Xshell (or another SSH management tool)</li>
<li>Xftp (or another file transfer tool)</li>
</ul>
<p>For the provider I chose IONOS. I picked the cheapest $2/month VPS, with the specs (1 vCore CPU, 1 GB RAM, 10 GB SSD storage, 1 Gbit/s unlimited traffic), which is more than enough for a personal FRP setup. (About 15 CNY/month.)</p>
<p>IONOS Speedtest results with frp running: Hosted by Clouvider Ltd (New York, NY) [6199.77 km], Download: 1557.67 Mbit/s - 2678.73 Mbit/s; Upload: 886.07 Mbit/s - 1017.50 Mbit/s (multiple tests).</p>
<p>This is recommended for North America only; for other regions, please look elsewhere.</p>
<p>For the server operating system I chose Ubuntu. After purchasing, just wait a little while for it to be provisioned, then connect to the server with Xshell and enter your username and password. (I was too lazy to change the password, so I left it as it is.)</p>
<p>To install FRP, download the Linux version of the FRP files from GitHub, extract them, and connect to the server with Xftp.</p>
<p>Use Xftp to manually upload the frps binary to /usr/bin/, then write an ini file wherever you like. Mine is at /etc/frp/frps.ini, with the following content:</p>
<div class="language-ini line-numbers-mode" data-highlighter="shiki" data-ext="ini" data-title="ini" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">[common]</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># frp对客户端的服务端口</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">bind_port</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {frp-port}</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># token，客户端会用到，改的复杂些</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">token</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {token}</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 访问frp客户端web服务的端口</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">vhost_http_port</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {web-port}</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># pool_count（下限），max_pool_count（上限）</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">max_pool_count</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> 50</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># tcp流多路复用，默认为true</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">tcp_mux</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> true</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> </span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># frp管理后台端口</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">dashboard_port</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {dashboard-port}</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># frp管理后台用户名和密码</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">dashboard_user</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {admin}</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">dashboard_pwd</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> {password}</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 允许服务监控</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">enable_prometheus</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> true</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># frp日志配置</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">log_file</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> /srv/frp/log</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">log_level</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> info</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">log_max_days</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> 3</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Replace {frp-port}, {token}, {web-port}, {dashboard-port}, {admin}, and {password} with your own ports and account credentials.</p>
<p>Create the log folder yourself; it just needs to have the right permissions.</p>
<p>Then go to the IONOS VPS console, find the firewall, and open all of the ports above, or simply turn the firewall off (not that highly recommended, but if you're only running frp, turning it off is the easier option).</p>
<p>Then enter the following commands on the server:</p>
<div class="language-shell line-numbers-mode" data-highlighter="shiki" data-ext="shell" data-title="shell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">nohup</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> frps</span><span style="--shiki-light:#986801;--shiki-dark:#D19A66"> -c</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> ini文件路径</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> &amp;</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Try logging in to the dashboard at the assigned IP, on port {dashboard-port}, with the username and password {admin} and {password}. As long as you can log in, you're good.</p>
<p>Then create a systemd service at /etc/systemd/system/frps.service with the following content:</p>
<div class="language-ini line-numbers-mode" data-highlighter="shiki" data-ext="ini" data-title="ini" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">[Unit]</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 服务名称，可自定义</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">Description</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> frp server</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">After</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> network.target syslog.target</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">Wants</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> =</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> network.target</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> </span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">[Service]</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 启动失败后重启服务</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">Restart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379">on-failure</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 重启间隔时间</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">RestartSec</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379">5</span></span>
<span class="line"><span style="--shiki-light:#A0A1A7;--shiki-light-font-style:italic;--shiki-dark:#7F848E;--shiki-dark-font-style:italic"># 修改为自己的frp目录，注意是frps</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">ExecStart</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379">/usr/bin/frps -c /etc/frp/frps.ini</span></span>
<span class="line"><span style="--shiki-light:#383A42;--shiki-dark:#98C379"> </span></span>
<span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">[Install]</span></span>
<span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#C678DD">WantedBy</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF">=</span><span style="--shiki-light:#383A42;--shiki-dark:#98C379">multi-user.target</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>Then enable the service to start on boot:</p>
<div class="language-shell line-numbers-mode" data-highlighter="shiki" data-ext="shell" data-title="shell" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#4078F2;--shiki-dark:#61AFEF">systemctl</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> enable</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> frps</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Then reboot the server and check whether it starts automatically. If everything works, you won't need to touch this server again except to renew it.</p>
<p>If you have a domain name, you can configure a subdomain A record pointing to the server IP, like mine: frp.wuyilingwei.com.</p>
<p>Then download the frp client for your platform. On Windows you can try Frp GUI; just configure it with the matching token and the domain + port. Remember to open the firewall after configuring.</p>
<p>Your low-cost North American FRP service is now set up. The average monthly cost is 15 CNY (or $2, with PayPal supported), with 1 Gbps bandwidth, a dedicated IP, and unlimited traffic.</p>
<p>This article is original content by the author Siyu Lei. If you repost it, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2024-01-26T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Stellaris: How to Install the Colorful Galaxy Mod</title>
    <id>https://leisiyu.dev/en/t/Colorful_Galaxy.html</id>
    <link href="https://leisiyu.dev/en/t/Colorful_Galaxy.html"/>
    <updated>2026-10-14T18:38:24.296Z</updated>
    <summary type="html"><![CDATA[<p>Stellaris NSFW Mod "Colorful Galaxy": Installation and How to Open the Menu</p>
]]></summary>
    <content type="html"><![CDATA[<p>Stellaris NSFW Mod "Colorful Galaxy": Installation and How to Open the Menu</p>
<!-- more -->
<p>*This tutorial only applies to the Steam version of Stellaris. Due to the publication date, some content may not match the current situation.</p>
<h2>Installation</h2>
<p>Press Win+R, enter <code>steam://open/console</code>, and press Enter to open the Steam console. Enter <code>workshop_download_item 281990 2923834739</code>, press Enter, and wait for the resource pack <em>Selflessness Was Never You, Following Him Without Understanding Her</em> to finish downloading. Then enter <code>workshop_download_item 281990 2748029219</code>, press Enter, and wait for the script pack <em>Colorful Galaxy</em> to finish downloading. Once the downloads are complete, close the console.</p>
<p>Launch the game and make sure the mods are enabled in your playset, with the resource pack placed before the script pack.</p>
<p>Start the game, enjoy it!</p>
<h2>Opening the NSFW Menu</h2>
<p>Go to Stellaris - Government - Edicts, and you will see a one-day edict that only costs 5 gems to activate.</p>
<p>*Note: look carefully at the Star Sea Commonwealth edict and don't click it by mistake, or it will directly start a war.</p>
<p>I slacked off for so long before remembering to update my blog. Sure enough, NSFW content really is the number one driver of productivity (runs away)</p>
<p>This article is original content by the author Siyu Lei. Please credit the source and include a link to the original when reposting. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="游戏"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2023-09-18T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">OneDrive Enhancement Guide</title>
    <id>https://leisiyu.dev/en/t/OneDrive_Link.html</id>
    <link href="https://leisiyu.dev/en/t/OneDrive_Link.html"/>
    <updated>2026-10-14T18:38:24.298Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">Sync Any Folder</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">Sync Any Folder</p>
<!-- more -->
<p>First, press Win+R, type <code>cmd</code>, and click OK while holding Shift+Ctrl to open a command prompt with elevated privileges. (If done correctly, you will see a UAC prompt and the word "Administrator" in the title bar.)</p>
<p>Press Win+E to open File Explorer, right-click the OneDrive folder, click Properties, and copy the path from the address bar.</p>
<p>Use the following command to link the folder you want to the OneDrive folder, for example:</p>
<div class="language-cmd line-numbers-mode" data-highlighter="shiki" data-ext="cmd" data-title="cmd" style="--shiki-light:#383A42;--shiki-dark:#abb2bf;--shiki-light-bg:#FAFAFA;--shiki-dark-bg:#282c34"><pre class="shiki shiki-themes one-light one-dark-pro vp-code"><code><span class="line"><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">mklink</span><span style="--shiki-light:#383A42;--shiki-dark:#ABB2BF"> /</span><span style="--shiki-light:#E45649;--shiki-dark:#E06C75">D</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "{OneDrive文件夹路径}\{OneDrive文件夹中的相对路径}"</span><span style="--shiki-light:#50A14F;--shiki-dark:#98C379"> "{你要链接的文件夹路径}"</span></span></code></pre>
<div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0"><div class="line-number"></div></div></div><p>Replace {} and the content inside it with your own path.</p>
<p>This uses the Windows symbolic link feature, which lets you link a folder to another location while it still appears in File Explorer as the original folder.</p>
<p>You can link a folder to another location without moving it, for example adding it to the OneDrive folder for easier syncing.</p>
<p>Type <code>mklink /?</code> in the command prompt to see more usage options.</p>
<p>This article is original content by the author Siyu Lei. If you repost it, please credit the source and include a link to the original. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2023-09-18T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
  <entry>
    <title type="text">Automatically Building Windows Subsystem for Android with Root and Google Play</title>
    <id>https://leisiyu.dev/en/t/WSA.html</id>
    <link href="https://leisiyu.dev/en/t/WSA.html"/>
    <updated>2026-10-14T18:38:24.299Z</updated>
    <summary type="html"><![CDATA[<p class="textkai">MagiskOnWSAOnlineBuild</p>
]]></summary>
    <content type="html"><![CDATA[<p class="textkai">MagiskOnWSAOnlineBuild</p>
<!-- more -->
<h2>Preface</h2>
<p>This project is based on Magisk on WSA (with Google Apps). That repository <s>in ancient times</s> once offered automated deployment through GitHub Actions.</p>
<p>However, because it became so popular and had so many forks, the repository was flagged for abusing GitHub Actions and was banned.</p>
<p>For many people, though, installing Linux or WSL and downloading the source code themselves is too difficult, and building it myself and copying it to friends is too much trouble.</p>
<h2>Usage</h2>
<p>Just download the latest Release.</p>
<h2>Solution</h2>
<p>So, after carefully reviewing the project structure, I used GitHub Actions to run the build, building through preset steps and uploading the result directly to a release, making it convenient for most people.</p>
<p>For now, requiring a GitHub Token should keep many people from simply forking it and using it directly, since you need to configure your own Token and repository path.</p>
<p>The workflow file also contains thorough comments, so it can be easily improved.</p>
<h2>Specific steps:</h2>
<ul>
<li>Install Git</li>
<li>Clone MagiskonWSA</li>
<li>Run the dependency installation script</li>
<li>Build the release</li>
<li>Download the GitHub CLI tool</li>
<li>Log in with the Token and publish a new release</li>
</ul>
<p>This article is original content by the author, Siyu Lei. When reposting, please credit the source and include a link to the original article. (leisiyu.dev)</p>
]]></content>
    <author>
      <name>Siyu Lei</name>
    </author>
    <category term="技术分享"/>
    <contributor>
      <name>Siyu Lei</name>
    </contributor>
    <published>2023-06-06T00:00:00.000Z</published>
    <rights>Copyright by Siyu Lei</rights>
  </entry>
</feed>