<?xml version="1.0" encoding="utf-8" standalone="yes"?><?xml-stylesheet type="text/xsl" href="/lib/rss/rss.xsl"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Yuesir</title>
    <link>https://vccv.cc/en/index.html</link>
    <description>Recent content on vccv.cc</description>
    <generator>Hugo</generator>
    <language>en</language>
    <lastBuildDate>Sat, 26 Jul 2025 21:05:47 +0800</lastBuildDate>
    <atom:link href="https://vccv.cc/en/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Building Flash Attention from Source</title>
      <link>https://vccv.cc/en/article/flash-attn-compile.html</link>
      <pubDate>Sat, 26 Jul 2025 21:05:47 +0800</pubDate>
      <guid>https://vccv.cc/en/article/flash-attn-compile.html</guid>
      <description>Notes from compiling Flash Attention on an A800 box. If you’re hitting endless build times or OOM “killed” errors, the key env vars and pitfalls here may save you time.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>Flash Attention is almost mandatory for LLM training and inference because of the speedup it brings. Usually <code>pip install flash-attn</code> is enough, but for specific hardware (e.g., A800) or bleeding-edge features you sometimes have to build from source.</p>
<p>After a few rounds of frustration, here’s the end-to-end process I used to build <code>flash-attn</code> from source on an A800 server, plus the traps to avoid.</p>
<h2 id="environment">Environment</h2>
<h3 id="hardwaresoftware">Hardware/Software</h3>
<ul>
<li><strong>Server</strong>: 64-core CPU, 512G RAM</li>
<li><strong>GPU</strong>: NVIDIA A800 80G (PCIe)</li>
<li><strong>CUDA</strong>: 12.2</li>
<li><strong>PyTorch</strong>: 2.7.1+cu118</li>
</ul>
<h3 id="official-readme">Official <a href="https://github.com/Dao-AILab/flash-attention" target="_blank" rel="noopener">README</a></h3>
<blockquote>
<p><strong>Requirements:</strong></p>
<ul>
<li>CUDA toolkit or ROCm toolkit</li>
<li>PyTorch 2.2 and above.</li>
<li><code>packaging</code> Python package (<code>pip install packaging</code>)</li>
<li><code>ninja</code> Python package (<code>pip install ninja</code>) *</li>
<li>Linux. Might work for Windows starting v2.3.2 (positive <a href="https://github.com/Dao-AILab/flash-attention/issues/595" target="_blank" rel="noopener">reports</a>), but Windows builds need more testing.</li>
</ul>
<p>* Make sure <code>ninja</code> is installed and works (<code>ninja --version</code> should exit 0). If not, reinstall (<code>pip uninstall -y ninja &amp;&amp; pip install ninja</code>). Without <code>ninja</code>, builds can take ~2h single-threaded; with <code>ninja</code>, 3–5 minutes on a 64-core box.</p>
<p><strong>To install:</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install flash-attn --no-build-isolation
</span></span></code></pre></td></tr></table>
</div>
</div><p>Or build from source:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">python setup.py install
</span></span></code></pre></td></tr></table>
</div>
</div><p>If your machine has less than 96GB RAM and lots of CPU cores, limit parallel jobs with <code>MAX_JOBS</code>.</p>
</blockquote>
<p>A small rant: “3–5 minutes on a 64-core machine” must be on some dream hardware…</p>
<h2 id="core-build-steps">Core Build Steps</h2>
<h3 id="upgrade-core-build-tools">Upgrade core build tools</h3>
<p>Keep <code>pip</code>, <code>wheel</code>, and <code>setuptools</code> current to dodge weird slowdowns.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install pip wheel setuptools -U
</span></span></code></pre></td></tr></table>
</div>
</div><p>Old <code>setuptools</code> can be painfully slow—ask me how I know.</p>
<h3 id="install-and-verify-ninja">Install and verify <code>ninja</code></h3>
<p>The README stresses <code>ninja</code>. Without it, the build falls back to single-threaded and drags on forever.</p>
<ol>
<li>
<p><strong>Install</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install ninja
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Verify</strong></p>
<p>The official check is <code>ninja --version</code> followed by <code>echo $?</code> for exit code 0. I prefer a visual check: start the build, open another terminal, run <code>htop</code>, and see dozens of <code>cicc</code>/<code>nvcc</code> processes pegging the CPUs. If not, reinstall <code>ninja</code> with <code>pip uninstall -y ninja &amp;&amp; pip install ninja</code>.</p>
<p><a href="/en/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp" data-fancybox="gallery" data-src="/en/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp" data-caption="Ninja enables multithreading">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/flash-attn-compile/QQ_1753589440483_hu_ac174cddc668ad3d.webp 480w, /en/article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp 720w, /en/article/flash-attn-compile/QQ_1753589440483_hu_f0014322694fb7e8.webp 960w, /en/article/flash-attn-compile/QQ_1753589440483_hu_529684eb3af8189e.webp 1440w, /en/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp 2662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2662"
                    height="986"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp"
                    srcset="/en/article/flash-attn-compile/QQ_1753589440483_hu_ac174cddc668ad3d.webp 480w, /en/article/flash-attn-compile/QQ_1753589440483_hu_8c818226d4cf0724.webp 720w, /en/article/flash-attn-compile/QQ_1753589440483_hu_f0014322694fb7e8.webp 960w, /en/article/flash-attn-compile/QQ_1753589440483_hu_529684eb3af8189e.webp 1440w, /en/article/flash-attn-compile/QQ_1753589440483_hu_846e30db22456e4e.webp 2662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Ninja enables multithreading"
                    
                />
            </picture>
        </a></p>
</li>
</ol>
<h3 id="set-critical-env-vars">Set critical env vars</h3>
<p>These variables decide whether the build succeeds and how fast.</p>
<ol>
<li>
<p><strong><code>FLASH_ATTN_CUDA_ARCHS</code>: limit architectures</strong></p>
<p>Tell the compiler which compute capability to target. A100 and A800 are compute capability <code>8.0</code>, so set it to <code>80</code>. Without it, the build will generate code for many architectures—wasting time.</p>
<ul>
<li><strong>Lookup</strong>: <a href="https://developer.nvidia.com/cuda-gpus" target="_blank" rel="noopener">NVIDIA CUDA GPUs</a></li>
</ul>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">FLASH_ATTN_CUDA_ARCHS</span><span class="o">=</span><span class="s2">&#34;80&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong><code>MAX_JOBS</code>: parallel build workers</strong></p>
<p>Controls how many CPU cores <code>ninja</code> uses. More cores = faster but also more RAM.</p>
<ul>
<li><strong>My run</strong>: On 64 cores / 512GB RAM, I set <code>MAX_JOBS=64</code>.</li>
<li><strong>Result</strong>: 64 cores maxed, peak RAM &gt;300GB, build took ~10–15 minutes. When RAM usage in <code>htop</code> drops, the build is almost done.</li>
<li><strong>Tip</strong>: If RAM is tighter, start with half the cores, e.g., <code>MAX_JOBS=32</code>.</li>
</ul>
</li>
</ol>
<h3 id="install">Install</h3>
<p>Combine everything and build:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">FLASH_ATTN_CUDA_ARCHS</span><span class="o">=</span><span class="s2">&#34;80&#34;</span> <span class="nv">MAX_JOBS</span><span class="o">=</span><span class="m">64</span> pip install flash-attn --no-build-isolation
</span></span></code></pre></td></tr></table>
</div>
</div><p><code>--no-build-isolation</code> is critical so the build process can see the env vars you exported in the current shell.</p>
<h2 id="troubleshooting">Troubleshooting</h2>
<ul>
<li>
<p><strong><code>g++: fatal error: Killed signal terminated program cc1plus</code></strong></p>
<ul>
<li>Cause: OOM (too many parallel jobs). Lower <code>MAX_JOBS</code> (e.g., 64 → 32 → 16).</li>
</ul>
</li>
<li>
<p><strong>GCC too new</strong></p>
<ul>
<li>
<p>At publish time, the build requires <code>gcc-11</code>/<code>g++-11</code>.</p>
</li>
<li>
<p>Fix (Ubuntu 22.04 example):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">apt install gcc-11 g++-11
</span></span><span class="line"><span class="cl">which gcc-11
</span></span><span class="line"><span class="cl">which g++-11
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CC</span><span class="o">=</span>/usr/bin/gcc-11
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CXX</span><span class="o">=</span>/usr/bin/g++-11
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
</li>
<li>
<p><strong>Build takes forever</strong></p>
<ul>
<li>Likely <code>ninja</code> isn’t actually used and the build is single-threaded. Verify/reinstall <code>ninja</code>.</li>
</ul>
</li>
<li>
<p><strong>CUDA-related build errors</strong></p>
<ul>
<li>Usually <code>FLASH_ATTN_CUDA_ARCHS</code> is wrong or PyTorch/CUDA toolkit versions don’t match. Double-check GPU model vs. compute capability, and compare <code>nvidia-smi</code> with <code>nvcc --version</code>.</li>
</ul>
</li>
</ul>
<h2 id="alternatives">Alternatives</h2>
<p>If source builds are too painful, try:</p>
<ol>
<li><strong>Prebuilt pip wheels</strong>: <code>pip install flash-attn</code> sometimes works out of the box, but versions may lag and hardware support isn’t guaranteed.</li>
<li><strong>conda</strong>: <code>conda install flash-attn -c conda-forge</code> might provide a prebuilt package.</li>
</ol>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/Dao-AILab/flash-attention" target="_blank" rel="noopener">Flash Attention on GitHub</a></p>
<p><a href="https://github.com/Dao-AILab/flash-attention/issues" target="_blank" rel="noopener">Issues in the official repo</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>VS Code for Remote Python Development</title>
      <link>https://vccv.cc/en/article/vscode-python-remote-development.html</link>
      <pubDate>Tue, 14 Jan 2025 17:12:58 +0800</pubDate>
      <guid>https://vccv.cc/en/article/vscode-python-remote-development.html</guid>
      <description>A quick guide to using VS Code with SSH for remote development, plus a plug for notebooks. Once you know the flow, spinning up a remote Python/Notebook workflow is incredibly convenient.</description>
      <content:encoded><![CDATA[<h2 id="straight-to-the-point">Straight to the Point</h2>
<p>Goal: use <a href="https://code.visualstudio.com" target="_blank" rel="noopener">Visual Studio Code</a> (aka <code>vscode</code>) to develop on a remote server over <strong>SSH</strong> with a local-like experience. Notebook support is especially smooth with the VS Code notebook extensions.</p>
<p>For consistency, I’ll use these terms:</p>
<ul>
<li>Visual Studio Code → <code>vscode</code></li>
<li>Remote server (usually Linux) → <strong>remote server</strong></li>
<li>Local machine (Windows/macOS/Linux) → <strong>host</strong></li>
<li><code>Remote-SSH</code> extension → <strong>remote extension</strong></li>
<li>Jupyter Notebook → <strong>notebook</strong></li>
<li>Extensions → <strong>plugins</strong></li>
</ul>
<p>VS Code’s success owes a lot to open source and a vibrant extension ecosystem. Remote development is powered by the <code>Remote-SSH</code> plugin.</p>
<p><a href="/en/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp" data-caption="Remote-SSH">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114172655999_hu_cd9ee5fc29b6dc23.webp 480w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp 720w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_f40b331df0e747ab.webp 960w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_5ea45bb823be981c.webp 1440w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1678"
                    height="414"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114172655999_hu_cd9ee5fc29b6dc23.webp 480w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_7865ced146d7f75a.webp 720w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_f40b331df0e747ab.webp 960w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_5ea45bb823be981c.webp 1440w, /en/article/vscode-python-remote-development/image-20250114172655999_hu_5ce2fe555b744b14.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Remote-SSH"
                    
                />
            </picture>
        </a></p>
<p>Remote dev isn’t limited to SSH:</p>
<ul>
<li>Windows host to local WSL</li>
<li>Local Docker containers</li>
<li>GitHub Codespaces</li>
</ul>
<p>First step: <a href="https://code.visualstudio.com/Download" target="_blank" rel="noopener">download VS Code</a> and install the remote extension. After installation, a remote icon appears in the lower-left corner.</p>
<blockquote>
<p>If the extension fails to install, update VS Code or reinstall.</p>
</blockquote>
<p><a href="/en/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp" data-caption="Install remote extension">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114180224389_hu_8e9c7eeb08ecd804.webp 480w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp 720w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_3d3faabe34fa564c.webp 960w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_cbc5330076ec159e.webp 1440w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114180224389_hu_8e9c7eeb08ecd804.webp 480w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_137351019c458612.webp 720w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_3d3faabe34fa564c.webp 960w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_cbc5330076ec159e.webp 1440w, /en/article/vscode-python-remote-development/image-20250114180224389_hu_cf5657df9b94a98e.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Install remote extension"
                    
                />
            </picture>
        </a></p>
<h2 id="configure-server-info">Configure Server Info</h2>
<p>Click the lower-left remote icon and choose the appropriate target. For SSH, pick <strong>Connect to Host</strong>. Two ways to configure:</p>
<h3 id="method-1-ssh-command">Method 1: ssh command</h3>
<p><a href="/en/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp" data-caption="SSH login">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114213238538_hu_dd58619068502464.webp 480w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp 720w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_e0f556e9645bae0f.webp 960w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_6a55ffc340d0770f.webp 1440w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114213238538_hu_dd58619068502464.webp 480w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_12163038dbb5b969.webp 720w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_e0f556e9645bae0f.webp 960w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_6a55ffc340d0770f.webp 1440w, /en/article/vscode-python-remote-development/image-20250114213238538_hu_d7b7690ef200342c.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="SSH login"
                    
                />
            </picture>
        </a></p>
<p>Enter a full <code>ssh</code> command directly. Replace <code>username</code> with your account, <code>host</code> with IP or domain, <code>port</code> with the SSH port. For a jump host, use <code>-J</code> with jump user/host/port.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Default port 22</span>
</span></span><span class="line"><span class="cl">ssh username@host:port
</span></span><span class="line"><span class="cl"><span class="c1"># Examples:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yuesir@127.0.0.1:22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yuesir@vccv.cc:22</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># With jump host</span>
</span></span><span class="line"><span class="cl">ssh username@host:port -J username@host:port
</span></span><span class="line"><span class="cl"><span class="c1"># Example:</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Jump host A: user yuesir, host 192.168.0.1, port 22</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Target B: user yueqingyou, host 192.168.0.2, port 2222</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ssh yueqingyou@192.168.0.2:2222 -J yuesir@192.168.0.1:22</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="method-2-config-file">Method 2: config file</h3>
<p>After connecting once, VS Code writes the config into your SSH config. Choose <strong>Connect to Host -&gt; Configure SSH Hosts</strong>, usually <code>~/.ssh/config</code> (e.g., <code>/Users/yuesir/.ssh/config</code>).</p>
<p><a href="/en/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp" data-caption="Config file">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114213636856_hu_65e0642b5462d1db.webp 480w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp 720w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_d3b9744e97d0c162.webp 960w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_84ed307bf2d6e26.webp 1440w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250114213636856_hu_65e0642b5462d1db.webp 480w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_4a6dfedec2f8e976.webp 720w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_d3b9744e97d0c162.webp 960w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_84ed307bf2d6e26.webp 1440w, /en/article/vscode-python-remote-development/image-20250114213636856_hu_e5fd05e466349f16.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Config file"
                    
                />
            </picture>
        </a></p>
<p>Two templates (with/without jump). <code>Host</code> is just a nickname; <strong>HostName</strong> is the actual host/IP.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># No jump host</span>
</span></span><span class="line"><span class="cl">Host MyServer
</span></span><span class="line"><span class="cl">  HostName &lt;server-host&gt;
</span></span><span class="line"><span class="cl">  Port &lt;port&gt;
</span></span><span class="line"><span class="cl">  User &lt;username&gt;
</span></span><span class="line"><span class="cl">  
</span></span><span class="line"><span class="cl"><span class="c1"># With jump host</span>
</span></span><span class="line"><span class="cl">Host TargetServer
</span></span><span class="line"><span class="cl">  HostName 192.168.0.2
</span></span><span class="line"><span class="cl">  Port <span class="m">2222</span>
</span></span><span class="line"><span class="cl">  User yueqingyou
</span></span><span class="line"><span class="cl">  ProxyJump yuesir@192.168.0.1:22
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="if-it-hangs-on-downloading-vs-code-server">If it hangs on “Downloading VS Code Server”</h3>
<p>This happens when the remote can’t reach the VS Code server URL (offline or blocked). Workaround: download the server locally and upload manually. References:</p>
<ul>
<li><a href="https://www.cnblogs.com/michaelcjl/p/18262833" target="_blank" rel="noopener">Offline install VS Code Server</a></li>
<li><a href="https://blog.csdn.net/mc_pang/article/details/123078089" target="_blank" rel="noopener">Offline install VS Code Server + SSH keys</a></li>
<li><a href="https://www.cnblogs.com/ziangshen/articles/17741402.html" target="_blank" rel="noopener">VS Code Server download stuck</a></li>
</ul>
<h2 id="configure-ssh-key-login">Configure SSH Key Login</h2>
<p>Typing passwords repeatedly is painful, especially with flaky VPNs. Use key-based auth—it’s also what VS Code recommends:</p>
<blockquote>
<p>We recommend using key-based authentication (otherwise you may be prompted multiple times).</p>
</blockquote>
<h3 id="check-for-existing-keys-on-the-host">Check for existing keys on the host</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check for .ssh directory</span>
</span></span><span class="line"><span class="cl">ls -la ~ <span class="p">|</span> grep .ssh
</span></span><span class="line"><span class="cl"><span class="c1"># If present, check for key files</span>
</span></span><span class="line"><span class="cl">ls -la ~/.ssh <span class="p">|</span> grep id_rsa
</span></span><span class="line"><span class="cl">ls -la ~/.ssh <span class="p">|</span> grep id_ed25519
</span></span></code></pre></td></tr></table>
</div>
</div><p>If you already have keys, skip creation.</p>
<p><a href="/en/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp" data-caption="Existing keys">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250115152319134_hu_b22cdd01149a9af5.webp 480w, /en/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp 710w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="710"
                    height="154"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp"
                    srcset="/en/article/vscode-python-remote-development/image-20250115152319134_hu_b22cdd01149a9af5.webp 480w, /en/article/vscode-python-remote-development/image-20250115152319134_hu_b376e829399128df.webp 710w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Existing keys"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>Quick crypto note: RSA vs Ed25519. Summary:</p>
<table>
  <thead>
      <tr>
          <th>Command</th>
          <th>ssh-keygen -t rsa -b 4096</th>
          <th>ssh-keygen -t ed25519</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Type</td>
          <td>RSA</td>
          <td>Ed25519</td>
      </tr>
      <tr>
          <td>Performance</td>
          <td>Slower (still fine)</td>
          <td>Faster</td>
      </tr>
      <tr>
          <td>Security</td>
          <td>High</td>
          <td>Higher</td>
      </tr>
      <tr>
          <td>Compatibility</td>
          <td>Better with legacy systems</td>
          <td>Very old systems may not support</td>
      </tr>
  </tbody>
</table>
<p>Default to <code>ssh-keygen -t ed25519</code>.</p>
</blockquote>
<h3 id="create-a-key-pair-on-the-host">Create a key pair on the host</h3>
<p>On Windows open cmd/PowerShell; on macOS/Linux use Terminal. Example on Windows 10:</p>
<p><a href="/en/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp" data-caption="Generate keys">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736926370168_hu_145e174e6415f113.webp 480w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp 720w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_f00bebaaa12b01ee.webp 960w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_9b11061ae15b4a00.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1702"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736926370168_hu_145e174e6415f113.webp 480w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_ea044de59e5bec0e.webp 720w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_f00bebaaa12b01ee.webp 960w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_9b11061ae15b4a00.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736926370168_hu_d49e598161aa8ec5.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Generate keys"
                    
                />
            </picture>
        </a></p>
<p>Prefer Ed25519, fall back to RSA:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Ed25519</span>
</span></span><span class="line"><span class="cl">ssh-keygen -t ed25519
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># RSA</span>
</span></span><span class="line"><span class="cl">ssh-keygen -t rsa -b <span class="m">4096</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Press Enter to accept defaults and empty passphrase. Keys are stored in <code>~/.ssh</code> (e.g., <code>C:/Users/&lt;user&gt;/.ssh</code> or <code>/home/&lt;user&gt;/.ssh</code>). You’ll see <code>id_ed25519.pub</code> (public) and <code>id_ed25519</code> (private). Keep the private key secret.</p>
<h3 id="add-the-public-key-to-the-remote-server">Add the public key to the remote server</h3>
<p>Cloud providers often let you paste/upload a key when provisioning (see screenshot below).</p>
<p><a href="/en/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp" data-caption="Add key in cloud console">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736926873754_hu_cd950c647632b795.webp 480w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp 720w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_d4e8d9a3f1fa710c.webp 960w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_d9a2c34723cda6c7.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="1456"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736926873754_hu_cd950c647632b795.webp 480w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_bdd970057d6e805e.webp 720w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_d4e8d9a3f1fa710c.webp 960w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_d9a2c34723cda6c7.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736926873754_hu_7d91c8b6a1751505.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Add key in cloud console"
                    
                />
            </picture>
        </a></p>
<p>If you just have SSH access, use the command-line or manual edit:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># From host</span>
</span></span><span class="line"><span class="cl">ssh-copy-id -i ~/.ssh/id_ed25519.pub username@host:port
</span></span></code></pre></td></tr></table>
</div>
</div><p>Or manually append the <code>.pub</code> content to <code>~/.ssh/authorized_keys</code> on the server (create the file if missing), then set permissions:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod <span class="m">700</span> ~/.ssh
</span></span><span class="line"><span class="cl">chmod <span class="m">600</span> ~/.ssh/authorized_keys
</span></span></code></pre></td></tr></table>
</div>
</div><p>Restart the SSH service if needed to apply key auth.</p>
<h2 id="recommended-plugins">Recommended Plugins</h2>
<p>Beyond <code>Remote-SSH</code>, these make Python/Notebook life easier:</p>
<ul>
<li><code>ms-python.python</code> (Python tooling, debugger, linting)</li>
<li><code>ms-toolsai.jupyter</code> (Notebook support)</li>
<li><code>ms-toolsai.jupyter-renderers</code></li>
<li><code>ms-toolsai.jupyter-keymap</code></li>
<li><code>ms-toolsai.jupyter-cell-tags</code></li>
<li><code>ms-toolsai.vscode-jupyter-powertoys</code></li>
<li><code>ms-toolsai.datawrangler</code> (data wrangling)</li>
<li><code>ms-toolsai.data-wrangler-vscode</code></li>
<li><code>ms-toolsai.data-wrangler-native-notebook</code></li>
<li><code>ms-toolsai.data-wrangler-lsp</code></li>
<li><code>ms-toolsai.data-wrangler-insiders</code></li>
<li><code>ms-toolsai.data-wrangler-debug</code></li>
<li><code>ms-toolsai.data-wrangler-darwin-x64</code></li>
<li><code>ms-toolsai.data-wrangler-darwin-arm64</code></li>
<li><code>ms-toolsai.data-wrangler-windows-x64</code></li>
<li><code>ms-toolsai.data-wrangler-windows-arm64</code></li>
</ul>
<blockquote>
<p>The last few are platform-specific binaries; VS Code will fetch the right one automatically.</p>
</blockquote>
<h2 id="final-thoughts">Final Thoughts</h2>
<p>Once SSH and keys are set, connecting is just a click. With the Python and Jupyter extensions, you get a near-local dev experience while running code on the remote server.
If you edit <code>authorized_keys</code> with vim, save and exit with:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">:wq
</span></span><span class="line"><span class="cl"><span class="c1"># or</span>
</span></span><span class="line"><span class="cl">ZZ
</span></span></code></pre></td></tr></table>
</div>
</div><p>Close VS Code and reconnect—if it no longer prompts for a password, key auth is working. The rest focuses on language-specific setup and notebooks.</p>
<h2 id="python">Python</h2>
<p>Developing remotely still requires installing language plugins on the <strong>remote</strong> side. VS Code will prompt you; just ensure you install to the server, not the host.</p>
<p><a href="/en/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp" data-fancybox="gallery" data-src="/en/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp" data-caption="Install plugins on remote">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736928419969_hu_4004eff5606954e2.webp 480w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp 720w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_eb600fa3c7a756eb.webp 960w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_e835b2af4343c874.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2392"
                    height="1700"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp"
                    srcset="/en/article/vscode-python-remote-development/QQ_1736928419969_hu_4004eff5606954e2.webp 480w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_3c2a4773c10993e9.webp 720w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_eb600fa3c7a756eb.webp 960w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_e835b2af4343c874.webp 1440w, /en/article/vscode-python-remote-development/QQ_1736928419969_hu_c6694abb8ea42579.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Install plugins on remote"
                    
                />
            </picture>
        </a></p>
<p>I recommend managing environments with Conda:</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Install the R Kernel for Jupyter with Conda
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                Due to the author's frequent use of conda to configure the R kernel jupyter notebook on Linux remote servers, some steps are forgotten over time (the main problem is that the same pit will be stepped on differently every time). After summarizing the relevant tutorials and personal experience on the internet, a guide is provided for everyone and future me to refer to.
            </div>
        </div>
    </a>
    
    
</div>

<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/conda-env-transfer.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Back Up and Migrate Conda Environments
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2024-06-29
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #conda pack
                #droplet
                #deep learning
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                I recently needed to move a Conda environment. Deep learning stacks are usually tightly coupled to driver versions and package versions, so being able to package a working environment and drop it onto another box saves a lot of time.
            </div>
        </div>
    </a>
    
    
</div>

<p>For Notebook + R/Python integration, see the next section.</p>
<h2 id="notebook">Notebook</h2>
<p>I’ve written several notebook setup posts; note some target the older 6.x series (current releases are 7.x).</p>
<p>If you’re new to notebooks, see the <a href="https://jupyter.org/install" target="_blank" rel="noopener">install guide</a> and <a href="https://jupyter-notebook.readthedocs.io/en/latest/" target="_blank" rel="noopener">official docs</a>.</p>
<p>If you’d like a detailed walkthrough, drop a comment (I’ll try not to bail ~~).</p>
<h3 id="r--notebook">R + Notebook</h3>
<p>R isn’t limited to <a href="https://posit.co/download/rstudio-desktop/" target="_blank" rel="noopener">RStudio</a> / <a href="https://posit.co/products/open-source/rstudio-server/" target="_blank" rel="noopener">RStudio Server</a>. Paired with Notebook, visualization can be even smoother.</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Install the R Kernel for Jupyter with Conda
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                Due to the author's frequent use of conda to configure the R kernel jupyter notebook on Linux remote servers, some steps are forgotten over time (the main problem is that the same pit will be stepped on differently every time). After summarizing the relevant tutorials and personal experience on the internet, a guide is provided for everyone and future me to refer to.
            </div>
        </div>
    </a>
    
    
</div>

<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/brew-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Install the R Kernel for Jupyter with Homebrew
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2023-01-16
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #brew
                #r
                #jupyter
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                I introduced in another article in the Linux remote server using conda configuration r-kernel jupyter notebook, but I found that conda for a variety of dependency conflicts are not handled well, often leading to unsuccessful installation. In macOS system locally using brew for installation is much easier and faster. Here I summarized steps for reference.
            </div>
        </div>
    </a>
    
    
</div>

<h3 id="python--notebook">Python + Notebook</h3>
<p>Some common issues are recorded here, though VS Code’s Notebook UI already solves most of them.</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/conda-r-jupyter.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Install the R Kernel for Jupyter with Conda
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-10-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #r
                #jupyter
                #droplet
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                Due to the author's frequent use of conda to configure the R kernel jupyter notebook on Linux remote servers, some steps are forgotten over time (the main problem is that the same pit will be stepped on differently every time). After summarizing the relevant tutorials and personal experience on the internet, a guide is provided for everyone and future me to refer to.
            </div>
        </div>
    </a>
    
    
</div>

<h2 id="thanks">Thanks</h2>
<p><a href="https://code.visualstudio.com/docs/remote/remote-overview" target="_blank" rel="noopener">VS Code Remote Development</a></p>
<p><a href="https://code.visualstudio.com/docs/remote/ssh-tutorial" target="_blank" rel="noopener">Remote development over SSH</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Back Up and Migrate Conda Environments</title>
      <link>https://vccv.cc/en/article/conda-env-transfer.html</link>
      <pubDate>Sat, 29 Jun 2024 12:28:14 +0800</pubDate>
      <guid>https://vccv.cc/en/article/conda-env-transfer.html</guid>
      <description>I recently needed to move a Conda environment. Deep learning stacks are usually tightly coupled to driver versions and package versions, so being able to package a working environment and drop it onto another box saves a lot of time.</description>
      <content:encoded><![CDATA[<h2 id="background">Background</h2>
<p>Deep learning projects rely on a web of dependencies: <code>torch</code>, <code>transformers</code>, <code>cuda</code>, and many more. Version mismatches often lead to obscure compatibility issues, making it hard to faithfully recreate an environment on a different server.</p>
<p>I already had a stable deep learning Conda environment on one server and wanted to migrate it to another. The easiest path was <code>conda-pack</code>, which can bundle a Conda environment into a single archive that works out of the box on another Linux host.</p>
<h2 id="export">Export</h2>
<p>To move the original environment off the source server, export it first.</p>
<ol>
<li>
<p><strong>List all environments</strong></p>
<p>Use <code>conda env list</code> to see every Conda environment on the machine. Make sure the target isn’t the default <code>base</code>. If you need to move <code>base</code>, clone it to a new name with <code>conda clone</code> first.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Activate the environment to migrate</strong></p>
<p>Suppose the environment name is <code>torch</code>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Install <code>conda-pack</code></strong></p>
<p>Install inside the activated environment:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda install conda-pack -c conda-forge
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Pack the environment</strong></p>
<p>Run <code>conda pack -n &lt;env&gt;</code> to generate a tarball. Replace <code>&lt;env&gt;</code> with your environment name, e.g. <code>torch</code>.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda pack -n torch
</span></span></code></pre></td></tr></table>
</div>
</div><p>The command creates <code>torch.tar.gz</code> in the current directory.</p>
</li>
</ol>
<p>Packing time scales with environment size. My <code>torch</code> env is large, so the job took a while—thankfully there’s a progress bar. The environment consumed ~20GB and the packed file landed just under 10GB.</p>
<p><a href="/en/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp" data-fancybox="gallery" data-src="/en/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp" data-caption="Conda environment size">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-env-transfer/image-20240629132237812_hu_38d0df800822b6df.webp 480w, /en/article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp 720w, /en/article/conda-env-transfer/image-20240629132237812_hu_74d4f7f55ae7def5.webp 960w, /en/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1038"
                    height="344"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp"
                    srcset="/en/article/conda-env-transfer/image-20240629132237812_hu_38d0df800822b6df.webp 480w, /en/article/conda-env-transfer/image-20240629132237812_hu_a0bf6e5b8fed4b65.webp 720w, /en/article/conda-env-transfer/image-20240629132237812_hu_74d4f7f55ae7def5.webp 960w, /en/article/conda-env-transfer/image-20240629132237812_hu_d15b4707209a1ab9.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Conda environment size"
                    
                />
            </picture>
        </a></p>
<p><a href="/en/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp" data-fancybox="gallery" data-src="/en/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp" data-caption="Packed torch archive size">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-env-transfer/image-20240629131923704_hu_4da93e99537b81b8.webp 480w, /en/article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp 720w, /en/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp 894w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="894"
                    height="156"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp"
                    srcset="/en/article/conda-env-transfer/image-20240629131923704_hu_4da93e99537b81b8.webp 480w, /en/article/conda-env-transfer/image-20240629131923704_hu_67f6d510d2ac9f57.webp 720w, /en/article/conda-env-transfer/image-20240629131923704_hu_c110c65733fd8f66.webp 894w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Packed torch archive size"
                    
                />
            </picture>
        </a></p>
<h2 id="import">Import</h2>
<p>After packing and downloading the archive, upload it to the target server and unpack it.</p>
<h3 id="upload-the-file-to-the-target">Upload the file to the target</h3>
<ol>
<li>
<p><strong>Download locally, then upload</strong></p>
<p>Keeps a local backup: download <code>torch.tar.gz</code> to your laptop, then upload to the target. Use whatever SSH/SFTP tool you like.</p>
</li>
<li>
<p><strong>Use <code>rsync</code> directly</strong></p>
<p>Transfer straight between servers:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">rsync -avz torch.tar.gz user@target_server:/path/to/destination
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h3 id="restore-the-environment">Restore the environment</h3>
<ol>
<li>
<p><strong>Ensure no environment with the same name exists</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div><p>If a duplicate exists, remove it first:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env remove -p &lt;env_path&gt;
</span></span><span class="line"><span class="cl"><span class="c1"># or</span>
</span></span><span class="line"><span class="cl">conda env remove -n &lt;env_name&gt;
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Prepare the destination directory</strong></p>
<p>Check where Conda keeps environments, e.g. <code>/mnt/nfs/yuesir/miniconda3/envs</code>. Create a folder matching the environment name:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">mkdir /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span><span class="line"><span class="cl">chmod <span class="m">777</span> /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Extract the archive</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">tar -xzvf torch.tar.gz -C /mnt/nfs/yuesir/miniconda3/envs/torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Activate the new environment</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h2 id="verify">Verify</h2>
<p>After importing, run a few checks.</p>
<ol>
<li>
<p><strong>List environments</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda env list
</span></span></code></pre></td></tr></table>
</div>
</div><p>You should see the migrated environment in the list.</p>
</li>
<li>
<p><strong>Activate it</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda activate &lt;env_name&gt;
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Inspect installed packages</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">conda list
</span></span></code></pre></td></tr></table>
</div>
</div><p>Confirm versions and dependencies look right.</p>
</li>
</ol>
<h2 id="extra">Extra</h2>
<p>For deep learning workloads (e.g., PyTorch) that depend on specific driver versions, verify CUDA driver compatibility between the two servers. CUDA drivers are backward compatible—if they don’t match, either upgrade the target’s driver (root required) or downgrade PyTorch (risky because of dependency complexity). In tricky cases, a clean install might be safer.</p>
<p>For choosing CUDA/PyTorch combos, see my earlier post:</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/cuda-conda-nlp.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Install CUDA and an NLP Stack with Conda (No Root)
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2024-03-10
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #conda
                #nvidia
                #cuda
                #transformers
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                How a non-root user can install a newer version of the transformers suite without being able to change the version of the installed cuda driver.
            </div>
        </div>
    </a>
    
    
</div>

<h2 id="thanks">Thanks</h2>
<p><a href="https://bbs.huaweicloud.com/blogs/405885" target="_blank" rel="noopener">Using conda pack for environment migration</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Hugo Image Optimization: Fancybox, Webp and Watermarks</title>
      <link>https://vccv.cc/en/article/hugo-img-watermark.html</link>
      <pubDate>Mon, 08 Apr 2024 11:21:44 +0800</pubDate>
      <guid>https://vccv.cc/en/article/hugo-img-watermark.html</guid>
      <description>Recently switching my blog from Hexo to Hugo, I discovered Hugo&amp;#39;s powerful customization capabilities, including image customization. After some fiddling around, I successfully converted the original images to Webp format, added fancybox gallery and blog watermark.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>I used to use Hexo framework. But with the increasing number of articles, custom projects are more and more, coupled with the NPM plug-ins are in constant conflict, have not dared to arbitrarily install new plug-ins, the difficulty of maintenance has risen greatly. Former Hexo blog project file has been a &ldquo;shit&rdquo;.</p>
<p>As the saying goes, &ldquo;break and then stand up&rdquo;, taking advantage of this period of time is relatively free, I directly switch to the Hugo framework. My first and deepest impression of Hugo is that it is very fast, more than twice as fast as Hexo, of course, I also found some of the places that are not adapted to: the original blog webp image compression and watermarking features are automatically generated by the plug-in, this is the use of Hugo&rsquo;s highly customizable and rich image processing api restore the blog&rsquo;s image structure.</p>
<h2 id="hugo-image-customization">Hugo Image Customization</h2>
<p>Hugo has a <strong>Render Hooks</strong> function, you can replace some of the components to generate styles, which contains images resources. Here is the official introduction, if you are interested, you can go to learn more about it.</p>
<blockquote>
<p>When rendering Markdown to HTML, render hooks override the conversion. Each render hook is a template, with one template for each supported element type :: Rendering hooks are used to render HTML to Markdown.</p>
<ul>
<li><a href="">Code blocks</a></li>
<li><a href="https://gohugo.io/render-hooks/code-blocks/" target="_blank" rel="noopener">Code blocks</a></li>
<li><a href="https://gohugo.io/render-hooks/headings/" target="_blank" rel="noopener">Headings</a></li>
<li><a href="https://gohugo.io/render-hooks/images/" target="_blank" rel="noopener">Images</a></li>
<li><a href="https://gohugo.io/render-hooks/links/" target="_blank" rel="noopener">Links</a></li>
</ul>
</blockquote>
<p>For images, we need to create or modify the content of<code>layouts/_default/_markup/render-image.html</code>file for customization. If this is the first time you know about this concept, please first create this file in the appropriate path in your blog root directory, note that it is not in the theme theme directory.</p>
<p><a href="/en/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp" data-fancybox="gallery" data-src="/en/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp" data-caption="Creating image customization files">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408115714382_hu_5b7f0f2a78357892.webp 480w, /en/article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp 720w, /en/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp 956w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="956"
                    height="400"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408115714382_hu_5b7f0f2a78357892.webp 480w, /en/article/hugo-img-watermark/image-20240408115714382_hu_5e267e1ec47a82ab.webp 720w, /en/article/hugo-img-watermark/image-20240408115714382_hu_555d39c3798cd2b9.webp 956w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Creating image customization files"
                    
                />
            </picture>
        </a></p>
<p>Next I will give a reference article and code for each treatment, I will give detailed comments at the end of the article all the code, each subsection of the code is for reference only, similar to <strong>pseudo-code</strong>, can not be used directly.</p>
<h2 id="webp-compression">Webp Compression</h2>
<h3 id="show-results">Show Results</h3>
<p>The memory usage of a static blog is dominated by images, which can be more than 100kb, making the already fast blog even worse (the blog is hosted on Cloudflare, which is free, and the speed in China is impressive). The common png, jpg and other image files can be compressed into webp format to significantly reduce the footprint.</p>
<p>The image above, for example, takes up 39.35 kb before compression and 8.87 kb after compression.</p>
<p><a href="/en/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp" data-fancybox="gallery" data-src="/en/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp" data-caption="Compare">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408120854759_hu_a5535acecc8538c0.webp 480w, /en/article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp 720w, /en/article/hugo-img-watermark/image-20240408120854759_hu_e12b0b33bbc3b624.webp 960w, /en/article/hugo-img-watermark/image-20240408120854759_hu_27319627b0bcca71.webp 1440w, /en/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp 1456w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1456"
                    height="1432"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408120854759_hu_a5535acecc8538c0.webp 480w, /en/article/hugo-img-watermark/image-20240408120854759_hu_b7cc59cc0648158a.webp 720w, /en/article/hugo-img-watermark/image-20240408120854759_hu_e12b0b33bbc3b624.webp 960w, /en/article/hugo-img-watermark/image-20240408120854759_hu_27319627b0bcca71.webp 1440w, /en/article/hugo-img-watermark/image-20240408120854759_hu_e6461a24ef8c74c4.webp 1456w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Compare"
                    
                />
            </picture>
        </a></p>
<h3 id="principle-analysis">Principle Analysis</h3>
<p>Refer to <a href="https://iblog.ren/posts/hugo_img_to_webp/" target="_blank" rel="noopener">Hugo&rsquo;s method of automatically converting images to webp</a>, which mainly utilizes the<code>image.Resize</code>method, <a href="https://gohugo.io/content-management/image-processing/#target-format" target="_blank" rel="noopener">official docs</a> means that you can specify the specific aspect and format.</p>
<p><a href="/en/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp" data-fancybox="gallery" data-src="/en/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp" data-caption="Target Format">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408121738191_hu_4c05e3422f76bb3a.webp 480w, /en/article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp 720w, /en/article/hugo-img-watermark/image-20240408121738191_hu_289b27129ed6a1c4.webp 960w, /en/article/hugo-img-watermark/image-20240408121738191_hu_bf37df2fe0b0717f.webp 1440w, /en/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp 1502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1502"
                    height="1006"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp"
                    srcset="/en/article/hugo-img-watermark/image-20240408121738191_hu_4c05e3422f76bb3a.webp 480w, /en/article/hugo-img-watermark/image-20240408121738191_hu_6b5799e0b1e39d50.webp 720w, /en/article/hugo-img-watermark/image-20240408121738191_hu_289b27129ed6a1c4.webp 960w, /en/article/hugo-img-watermark/image-20240408121738191_hu_bf37df2fe0b0717f.webp 1440w, /en/article/hugo-img-watermark/image-20240408121738191_hu_855643dfff590a67.webp 1502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Target Format"
                    
                />
            </picture>
        </a></p>
<p>Reference article added to recognize image EXIF orientation to prevent image orientation change after format conversion.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="p">.</span><span class="nx">Exif</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp r180&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r270&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r90&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="add-watermarks">Add Watermarks</h2>
<h3 id="method-source">Method Source</h3>
<p>I basically didn&rsquo;t find what I needed on the Chinese Internet, and finally found a three-year-old article in the blog of the author of the <a href="https://github.com/adityatelange/hugo-PaperMod" target="_blank" rel="noopener">PaperMod</a> theme (which is the theme used in this blog): <a href="https://adityatelange.in/blog/hugo-watermarking-images/" target="_blank" rel="noopener">Watermarking images with HUGO</a>.</p>
<p>The main idea is to use the <code>image.Filter</code> and <code>image.Overlay</code> methods to overlay a watermarked image onto each image.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="o">-</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx jpg&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="o">-</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>This requires a simple structure for the watermark image, and it is recommended to use a website logo or blog URL to create the watermark overlay. My watermark is made through this <a href="https://www.logoly.pro/" target="_blank" rel="noopener">tool</a>.</p>
<h3 id="code-show">Code Show</h3>
<p>The original author will cover the watermark to the lower right corner of the picture, I modified the <strong>centered transparent tilt</strong> placed, not too much impact on the reading experience, but also to better protect their image copyright.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nf">Round</span><span class="w"> </span><span class="p">(</span><span class="nx">mul</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="mf">0.80</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nf">cond</span><span class="w"> </span><span class="p">(</span><span class="nx">ge</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mi">250</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mf">250.0</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Opacity</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)</span><span class="w">  </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx png r30&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">))</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>You need to calculate the length and width of the original image to determine the logo position, then use the<code>image.Opacity</code>method to set the transparency, and finally center it.</p>
<h2 id="using-fancybox">Using Fancybox</h2>
<p>My blog images usually contain a lot of textual information, and it would be very difficult to view the original image without zooming in. It so happens that <a href="https://fancyapps.com/fancybox/" target="_blank" rel="noopener">fancybox</a> is a js library that solves this kind of problem. The official website description is as follows:</p>
<blockquote>
<p>Fancybox is the ultimate JavaScript lightbox alternative that sets the standard for premium user experience in multimedia display. Supports images, videos, maps, inline content, iframes and any other HTML content.</p>
</blockquote>
<h3 id="reference-tutorial">Reference Tutorial</h3>
<p>The functionality is very powerful and will be shown here only for the image gallerygallery function. This step happens to be referenced in a previous tutorial I wrote for the Hexo Cactus theme:</p>
<div style="height: 100%;
            position: relative;
            border-radius: var(--radius);
            box-shadow: 0 2px 4px rgb(0 0 0 / 25%), 0 0 2px rgb(0 0 0 / 25%);
            background: var(--entry);">
    
    
    <a target="_blank" href="https://vccv.cc/en/article/fancybox-cactus.html" style="box-shadow: none">
        <div style="margin: 1em auto;
                    padding: 25px;">
            <div style="font-size: 1.5rem; font-weight: bold">
            Adding Fancybox Image Zoom to the Cactus Theme
            </div>
            <span style="font-size: 0.9rem; color: #999">
                <svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M8 2v4" />
    <path d="M16 2v4" />
    <rect x="3" y="4" width="18" height="18" rx="2" />
    <path d="M3 10h18" />
    <circle cx="12" cy="16" r="2.5" />
</svg> 2022-02-20
                
                &nbsp;<svg class="icon-inline" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
    <path d="M20 10 10 20 2 12V4h8l10 10z" />
    <circle cx="7" cy="7" r="1.5" />
</svg>
                #cactus
                #beautify
                #fancybox
                
            </span>
            <div style="font-size: 1rem; line-height: 1.8;max-height: 5rem; overflow: hidden; margin-top: 5px;">
                Install fancybox to hexo theme cactus some experience for your reference. fancybox can solve the problem of cactus theme images can not be enlarged, thanks to fancyapps to make a contribution.
            </div>
        </div>
    </a>
    
    
</div>

<h3 id="code-show-1">Code Show</h3>
<p>Pay special attention to the first need to import the relevant css file and js file, and then modify the img upper layer of the a tag.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span> <span class="na">data-fancybox</span><span class="o">=</span><span class="s">&#34;gallery&#34;</span> <span class="na">data-src</span><span class="o">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span> <span class="na">data-caption</span><span class="o">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">picture</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">source</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;image/webp&#34;</span> <span class="na">srcset</span><span class="o">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">img</span>
</span></span><span class="line"><span class="cl">            <span class="na">width</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.Width }}px&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">height</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.Height }}px&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">style</span><span class="o">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">loading</span><span class="o">=</span><span class="s">&#34;lazy&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">src</span><span class="o">=</span><span class="s">&#34;{{ $rawImage.RelPermalink }}&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="na">alt</span><span class="o">=</span><span class="s">&#34;{{ .Text }}&#34;</span>
</span></span><span class="line"><span class="cl">            <span class="err">{{</span> <span class="na">with</span> <span class="err">.</span><span class="na">Title</span> <span class="err">}}</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;{{ . }}&#34;</span> <span class="err">{{</span> <span class="na">end</span> <span class="err">}}</span>
</span></span><span class="line"><span class="cl">        <span class="p">/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&lt;/</span><span class="nt">picture</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Add the picture tag is to adapt old devices that can&rsquo;t parse webp files to display the original image and improve code compatibility. The width and height parameters are added to minimize the impact of <a href="https://web.dev/articles/cls" target="_blank" rel="noopener">CLS</a>.</p>
<h2 id="summary">Summary</h2>
<p>There is no guarantee that the code can be used 100% directly, a better way is to learn the principle step by step and modify it with your own theme features.</p>
<h3 id="code-summary">Code Summary</h3>
<p>I&rsquo;ll try to comment the following code in detail, just remove the comments when you use it. If there are other questions, you can leave a message in the comments section.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span><span class="lnt">56
</span><span class="lnt">57
</span><span class="lnt">58
</span><span class="lnt">59
</span><span class="lnt">60
</span><span class="lnt">61
</span><span class="lnt">62
</span><span class="lnt">63
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* Get the resource image of the current page matching */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">.</span><span class="nx">Page</span><span class="p">.</span><span class="nx">Resources</span><span class="p">.</span><span class="nx">GetMatch</span><span class="w"> </span><span class="p">.</span><span class="nx">Destination</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* Get logo images from resources, transparent background images work best */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* The image needs to be placed in the assets/images directory in the root directory */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="p">(</span><span class="nx">resources</span><span class="p">.</span><span class="nx">Get</span><span class="w"> </span><span class="s">&#34;images/logo.png&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="cm">/* Check if the media type of the image is not gif or svg */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nf">not</span><span class="w"> </span><span class="p">(</span><span class="nf">in</span><span class="w"> </span><span class="p">(</span><span class="nx">slice</span><span class="w"> </span><span class="s">&#34;gif&#34;</span><span class="w"> </span><span class="s">&#34;svg&#34;</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">MediaType</span><span class="p">.</span><span class="nx">SubType</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Preserve references to the original image */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Calculate 80% of the image height and make sure the minimum value is 250 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nx">math</span><span class="p">.</span><span class="nf">Round</span><span class="w"> </span><span class="p">(</span><span class="nx">mul</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="mf">0.80</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="nf">cond</span><span class="w"> </span><span class="p">(</span><span class="nx">ge</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mi">250</span><span class="p">)</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="w"> </span><span class="mf">250.0</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Adjust the transparency of the logo to 50% */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Opacity</span><span class="w"> </span><span class="mf">0.5</span><span class="p">)</span><span class="w">  </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Resize the logo to the calculated $size in height, keeping the aspect ratio and rounding the corners with a radius of 30 */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">printf</span><span class="w"> </span><span class="s">&#34;%.0fx png r30&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">size</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* If the original image has EXIF information */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="err">$</span><span class="nx">rawImage</span><span class="p">.</span><span class="nx">Exif</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="cm">/* Resize and rotate the image according to its orientation */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">3</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp r180&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">6</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r270&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="nx">eq</span><span class="w"> </span><span class="p">.</span><span class="nx">Tags</span><span class="p">.</span><span class="nx">Orientation</span><span class="w"> </span><span class="mi">8</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34; webp r90&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="cm">/* If there is no EXIF information, then only resize, no rotation */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Resize</span><span class="w"> </span><span class="p">(</span><span class="nx">print</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="s">&#34;x&#34;</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="s">&#34; webp&#34;</span><span class="p">)</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Add a logo watermark to the image, positioned in the center of the image */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nf">Filter</span><span class="w"> </span><span class="p">(</span><span class="nx">images</span><span class="p">.</span><span class="nx">Overlay</span><span class="w"> </span><span class="err">$</span><span class="nf">logo</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Width</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Width</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">)</span><span class="w"> </span><span class="p">(</span><span class="nf">div</span><span class="w"> </span><span class="p">(</span><span class="nx">sub</span><span class="w"> </span><span class="err">$</span><span class="nx">image</span><span class="p">.</span><span class="nx">Height</span><span class="w"> </span><span class="err">$</span><span class="nx">logo</span><span class="p">.</span><span class="nx">Height</span><span class="p">)</span><span class="w"> </span><span class="mi">2</span><span class="p">))</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* Create a link to a data attribute that meets fancybox&#39;s requirements, showing the processed image */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="nx">a</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">fancybox</span><span class="p">=</span><span class="s">&#34;gallery&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">caption</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="nx">picture</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">&lt;</span><span class="nx">source</span><span class="w"> </span><span class="kd">type</span><span class="p">=</span><span class="s">&#34;image/webp&#34;</span><span class="w"> </span><span class="nx">srcset</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">&lt;</span><span class="nx">img</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">width</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.Width }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">height</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.Height }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">style</span><span class="p">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">loading</span><span class="p">=</span><span class="s">&#34;lazy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $rawImage.RelPermalink }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="nx">alt</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">                </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="nx">title</span><span class="p">=</span><span class="s">&#34;{{ . }}&#34;</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="o">/</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">picture</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">a</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">{{</span><span class="cm">/* No webp compression for gif or svg images */</span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="nx">a</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">fancybox</span><span class="p">=</span><span class="s">&#34;gallery&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w"> </span><span class="nx">data</span><span class="o">-</span><span class="nx">caption</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="p">&lt;</span><span class="nx">img</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">width</span><span class="p">=</span><span class="s">&#34;{{ $image.Width }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">height</span><span class="p">=</span><span class="s">&#34;{{ $image.Height }}px&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">style</span><span class="p">=</span><span class="s">&#34;width: 100%; height: 100%; max-height: 36rem;&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">loading</span><span class="p">=</span><span class="s">&#34;lazy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">src</span><span class="p">=</span><span class="s">&#34;{{ $image.RelPermalink }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="nx">alt</span><span class="p">=</span><span class="s">&#34;{{ .Text }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">            </span><span class="p">{{</span><span class="w"> </span><span class="nx">with</span><span class="w"> </span><span class="p">.</span><span class="nx">Title</span><span class="w"> </span><span class="p">}}</span><span class="w"> </span><span class="nx">title</span><span class="p">=</span><span class="s">&#34;{{ . }}&#34;</span><span class="w"> </span><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">        </span><span class="o">/</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="p">&lt;</span><span class="o">/</span><span class="nx">a</span><span class="p">&gt;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="p">{{</span><span class="w"> </span><span class="nx">end</span><span class="w"> </span><span class="p">}}</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h2 id="thanks">Thanks</h2>
<p><a href="https://gohugo.io/render-hooks/images/" target="_blank" rel="noopener">Hugo: Image render hooks</a></p>
<p><a href="https://iblog.ren/posts/hugo_img_to_webp/" target="_blank" rel="noopener">Hugo图片自动转webp的方法</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Notes While Reading Hugging Face Transformers Docs</title>
      <link>https://vccv.cc/en/article/llm-transformers.html</link>
      <pubDate>Mon, 11 Mar 2024 19:17:56 +0000</pubDate>
      <guid>https://vccv.cc/en/article/llm-transformers.html</guid>
      <description>Briefly record the conclusions and methods that appear in the official documentation of hugging face. By the way, record some personal thinking and confusion, so that it is convenient to go back and solve the problem later. Welcome to comment.</description>
      <content:encoded><![CDATA[<h2 id="single-gpu-optimization">Single GPU Optimization</h2>
<p>Resource: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<table>
  <thead>
      <tr>
          <th>Method/tool</th>
          <th>Improves training speed</th>
          <th>Optimizes memory utilization</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#batch-size-choice" target="_blank" rel="noopener">Batch size choice</a></td>
          <td>Yes</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#gradient-accumulation" target="_blank" rel="noopener">Gradient accumulation</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#gradient-checkpointing" target="_blank" rel="noopener">Gradient checkpointing</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#mixed-precision-training" target="_blank" rel="noopener">Mixed precision training</a></td>
          <td>Yes</td>
          <td>(<strong>No</strong>)</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#optimizer-choice" target="_blank" rel="noopener">Optimizer choice</a></td>
          <td>Yes</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#data-preloading" target="_blank" rel="noopener">Data preloading</a></td>
          <td>Yes</td>
          <td>No</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#deepspeed-zero" target="_blank" rel="noopener">DeepSpeed Zero</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#using-torchcompile" target="_blank" rel="noopener">torch.compile</a></td>
          <td>Yes</td>
          <td>No</td>
      </tr>
      <tr>
          <td><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#using--peft" target="_blank" rel="noopener">Parameter-Efficient Fine Tuning (PEFT)</a></td>
          <td>No</td>
          <td>Yes</td>
      </tr>
  </tbody>
</table>
<h3 id="fp16">FP16</h3>
<blockquote>
<p>If your model doesn’t work well with mixed precision, for example if it wasn’t pretrained in mixed precision, you may encounter overflow or underflow issues which can cause NaN loss. For these cases, you should use full fp32 precision by explicitly disabling the default fp16 mode.</p>
</blockquote>
<h3 id="zero">ZERO</h3>
<p>stage 1 Optimizer state</p>
<p>stage 2 Optimizer state + gradient</p>
<p>stage 3 optimizer state + gradient + model parameters (weights)</p>
<p>The inference stage zero-1 zero-2 does nothing, only zero-3 can be set (no optimizer is needed for the inference stage and no gradient is generated). Also if Transformers&lt;4.28, you need to set <code>synced_gpus=True</code> when generating.</p>
<blockquote>
<p>Using multiple GPUs with ZeRO-3 for generation requires synchronizing the GPUs by setting <code>synced_gpus=True</code> in the <a href="https://huggingface.co/docs/transformers/main/en/model_doc/phi#transformers.PhiForCausalLM.generate" target="_blank" rel="noopener">generate()</a> method. Otherwise, if one GPU is finished generating before another one, the whole system hangs because the remaining GPUs haven’t received the weight shard from the GPU that finished first.</p>
<p>For Transformers&gt;=4.28, if <code>synced_gpus</code> is automatically set to <code>True</code> if multiple GPUs are detected during generation.</p>
</blockquote>
<p>If offload is configured, you need to choose an optimizer that is adapted to both CPU and GPU, and the commonly used Adam cannot be used.</p>
<blockquote>
<p>DeepSpeed and Transformers optimizer and scheduler can be mixed and matched as long as you don’t enable <code>offload_optimizer</code>. When <code>offload_optimizer</code> is enabled, you could use a <u>non-DeepSpeed optimizer</u> (except for LAMB) as long as it has <u>both a CPU and GPU implementation</u>.</p>
</blockquote>
<h2 id="multi-gpu-optimization">Multi-GPU Optimization</h2>
<p>Resource: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_many" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<p>It&rsquo;s mostly just a few latitudes of parallelism: Data + Pipeline + Tensor.</p>
<h2 id="confusion">Confusion</h2>
<h3 id="fp16-1">FP16</h3>
<p>Only speeds up the training process, <strong>not necessarily</strong> reduces the memory footprint (maybe even by a factor of 1.5).</p>
<blockquote>
<p>While mixed precision training results in faster computations, it can also lead to more GPU memory being utilized, especially for small batch sizes. <u>This is because the model is now present on the GPU in both 16-bit and 32-bit precision</u> (1.5x the original model on the GPU). From: <a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one#mixed-precision-training" target="_blank" rel="noopener">Hugging Face Doc</a></p>
<p><u>Note</u>: when using mixed precision with a small model and a large batch size, there will be some memory savings but with a large model and a small batch size, the memory use will be larger.</p>
</blockquote>
<h4 id="small-models-large-batch-sizes">Small models, large batch sizes</h4>
<ul>
<li><strong>MEMORY SAVINGS</strong>: For small models, the model parameters and weights take up relatively little memory. When training with large batch sizes, the memory occupied by activations and gradients becomes the main memory usage part. In this case, converting activations and gradients to FP16 can significantly reduce this portion of memory usage, as FP16 occupies half the memory of FP32. Even when considering the retention of FP32-accurate copies of the model weights, the overall memory usage is still reduced because the memory savings of the activations and gradients outweigh the memory overhead of the additional copies of the weights.</li>
<li><strong>EFFICIENCY AND SAVINGS</strong>: Large batch sizes mean that more data is processed per iteration, which increases the amount of memory required to compute activations and gradients. Since this part now uses FP16, the overall memory requirement is reduced compared to using only FP32.</li>
</ul>
<h4 id="large-model-small-batch-size">Large model, small batch size</h4>
<ul>
<li><strong>Increased memory usage</strong>: for large models, the model parameters and weights themselves take up a lot of memory. In mixed-precision training, even if the activations and gradients are stored as FP16, a copy of the FP32-precision weights still needs to be retained to ensure the accuracy of the updates. This means that the additional memory overhead (due to the FP32 copy of the weights) is a relatively large part of the total memory footprint relative to the size of the model itself. When the batch size is small, the activations and gradients take up relatively little memory, so the memory saving effect from FP16 is not enough to offset the additional memory usage added by keeping FP32 weight copies.</li>
<li><strong>Impact of weighted copies</strong>: in this case, the additional memory used by FP32 weighted copies becomes a significant factor because the model itself is large. Even if FP16 is used for activation and gradient, the total memory usage may still increase due to FP32 weighted copies.</li>
</ul>
<h3 id="gradient-accumulation">Gradient accumulation</h3>
<p>Effective batch = gradient accumulation * actual batch.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="n">training_args</span> <span class="o">=</span> <span class="n">TrainingArguments</span><span class="p">(</span><span class="n">per_device_train_batch_size</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="n">gradient_accumulation_steps</span><span class="o">=</span><span class="mi">4</span><span class="p">,</span> <span class="o">**</span><span class="n">default_args</span><span class="p">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>In the above example, your effective batch size becomes 4.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="cl"><span class="k">for</span> <span class="n">epoch</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">):</span> <span class="c1"># Assume 2 epochs of training</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="n">i</span><span class="p">,</span> <span class="p">(</span><span class="n">inputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">dataloader</span><span class="p">)::</span> <span class="n">inputs</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">inputs</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">float32</span><span class="p">):</span> <span class="c1"># Suppose train 2 epochs.</span>
</span></span><span class="line"><span class="cl">        <span class="n">inputs</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">inputs</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">float32</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">labels</span> <span class="o">=</span> <span class="n">torch</span><span class="o">.</span><span class="n">tensor</span><span class="p">(</span><span class="n">labels</span><span class="p">,</span> <span class="n">dtype</span><span class="o">=</span><span class="n">torch</span><span class="o">.</span><span class="n">long</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Forward propagation</span>
</span></span><span class="line"><span class="cl">        <span class="n">outputs</span> <span class="o">=</span> <span class="n">model</span><span class="p">(</span><span class="n">inputs</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">        <span class="n">loss</span> <span class="o">=</span> <span class="n">criterion</span><span class="p">(</span><span class="n">outputs</span><span class="p">,</span> <span class="n">labels</span><span class="p">)</span> <span class="o">/</span> <span class="n">accumulation_steps</span> <span class="c1"># Note that this is divided by the number of accumulated steps</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Backward propagation</span>
</span></span><span class="line"><span class="cl">        <span class="n">loss</span><span class="o">.</span><span class="n">backward</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">        <span class="c1"># Update model parameters every accumulation_steps</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">%</span> <span class="n">accumulation_steps</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="p">(</span><span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">dataloader</span><span class="p">)</span><span class="o">.</span>
</span></span><span class="line"><span class="cl">            <span class="n">optimizer</span><span class="o">.</span><span class="n">step</span><span class="p">()</span> <span class="c1"># update parameters</span>
</span></span><span class="line"><span class="cl">            <span class="n">optimizer</span><span class="o">.</span><span class="n">zero_grad</span><span class="p">()</span> <span class="c1"># clear the gradient</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>BP is required each time, but the optimizer updates the parameters only when the cumulative number of gradient steps is reached.</p>
<blockquote>
<p>optimizer.step() vs optimizer.zero_grad()</p>
<p>Normal training flow: zero_grad then step Avoid the gradient computed by previous batch to affect the current optimizer state.</p>
<p>Gradient accumulation process: step then zero_grad As the name suggests, we want to let the gradient accumulation take effect and then update the parameters at the end.</p>
</blockquote>
<p>Prioritize the <code>per_device_train_batch_size</code> setting that guarantees the GPU limit is reached before considering accumulation.</p>
<blockquote>
<p>While it is advised to max out GPU usage as much as possible, a high number of gradient accumulation steps can result in a more pronounced training slowdown. Consider the following example. Let’s say, the <code>per_device_train_batch_size=4</code> without gradient accumulation hits the GPU’s limit. If you would like to train with batches of size 64, do not set the <code>per_device_train_batch_size</code> to 1 and <code>gradient_accumulation_steps</code> to 64. Instead, keep <code>per_device_train_batch_size=4</code> and set <code>gradient_accumulation_steps=16</code>. This results in the same effective batch size while making better use of the available GPU resources.</p>
</blockquote>
<p>It is not known whether gradient accumulation causes excess memory usage. Or rather I don&rsquo;t think it does, I think the gradient just changes from one number to another number resulting from multiple accumulations, the data format doesn&rsquo;t change and the number of bytes taken up doesn&rsquo;t change. In practice it seems to have an effect, but I can&rsquo;t find a reason to rationalize it.</p>
<h2 id="reference">Reference</h2>
<p><a href="https://huggingface.co/docs/transformers/main/en/perf_train_gpu_one" target="_blank" rel="noopener">Hugging Face Doc</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Install CUDA and an NLP Stack with Conda (No Root)</title>
      <link>https://vccv.cc/en/article/cuda-conda-nlp.html</link>
      <pubDate>Sun, 10 Mar 2024 16:13:14 +0000</pubDate>
      <guid>https://vccv.cc/en/article/cuda-conda-nlp.html</guid>
      <description>How a non-root user can install a newer version of the transformers suite without being able to change the version of the installed cuda driver.</description>
      <content:encoded><![CDATA[<p>Non-ROOT users configure a remote CUDA server for a deep learning environment, below is an example of Pytorch.</p>
<h2 id="cuda-driver">CUDA driver</h2>
<p>Check the version of CUDA already installed on the server:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nvcc -V
</span></span></code></pre></td></tr></table>
</div>
</div><p>Showing version 11.4 here, but it doesn&rsquo;t matter. Next to check the driver version, this relates to the latest CUDA version that we can install in the conda virtual environment.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">nvidia-smi
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">### Output</span>
</span></span><span class="line"><span class="cl"><span class="c1">### Driver Version: 535.129.03   CUDA Version: 12.2</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Tips:</p>
<p>The CUDA Version shown here is 12.2, which is actually the latest CUDA version that the CUDA driver installed on the server supports to install, which means that the highest CUDA version we can install next is 12.2, and the CUDA version that has already been installed on this machine is 11.4.</p>
<p>Because we are a NON-ROOT user, we can&rsquo;t change the <u>installed driver version</u>, but we can install the new CUDA version through the Conda virtual environment.</p>
</blockquote>
<h2 id="conda">Conda</h2>
<p>When configuring python-related environments for non-root users, I extremely recommend using the conda package manager for dependency management (in fact, it&rsquo;s also recommended for those using R).</p>
<p>I&rsquo;m installing the miniconda version here (the minimized version), but you can also install anaconda (the full version).</p>
<p>The blog has been written about <a href="https://vccv.cc/en/article/conda-r-jupyter.html" target="_blank" rel="noopener">related content</a> before.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># I installed the environment with python 3.10</span>
</span></span><span class="line"><span class="cl">conda create -n torch <span class="nv">python</span><span class="o">=</span>3.10
</span></span><span class="line"><span class="cl">conda activate torch
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="pytorch">Pytorch</h2>
<p>You can check the Pytorch history release at <a href="https://pytorch.org/get-started/previous-versions/" target="_blank" rel="noopener">Pytorch History Release</a> and combine it with your own needs (e.g., [Colossal-AI](https:// colossalai.org/zh-Hans/docs/get_started/installation/) requires PyTorch &gt;= 1.11 and PyTorch &lt;= 2.1). I ended up with pytorch==2.1.0 and CUDA==11.8.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># CUDA 11.8</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Less than the maximum supported driver version 12.2 but more than the installed CUDA version 11.4</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Try not to jump to a bigger version</span>
</span></span><span class="line"><span class="cl"><span class="c1"># For example, if I have 11.4 installed on my machine, then I would install it with cuda=11.8. Does it seem to be a problem to install 12.1?</span>
</span></span><span class="line"><span class="cl">conda install <span class="nv">pytorch</span><span class="o">==</span>2.1.0 <span class="nv">torchvision</span><span class="o">==</span>0.16.0 <span class="nv">torchaudio</span><span class="o">==</span>2.1.0 pytorch-cuda<span class="o">=</span>11.8 -c pytorch -c nvidia
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Thinking:</p>
<p>As for why pytorch doesn&rsquo;t redistribute for some cuda versions, in this <a href="https://github.com/pytorch/pytorch/issues/75992" target="_blank" rel="noopener">issue</a> one of pytorch&rsquo;s developers explains that pytorch-cuda113 can be used on cuda114 This simply means that there is no need to re-release it, and that the 113 version can be used for the 114 version.</p>
<p><a href="/en/article/cuda-conda-nlp/image-20240315144020525_hu_9eded2ef2122ef6d.webp" data-fancybox="gallery" data-src="/en/article/cuda-conda-nlp/image-20240315144020525_hu_9eded2ef2122ef6d.webp" data-caption="pytorch-cuda">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/cuda-conda-nlp/image-20240315144020525_hu_3a061dabc4b08a2f.webp 480w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_f19a41cbd90fdf1c.webp 720w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_9aab27c2a1b42bac.webp 960w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_dc2bef92e49c5a29.webp 1440w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_9eded2ef2122ef6d.webp 2002w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2002"
                    height="442"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/cuda-conda-nlp/image-20240315144020525_hu_f19a41cbd90fdf1c.webp"
                    srcset="/en/article/cuda-conda-nlp/image-20240315144020525_hu_3a061dabc4b08a2f.webp 480w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_f19a41cbd90fdf1c.webp 720w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_9aab27c2a1b42bac.webp 960w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_dc2bef92e49c5a29.webp 1440w, /en/article/cuda-conda-nlp/image-20240315144020525_hu_9eded2ef2122ef6d.webp 2002w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="pytorch-cuda"
                    
                />
            </picture>
        </a></p>
</blockquote>
<p>Check availability</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">(</span>torch<span class="o">)</span> <span class="o">[</span>username/pwd<span class="o">]</span>$ python
</span></span><span class="line"><span class="cl">Python 3.10.13 <span class="o">(</span>main, Sep <span class="m">11</span> 2023, 13:44:35<span class="o">)</span> <span class="o">[</span>GCC 11.2.0<span class="o">]</span> on linux
</span></span><span class="line"><span class="cl">Type <span class="s2">&#34;help&#34;</span>, <span class="s2">&#34;copyright&#34;</span>, <span class="s2">&#34;credits&#34;</span> or <span class="s2">&#34;license&#34;</span> <span class="k">for</span> more information.
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; import torch
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; torch.cuda.is_available<span class="o">()</span>
</span></span><span class="line"><span class="cl">True
</span></span><span class="line"><span class="cl">&gt;&gt;&gt; exit<span class="o">()</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="cuda">CUDA</h2>
<p>At <a href="https://anaconda.org/nvidia/cuda" target="_blank" rel="noopener">Nvidia-Cuda</a> look for the CUDA version corresponding to the installed Pytorch, in my case 11.8.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># In nvidia, this channel doesn&#39;t even show a progress bar when downloading packages.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># It will only show 0% or 100%, but the download speed is fine, it&#39;s not walled off, just wait patiently.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Officially: conda install nvidia/label/cuda-11.8.0::cuda</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">conda install cuda -c nvidia/label/cuda-11.8.0
</span></span></code></pre></td></tr></table>
</div>
</div><p>At this point, enter the <code>nvcc -V</code> command to find that the installed version is now 11.8.</p>
<p><a href="/en/article/cuda-conda-nlp/image-20240315144208260_hu_6805f613f1d6bb40.webp" data-fancybox="gallery" data-src="/en/article/cuda-conda-nlp/image-20240315144208260_hu_6805f613f1d6bb40.webp" data-caption="nvcc -V">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/cuda-conda-nlp/image-20240315144208260_hu_ddb2ea133a6f7da9.webp 480w, /en/article/cuda-conda-nlp/image-20240315144208260_hu_77533de7f074319e.webp 720w, /en/article/cuda-conda-nlp/image-20240315144208260_hu_6805f613f1d6bb40.webp 916w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="916"
                    height="198"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/cuda-conda-nlp/image-20240315144208260_hu_77533de7f074319e.webp"
                    srcset="/en/article/cuda-conda-nlp/image-20240315144208260_hu_ddb2ea133a6f7da9.webp 480w, /en/article/cuda-conda-nlp/image-20240315144208260_hu_77533de7f074319e.webp 720w, /en/article/cuda-conda-nlp/image-20240315144208260_hu_6805f613f1d6bb40.webp 916w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="nvcc -V"
                    
                />
            </picture>
        </a></p>
<h3 id="cuda-installed-using-conda">Cuda installed using conda</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># This prevents programs that cannot find the CUDA (11.8) installed by conda from using the CUDA (11.4) that comes with the system.</span>
</span></span><span class="line"><span class="cl"><span class="nb">export</span> <span class="nv">CUDA_HOME</span><span class="o">=</span><span class="nv">$CONDA_PREFIX</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="extra">Extra</h2>
<h3 id="gcc-clang-g-clang">gcc clang g++ clang++</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># The server comes with a version of gcc that is too low and doesn&#39;t even support g++. Use conda to install it and it works straight away.</span>
</span></span><span class="line"><span class="cl">conda install -c conda-forge cxx-compiler
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="xformers">xformers</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Official repository suggested commands</span>
</span></span><span class="line"><span class="cl">conda install xformers -c xformers
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Be sure to double-check the package change log before confirming the installation.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># There is a chance that it could replace an installed version of pytorch, so don&#39;t install it.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Try adding -c nvidia -c pytorch and you should be fine.</span>
</span></span><span class="line"><span class="cl">conda install xformers -c xformers -c nvidia -c pytorch
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="transformers--datasets--accelerate">transformers &amp; datasets &amp; accelerate</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Installation with conda may not be the latest version</span>
</span></span><span class="line"><span class="cl">pip install transformers datasets accelerate -U
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="reference">Reference</h2>
<p><a href="https://anaconda.org/nvidia/cuda" target="_blank" rel="noopener">Nvidia-Cuda</a></p>
<p><a href="https://pytorch.org/get-started/previous-versions/" target="_blank" rel="noopener">Pytorch History Release</a></p>
<p><a href="https://github.com/pytorch/pytorch/issues/75992" target="_blank" rel="noopener">Pytorch Github Issue</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Capture the Star Rail Gacha URL on Rooted Android with HttpCanary</title>
      <link>https://vccv.cc/en/article/hkrpg-android-httpcanary.html</link>
      <pubDate>Sat, 06 May 2023 17:13:20 +0000</pubDate>
      <guid>https://vccv.cc/en/article/hkrpg-android-httpcanary.html</guid>
      <description>Some guides show how to sniff the Star Rail gacha URL on Android via ADB/PC. This walkthrough is for rooted tinkerers who want to capture traffic directly on-device. The steps are general enough for sniffing other apps too.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>I’ve seen several guides on sniffing the Star Rail gacha link on Android (ADB or desktop assisted). Thanks to the WeChat public account <em><a href="https://mp.weixin.qq.com/s/HS7TD189krbUJr4VbhWZCw" target="_blank" rel="noopener">星穹铁道工坊</a></em> for sharing.</p>
<blockquote>
<p>For Star Rail sniffing:</p>
<p>The simplest approach is on a PC or iOS. If you only have Android, the ADB method above is simpler for non-tinkerers.</p>
<p>The method here isn’t simple—it’s fairly involved. But hey, tinkering is about persistence.</p>
</blockquote>
<p>This guide targets rooted users who want to operate entirely on-device. The same approach works for other apps besides Star Rail.</p>
<h2 id="prep">Prep</h2>
<blockquote>
<p>Prerequisites:</p>
<ul>
<li><a href="https://github.com/topjohnwu/Magisk" target="_blank" rel="noopener">Magisk</a> installed (KernelSU unknown because we need Magisk modules)</li>
<li><a href="https://github.com/LSPosed/LSPosed" target="_blank" rel="noopener">LSPosed</a> installed (Xposed compatibility unknown)</li>
</ul>
</blockquote>
<p>Install these apps/modules:</p>
<ul>
<li>Http Canary (v3.3.6): packet capture (aka “Little Yellow Bird”)</li>
<li>AiWanJi Toolbox: fixes the Http Canary cert</li>
<li>TrustMeAlready &amp; JustTrustMe: <em>partially</em> handle apps that pin certificates</li>
<li>“CA certificate completion” Magisk module</li>
</ul>
<p>I’ve bundled them on Lanzou: <a href="https://yuesir.lanzoum.com/b03k88ype" target="_blank" rel="noopener">download</a> (password: <strong>ft5q</strong>). Steps below explain the setup.</p>
<h2 id="http-canary">Http Canary</h2>
<p>This section shows how to install Http Canary’s certificate into the system store on newer Android versions. You can also read the original (in Chinese) <a href="https://www.coolapk1s.com/feed/40140406" target="_blank" rel="noopener">here</a> by user 密西根碎冰蓝. My short version:</p>
<ul>
<li>
<p>Tip: in Shamiko choose <strong>Blacklist</strong> mode (default). Don’t hide root from Http Canary even if it already has root.</p>
</li>
<li>
<p>Flash the <strong>抓包CA证书补齐_18002.zip</strong> module via Magisk, reboot to apply.</p>
</li>
<li>
<p>Install and open Http Canary. If prompted to install a cert, tap <strong>Skip</strong>.</p>
<blockquote>
<p>We rely on the Magisk module to install the cert, not the in-app flow.</p>
</blockquote>
</li>
<li>
<p>Reopen Http Canary; it will still say the cert is missing. Force stop the app, install AiWanJi Toolbox (grant root via Magisk module mode), and run the fix:</p>
<p>Path: App-related -&gt; Third-party app assist -&gt; Http Canary cert fix.</p>
<p><a href="/en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp" data-caption="Cert fix">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_dfd2adf4bb9db0cb.webp 480w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp 720w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_7bd191d2c9b7bb1.webp 960w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="880"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_dfd2adf4bb9db0cb.webp 480w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_bb061566a262e711.webp 720w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_7bd191d2c9b7bb1.webp 960w, /en/article/hkrpg-android-httpcanary/71ad2311b501ab487e9a3c4aab1d68fa_hu_ff7a9939e7c169d9.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Cert fix"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>In Http Canary open the side menu -&gt; Settings -&gt; <strong>HttpCanary root certificate</strong>. The subtitle under <strong>Install HttpCanary root certificate</strong> should say <strong>Installed</strong>. If not, reinstall and repeat the step above.</p>
<p><a href="/en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp" data-caption="Cert installed">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_5b19a10905da0fd4.webp 480w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp 720w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_d47522c3b8f471c8.webp 960w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="432"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_5b19a10905da0fd4.webp 480w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_cbcd39549101103a.webp 720w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_d47522c3b8f471c8.webp 960w, /en/article/hkrpg-android-httpcanary/71fadae2e524ae6f917624f85c97aae6_hu_af5e12dea7c34ce5.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Cert installed"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>Tap <strong>Add root certificate to system (Root)</strong>, then tap Move and grant root. Even if the move fails, the setup still worked for me.</p>
<p><a href="/en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp" data-caption="Add to system">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_5ff767bc2374a9ce.webp 480w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp 720w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_10679293244fbf59.webp 960w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="279"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_5ff767bc2374a9ce.webp 480w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_95c72bee45c1b685.webp 720w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_10679293244fbf59.webp 960w, /en/article/hkrpg-android-httpcanary/d72c53d6c63d85664929c6b8be132a4a_hu_a7eb34704bd468fb.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Add to system"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>Flash the LSPosed modules <strong>JustTrustMe</strong> and <strong>TrustMeAlready</strong>, then tick the target apps (both modules need the app checked).</p>
<p><a href="/en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp" data-caption="JustTrustMe">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_140a48d6fa66e0b8.webp 480w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp 720w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_129553bd58c29c79.webp 960w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="934"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_140a48d6fa66e0b8.webp 480w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_2600d8f2d40a9148.webp 720w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_129553bd58c29c79.webp 960w, /en/article/hkrpg-android-httpcanary/45178b70c463265af680caddd3928ded_hu_79b3951fa54d5244.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="JustTrustMe"
                    
                />
            </picture>
        </a></p>
<p><a href="/en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp" data-caption="TrustMeAlready">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_36f02f5742230ddc.webp 480w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp 720w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_6fd5e63b01b04844.webp 960w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="913"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_36f02f5742230ddc.webp 480w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_af4520d166811373.webp 720w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_6fd5e63b01b04844.webp 960w, /en/article/hkrpg-android-httpcanary/604b8e25d070b048ab9dc06696edf7d9_hu_dd75299bcbab9386.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="TrustMeAlready"
                    
                />
            </picture>
        </a></p>
</li>
</ul>
<p>That’s all the environment setup.</p>
<h2 id="star-rail">Star Rail</h2>
<p>This part is Star Rail-specific, but the same logic applies to other apps.</p>
<blockquote>
<p>Note:</p>
<p>Even with this setup, some apps can’t be sniffed due to enhanced network security (e.g., banking apps). For those you’ll need other techniques (reverse-engineering, etc.). See <a href="https://bbs.kanxue.com/thread-276015.htm" target="_blank" rel="noopener">this thread</a>.</p>
</blockquote>
<p>Star Rail has similar protections—if you start capturing before entering the game you’ll see network errors. Instead, log in normally, enter the Warp page, then start Http Canary. Return to the Warp screen, view Details, then History to grab the data.</p>
<p><a href="/en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp" data-caption="Warp history link">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_3f3b9deee64890d.webp 480w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp 720w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_d07712a9351d22a9.webp 960w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_22311d46e5b56c1d.webp 1440w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp 2712w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2712"
                    height="1220"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_3f3b9deee64890d.webp 480w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_2658f1e2c9874df6.webp 720w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_d07712a9351d22a9.webp 960w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_22311d46e5b56c1d.webp 1440w, /en/article/hkrpg-android-httpcanary/b5ff3308b5a5db9490edb93c8b0b7801_hu_4e802951b1f0b1fd.webp 2712w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Warp history link"
                    
                />
            </picture>
        </a></p>
<p>Back in Http Canary, find the URL starting with <strong>api-takumi.mihoyo.com</strong>. Open it and long-press the highlighted area to copy.</p>
<p><a href="/en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp" data-fancybox="gallery" data-src="/en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp" data-caption="Long press to copy">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_40a9d29deb314144.webp 480w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp 720w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_d83b63099bb4db9f.webp 960w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1220"
                    height="659"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp"
                    srcset="/en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_40a9d29deb314144.webp 480w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_93999977f5914ff7.webp 720w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_d83b63099bb4db9f.webp 960w, /en/article/hkrpg-android-httpcanary/a76589c08727b37ff2f27c652f65b096_hu_fb83179d5098b799.webp 1220w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Long press to copy"
                    
                />
            </picture>
        </a></p>
<h2 id="wrap-up">Wrap-up</h2>
<p>Most of this post is about getting Http Canary running. For apps without heavy network hardening, that’s enough. For stricter apps, tailor the approach accordingly.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Switch Xcode Versions to Build Theos Tweaks</title>
      <link>https://vccv.cc/en/article/switch-xcode-theos.html</link>
      <pubDate>Mon, 24 Apr 2023 22:52:25 +0000</pubDate>
      <guid>https://vccv.cc/en/article/switch-xcode-theos.html</guid>
      <description>After recently replacing my device with a new one, I was about to recompile an iOS jailbreak plugin called PassBy, and found that it frequently reported errors. After a bit of troubleshooting and searching, I determined that switching Xcode to an older version was the easiest solution, so I documented it.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>Recently, I need to recompile an iOS jailbreak plugin named <a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">PassBy</a>, and found that it reported errors frequently on my new device, so I recorded the exploration and solution process below.</p>
<p>Since I&rsquo;m not a professional, and I don&rsquo;t even know much about iOS development, this is a record of my exploration with the attitude of learning. If there are any mistakes, welcome to criticize and correct in the comment section.</p>
<blockquote>
<p>By the way, I would like to advertise my other related article haha:</p>
<p><a href="https://vccv.cc/article/passby-fix.html" target="_blank" rel="noopener">iOS Jailbreak Plugin PassBy Customization</a>, documenting my attempts to solve PassBy&rsquo;s non-recognition of Bluetooth wearable devices other than the Apple Watch.</p>
</blockquote>
<h2 id="trying-to-compile">Trying to compile</h2>
<h3 id="firstly">Firstly</h3>
<blockquote>
<p>System: macOS Monterey 12.6.5</p>
<p>Chip type: Intel chip, not M series</p>
<p>Xcode version: 14.2</p>
</blockquote>
<p>I first tried to compile directly by typing <code>make package</code>, which prompted openURL has been deprecated.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315141449391_hu_c5f919f04345e0d0.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315141449391_hu_c5f919f04345e0d0.webp" data-caption="openurl deprecated">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141449391_hu_e365cfdc20a7c501.webp 480w, /en/article/switch-xcode-theos/image-20240315141449391_hu_67c8b62d4a3c7733.webp 720w, /en/article/switch-xcode-theos/image-20240315141449391_hu_e1367ead4f58da76.webp 960w, /en/article/switch-xcode-theos/image-20240315141449391_hu_68f840973dd62db9.webp 1440w, /en/article/switch-xcode-theos/image-20240315141449391_hu_c5f919f04345e0d0.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="714"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315141449391_hu_67c8b62d4a3c7733.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141449391_hu_e365cfdc20a7c501.webp 480w, /en/article/switch-xcode-theos/image-20240315141449391_hu_67c8b62d4a3c7733.webp 720w, /en/article/switch-xcode-theos/image-20240315141449391_hu_e1367ead4f58da76.webp 960w, /en/article/switch-xcode-theos/image-20240315141449391_hu_68f840973dd62db9.webp 1440w, /en/article/switch-xcode-theos/image-20240315141449391_hu_c5f919f04345e0d0.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="openurl deprecated"
                    
                />
            </picture>
        </a></p>
<p>At this point I guessed that the Xcode version was too high to cause the mismatch, and I was going to go to the <a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">source code</a> on GitHub first to see if the author had made any updates. Unfortunately, there was nothing I could do but try to modify the code.</p>
<p>According to the error message I first found the relevant c file, searched for the openURL keyword and commented out the relevant code.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315141626698_hu_dfdae32419d3d8dd.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315141626698_hu_dfdae32419d3d8dd.webp" data-caption="comment openURL code">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141626698_hu_6e704889c8ec55eb.webp 480w, /en/article/switch-xcode-theos/image-20240315141626698_hu_f9f2eb4dfce65af0.webp 720w, /en/article/switch-xcode-theos/image-20240315141626698_hu_24e680bd665d5ee8.webp 960w, /en/article/switch-xcode-theos/image-20240315141626698_hu_7de06ef5bd85d8fc.webp 1440w, /en/article/switch-xcode-theos/image-20240315141626698_hu_dfdae32419d3d8dd.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3360"
                    height="934"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315141626698_hu_f9f2eb4dfce65af0.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141626698_hu_6e704889c8ec55eb.webp 480w, /en/article/switch-xcode-theos/image-20240315141626698_hu_f9f2eb4dfce65af0.webp 720w, /en/article/switch-xcode-theos/image-20240315141626698_hu_24e680bd665d5ee8.webp 960w, /en/article/switch-xcode-theos/image-20240315141626698_hu_7de06ef5bd85d8fc.webp 1440w, /en/article/switch-xcode-theos/image-20240315141626698_hu_dfdae32419d3d8dd.webp 3360w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="comment openURL code"
                    
                />
            </picture>
        </a></p>
<p>Continue to look for, you can find that this is not affect the main function of the code, should be to perform a donation and source code to open the URL of the operation, because I am not familiar with Objective-C language, the simplest way is to directly comment out, but fortunately does not affect the main function of the plug-in. The two URLs I pasted below:</p>
<ul>
<li>Donate (Donate): <a href="https://paypal.me/giorgioiavicoli" target="_blank" rel="noopener">https://paypal.me/giorgioiavicoli</a></li>
<li>Source Code: <a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">https://github.com/giorgioiavicoli/PassBy</a></li>
</ul>
<p><a href="/en/article/switch-xcode-theos/image-20240315141700986_hu_4cb9f381a8c42340.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315141700986_hu_4cb9f381a8c42340.webp" data-caption="comment openURL code">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141700986_hu_970de69b88fc6f91.webp 480w, /en/article/switch-xcode-theos/image-20240315141700986_hu_1525860c695110e2.webp 720w, /en/article/switch-xcode-theos/image-20240315141700986_hu_405ca1aa82dfc4a1.webp 960w, /en/article/switch-xcode-theos/image-20240315141700986_hu_4cb9f381a8c42340.webp 1388w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1388"
                    height="344"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315141700986_hu_1525860c695110e2.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141700986_hu_970de69b88fc6f91.webp 480w, /en/article/switch-xcode-theos/image-20240315141700986_hu_1525860c695110e2.webp 720w, /en/article/switch-xcode-theos/image-20240315141700986_hu_405ca1aa82dfc4a1.webp 960w, /en/article/switch-xcode-theos/image-20240315141700986_hu_4cb9f381a8c42340.webp 1388w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="comment openURL code"
                    
                />
            </picture>
        </a></p>
<h3 id="secondly">Secondly</h3>
<p>Trying to continue compiling, unsurprisingly, a new problem arises.</p>
<p>This time, the problem is even more difficult, as theos is directly prompted by the Xcode compiler that it cannot find the Message framework.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315141745773_hu_535af8652e729a74.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315141745773_hu_535af8652e729a74.webp" data-caption="Message framework not found">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141745773_hu_d9611c7a4082079c.webp 480w, /en/article/switch-xcode-theos/image-20240315141745773_hu_9fdc990c4cdb4fe9.webp 720w, /en/article/switch-xcode-theos/image-20240315141745773_hu_6f23ded2c10eb603.webp 960w, /en/article/switch-xcode-theos/image-20240315141745773_hu_1b36bcc550c86fa4.webp 1440w, /en/article/switch-xcode-theos/image-20240315141745773_hu_535af8652e729a74.webp 2164w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2164"
                    height="730"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315141745773_hu_9fdc990c4cdb4fe9.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141745773_hu_d9611c7a4082079c.webp 480w, /en/article/switch-xcode-theos/image-20240315141745773_hu_9fdc990c4cdb4fe9.webp 720w, /en/article/switch-xcode-theos/image-20240315141745773_hu_6f23ded2c10eb603.webp 960w, /en/article/switch-xcode-theos/image-20240315141745773_hu_1b36bcc550c86fa4.webp 1440w, /en/article/switch-xcode-theos/image-20240315141745773_hu_535af8652e729a74.webp 2164w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Message framework not found"
                    
                />
            </picture>
        </a></p>
<p>This problem would not be something I could fix with a simple modification. My guess is that the newer versions of Xcode have discarded the framework, which leaves me with two options: either refactor the code (which would be too difficult for me to do), or switch to an older version of Xcode (which is a bit of an unknown quantity until I get my hands on it, and I can&rsquo;t guarantee that I&rsquo;ll be able to fix it).</p>
<p>I can only try to change the Xcode version.</p>
<h2 id="change-the-xcode-version">Change the Xcode version</h2>
<p>First check the current version, you can see that it is version 14.2.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315141951902_hu_1ec2e371565ba1a5.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315141951902_hu_1ec2e371565ba1a5.webp" data-caption="View version">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141951902_hu_87f0c569945233ee.webp 480w, /en/article/switch-xcode-theos/image-20240315141951902_hu_1ea760faee46f840.webp 720w, /en/article/switch-xcode-theos/image-20240315141951902_hu_81ec99dffb4ca0e7.webp 960w, /en/article/switch-xcode-theos/image-20240315141951902_hu_27709981de171d69.webp 1440w, /en/article/switch-xcode-theos/image-20240315141951902_hu_1ec2e371565ba1a5.webp 1480w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1480"
                    height="530"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315141951902_hu_1ea760faee46f840.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315141951902_hu_87f0c569945233ee.webp 480w, /en/article/switch-xcode-theos/image-20240315141951902_hu_1ea760faee46f840.webp 720w, /en/article/switch-xcode-theos/image-20240315141951902_hu_81ec99dffb4ca0e7.webp 960w, /en/article/switch-xcode-theos/image-20240315141951902_hu_27709981de171d69.webp 1440w, /en/article/switch-xcode-theos/image-20240315141951902_hu_1ec2e371565ba1a5.webp 1480w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="View version"
                    
                />
            </picture>
        </a></p>
<p>On the <a href="https://developer.apple.com/support/xcode/" target="_blank" rel="noopener">Xcode support page</a> you can clearly see the minimum system requirements for each Xcode version as well as the included SDKs and other information.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142009732_hu_35c102dffec9904c.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142009732_hu_35c102dffec9904c.webp" data-caption="Xcode version differences">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142009732_hu_6fb004ee24f4d441.webp 480w, /en/article/switch-xcode-theos/image-20240315142009732_hu_72c7fd7162d801b1.webp 720w, /en/article/switch-xcode-theos/image-20240315142009732_hu_a8fd321dab3244a4.webp 960w, /en/article/switch-xcode-theos/image-20240315142009732_hu_46471bab49d58bfe.webp 1440w, /en/article/switch-xcode-theos/image-20240315142009732_hu_35c102dffec9904c.webp 1654w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1654"
                    height="290"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142009732_hu_72c7fd7162d801b1.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142009732_hu_6fb004ee24f4d441.webp 480w, /en/article/switch-xcode-theos/image-20240315142009732_hu_72c7fd7162d801b1.webp 720w, /en/article/switch-xcode-theos/image-20240315142009732_hu_a8fd321dab3244a4.webp 960w, /en/article/switch-xcode-theos/image-20240315142009732_hu_46471bab49d58bfe.webp 1440w, /en/article/switch-xcode-theos/image-20240315142009732_hu_35c102dffec9904c.webp 1654w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Xcode version differences"
                    
                />
            </picture>
        </a></p>
<p>Next go to Apple&rsquo;s official download page about <a href="https://developer.apple.com/download/all/?q=xcode" target="_blank" rel="noopener">all versions of Xcode</a> and just download an older version. I downloaded version 12.5.1.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142032937_hu_2d101527363b0cd3.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142032937_hu_2d101527363b0cd3.webp" data-caption="Download version 12.5.1 of Xcode">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142032937_hu_b1aa277a8f45c7e3.webp 480w, /en/article/switch-xcode-theos/image-20240315142032937_hu_b50482f6b0327468.webp 720w, /en/article/switch-xcode-theos/image-20240315142032937_hu_1ff03dcd471df7ce.webp 960w, /en/article/switch-xcode-theos/image-20240315142032937_hu_9da855de5fc2f5b7.webp 1440w, /en/article/switch-xcode-theos/image-20240315142032937_hu_2d101527363b0cd3.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2392"
                    height="1144"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142032937_hu_b50482f6b0327468.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142032937_hu_b1aa277a8f45c7e3.webp 480w, /en/article/switch-xcode-theos/image-20240315142032937_hu_b50482f6b0327468.webp 720w, /en/article/switch-xcode-theos/image-20240315142032937_hu_1ff03dcd471df7ce.webp 960w, /en/article/switch-xcode-theos/image-20240315142032937_hu_9da855de5fc2f5b7.webp 1440w, /en/article/switch-xcode-theos/image-20240315142032937_hu_2d101527363b0cd3.webp 2392w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Download version 12.5.1 of Xcode"
                    
                />
            </picture>
        </a></p>
<p>The next step is to extract the .xip file, change the name of the extracted Xcode.app to a name like Xcode_12.5.app, and finally move it to the /Application directory.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142049748_hu_39826ceb05389ef7.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142049748_hu_39826ceb05389ef7.webp" data-caption="Unzip and rename">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142049748_hu_42695a99e749e09c.webp 480w, /en/article/switch-xcode-theos/image-20240315142049748_hu_39826ceb05389ef7.webp 642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="642"
                    height="160"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142049748_hu_39826ceb05389ef7.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142049748_hu_42695a99e749e09c.webp 480w, /en/article/switch-xcode-theos/image-20240315142049748_hu_39826ceb05389ef7.webp 642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Unzip and rename"
                    
                />
            </picture>
        </a></p>
<p>As you can see in the image above, my old version of Xcode doesn&rsquo;t open directly, but it doesn&rsquo;t matter for the purposes of this chapter, we don&rsquo;t need to open the old version of Xcode directly to operate it. Please read on to find out why.</p>
<blockquote>
<p>It takes a while to unpack, so be patient.</p>
<p>Alternatively, you can download and update Xcode in the usual way. With a multi-threaded download tool, you can basically run at full broadband speed and avoid App Store download failures. The disadvantage is that decompression is more time-consuming.</p>
</blockquote>
<h2 id="switch-development">Switch Development</h2>
<p>Note that the subtitle of this section is not &ldquo;Switching Xcode Versions&rdquo;, because for us, all we need is the scripting tools that come with older versions of Xcode in the development directory, such as gcc and so on.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142237680_hu_56a6b9bf26d7cb97.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142237680_hu_56a6b9bf26d7cb97.webp" data-caption="developer tools directory">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142237680_hu_25ff8ccb828c1ce0.webp 480w, /en/article/switch-xcode-theos/image-20240315142237680_hu_18a25fd760e3ec9d.webp 720w, /en/article/switch-xcode-theos/image-20240315142237680_hu_63de961a4a350280.webp 960w, /en/article/switch-xcode-theos/image-20240315142237680_hu_56a6b9bf26d7cb97.webp 1426w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1426"
                    height="536"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142237680_hu_18a25fd760e3ec9d.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142237680_hu_25ff8ccb828c1ce0.webp 480w, /en/article/switch-xcode-theos/image-20240315142237680_hu_18a25fd760e3ec9d.webp 720w, /en/article/switch-xcode-theos/image-20240315142237680_hu_63de961a4a350280.webp 960w, /en/article/switch-xcode-theos/image-20240315142237680_hu_56a6b9bf26d7cb97.webp 1426w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="developer tools directory"
                    
                />
            </picture>
        </a></p>
<p>Next just use this command to switch the xcode-select directory:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo xcode-select -s /Applications/<span class="o">{</span>modify here to a specific filename<span class="o">}</span>/Contents/Developer/
</span></span></code></pre></td></tr></table>
</div>
</div><p>Just change it to your old version of the file name, and enter the password without showing it.</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142300052_hu_83e406e4325579aa.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142300052_hu_83e406e4325579aa.webp" data-caption="switch path">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142300052_hu_db77e6fc44eb80cb.webp 480w, /en/article/switch-xcode-theos/image-20240315142300052_hu_33e411312bcb432e.webp 720w, /en/article/switch-xcode-theos/image-20240315142300052_hu_573389fd3d886b60.webp 960w, /en/article/switch-xcode-theos/image-20240315142300052_hu_83e406e4325579aa.webp 1078w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1078"
                    height="142"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142300052_hu_33e411312bcb432e.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142300052_hu_db77e6fc44eb80cb.webp 480w, /en/article/switch-xcode-theos/image-20240315142300052_hu_33e411312bcb432e.webp 720w, /en/article/switch-xcode-theos/image-20240315142300052_hu_573389fd3d886b60.webp 960w, /en/article/switch-xcode-theos/image-20240315142300052_hu_83e406e4325579aa.webp 1078w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="switch path"
                    
                />
            </picture>
        </a></p>
<p>At this point, enter the command again to verify:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">xcodebuild -version
</span></span><span class="line"><span class="cl">xcode-select -p
</span></span><span class="line"><span class="cl">gcc -v
</span></span><span class="line"><span class="cl">g++ -v
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/switch-xcode-theos/image-20240315142336388_hu_8981dc30cc383260.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142336388_hu_8981dc30cc383260.webp" data-caption="old version of gcc">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142336388_hu_7a77f00558e214e2.webp 480w, /en/article/switch-xcode-theos/image-20240315142336388_hu_482f1c64dfcf4e54.webp 720w, /en/article/switch-xcode-theos/image-20240315142336388_hu_55d740bccae06e30.webp 960w, /en/article/switch-xcode-theos/image-20240315142336388_hu_c6778e189c44eb41.webp 1440w, /en/article/switch-xcode-theos/image-20240315142336388_hu_8981dc30cc383260.webp 3176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="3176"
                    height="542"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142336388_hu_482f1c64dfcf4e54.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142336388_hu_7a77f00558e214e2.webp 480w, /en/article/switch-xcode-theos/image-20240315142336388_hu_482f1c64dfcf4e54.webp 720w, /en/article/switch-xcode-theos/image-20240315142336388_hu_55d740bccae06e30.webp 960w, /en/article/switch-xcode-theos/image-20240315142336388_hu_c6778e189c44eb41.webp 1440w, /en/article/switch-xcode-theos/image-20240315142336388_hu_8981dc30cc383260.webp 3176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="old version of gcc"
                    
                />
            </picture>
        </a></p>
<p>The output of all the above commands can be seen in the words of the name of the old version of Xcode file you chose, something like <strong>Xcode_12.5</strong>.</p>
<h2 id="thirdly">Thirdly</h2>
<p>Trying to compile again, the problem is finally solved.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yuesir at iMac in /Volumes/Data/Xcode/PassBy
</span></span><span class="line"><span class="cl">$ make package
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl">make<span class="o">[</span>2<span class="o">]</span>: Nothing to be <span class="k">done</span> <span class="k">for</span> <span class="s1">&#39;internal-library-compile&#39;</span>.
</span></span><span class="line"><span class="cl">&gt; Making all in passbyprefs…
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Compiling PassByRootListController.m <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Linking bundle PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Generating debug symbols <span class="k">for</span> PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Stripping PassByPrefs <span class="o">(</span>arm64e<span class="o">)</span>…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Merging bundle PassByPrefs…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Signing PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making all in passbyflipswitch…
</span></span><span class="line"><span class="cl">&gt; Making all <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; Copying resource directories into the bundle wrapper…
</span></span><span class="line"><span class="cl">make<span class="o">[</span>3<span class="o">]</span>: Nothing to be <span class="k">done</span> <span class="k">for</span> <span class="s1">&#39;internal-bundle-compile&#39;</span>.
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> tweak PassBy…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyprefs…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByPrefs…
</span></span><span class="line"><span class="cl">&gt; Making stage in passbyflipswitch…
</span></span><span class="line"><span class="cl">&gt; Making stage <span class="k">for</span> bundle PassByFlipswitch…
</span></span><span class="line"><span class="cl">dm.pl: building package <span class="sb">`</span>com.giorgioiavicoli.passby:iphoneos-arm<span class="s1">&#39; in `./packages/com.giorgioiavicoli.passby_1.9.5_iphoneos-arm.deb&#39;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>In fact, I tried to restore the above commented out code to normal, but I didn&rsquo;t realize that it still reported the same error!</p>
<p>I suspected that it might be a problem with the version of Command Line Tools installed. I didn&rsquo;t try it because I didn&rsquo;t know what would happen if I installed a lower version of Tools.</p>
</blockquote>
<h2 id="switch-back">Switch Back</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sudo xcode-select -s /Applications/Xcode.app/Contents/Developer/
</span></span></code></pre></td></tr></table>
</div>
</div><p>Simply verify it:</p>
<p><a href="/en/article/switch-xcode-theos/image-20240315142734101_hu_ce1e831a1af96d20.webp" data-fancybox="gallery" data-src="/en/article/switch-xcode-theos/image-20240315142734101_hu_ce1e831a1af96d20.webp" data-caption="Switch back to original version">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142734101_hu_8a6a9db08834231c.webp 480w, /en/article/switch-xcode-theos/image-20240315142734101_hu_50f56ae46a3cd14d.webp 720w, /en/article/switch-xcode-theos/image-20240315142734101_hu_fbb99a66c2aec6c7.webp 960w, /en/article/switch-xcode-theos/image-20240315142734101_hu_b64e48f9d475761b.webp 1440w, /en/article/switch-xcode-theos/image-20240315142734101_hu_ce1e831a1af96d20.webp 1584w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1584"
                    height="502"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/switch-xcode-theos/image-20240315142734101_hu_50f56ae46a3cd14d.webp"
                    srcset="/en/article/switch-xcode-theos/image-20240315142734101_hu_8a6a9db08834231c.webp 480w, /en/article/switch-xcode-theos/image-20240315142734101_hu_50f56ae46a3cd14d.webp 720w, /en/article/switch-xcode-theos/image-20240315142734101_hu_fbb99a66c2aec6c7.webp 960w, /en/article/switch-xcode-theos/image-20240315142734101_hu_b64e48f9d475761b.webp 1440w, /en/article/switch-xcode-theos/image-20240315142734101_hu_ce1e831a1af96d20.webp 1584w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Switch back to original version"
                    
                />
            </picture>
        </a></p>
<h2 id="script">Script</h2>
<p>Here&rsquo;s another script shared by others, but I didn&rsquo;t try it myself, so I&rsquo;m posting the link here as a thank you.</p>
<p>Link to the article: <a href="https://www.cnblogs.com/zndxall/p/12463744.html" target="_blank" rel="noopener">https://www.cnblogs.com/zndxall/p/12463744.html</a></p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://developer.apple.com/download/all/?q=xcode%2012.5.1" target="_blank" rel="noopener">Apple Xcode</a></p>
<p><a href="https://www.cnblogs.com/zndxall/p/12463744.html" target="_blank" rel="noopener">Xcode installs multiple versions and switches versions automatically</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Install the R Kernel for Jupyter with Homebrew</title>
      <link>https://vccv.cc/en/article/brew-r-jupyter.html</link>
      <pubDate>Mon, 16 Jan 2023 11:40:36 +0000</pubDate>
      <guid>https://vccv.cc/en/article/brew-r-jupyter.html</guid>
      <description>I introduced in another article in the Linux remote server using conda configuration r-kernel jupyter notebook, but I found that conda for a variety of dependency conflicts are not handled well, often leading to unsuccessful installation. In macOS system locally using brew for installation is much easier and faster. Here I summarized steps for reference.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>My other post describes using <a href="https://vccv.cc/en/article/conda-r-jupyter.html" target="_blank" rel="noopener">Conda installing R kernel Notebook</a> on a Linux remote server, but I&rsquo;ve found that conda doesn&rsquo;t handle various dependency conflicts very well, often resulting in installations that don&rsquo;t I found that conda doesn&rsquo;t handle dependency conflicts well, which often leads to unsuccessful installations.</p>
<p>Later, I also used brew to install it on my macOS system, and found that it was easier and faster, so I summarized the steps.</p>
<blockquote>
<p>System: macOS Venture 13.1 (22C65)</p>
<p>Product: Intel Chip MacBook</p>
</blockquote>
<h2 id="requirement">Requirement</h2>
<p>Install <a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a>.</p>
<p>Homebrew is the most used package manager on macOS, and this is its <a href="https://docs.brew.sh/Installation" target="_blank" rel="noopener">official installation tutorial</a>. But usually, we just need to enter the following command while making sure the network is accessible:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/bin/bash -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="r">R</h2>
<p>It is so easy to install r package with brew:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install r
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="jupyter">Jupyter</h2>
<p>Almost the same as before:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install jupyterlab
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="r-kernel">R-Kernel</h2>
<p>Use r to install <a href="https://github.com/IRkernel/IRkernel" target="_blank" rel="noopener">IRkernel</a>:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Go to the r console first</span>
</span></span><span class="line"><span class="cl">R
</span></span><span class="line"><span class="cl"><span class="c1"># Install devtools</span>
</span></span><span class="line"><span class="cl">install.packages<span class="o">(</span><span class="s1">&#39;IRkernel&#39;</span><span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="c1"># At this point you might be asked to choose a mirror, just choose the nearest one</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Register the kernel with R</span>
</span></span><span class="line"><span class="cl">IRkernel::installspec<span class="o">()</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Install the RStudio shortcut.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># If RStudio is installed, you can choose to install it, but not if you&#39;re using a notebook.</span>
</span></span><span class="line"><span class="cl">jupyter labextension install @techrah/text-shortcuts
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="launch-notebook">Launch Notebook</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><p>Click Create or New button and find that you can create r-kernel notebooks now.</p>
<h2 id="landscaping">Landscaping</h2>
<p>This part is not necessary and is for record only.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Configure themes</span>
</span></span><span class="line"><span class="cl">pip install jupyterthemes
</span></span><span class="line"><span class="cl"><span class="c1"># A set of theme settings that I personally like and have gotten used to</span>
</span></span><span class="line"><span class="cl">jt -t monokai -f fira -fs <span class="m">13</span> -cellw 90% -ofs <span class="m">11</span> -dfs <span class="m">11</span> -T -N
</span></span><span class="line"><span class="cl"><span class="c1"># Restore the default theme</span>
</span></span><span class="line"><span class="cl">jt -r
</span></span><span class="line"><span class="cl"><span class="c1"># Configure plugins</span>
</span></span><span class="line"><span class="cl">pip install jupyter_contrib_nbextensions
</span></span><span class="line"><span class="cl">jupyter contrib nbextension install --user
</span></span><span class="line"><span class="cl"><span class="c1"># Install the plugin manager This step may fail See update 1 later for details</span>
</span></span><span class="line"><span class="cl">pip install jupyter_nbextensions_configurator
</span></span><span class="line"><span class="cl"><span class="c1"># Suggested configuration items</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Hinterland code completion</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Collapsible headings</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Notify Notify mechanism to run time-consuming tasks and notify when they&#39;re done.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># zenmode Hide active status bar, easy to notice the code.</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ExecuteTime Show execution time</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="postscript">Postscript</h2>
<p>I didn&rsquo;t run into any snags with this installation, so if you run into any other issues, feel free to leave them in the comments section.</p>
<h2 id="update-1">Update 1</h2>
<p>When I repeated this tutorial on 2023.03.20, I found that the <strong>Nbextensions</strong> tag would not appear. Upon checking, this was caused by the plugin not being updated to adapt a new version of the dependency package nbclassic.</p>
<p>See the GitHub <a href="https://github.com/Jupyter-contrib/jupyter_nbextensions_configurator/issues/151" target="_blank" rel="noopener">issue</a> for details.</p>
<p>Solution: Downgrade the dependency package. We may update it later.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pip install <span class="s2">&#34;nbclassic&lt;0.5&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="update-2">Update 2</h2>
<p>2024.03.15 Update: The notebook was officially upgraded to version 7.x a couple months back. I haven&rsquo;t had to do any 3rd party manipulation with the new version. It can be changed directly inside the settings with a high degree of customization.</p>
<p><a href="/en/article/brew-r-jupyter/image-20240315140244649_hu_5d447b0f666c2bce.webp" data-fancybox="gallery" data-src="/en/article/brew-r-jupyter/image-20240315140244649_hu_5d447b0f666c2bce.webp" data-caption="notebook-setting">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/brew-r-jupyter/image-20240315140244649_hu_ae6f509b005b588d.webp 480w, /en/article/brew-r-jupyter/image-20240315140244649_hu_5e7e909fe76520ff.webp 720w, /en/article/brew-r-jupyter/image-20240315140244649_hu_c169a3dc8c4989d4.webp 960w, /en/article/brew-r-jupyter/image-20240315140244649_hu_f413b848ae2c2d64.webp 1440w, /en/article/brew-r-jupyter/image-20240315140244649_hu_5d447b0f666c2bce.webp 1938w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1938"
                    height="1136"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/brew-r-jupyter/image-20240315140244649_hu_5e7e909fe76520ff.webp"
                    srcset="/en/article/brew-r-jupyter/image-20240315140244649_hu_ae6f509b005b588d.webp 480w, /en/article/brew-r-jupyter/image-20240315140244649_hu_5e7e909fe76520ff.webp 720w, /en/article/brew-r-jupyter/image-20240315140244649_hu_c169a3dc8c4989d4.webp 960w, /en/article/brew-r-jupyter/image-20240315140244649_hu_f413b848ae2c2d64.webp 1440w, /en/article/brew-r-jupyter/image-20240315140244649_hu_5d447b0f666c2bce.webp 1938w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="notebook-setting"
                    
                />
            </picture>
        </a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Unix Terminal Setup with Oh My Zsh</title>
      <link>https://vccv.cc/en/article/omz-terminal.html</link>
      <pubDate>Wed, 07 Dec 2022 10:04:46 +0000</pubDate>
      <guid>https://vccv.cc/en/article/omz-terminal.html</guid>
      <description>macOS has now replaced the default shell with zsh, which is a perfect match for the Oh My Zsh project to achieve an unimaginable terminal experience. With its colorful themes, powerful plug-ins, and active community, the &amp;#34;Black Windows&amp;#34; is no longer the cold terminal interface it used to be, but a unique my zsh of your own!</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<h3 id="what-is-oh-my-zsh">What is Oh My Zsh</h3>
<ul>
<li><strong>Oh My Zsh</strong> is a community-driven command line tool, and as its homepage says, <strong>Oh My Zsh</strong> is a way of life. It is based on the <strong>zsh</strong> command line and offers theme configuration, plugin mechanism, and already built-in convenience operations. It gives us a whole new way to use the command line.</li>
<li><strong>Oh My Zsh</strong> is an extended toolset based on the <strong>zsh</strong> command line, providing a rich set of extended features.</li>
</ul>
<h3 id="official-website">Official Website</h3>
<p><a href="https://ohmyz.sh/" target="_blank" rel="noopener">Oh My Zsh official website</a></p>
<p>If you are interested in more, you can go to the official website for details.</p>
<h2 id="preparation">Preparation</h2>
<ul>
<li>
<p>Install <strong>zsh</strong> to replace bash, etc. The default shell for macOS systems is currently zsh, other Linux systems may need to install zsh first.</p>
<p>Ubuntu：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Install zsh</span>
</span></span><span class="line"><span class="cl">apt install zsh
</span></span><span class="line"><span class="cl"><span class="c1"># set zsh as the default shell (if you don&#39;t set it, start zsh with the direct zsh command)</span>
</span></span><span class="line"><span class="cl">chsh -s /bin/zsh
</span></span></code></pre></td></tr></table>
</div>
</div><p>Centos：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">yum install zsh
</span></span><span class="line"><span class="cl">chsh -s /bin/zsh
</span></span></code></pre></td></tr></table>
</div>
</div><p>Same for the others.</p>
</li>
<li>
<p>Install <strong>git</strong>, same as above using apt or yum package manager.</p>
</li>
<li>
<p>Finally you need <strong>curl</strong> or <strong>wget</strong>, install the same as above.</p>
</li>
</ul>
<h2 id="install">Install</h2>
<h3 id="curl-installation">curl installation</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="wget-installation">wget installation</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">sh -c <span class="s2">&#34;</span><span class="k">$(</span>wget https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh -O -<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>There is no difference between the two installs.</p>
<h2 id="themes">Themes</h2>
<p>I usually use the <strong>steeef</strong> theme that comes with it, which is pretty clean and easy to use.</p>
<p>If you want to change the theme, just edit the <code>~/.zshrc</code> file and replace ZSH_THEME with the theme you like after it.</p>
<p><a href="/en/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp" data-fancybox="gallery" data-src="/en/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp" data-caption="Change Theme">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/omz-terminal/image-20221209104217575_hu_aebdba3056600f52.webp 480w, /en/article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp 720w, /en/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp 960w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="960"
                    height="202"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp"
                    srcset="/en/article/omz-terminal/image-20221209104217575_hu_aebdba3056600f52.webp 480w, /en/article/omz-terminal/image-20221209104217575_hu_96d69bc5a1e59098.webp 720w, /en/article/omz-terminal/image-20221209104217575_hu_5e1d6ed8fb16d72c.webp 960w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Change Theme"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>The .zshrc file.</p>
<p>The <code>.zshrc</code> file does the same thing as the <code>.bashrc</code> file. The default shell for most unix systems used to be bash, and the .bashrc file is the configuration file for bash.</p>
<p>The relevant explanation in the online help file, as viewed with the man bash command, is as follows.
.bashrc - The individual per-interactive-shell startup file.</p>
<p>This file mainly stores personalized settings, such as command aliases, paths, etc.</p>
<p>Each time you modify .bashrc, use source ~/.bashrc (or . ~/.bashrc) to immediately load the modified settings and make them take effect. Typically .bashrc is called explicitly in the .bash_profile file.</p>
<p>When you log in to linux and start bash, it will first read the ~/.bash_profile file, so ~/.bashrc will be executed and your personalized settings will take effect.</p>
</blockquote>
<h2 id="plugins">Plugins</h2>
<p>The management of omz plugins is very simple, there are two plugins directories, where <strong>user</strong> is your username:</p>
<ul>
<li>
<p><strong>/Users/user/.oh-my-zsh/plugins</strong></p>
<p>The official plugins directory. This directory is already preloaded with many useful plugins, which only need to be activated manually.</p>
</li>
<li>
<p><strong>/Users/user/.oh-my-zsh/custom/plugins</strong></p>
<p>Third-party plugins directory, shortcut command: <code>$ZSH_CUSTOM/plugins</code>.</p>
</li>
</ul>
<p>To install the plugins, just download the plugins to the third-party plugins directory, and then add the name of the corresponding plugins to the <code>plugins</code> variable in the <code>~/.zshrc</code> configuration file.</p>
<h3 id="download-plugin">Download Plugin</h3>
<h4 id="zsh-syntax-highlighting">zsh-syntax-highlighting</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Command syntax highlighting</span>
</span></span><span class="line"><span class="cl">git clone https://github.com/zsh-users/zsh-syntax-highlighting.git <span class="si">${</span><span class="nv">ZSH_CUSTOM</span><span class="k">:-</span><span class="p">~/.oh-my-zsh/custom</span><span class="si">}</span>/plugins/zsh-syntax-highlighting
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp" data-fancybox="gallery" data-src="/en/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp" data-caption="Command syntax highlighting">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/omz-terminal/image-20221207141425504_hu_6e13f04f14dbcd91.webp 480w, /en/article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp 720w, /en/article/omz-terminal/image-20221207141425504_hu_ac57e4cb25cb9153.webp 960w, /en/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp 996w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="996"
                    height="424"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp"
                    srcset="/en/article/omz-terminal/image-20221207141425504_hu_6e13f04f14dbcd91.webp 480w, /en/article/omz-terminal/image-20221207141425504_hu_6abb72c853d42629.webp 720w, /en/article/omz-terminal/image-20221207141425504_hu_ac57e4cb25cb9153.webp 960w, /en/article/omz-terminal/image-20221207141425504_hu_9fda11391ad302f2.webp 996w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Command syntax highlighting"
                    
                />
            </picture>
        </a></p>
<h4 id="zsh-autosuggestions">zsh-autosuggestions</h4>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Command auto-completion</span>
</span></span><span class="line"><span class="cl">git clone https://github.com/zsh-users/zsh-autosuggestions <span class="si">${</span><span class="nv">ZSH_CUSTOM</span><span class="k">:-</span><span class="p">~/.oh-my-zsh/custom</span><span class="si">}</span>/plugins/zsh-autosuggestions
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp" data-fancybox="gallery" data-src="/en/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp" data-caption="Command auto-completion">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/omz-terminal/image-20221207141800253_hu_ab07db22097dda02.webp 480w, /en/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp 492w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="492"
                    height="188"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp"
                    srcset="/en/article/omz-terminal/image-20221207141800253_hu_ab07db22097dda02.webp 480w, /en/article/omz-terminal/image-20221207141800253_hu_71dd9e5788739c05.webp 492w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Command auto-completion"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>If you feel that <em>Tab key</em> is not convenient for completing, you can also customize the shortcut keys for completing.
For example, to set comma completion, just add the following line to <code>~/.zshrc</code> file.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">bindkey &#39;,&#39; autosuggest-accept
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="enable-plugin">Enable Plugin</h3>
<p>In the <strong>.zshrc</strong> file set.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">plugins</span><span class="o">=(</span>git zsh-syntax-highlighting zsh-autosuggestions<span class="o">)</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Enable other plugins in the same way.</p>
<h2 id="configuring-to-take-effect">Configuring to take effect</h2>
<p>One way to do this is to exit the terminal and reopen it, another, more common way is to use the <code>source</code> command I described earlier.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nb">source</span> ~/.zshrc
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="thanks">Thanks</h2>
<p><a href="https://ohmyz.sh/" target="_blank" rel="noopener">Oh My Zsh</a></p>
<p><a href="https://segmentfault.com/a/1190000018093021" target="_blank" rel="noopener">安装oh my zsh插件</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Lightweight Docker Setup on macOS</title>
      <link>https://vccv.cc/en/article/docker-macos.html</link>
      <pubDate>Sat, 05 Nov 2022 12:49:31 +0000</pubDate>
      <guid>https://vccv.cc/en/article/docker-macos.html</guid>
      <description>If you&amp;#39;re like me and don&amp;#39;t like the &amp;#34;bloat&amp;#34; of the official docker client, or simply want to try new things and tinker with new methods, then you&amp;#39;re welcome to read this post. Since the blogger is using macOS, this is only a record of exploration under Mac. If there are any errors of omission, please feel free to criticize and point them out in the comment section.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>If you don&rsquo;t like the &ldquo;bloat&rdquo; of the official docker client, like me, and just want a separate and pure docker service without a GUI, or just want to try new things and tinker with new methods, then you are welcome to read this article.</p>
<p>Since I am using macOS, there is only one exploration record under Mac. If there are any omissions and errors, please feel free to criticize and point them out in the comment section.</p>
<blockquote>
<p>Computer environment for this article.</p>
<p>System：macOS Ventura 13.0.1 (22A400)</p>
<p>CPU：Intel Core i5（not sure if <em>Apple M series</em> processors are common）</p>
</blockquote>
<h2 id="preparation">Preparation</h2>
<ul>
<li>
<p>Install <a href="https://brew.sh/" target="_blank" rel="noopener">Homebrew</a>.</p>
<p>Homebrew is the most used package manager under macOS platform, and this is its <a href="https://docs.brew.sh/Installation" target="_blank" rel="noopener">official installation tutorial</a>. But usually, we just need to enter the following command while making sure the network is open.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/bin/bash -c <span class="s2">&#34;</span><span class="k">$(</span>curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh<span class="k">)</span><span class="s2">&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="install-packages">Install packages</h2>
<ul>
<li>
<p>Use Homebrew to install docker.</p>
<p>Installing the most basic docker service is also very simple and can be done with one command.</p>
<p>Remember not to use the <code>brew install docker --cask</code> command, this will install docker graphically on macOS!!!</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>Installing Colima with Homebrew.</p>
<p><a href="https://github.com/abiosoft/colima" target="_blank" rel="noopener">Colima</a> takes its name from Container on Lima. <a href="https://github.com/lima-vm/lima" target="_blank" rel="noopener">Lima</a> is a virtual machine tool that enables automatic file sharing, port forwarding, and containerd.</p>
<p>Colima actually starts a virtual machine named <strong>colima</strong> through Lima. It helps us to simplify the usage process, but of course it is less customizable. If you are interested, you can of course use Lima to do the process manually yourself, which is more customizable, but more complex.</p>
<p>The installation is also very simple and is done with one command.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install colima
</span></span></code></pre></td></tr></table>
</div>
</div><p>This should take much longer to download, which is normal. As you can see below, Colima has a lot of dependencies.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ brew deps colima
</span></span><span class="line"><span class="cl">bdw-gc
</span></span><span class="line"><span class="cl">ca-certificates
</span></span><span class="line"><span class="cl">capstone
</span></span><span class="line"><span class="cl">gettext
</span></span><span class="line"><span class="cl">glib
</span></span><span class="line"><span class="cl">gmp
</span></span><span class="line"><span class="cl">gnutls
</span></span><span class="line"><span class="cl">guile
</span></span><span class="line"><span class="cl">jpeg-turbo
</span></span><span class="line"><span class="cl">libevent
</span></span><span class="line"><span class="cl">libidn2
</span></span><span class="line"><span class="cl">libnghttp2
</span></span><span class="line"><span class="cl">libpng
</span></span><span class="line"><span class="cl">libslirp
</span></span><span class="line"><span class="cl">libssh
</span></span><span class="line"><span class="cl">libtasn1
</span></span><span class="line"><span class="cl">libtool
</span></span><span class="line"><span class="cl">libunistring
</span></span><span class="line"><span class="cl">libusb
</span></span><span class="line"><span class="cl">lima
</span></span><span class="line"><span class="cl">lz4
</span></span><span class="line"><span class="cl">lzo
</span></span><span class="line"><span class="cl">m4
</span></span><span class="line"><span class="cl">ncurses
</span></span><span class="line"><span class="cl">nettle
</span></span><span class="line"><span class="cl">openssl@1.1
</span></span><span class="line"><span class="cl">p11-kit
</span></span><span class="line"><span class="cl">pcre2
</span></span><span class="line"><span class="cl">pixman
</span></span><span class="line"><span class="cl">pkg-config
</span></span><span class="line"><span class="cl">qemu
</span></span><span class="line"><span class="cl">readline
</span></span><span class="line"><span class="cl">snappy
</span></span><span class="line"><span class="cl">unbound
</span></span><span class="line"><span class="cl">vde
</span></span><span class="line"><span class="cl">xz
</span></span><span class="line"><span class="cl">zstd
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ul>
<h2 id="start-colima">Start Colima</h2>
<p>The official installation documentation describes that creating a docker runtime environment requires only the simplest command.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">colima start
</span></span></code></pre></td></tr></table>
</div>
</div><p>Perhaps this is also the reason why the author has optimized the process specifically for docker, which is why I recommend using colima, it&rsquo;s simple enough.</p>
<p><a href="/en/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp" data-caption="Colima Run">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20221205160750680_hu_e3ed76cda5baa397.webp 480w, /en/article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp 720w, /en/article/docker-macos/image-20221205160750680_hu_cbea94180668f26f.webp 960w, /en/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="338"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp"
                    srcset="/en/article/docker-macos/image-20221205160750680_hu_e3ed76cda5baa397.webp 480w, /en/article/docker-macos/image-20221205160750680_hu_ce292810ed12db23.webp 720w, /en/article/docker-macos/image-20221205160750680_hu_cbea94180668f26f.webp 960w, /en/article/docker-macos/image-20221205160750680_hu_c85422a993811e16.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Colima Run"
                    
                />
            </picture>
        </a></p>
<h2 id="boot-up">Boot-up</h2>
<blockquote>
<p>2023.12.20 Update:</p>
<p>Based on feedback from comments, colima already supports boot-up.</p>
<p>The method is also simple, since we installed colima using brew, we can just take over directly using <code>brew service</code>.</p>
<p><a href="/en/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp" data-caption="Boot-up">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20231220215607833_hu_186dfc3bfe614db5.webp 480w, /en/article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp 720w, /en/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp 958w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="958"
                    height="172"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp"
                    srcset="/en/article/docker-macos/image-20231220215607833_hu_186dfc3bfe614db5.webp 480w, /en/article/docker-macos/image-20231220215607833_hu_3a2328186c2a696c.webp 720w, /en/article/docker-macos/image-20231220215607833_hu_6f95cdf5a48ccc0e.webp 958w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Boot-up"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew services start colima
</span></span></code></pre></td></tr></table>
</div>
</div><p>If you are using other ways to install, make good use of search engines. Or follow the tip from comments by adding the <code>-foreground</code> parameter to set it up (<em>untested</em>).</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">colima start –foreground
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<p><del>Although Colima still doesn&rsquo;t provide such a feature so far, it is <a href="https://github.com/abiosoft/colima/issues/96" target="_blank" rel="noopener">in development</a>.</del></p>
<p><del>Alternatively, for simple single-container docker use, we can create our own shell scripts and set the startup entries to achieve the same effect.</del></p>
<ul>
<li>
<p><del>To create the shell script.</del></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch colima.sh
</span></span><span class="line"><span class="cl">chmod +x colima.sh
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><del>Modify the contents of the script.</del></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">vim colima.sh
</span></span></code></pre></td></tr></table>
</div>
</div><div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Just write the start command to colima.sh</span>
</span></span><span class="line"><span class="cl">colima start
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><del>Add to the login entry.</del></p>
<p><del><a href="/en/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp" data-caption="Login Entry">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20221213120548391_hu_d55e12072a00333b.webp 480w, /en/article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp 720w, /en/article/docker-macos/image-20221213120548391_hu_ab749c64f61848b8.webp 960w, /en/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp 990w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="990"
                    height="550"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp"
                    srcset="/en/article/docker-macos/image-20221213120548391_hu_d55e12072a00333b.webp 480w, /en/article/docker-macos/image-20221213120548391_hu_b967e8e3b153bd3c.webp 720w, /en/article/docker-macos/image-20221213120548391_hu_ab749c64f61848b8.webp 960w, /en/article/docker-macos/image-20221213120548391_hu_72f0c58ec4ebc493.webp 990w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Login Entry"
                    
                />
            </picture>
        </a></del></p>
</li>
<li>
<p><del>Set the default open method to your terminal program.</del></p>
<p><del><a href="/en/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp" data-caption="Default iTerm2">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20221213121901639_hu_b9784d0adc4ae390.webp 480w, /en/article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp 720w, /en/article/docker-macos/image-20221213121901639_hu_37e806338b1d0bc7.webp 960w, /en/article/docker-macos/image-20221213121901639_hu_d8a7ae63a5208d35.webp 1440w, /en/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1850"
                    height="972"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp"
                    srcset="/en/article/docker-macos/image-20221213121901639_hu_b9784d0adc4ae390.webp 480w, /en/article/docker-macos/image-20221213121901639_hu_6548563fce583dd0.webp 720w, /en/article/docker-macos/image-20221213121901639_hu_37e806338b1d0bc7.webp 960w, /en/article/docker-macos/image-20221213121901639_hu_d8a7ae63a5208d35.webp 1440w, /en/article/docker-macos/image-20221213121901639_hu_c7b53f85fb758a35.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Default iTerm2"
                    
                />
            </picture>
        </a></del></p>
</li>
</ul>
<h2 id="enjoy">Enjoy</h2>
<p>It&rsquo;s that simple, and the docker service is up and running. Type <code>docker ps -a</code> and simply test to see if it runs successfully. If you still have errors, keep reading on.</p>
<p><a href="/en/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp" data-caption="Docker Run">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20221205160832483_hu_8c17874b518583bf.webp 480w, /en/article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp 720w, /en/article/docker-macos/image-20221205160832483_hu_490a2af54ecb5cfb.webp 960w, /en/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp 1110w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1110"
                    height="150"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp"
                    srcset="/en/article/docker-macos/image-20221205160832483_hu_8c17874b518583bf.webp 480w, /en/article/docker-macos/image-20221205160832483_hu_15e72e63a2f6d581.webp 720w, /en/article/docker-macos/image-20221205160832483_hu_490a2af54ecb5cfb.webp 960w, /en/article/docker-macos/image-20221205160832483_hu_7f666cfe506ee63f.webp 1110w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Docker Run"
                    
                />
            </picture>
        </a></p>
<h2 id="troubleshooting">Troubleshooting</h2>
<p><a href="/en/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp" data-fancybox="gallery" data-src="/en/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp" data-caption="Docker No Service">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-macos/image-20221205153421353_hu_aaeffb07028a25b5.webp 480w, /en/article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp 720w, /en/article/docker-macos/image-20221205153421353_hu_cac7d65a031c6088.webp 960w, /en/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp 1396w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1396"
                    height="118"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp"
                    srcset="/en/article/docker-macos/image-20221205153421353_hu_aaeffb07028a25b5.webp 480w, /en/article/docker-macos/image-20221205153421353_hu_ccbf2adf077fb7d9.webp 720w, /en/article/docker-macos/image-20221205153421353_hu_cac7d65a031c6088.webp 960w, /en/article/docker-macos/image-20221205153421353_hu_64e1642e091ed315.webp 1396w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Docker No Service"
                    
                />
            </picture>
        </a></p>
<p>The diagram indicates that the docker service is not running, which is a problem with the colima configuration. You can try to reinstall Colima or re-run <code>colima start</code> to check if it is resolved.</p>
<h2 id="additional">Additional</h2>
<ul>
<li>
<p>You can further install <strong>docker-compose</strong> to use it.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">brew install docker-compose
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>If you want to run multiple containers, you can make configuration changes to the containers created by Colima.</p>
<p>Colima&rsquo;s default resource configuration is 2 CPU / 2 G memory, which may not be enough in some cases. For example, if you start three mysql instances with docker-compose, it will happen that at least one of them will not start properly.</p>
<p>In this case, you can change the default configuration with the <code>-c</code> and <code>-m</code> start parameters, or with <code>colima start --edit</code>.</p>
</li>
</ul>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/abiosoft/colima" target="_blank" rel="noopener">Colima</a></p>
<p><a href="https://github.com/lima-vm/lima" target="_blank" rel="noopener">Lima</a></p>
<p><a href="https://www.docker.com/" target="_blank" rel="noopener">Docker</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Install the R Kernel for Jupyter with Conda</title>
      <link>https://vccv.cc/en/article/conda-r-jupyter.html</link>
      <pubDate>Mon, 10 Oct 2022 17:27:01 +0000</pubDate>
      <guid>https://vccv.cc/en/article/conda-r-jupyter.html</guid>
      <description>Due to the author&amp;#39;s frequent use of conda to configure the R kernel jupyter notebook on Linux remote servers, some steps are forgotten over time (the main problem is that the same pit will be stepped on differently every time). After summarizing the relevant tutorials and personal experience on the internet, a guide is provided for everyone and future me to refer to.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>Due to the author&rsquo;s frequent use of conda to configure the R kernel jupyter notebook on Linux remote servers, some steps are forgotten over time (the main problem is that the same pit will be stepped on differently every time).</p>
<p>After summarizing the relevant tutorials and personal experience on the internet, a guide is provided for everyone and future me to refer to.</p>
<h2 id="guide">Guide</h2>
<h3 id="install-conda">Install Conda</h3>
<blockquote>
<p>To start with an introduction to Conda, Anaconda and some of the connections between them.</p>
<p><a href="https://conda.io/" target="_blank" rel="noopener">Conda</a> is a package manager that supports binary packages, so you don&rsquo;t need to compile from source when installing, and you can also install native libraries. However, some of the Python libraries in pip are not found in conda.</p>
<ul>
<li><a href="https://anaconda.org/anaconda/" target="_blank" rel="noopener">Anaconda</a> is a Python scientific computing distribution managed with Conda.</li>
<li><a href="https://conda-forge.org/" target="_blank" rel="noopener">Conda Forge</a> is another Python distribution that is more package rich than Anaconda. But one pitfall here is that Conda Forge and Anaconda <strong>are not fully compatible</strong>, so if you have a project that uses packages from both Anaconda and Conda Forge, there is a chance that it will hang.</li>
</ul>
</blockquote>
<p>Usually the servers I use have Anaconda installed beforehand,</p>
<p>Here is the official Anaconda <strong><a href="https://docs.anaconda.com/anaconda/install/linux/" target="_blank" rel="noopener">Installing Anaconda on Linux</a></strong> document with detailed step-by-step instructions and command explanations.</p>
<p><del>2022.10.17 Update Linux - Anaconda installation process under Centos7.</del></p>
<p><del>Due to the special domestic environment, it is still recommended to download Anaconda installation scripts directly from domestic sources such as <a href="https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?C=M&amp;O=D" target="_blank" rel="noopener">Tsinghua University Mirror Source</a>, usually choosing the <strong>x86_64 version</strong> of.</del></p>
<p><a href="/en/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp" data-caption="Mirror Source">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221017223737389_hu_67526115fbcf0afe.webp 480w, /en/article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp 720w, /en/article/conda-r-jupyter/image-20221017223737389_hu_6461f068d7524d47.webp 960w, /en/article/conda-r-jupyter/image-20221017223737389_hu_cb8bfdc0e2d080ae.webp 1440w, /en/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1572"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221017223737389_hu_67526115fbcf0afe.webp 480w, /en/article/conda-r-jupyter/image-20221017223737389_hu_d0411eba4621dc5e.webp 720w, /en/article/conda-r-jupyter/image-20221017223737389_hu_6461f068d7524d47.webp 960w, /en/article/conda-r-jupyter/image-20221017223737389_hu_cb8bfdc0e2d080ae.webp 1440w, /en/article/conda-r-jupyter/image-20221017223737389_hu_96426011afab3f0e.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Mirror Source"
                    
                />
            </picture>
        </a></p>
<p>Chrome can be downloaded by right clicking and copying the file link address and then using wget in centos:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Download script</span>
</span></span><span class="line"><span class="cl">wget https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/Anaconda3-2022.05-Linux-x86_64.sh
</span></span><span class="line"><span class="cl"><span class="c1"># If prompted without wget use yum install</span>
</span></span><span class="line"><span class="cl">yum install wget
</span></span><span class="line"><span class="cl"><span class="c1"># Execute the installation script Change the script name yourself</span>
</span></span><span class="line"><span class="cl">bash Anaconda3-2022.05-Linux-x86_64.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>Here are some options I encountered myself, for the record. Please follow the script prompts as you see fit and enter.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Follow the prompt and type ENTER (enter)</span>
</span></span><span class="line"><span class="cl">Welcome to Anaconda3 2022.05
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">In order to <span class="k">continue</span> the installation process, please review the license
</span></span><span class="line"><span class="cl">agreement.
</span></span><span class="line"><span class="cl">Please, press ENTER to <span class="k">continue</span>
</span></span><span class="line"><span class="cl">&gt;&gt; ENTER
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Follow the prompts and enter yes</span>
</span></span><span class="line"><span class="cl">Do you accept the license terms?
</span></span><span class="line"><span class="cl"><span class="o">[</span>no<span class="o">]</span> &gt;&gt;&gt;
</span></span><span class="line"><span class="cl">Please answer <span class="s1">&#39;yes&#39;</span> or <span class="s1">&#39;no&#39;</span>:<span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">&gt;&gt;&gt; yes
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># Follow the prompts and type ENTER (enter)
</span></span></span><span class="line"><span class="cl"><span class="s1"># Anaconda3 will now be installed into this location:
</span></span></span><span class="line"><span class="cl"><span class="s1">/root/anaconda3
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Press ENTER to confirm the location
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Press CTRL-C to abort the installation
</span></span></span><span class="line"><span class="cl"><span class="s1">  - Or specify a different location below
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">[/root/anaconda3] &gt;&gt;&gt; ENTER
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># conda initialization default no recommend entering yes
</span></span></span><span class="line"><span class="cl"><span class="s1"># If you choose no, you need to configure the environment variables yourself (Baidu keyword anaconda environment variables)
</span></span></span><span class="line"><span class="cl"><span class="s1">installation finished.
</span></span></span><span class="line"><span class="cl"><span class="s1">Do you wish the installer to initialize Anaconda3 by running conda init?
</span></span></span><span class="line"><span class="cl"><span class="s1">Do you want the installer to initialize Anaconda3 by running conda init?
</span></span></span><span class="line"><span class="cl"><span class="s1">[no] &gt;&gt;&gt; yes
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># Here are some tips, briefly translated
</span></span></span><span class="line"><span class="cl"><span class="s1"># For conda to take effect you need to close and reopen the current shell (reconnect to ssh)
</span></span></span><span class="line"><span class="cl"><span class="s1"># If you don&#39;</span>t need to activate the conda base environment at startup enter conda config --set auto_activate_base <span class="nb">false</span>
</span></span><span class="line"><span class="cl"><span class="o">==</span>&gt; For changes to take effect, close and re-open your current shell.
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">If you<span class="s1">&#39;d prefer that conda&#39;</span>s base environment not be activated on startup,
</span></span><span class="line"><span class="cl">   <span class="nb">set</span> the auto_activate_base parameter to false:
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">conda config --set auto_activate_base <span class="nb">false</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><del>Anaconda is now installed, and by the way it is recommended to add domestic sources:</del></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Only for Chinese</span>
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/main/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/pkgs/free/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/conda-forge/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/msys2/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/bioconda/
</span></span><span class="line"><span class="cl">conda config --add channels https://mirrors.ustc.edu.cn/anaconda/cloud/menpo/
</span></span><span class="line"><span class="cl">conda config --set show_channel_urls yes
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp" data-caption="For Chinese">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221017233347844_hu_db5a4a88af66a656.webp 480w, /en/article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp 720w, /en/article/conda-r-jupyter/image-20221017233347844_hu_803415409bf7b46f.webp 960w, /en/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp 1052w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1052"
                    height="280"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221017233347844_hu_db5a4a88af66a656.webp 480w, /en/article/conda-r-jupyter/image-20221017233347844_hu_ba7b8f85f9f0237c.webp 720w, /en/article/conda-r-jupyter/image-20221017233347844_hu_803415409bf7b46f.webp 960w, /en/article/conda-r-jupyter/image-20221017233347844_hu_3fda9d92640c4dac.webp 1052w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="For Chinese"
                    
                />
            </picture>
        </a></p>
<h3 id="creating-environment">Creating Environment</h3>
<p>I am creating a new conda environment directly to avoid dependency conflicts with the least effort.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># View existing conda environments</span>
</span></span><span class="line"><span class="cl">conda env list
</span></span><span class="line"><span class="cl"><span class="c1"># Create a new environment by name</span>
</span></span><span class="line"><span class="cl"><span class="c1"># your_new_name_to_conda Replace with the name of the environment you want</span>
</span></span><span class="line"><span class="cl">conda create -n your_new_name_to_conda
</span></span><span class="line"><span class="cl"><span class="c1"># Activate the new environment</span>
</span></span><span class="line"><span class="cl">conda activate your_new_name_to_conda
</span></span><span class="line"><span class="cl"><span class="c1"># Check the installed dependencies</span>
</span></span><span class="line"><span class="cl"><span class="c1"># The new environment is, of course, free of anything</span>
</span></span><span class="line"><span class="cl">conda list
</span></span><span class="line"><span class="cl"><span class="c1"># Quit the new environment</span>
</span></span><span class="line"><span class="cl">conda deactivate
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp" data-caption="CLI Conda">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010174813001_hu_3152919ce551edc.webp 480w, /en/article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp 720w, /en/article/conda-r-jupyter/image-20221010174813001_hu_bdef54328209d3a6.webp 960w, /en/article/conda-r-jupyter/image-20221010174813001_hu_153412c75d27f165.webp 1440w, /en/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp 2088w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2088"
                    height="1236"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010174813001_hu_3152919ce551edc.webp 480w, /en/article/conda-r-jupyter/image-20221010174813001_hu_7019c8a703e3466d.webp 720w, /en/article/conda-r-jupyter/image-20221010174813001_hu_bdef54328209d3a6.webp 960w, /en/article/conda-r-jupyter/image-20221010174813001_hu_153412c75d27f165.webp 1440w, /en/article/conda-r-jupyter/image-20221010174813001_hu_a591c99a2b1f6762.webp 2088w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="CLI Conda"
                    
                />
            </picture>
        </a></p>
<h3 id="install-r">Install R</h3>
<p>Note here that you <strong>cannot</strong> use <code>conda install r</code> directly to install R.</p>
<p>If you enter the above command directly, you will be installing version 3.6 (I think) of R. This version is too old and many R packages are not available. As of 2022.10.10, the latest version of R&rsquo;s conda is 4.2.1.</p>
<p>The following will explain how to install the latest version of R (4.2.1).</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># conda install r-base via conda-forge</span>
</span></span><span class="line"><span class="cl">conda install -c conda-forge r-base
</span></span></code></pre></td></tr></table>
</div>
</div><p>conda-forge is also described at the beginning of the article, I feel it can be understood as a distribution inside Linux, maybe?</p>
<p>Before confirming the installation (i.e. before entering y), you can make sure beforehand if the version of r-base is version 4 or higher (currently 4.2.1).</p>
<p><a href="/en/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp" data-caption="4.2.1 version">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010182224588_hu_1749abbe2a720ffd.webp 480w, /en/article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp 720w, /en/article/conda-r-jupyter/image-20221010182224588_hu_5eab3cb009e79080.webp 960w, /en/article/conda-r-jupyter/image-20221010182224588_hu_fb6b8f7bb19ca795.webp 1440w, /en/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp 1754w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1754"
                    height="928"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010182224588_hu_1749abbe2a720ffd.webp 480w, /en/article/conda-r-jupyter/image-20221010182224588_hu_ac14736517963e83.webp 720w, /en/article/conda-r-jupyter/image-20221010182224588_hu_5eab3cb009e79080.webp 960w, /en/article/conda-r-jupyter/image-20221010182224588_hu_fb6b8f7bb19ca795.webp 1440w, /en/article/conda-r-jupyter/image-20221010182224588_hu_979394f244082aa1.webp 1754w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="4.2.1 version"
                    
                />
            </picture>
        </a></p>
<h3 id="install-r-kernel-and-jupyter">Install R kernel and Jupyter</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1">### Specify to install using the default source</span>
</span></span><span class="line"><span class="cl"><span class="c1"># r-irkernel is the r-kernel for jupyter notebook</span>
</span></span><span class="line"><span class="cl"><span class="c1"># jupyter includes jupyter notebook</span>
</span></span><span class="line"><span class="cl">conda install -c defaults r-irkernel jupyter
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Note:</p>
<p>Do not use conda-forge to install r-irkernel and jupyter here.</p>
<p>As mentioned before, Conda Forge and Anaconda <em>are not fully compatible</em>. I personally tried to install it using the <code>conda install -c conda-forge r-irkernel jupyter</code> command and jupyter notebook did not start properly. In this case just uninstall and reinstall.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Uninstall</span>
</span></span><span class="line"><span class="cl">conda uninstall r-irkernel jupyter
</span></span><span class="line"><span class="cl"><span class="c1"># Install</span>
</span></span><span class="line"><span class="cl">conda install -c defaults r-irkernel jupyter
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="start-notebook">Start Notebook</h3>
<p>If everything is fine in the previous section, you will be able to start Jupyter Notebook properly here and create R&rsquo;s notebook.</p>
<p>If it doesn&rsquo;t start properly, please continue to read <strong>[Exception Handling]</strong> below.</p>
<p><a href="/en/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp" data-caption="Normal Run">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010201826507_hu_dd066c8618eda387.webp 480w, /en/article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp 720w, /en/article/conda-r-jupyter/image-20221010201826507_hu_71616f7a6d47b064.webp 960w, /en/article/conda-r-jupyter/image-20221010201826507_hu_5d9f5860f0d5079c.webp 1440w, /en/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp 2444w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2444"
                    height="598"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010201826507_hu_dd066c8618eda387.webp 480w, /en/article/conda-r-jupyter/image-20221010201826507_hu_70de8bb93e791e09.webp 720w, /en/article/conda-r-jupyter/image-20221010201826507_hu_71616f7a6d47b064.webp 960w, /en/article/conda-r-jupyter/image-20221010201826507_hu_5d9f5860f0d5079c.webp 1440w, /en/article/conda-r-jupyter/image-20221010201826507_hu_2bb88cefde2f1bc.webp 2444w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Normal Run"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Start Jupyter Notebook</span>
</span></span><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="exception-handling">Exception Handling</h3>
<h4 id="module-missing">Module Missing</h4>
<p>If you are prompted with <em><strong>ModuleNotFoundError: No module named &lsquo;zmq.backend.cffi._cffi&rsquo;</strong></em> when starting a notebook, the following is a similar situation.</p>
<p><a href="/en/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp" data-caption="Module Missing">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221018152019887_hu_94bc8bb977b9b635.webp 480w, /en/article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp 720w, /en/article/conda-r-jupyter/image-20221018152019887_hu_215fca54b3aab7c7.webp 960w, /en/article/conda-r-jupyter/image-20221018152019887_hu_b17897ea57254799.webp 1440w, /en/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp 2746w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2746"
                    height="850"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221018152019887_hu_94bc8bb977b9b635.webp 480w, /en/article/conda-r-jupyter/image-20221018152019887_hu_5f6b2dabbf598904.webp 720w, /en/article/conda-r-jupyter/image-20221018152019887_hu_215fca54b3aab7c7.webp 960w, /en/article/conda-r-jupyter/image-20221018152019887_hu_b17897ea57254799.webp 1440w, /en/article/conda-r-jupyter/image-20221018152019887_hu_e4e6e1f4dd061cfa.webp 2746w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Module Missing"
                    
                />
            </picture>
        </a></p>
<p>The solution can be found in <a href="https://github.com/jupyter/notebook/issues/3435#issuecomment-398549304" target="_blank" rel="noopener">an issue under the official repository</a> by uninstalling the module in question using pip and reinstalling it:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Use pip instead of conda to manage pyzmq packages</span>
</span></span><span class="line"><span class="cl">pip uninstall pyzmq
</span></span><span class="line"><span class="cl">pip install pyzmq
</span></span></code></pre></td></tr></table>
</div>
</div><p>Pro-tested to work.</p>
<blockquote>
<p>If you have similar <em>ModuleNotFoundError</em> problems, you can try the above method and use pip instead of conda to manage those python packages, uninstall and reinstall them first.</p>
<p>The main thing is to find that exact package name, you can try to search keywords in <a href="https://pypi.org/" target="_blank" rel="noopener">pypi</a>.</p>
</blockquote>
<h4 id="port-possession">Port Possession</h4>
<p>Since it is a server shared by multiple people in the lab, the default port 8888 of the notebook is also occupied. Here is the solution.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">ipython
</span></span><span class="line"><span class="cl"><span class="c1"># Access the python console</span>
</span></span><span class="line"><span class="cl">Python 3.7.13 <span class="o">(</span>default, Mar <span class="m">29</span> 2022, 02:18:16<span class="o">)</span> 
</span></span><span class="line"><span class="cl">Type <span class="s1">&#39;copyright&#39;</span>, <span class="s1">&#39;credits&#39;</span> or <span class="s1">&#39;license&#39;</span> <span class="k">for</span> more information
</span></span><span class="line"><span class="cl">IPython 7.31.1 -- An enhanced Interactive Python. <span class="nb">type</span> <span class="s1">&#39;? for help.
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">In [1]: from notebook.auth import passwd
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">In [2]: passwd()
</span></span></span><span class="line"><span class="cl"><span class="s1">Enter password: 
</span></span></span><span class="line"><span class="cl"><span class="s1">Verify password: 
</span></span></span><span class="line"><span class="cl"><span class="s1">Out [2]: &#39;</span>argon2:<span class="nv">$argon2id$v</span><span class="o">=</span>19<span class="nv">$m</span><span class="o">=</span>10240,t<span class="o">=</span>10,p<span class="o">=</span>xxxxxxxxx<span class="s1">&#39; # Copy the content between &#39;&#39; needed later
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">In [2]: exit
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1">jupyter notebook --generate-config # This will prompt you where the generated file is
</span></span></span><span class="line"><span class="cl"><span class="s1">vim ~/.jupyter/jupyter_notebook_config.py # Edit the file prompted in the previous step here
</span></span></span><span class="line"><span class="cl"><span class="s1">
</span></span></span><span class="line"><span class="cl"><span class="s1"># Add or modify the following
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.allow_remote_access = True
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.ip = &#39;</span>*<span class="s1">&#39;
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.password = u&#39;</span>argon2:<span class="nv">$argon2id$v</span><span class="o">=</span>19<span class="nv">$m</span><span class="o">=</span>10240,t<span class="o">=</span>10,p<span class="o">=</span>8<span class="nv">$Vc5lLVsXKZLGftp6xrHfEfOkQvIU5YiOhdw</span><span class="s1">&#39; # Paste the previously copied key
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.open_browser = False
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.port = 61111 # Set the port and be careful not to duplicate it with others
</span></span></span><span class="line"><span class="cl"><span class="s1">c.NotebookApp.notebook_dir = &#39;</span>/home/xxx/<span class="err">&#39;</span> <span class="c1"># not necessary set jupyter default directory</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Once set, you should be able to access it normally</span>
</span></span><span class="line"><span class="cl">jupyter notebook
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="beautification-enhancements">Beautification enhancements</h3>
<p>This part is not essential and is for record only.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Configure themes</span>
</span></span><span class="line"><span class="cl">pip install jupyterthemes
</span></span><span class="line"><span class="cl"><span class="c1"># A set of theme settings that I personally like and have gotten used to</span>
</span></span><span class="line"><span class="cl">jt -t monokai -f fira -fs <span class="m">13</span> -cellw 90% -ofs <span class="m">11</span> -dfs <span class="m">11</span> -T -N
</span></span><span class="line"><span class="cl"><span class="c1"># Restore the default theme</span>
</span></span><span class="line"><span class="cl">jt -r
</span></span><span class="line"><span class="cl"><span class="c1"># Configure plugins</span>
</span></span><span class="line"><span class="cl">pip install jupyter_contrib_nbextensions
</span></span><span class="line"><span class="cl">jupyter contrib nbextension install --user
</span></span><span class="line"><span class="cl">pip install jupyter_nbextensions_configurator
</span></span><span class="line"><span class="cl"><span class="c1"># Suggested configuration items</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Hinterland code completion</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Collapsible headings Collapse headings</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Notify notification mechanism to run time-consuming tasks and notify when they are completed</span>
</span></span><span class="line"><span class="cl"><span class="c1"># Codefolding collapsing code</span>
</span></span><span class="line"><span class="cl"><span class="c1"># zenmode Hide the active status bar for easy attention to the code</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ExecuteTime shows the running time</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-fancybox="gallery" data-src="/en/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp" data-caption="Plugin">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /en/article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /en/article/conda-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /en/article/conda-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /en/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1576"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp"
                    srcset="/en/article/conda-r-jupyter/image-20221010205123146_hu_a41617526a284565.webp 480w, /en/article/conda-r-jupyter/image-20221010205123146_hu_d2ab4db171af1ab0.webp 720w, /en/article/conda-r-jupyter/image-20221010205123146_hu_a76e43c7eebd5b78.webp 960w, /en/article/conda-r-jupyter/image-20221010205123146_hu_cb4dcb98a38176df.webp 1440w, /en/article/conda-r-jupyter/image-20221010205123146_hu_30ba7af07d52b738.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Plugin"
                    
                />
            </picture>
        </a></p>
<h2 id="thanks">Thanks</h2>
<p>All the users who enthusiastically shared their tutorial experience.</p>
]]></content:encoded>
    </item>
    <item>
      <title>BiliBili Automation on Qinglong Panel</title>
      <link>https://vccv.cc/en/article/bilibili-qinglong.html</link>
      <pubDate>Wed, 07 Sep 2022 11:45:10 +0000</pubDate>
      <guid>https://vccv.cc/en/article/bilibili-qinglong.html</guid>
      <description>Following the basic Qinglong setup and JD coins automation, here’s a walkthrough for the BiliTools project. I added notes based on the original docs—use as a reference.</description>
      <content:encoded><![CDATA[<h2 id="2023101-update">2023.10.1 Update</h2>
<p>This content may be outdated—please cross-check with the <a href="https://github.com/whyour/qinglong" target="_blank" rel="noopener">official repo</a>.</p>
<blockquote>
<p>Heads-up:</p>
<p>As of 2023.10.1, new users can pull the <em>Debian</em> image <code>docker pull whyour/qinglong:debian</code>.</p>
<p>It’s more compatible with some Python deps: e.g., <a href="https://github.com/sml2h3/ddddocr" target="_blank" rel="noopener">ddddocr</a> installs on the Debian tag but not on the default image.</p>
</blockquote>
<h2 id="preface">Preface</h2>
<p>After sharing the <a href="https://vccv.cc/article/qinglong-jd.html" target="_blank" rel="noopener">Qinglong setup and JD beans task</a>, I found another fun project: BiliTools.</p>
<p>Based on the <a href="https://btdocs.vercel.app/" target="_blank" rel="noopener">original docs</a>, here’s my configuration tutorial plus personal notes. Take what you need.</p>
<blockquote>
<p>Note:</p>
<p>vercel.app was recently blocked in China; you’ll need a proxy to read the original docs.</p>
</blockquote>
<h2 id="prerequisites">Prerequisites</h2>
<p>A running Qinglong server (local or cloud).</p>
<p>Setup guide: <a href="https://vccv.cc/article/qinglong-jd.html" target="_blank" rel="noopener">click here</a>.</p>
<blockquote>
<p>The project supports many environments (local, Qinglong, Docker, serverless, etc.). This post only covers Qinglong.</p>
</blockquote>
<h2 id="tutorial">Tutorial</h2>
<h3 id="install-dependency">Install dependency</h3>
<p>In <strong>Qinglong Panel -&gt; Dependency Management -&gt; NodeJs -&gt; New dependency</strong>, enter <code>@catlair/bilitools</code> and install.</p>
<p><a href="/en/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp" data-caption="Install dependency">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907120359433_hu_4028008303421a3f.webp 480w, /en/article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp 720w, /en/article/bilibili-qinglong/image-20220907120359433_hu_66c5ce72f2028a6a.webp 960w, /en/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1038"
                    height="994"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907120359433_hu_4028008303421a3f.webp 480w, /en/article/bilibili-qinglong/image-20220907120359433_hu_96bdae57856d2a36.webp 720w, /en/article/bilibili-qinglong/image-20220907120359433_hu_66c5ce72f2028a6a.webp 960w, /en/article/bilibili-qinglong/image-20220907120359433_hu_a33ddff109d29a07.webp 1038w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Install dependency"
                    
                />
            </picture>
        </a></p>
<h3 id="pull-the-script">Pull the script</h3>
<p>In <strong>Qinglong Panel -&gt; Cron Jobs -&gt; New job</strong>, set Name (anything), Command (<code>ql raw https://gitee.com/Kudouran/BiliTools/raw/main/tools/bilitools_npm.js</code>), Schedule (<code>0 0 0 * * *</code>), then create and run once manually.</p>
<blockquote>
<p>About the cron rule:</p>
<p>This uses a Java-style cron expression. <code>0 0 0 * * *</code> means once daily at midnight. Adjust with an <a href="https://tool.lu/crontab/" target="_blank" rel="noopener">online tool</a> if needed.</p>
<p><a href="/en/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp" data-caption="Cron expression">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907121154016_hu_fe904c88afef0c14.webp 480w, /en/article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp 720w, /en/article/bilibili-qinglong/image-20220907121154016_hu_13953584f5a5767.webp 960w, /en/article/bilibili-qinglong/image-20220907121154016_hu_51397d3a9ed22507.webp 1440w, /en/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp 1618w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1618"
                    height="1252"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907121154016_hu_fe904c88afef0c14.webp 480w, /en/article/bilibili-qinglong/image-20220907121154016_hu_20718d16a9abba1e.webp 720w, /en/article/bilibili-qinglong/image-20220907121154016_hu_13953584f5a5767.webp 960w, /en/article/bilibili-qinglong/image-20220907121154016_hu_51397d3a9ed22507.webp 1440w, /en/article/bilibili-qinglong/image-20220907121154016_hu_21df22143abe9d1.webp 1618w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Cron expression"
                    
                />
            </picture>
        </a></p>
</blockquote>
<p><a href="/en/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp" data-caption="Pull script">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907120800606_hu_84f39b8744ab70f7.webp 480w, /en/article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp 720w, /en/article/bilibili-qinglong/image-20220907120800606_hu_35ff513bbd781ab6.webp 960w, /en/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp 1036w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1036"
                    height="1036"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907120800606_hu_84f39b8744ab70f7.webp 480w, /en/article/bilibili-qinglong/image-20220907120800606_hu_33dfa0bf2703877d.webp 720w, /en/article/bilibili-qinglong/image-20220907120800606_hu_35ff513bbd781ab6.webp 960w, /en/article/bilibili-qinglong/image-20220907120800606_hu_80aa88372da57dc2.webp 1036w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Pull script"
                    
                />
            </picture>
        </a></p>
<h3 id="update-npm-package">Update npm package</h3>
<p>Auto-update looks like this:</p>
<p><a href="/en/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp" data-caption="Update npm package">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/ql_update_hu_f2d8286ff3ff1083.webp 480w, /en/article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp 720w, /en/article/bilibili-qinglong/ql_update_hu_3fbe1fc8dad22663.webp 960w, /en/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp 1308w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1308"
                    height="545"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp"
                    srcset="/en/article/bilibili-qinglong/ql_update_hu_f2d8286ff3ff1083.webp 480w, /en/article/bilibili-qinglong/ql_update_hu_986ce5571027bc92.webp 720w, /en/article/bilibili-qinglong/ql_update_hu_3fbe1fc8dad22663.webp 960w, /en/article/bilibili-qinglong/ql_update_hu_711416eb784b61fe.webp 1308w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Update npm package"
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">pnpm remove -g @catlair/bilitools <span class="o">&amp;&amp;</span> pnpm add -g @catlair/bilitools
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Without <code>pnpm remove -g @catlair/bilitools</code>, old versions linger on disk.</p>
</blockquote>
<h2 id="get-cookies">Get cookies</h2>
<h3 id="desktop-browser-incognito-recommended">Desktop browser incognito (recommended)</h3>
<p>Example with Firefox/Chrome/Edge. Final cookie resembles (line breaks added for readability):</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">_uuid=D2282D0F-257B-845A-BDF5-C770ED288F4001440infoc; buvid3=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">fingerprint=5502cd4fe9637738de04bd9c3d1bdbc5;
</span></span><span class="line"><span class="cl">buvid_fp=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">SESSDATA=21607773%2C1631089673%2C71a42%2A31; bili_jct=dd92c55a6d67041ce2f3fb1650889ea8;
</span></span><span class="line"><span class="cl">DedeUserID=521268093; DedeUserID__ckMd5=47d541f04b605da9;
</span></span><span class="line"><span class="cl">sid=ivie73r8; fingerprint3=792b32adfecbe31a4aca53ab7be1ad76;
</span></span><span class="line"><span class="cl">fingerprint_s=bb6736758e7344a295c2ed6070cc642e;
</span></span><span class="line"><span class="cl">buvid_fp_plain=BF17608E-FB87-4F49-A922-56FD2E284D6F18534infoc;
</span></span><span class="line"><span class="cl">CURRENT_FNVAL=80; blackside_state=1; rpdid=|(kmJYYJ)lkR0J&#39;uYu)llkJYJ; _dfcaptcha=a46d7562a42065d43a88c053e283e876;
</span></span><span class="line"><span class="cl">LIVE_BUVID=AUTO8016188357987702; bsource=search_baidu; PVID=2
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>To avoid cookie refresh/invalidations</strong> (e.g., if you frequently browse Bilibili, the session might rotate), don’t copy cookies from your everyday session. Instead, open a <strong>private/incognito window</strong>, log in, and capture a fresh cookie. Close the window directly—don’t log out or the cookie dies immediately.</p>
<p>Incognito shortcuts (examples):</p>
<p><a href="/en/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp" data-caption="Incognito window">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/br_ys.29d7da3d_hu_bbcce4de71f1bc46.webp 480w, /en/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp 502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="502"
                    height="558"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp"
                    srcset="/en/article/bilibili-qinglong/br_ys.29d7da3d_hu_bbcce4de71f1bc46.webp 480w, /en/article/bilibili-qinglong/br_ys.29d7da3d_hu_e9dc596a05b80f30.webp 502w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Incognito window"
                    
                />
            </picture>
        </a></p>
<h3 id="chrome">Chrome</h3>
<p>Open an incognito window, visit Bilibili, log in. Press F12 (or right-click -&gt; Inspect), switch to <code>Network</code>, refresh, click a request (often the first nav request), then copy the cookie.</p>
<p><a href="/en/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp" data-caption="Chrome cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/chrome-net-bnav_hu_ba4afd0b0722d1c6.webp 480w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp 720w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_aab63857d3d8c7c8.webp 960w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp 1127w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1127"
                    height="774"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp"
                    srcset="/en/article/bilibili-qinglong/chrome-net-bnav_hu_ba4afd0b0722d1c6.webp 480w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_b5e409a3ebea79d0.webp 720w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_aab63857d3d8c7c8.webp 960w, /en/article/bilibili-qinglong/chrome-net-bnav_hu_17886d2f3b02b3b.webp 1127w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Chrome cookie"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>When copying in Chromium browsers, choose <strong>Copy</strong> (not “Copy value”).</p>
</blockquote>
<h3 id="firefox">Firefox</h3>
<p>Open a private window, visit Bilibili, log in. Press F12 (or right-click -&gt; Inspect), go to <code>Network</code>, refresh.</p>
<p><a href="/en/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp" data-caption="Firefox network">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/firefox-network_hu_686ef5ab639b6640.webp 480w, /en/article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp 720w, /en/article/bilibili-qinglong/firefox-network_hu_d687112af33b1655.webp 960w, /en/article/bilibili-qinglong/firefox-network_hu_465c97c053bd5673.webp 1440w, /en/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp 1802w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1802"
                    height="829"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp"
                    srcset="/en/article/bilibili-qinglong/firefox-network_hu_686ef5ab639b6640.webp 480w, /en/article/bilibili-qinglong/firefox-network_hu_9147886ca2eb6caa.webp 720w, /en/article/bilibili-qinglong/firefox-network_hu_d687112af33b1655.webp 960w, /en/article/bilibili-qinglong/firefox-network_hu_465c97c053bd5673.webp 1440w, /en/article/bilibili-qinglong/firefox-network_hu_daee1fcfab95c142.webp 1802w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Firefox network"
                    
                />
            </picture>
        </a></p>
<p><a href="/en/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp" data-caption="Firefox cookie">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/firefox-net-bnav_hu_859a8f6a9593c8.webp 480w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp 720w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_72fb7e541fced3b0.webp 960w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_820d722bf31b6a3e.webp 1440w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp 1919w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1919"
                    height="711"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp"
                    srcset="/en/article/bilibili-qinglong/firefox-net-bnav_hu_859a8f6a9593c8.webp 480w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_87025ddb36af3c96.webp 720w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_72fb7e541fced3b0.webp 960w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_820d722bf31b6a3e.webp 1440w, /en/article/bilibili-qinglong/firefox-net-bnav_hu_2dada2f1499db66f.webp 1919w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Firefox cookie"
                    
                />
            </picture>
        </a></p>
<h3 id="mobile">Mobile</h3>
<p>Not recommended—too many pitfalls.</p>
<h2 id="config-file-important">Config file (important)</h2>
<p>Configuration is the core of the project. Only a correct config will run properly—read carefully.</p>
<h3 id="lazy-single-user-template-edit-as-needed">Lazy single-user template (edit as needed)</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// Lines starting with // are comments
</span></span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Browser User-Agent; grab from http://service.spiritsoft.cn/ua.html
</span></span></span><span class="line"><span class="cl">    <span class="err">userAgent:</span> <span class="err">&#39;&#39;,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// General API delay range (seconds)
</span></span></span><span class="line"><span class="cl">    <span class="err">apiDelay:</span> <span class="err">[2,</span> <span class="err">6],</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Bilibili cookie (see above)
</span></span></span><span class="line"><span class="cl">    <span class="err">cookie:</span> <span class="nt">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Features to run
</span></span></span><span class="line"><span class="cl">    <span class="err">function:</span> <span class="err">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">silver2Coin:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">addCoins:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveSignTask:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">shareAndWatch:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">mangaTask:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">supGroupSign:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">useCouponBp:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">getVipPrivilege:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">giveGift:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">matchGame:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">batchUnfollow:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveLottery:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveRedPack:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveIntimacy:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">bigPoint:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">judgement:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">activityLottery:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Live red packet
</span></span></span><span class="line"><span class="cl">    <span class="err">redPack:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// 1: activity link (may be outdated); 2: scan; other = try all
</span></span></span><span class="line"><span class="cl">      <span class="err">source:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Activity link
</span></span></span><span class="line"><span class="cl">      <span class="err">uri:</span> <span class="err">&#39;https:</span><span class="c1">//api.live.bilibili.com/xlive/fuxi-interface/AugRedPacket2022Controller/redPocketPlaying&#39;,
</span></span></span><span class="line"><span class="cl">      <span class="c1">// Interval between rounds (seconds)
</span></span></span><span class="line"><span class="cl">      <span class="err">intervalActive:</span> <span class="err">60,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Mid-break: [count, rest minutes (&lt;1 ends)]
</span></span></span><span class="line"><span class="cl">      <span class="err">restTime:</span> <span class="err">[-1,</span> <span class="err">-1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Suspected risk cooldown: [count, rest minutes (&lt;1 ends)]
</span></span></span><span class="line"><span class="cl">      <span class="err">riskTime:</span> <span class="err">[-1,</span> <span class="err">-1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Concurrent rooms
</span></span></span><span class="line"><span class="cl">      <span class="err">linkRoomNum:</span> <span class="err">1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Bullet comments sent while waiting [fixed] or [min,max]
</span></span></span><span class="line"><span class="cl">      <span class="err">dmNum:</span> <span class="err">[10],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Handle followed users while waiting (read/move)
</span></span></span><span class="line"><span class="cl">      <span class="err">moveUpInWait:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">Move</span> <span class="err">followed</span> <span class="err">UPs</span> <span class="err">into</span> <span class="err">group</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">moveTag:</span> <span class="err">&#39;rp关注&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">Follow</span> <span class="err">reply</span> <span class="err">handling</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">actFollowMsg:</span> <span class="err">&#39;read&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Total participation limit (-1 = none)
</span></span></span><span class="line"><span class="cl">      <span class="err">totalNum:</span> <span class="err">-1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Stop after N consecutive losses (&lt;1 = no limit)
</span></span></span><span class="line"><span class="cl">      <span class="err">noWinNum:</span> <span class="err">10,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Stop after N suspected risk events (&lt;1 = no limit)
</span></span></span><span class="line"><span class="cl">      <span class="err">riskNum:</span> <span class="err">5,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Auto unfollow
</span></span></span><span class="line"><span class="cl">    <span class="err">unFollow:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Interval per unfollow (seconds)
</span></span></span><span class="line"><span class="cl">      <span class="err">delay:</span> <span class="err">3,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Mid-break [count, rest minutes] (positive only)
</span></span></span><span class="line"><span class="cl">      <span class="err">restTime:</span> <span class="err">[20,</span> <span class="err">-1],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Total limit (-1 = none)
</span></span></span><span class="line"><span class="cl">      <span class="err">totalNum:</span> <span class="err">-1,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Tags to unfollow
</span></span></span><span class="line"><span class="cl">      <span class="err">tags:</span> <span class="err">[&#39;天选时刻&#39;,</span> <span class="err">&#39;rp关注&#39;],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Notifications
</span></span></span><span class="line"><span class="cl">    <span class="err">message:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">br:</span> <span class="err">&#39;\n&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Qinglong-friendly example: WeCom webhook key
</span></span></span><span class="line"><span class="cl">      <span class="err">&#39;QYWX_KEY&#39;:</span> <span class="nt">&#34;Fill your key here&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Coin settings
</span></span></span><span class="line"><span class="cl">    <span class="err">coin:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">targetLevel:</span> <span class="err">6,</span>
</span></span><span class="line"><span class="cl">      <span class="err">stayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">targetCoins:</span> <span class="err">5,</span>
</span></span><span class="line"><span class="cl">      <span class="err">customizeUp:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">todayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">upperAccMatch:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Use B-coins
</span></span></span><span class="line"><span class="cl">    <span class="err">couponBalance:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">Default</span> <span class="err">charge</span> <span class="err">target</span> <span class="err">(self</span> <span class="err">by</span> <span class="err">default)</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">mid:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">Preset</span> <span class="err">days;</span> <span class="err">empty</span> <span class="err">=</span> <span class="err">daily</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">presetTime:</span> <span class="err">[10,</span> <span class="err">20],</span>
</span></span><span class="line"><span class="cl">      <span class="err">/**</span> <span class="err">Mode:</span> <span class="err">charge/battery</span> <span class="err">*/</span>
</span></span><span class="line"><span class="cl">      <span class="err">use:</span> <span class="err">&#39;充电&#39;,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Live gifts
</span></span></span><span class="line"><span class="cl">    <span class="err">gift:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Custom gift targets (randomly chosen)
</span></span></span><span class="line"><span class="cl">      <span class="err">mids:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Other fields omitted
</span></span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Intimacy
</span></span></span><span class="line"><span class="cl">    <span class="err">intimacy:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveSendMessage:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveLike:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">limitFeed:</span> <span class="err">1500,</span>
</span></span><span class="line"><span class="cl">      <span class="err">liveHeart:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">whiteList:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">blackList:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Manga
</span></span></span><span class="line"><span class="cl">    <span class="err">manga:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">sign:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">buy:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">      <span class="err">mc:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">name:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">love:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">buyInterval:</span> <span class="err">2,</span>
</span></span><span class="line"><span class="cl">      <span class="err">buyWeek:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Jury
</span></span></span><span class="line"><span class="cl">    <span class="err">jury:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">mode:</span> <span class="err">1,</span>
</span></span><span class="line"><span class="cl">      <span class="err">vote:</span> <span class="err">[0,</span> <span class="err">0,</span> <span class="err">1],</span>
</span></span><span class="line"><span class="cl">      <span class="err">once:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">opinionMin:</span> <span class="err">3,</span>
</span></span><span class="line"><span class="cl">      <span class="err">waitTime:</span> <span class="err">20,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">// Big points
</span></span></span><span class="line"><span class="cl">    <span class="err">bigPoint:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">isRetry:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">isWatch:</span> <span class="err">true,</span>
</span></span><span class="line"><span class="cl">      <span class="err">epids:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">watchDelay:</span> <span class="err">40,</span>
</span></span><span class="line"><span class="cl">    <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="err">}</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>If you use the template, edit these four places:</p>
<ol>
<li>
<p><strong>User-Agent</strong> <em>required</em> — copy the red text from <a href="http://service.spiritsoft.cn/ua.html" target="_blank" rel="noopener">this site</a>.</p>
</li>
<li>
<p><strong>Cookie</strong> <em>required</em> — see above.</p>
</li>
<li>
<p><strong>Coin settings</strong> — adjust as needed (e.g., disable once you reach Lv6).</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">coin:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">targetLevel:</span> <span class="err">6,</span>
</span></span><span class="line"><span class="cl">      <span class="err">stayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">targetCoins:</span> <span class="err">5,</span>
</span></span><span class="line"><span class="cl">      <span class="err">customizeUp:</span> <span class="err">[],</span>
</span></span><span class="line"><span class="cl">      <span class="err">todayCoins:</span> <span class="err">0,</span>
</span></span><span class="line"><span class="cl">      <span class="err">upperAccMatch:</span> <span class="err">false,</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p><strong>Notification</strong> — recommended to fill.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">message:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="err">br:</span> <span class="err">&#39;\n&#39;,</span>
</span></span><span class="line"><span class="cl">      <span class="err">&#39;QYWX_KEY&#39;:</span> <span class="nt">&#34;Fill your key here&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// Other providers are also supported (GOBOT, SCKEY, QQ, etc.)
</span></span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
</ol>
<h3 id="add-environment-variable">Add environment variable</h3>
<ul>
<li>
<p>Config uses <code>json5</code> (supports comments). Validate with an <a href="https://verytoolz.com/json5-validator.html" target="_blank" rel="noopener">online json5 validator</a> before use.</p>
</li>
<li>
<p>Paste the validated config into the <a href="https://www.baidufe.com/fehelper/en-decode/" target="_blank" rel="noopener">Gzip tool</a>, choose Gzip compress, then copy the output.</p>
<p><a href="/en/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp" data-caption="Gzip compress config">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907133801593_hu_a66382664af187e5.webp 480w, /en/article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp 720w, /en/article/bilibili-qinglong/image-20220907133801593_hu_bef1daffdb8324bb.webp 960w, /en/article/bilibili-qinglong/image-20220907133801593_hu_132bfb28a35afce5.webp 1440w, /en/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp 2724w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2724"
                    height="664"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907133801593_hu_a66382664af187e5.webp 480w, /en/article/bilibili-qinglong/image-20220907133801593_hu_68c06583dee9460e.webp 720w, /en/article/bilibili-qinglong/image-20220907133801593_hu_bef1daffdb8324bb.webp 960w, /en/article/bilibili-qinglong/image-20220907133801593_hu_132bfb28a35afce5.webp 1440w, /en/article/bilibili-qinglong/image-20220907133801593_hu_e93033f028690156.webp 2724w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Gzip compress config"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>In <strong>Qinglong Panel -&gt; Environment variables -&gt; New variable</strong>, set Name <strong>BILITOOLS_CONFIG</strong>, Value = the Gzip output, then save.</p>
<p><a href="/en/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp" data-caption="Add variable">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907133920012_hu_7421b03786c8547b.webp 480w, /en/article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp 720w, /en/article/bilibili-qinglong/image-20220907133920012_hu_a179b27a01e895d2.webp 960w, /en/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp 1016w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1016"
                    height="436"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907133920012_hu_7421b03786c8547b.webp 480w, /en/article/bilibili-qinglong/image-20220907133920012_hu_436ea7bccc3346cb.webp 720w, /en/article/bilibili-qinglong/image-20220907133920012_hu_a179b27a01e895d2.webp 960w, /en/article/bilibili-qinglong/image-20220907133920012_hu_cf59e6447650466b.webp 1016w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Add variable"
                    
                />
            </picture>
        </a></p>
</li>
</ul>
<h2 id="run-manually">Run manually</h2>
<p>Back on the Qinglong tasks page you should see three BiliBili jobs:</p>
<p><a href="/en/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp" data-fancybox="gallery" data-src="/en/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp" data-caption="Bilibili tasks">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907134421036_hu_43a67087bd3feef1.webp 480w, /en/article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp 720w, /en/article/bilibili-qinglong/image-20220907134421036_hu_43093c4d992f6cbf.webp 960w, /en/article/bilibili-qinglong/image-20220907134421036_hu_4fe9c21602c9ee0d.webp 1440w, /en/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp 2362w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2362"
                    height="368"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp"
                    srcset="/en/article/bilibili-qinglong/image-20220907134421036_hu_43a67087bd3feef1.webp 480w, /en/article/bilibili-qinglong/image-20220907134421036_hu_4a970c21f7a366e5.webp 720w, /en/article/bilibili-qinglong/image-20220907134421036_hu_43093c4d992f6cbf.webp 960w, /en/article/bilibili-qinglong/image-20220907134421036_hu_4fe9c21602c9ee0d.webp 1440w, /en/article/bilibili-qinglong/image-20220907134421036_hu_8d98bf70715f7847.webp 2362w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Bilibili tasks"
                    
                />
            </picture>
        </a></p>
<p>Names can be anything—watch the commands:</p>
<ul>
<li>First: update dependency</li>
<li>Third: pull repo</li>
<li>Second: <strong>main program</strong> (visible after running the pull once)</li>
</ul>
<p>When ready, run the main job manually.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://btdocs.vercel.app/" target="_blank" rel="noopener">BiliTools</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Recommended Legacy iOS Apps and Downgrade Methods</title>
      <link>https://vccv.cc/en/article/ios-app.html</link>
      <pubDate>Thu, 01 Sep 2022 13:56:22 +0000</pubDate>
      <guid>https://vccv.cc/en/article/ios-app.html</guid>
      <description>Tired of iPhone aggressively killing apps? Try older versions. They’re usually lighter, smoother, and less ad-heavy—and some were free before switching to subscriptions (e.g., Caiyun Weather Pro, BaiMiao). Here’s a list plus downgrade tips.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>If iOS keeps killing your apps, try older versions. They often use fewer resources, feel smoother, burn less battery, and show fewer ads. Some apps were free before turning paid (e.g., Caiyun Weather Pro, BaiMiao). Even WiFi Master Key still works unfiltered—so grab it!</p>
<blockquote>
<p>Tip: On desktop, use Ctrl+F (Command+F on macOS) to search quickly.</p>
</blockquote>
<h2 id="changelog">Changelog</h2>
<p><strong>2022/09/25</strong></p>
<ul>
<li>JD 10.2.0 is the lowest version where sending images on iOS 16 works; 10.2.4 has no Double-11 icon</li>
<li>Xiaohongshu 7.4 supports new emoji</li>
</ul>
<p><strong>2022/09/12</strong></p>
<ul>
<li>Amap below 9.05.2 loses search</li>
</ul>
<p><strong>2022/09/03</strong></p>
<ul>
<li>WeCom 4.0 supports live meetings</li>
<li>QQ 8.5.0 supports group classroom</li>
<li>IdleFish 7.4.10 adds elder mode, no launch ads, phone-login only</li>
<li>Taobao 10.13.0: first dark-mode release after 10.12.20, no 618 icon; set region to Global to reduce ads</li>
<li>Alipay 10.2.76 adds elder mode</li>
<li>NetEase Cloud Music 4.1.2 supports new ncm format download/playback</li>
<li>Tieba internal 1.0.8 delisted; still downloadable if purchased; no ads; no search</li>
<li>BaiMiao 2.1.6 no ads</li>
</ul>
<p><strong>2022/08/31</strong></p>
<ul>
<li>Douyin Lite 16.8.0 supports playback speed</li>
<li>Douyin 16.5.0 supports playback speed</li>
</ul>
<p><strong>2022/08/28</strong></p>
<ul>
<li>Douban 6.x.x removed; minimum usable 7.0.0</li>
<li>Taobao versions before 10.12.20 all show update popups; 10.12.20 is the first dark-mode version</li>
</ul>
<h2 id="perks">Perks</h2>
<p><strong>Halide Mark II</strong></p>
<ul>
<li>RAW camera support</li>
<li>Switched from paid download (¥30) to subscription (¥20/mo) on 2020-10-22. Download 1.17.3 (850784840) to use all features free.</li>
</ul>
<p><strong>FiLMiC Pro</strong></p>
<ul>
<li>Powerful video camera</li>
<li>Switched from paid (¥99) to subscription (¥35/week) on 2022-08-25. Download 6.19.7 (851609129) to use basic features free.</li>
<li>Jailbroken users can unlock Log etc. via <a href="http://apt.cdalei.com/" target="_blank" rel="noopener">iOSGods iAP</a>.</li>
</ul>
<p><strong>Pixelmator Photo</strong></p>
<ul>
<li>Excellent photo editor</li>
<li>Switched from paid (¥30) to subscription (¥33/mo) on 2022-08-18. Download 2.0.12 (850784840) to use all features free.</li>
</ul>
<h2 id="version-recommendations">Version Recommendations</h2>
<ul>
<li>iPhone X launched 2017-11-03; versions after that support full screen.</li>
<li>iOS 13.0 Beta 1 (2019-06-04) introduced dark mode.</li>
<li>iOS 14.5 Beta 1 (2021-02-02) guarantees support for iOS 14.5+.</li>
<li>iOS 15.0 Beta 1 (2021-06-18) guarantees support for iOS 15.0+.</li>
<li>◆ marks my personal daily version (iPhone 11 Pro Max, iOS 14.2).</li>
<li>Be cautious updating iOS: many legacy apps can’t be installed on 14.5+ (package incomplete errors).</li>
<li>Check version histories and release dates on <a href="https://www.qimai.cn/" target="_blank" rel="noopener">Qimai</a>.</li>
<li>If a version stops working, leave a comment.</li>
</ul>
<p>Below are the version lists grouped by category. Version notes largely keep the original wording to avoid losing nuance.</p>
<p><strong>Social</strong></p>
<ul>
<li>QQ 6.2.2 (very fast launch, rarely killed; bubble display glitch) 6.5.9 6.6.5 (lowest version with working cloud sync) 6.7.1 (no side-eye emoji; requires overlay install) 7.1.0 (lowest direct-login version) 7.2.5 7.2.8 (full screen) 7.3.2 (Apple Watch) 7.3.5 7.5.5 7.7.8 8.0.6 8.1.0 (first simple mode; space videos won’t load) 8.1.5 (iOS 15.5) ◆8.1.8◆ (minimum for overlay-install dark mode) 8.2.6 (iOS 14.5) 8.2.8 (iOS 15.3) 8.4.1 (minimum for downloading night themes) 8.4.2 (iOS 15.3) 8.4.10 (bull-emoji pack) 8.5.0 (group classroom) 8.7.5 (Caiwang emoji, iOS 16) 8.8.38 (QQ Channels) 8.8.50</li>
<li>TIM 1.1.5 ◆2.3.0◆ (structured messages, online docs, full screen) 2.5.2 2.5.6 3.0.0 3.1.0 (earlier versions require overlay install; iOS 16 cannot overlay)</li>
<li>WeChat 6.5.19 6.6.1 6.7.0 (iOS 15.6 crashes) 6.7.4 (iOS 14.5; last with China region; see <a href="https://qianling.pw/wechat-blank" target="_blank" rel="noopener">https://qianling.pw/wechat-blank</a>) 7.0.5 (first floating window; auto-play Moments videos) 7.0.9 7.0.12 (first dark mode; no ads in Official Accounts; iOS 15.3) 7.0.13 (first “poke” + Channels) ◆7.0.14◆ (last with mini-program floating window; supports iPad+iphone login; face unlock broken; 836563902) 7.0.15 (face unlock broken) 7.0.18 (Yue Sheng Shi minimum) 7.0.20 (iOS 14 photo permissions) 7.0.21 (Yue Kang code minimum) 8.0.3 (Apple Watch; 999-sticker limit) 8.0.8 (change notification sound) 8.0.9 (auto desktop login) 8.0.14 (folded groups) 8.0.22 (iOS 16)</li>
<li>WeCom 3.1.8 (lowest login) 4.0 (live meeting)</li>
<li>Weibo 6.5.1 (no ads) 7.3.1 (last before homepage live icon; no ads in comments) 8.5.3 8.12.3 (iOS 14.7) 10.11.0 11.0.0 (lowest without outdated-version warning on profile) 11.3.0 (iPad minimum without bugs)</li>
<li>Weibo Intl 3.6.8 3.8.4 ◆4.1.5◆ (dark mode) 4.2.0 (last without homepage recommendations)</li>
<li>vvebo 3.1.4 (last before paid IAP)</li>
<li>DingTalk 4.6.10 ◆5.1.10◆ (logs) 6.0.0 (iOS 15.3) 6.0.26 (iOS 14.7)</li>
<li>Qzone 8.6.1</li>
<li>Baidu Tieba 6.8.5 6.9.6 (in-bar search) 7.1.0 (no launch ads) 7.3.0 (VIP can remove ads) 8.9.0 (full screen) 9.2.0 (clean, few ads) 9.3.0 9.3.1 (iOS 14.5) ◆9.6.0◆ (minimum for Safari invoke; pair with Flex for ad blocking) 9.7.1 9.7.11 9.7.5 9.8.4 (iOS 14.7) 9.9.9 (cannot edit images) 10.3.11 (dark mode) 11.0.0 (use Flex to block ads) 11.3.2 12.0.5</li>
<li>Tieba internal 1.0.8 (delisted; downloadable if purchased; no ads; no search)</li>
<li>Zhihu ◆6.0.0◆ (search works; no launch ads; iOS 15.3) 6.5.0 6.7.0 (last without launch ads) 6.14.0 (dark mode) 6.65.0 6.62.0 (iOS 14 widgets) 6.67.0</li>
<li>Douban ◆7.0.0◆ 7.15.0</li>
<li>Hupu ◆7.3.2◆</li>
<li>Coolapk 3.1 (last without launch ads; messages broken) 4.5.1 (iOS 15.3) ◆4.9◆ (847456398) 4.9.1 (last blue theme; 848225916)</li>
<li>WeFeng 5.5.1 (last without ads but network issues) ◆6.4◆ (840909450; use Flex to block ads) 6.6.5</li>
<li>NGA 5.3.0 (no launch/banner/interstitial ads) 6.0.8 (iOS 14.5/16) 6.3.2</li>
<li>PiPiXia 1.3.2 1.3.9 (no ads)</li>
<li>Twitter 7.37.2 (translation) 7.60 (dark mode) 8.44 (no Fleets) 8.47.1 (iOS 14 photo permissions)</li>
<li>Instagram 124.0 (dark mode) 165.0 (iOS 14 photo permissions)</li>
<li>Nicegram 8.3.2 (bypasses forced update)</li>
</ul>
<p><strong>Shopping</strong></p>
<ul>
<li>Taobao 7.12.20 (iOS 15) 8.0.0 (iOS 15.6) 8.6.10 8.8.0 (iOS 14.3) 9.1.1 (iOS 14.3 crash) 9.2.0 (no visual search) 9.17.0 (iOS 14 widget) 9.20.0 (find similar) 10.12.20 (dark mode; earlier versions show update popups) ◆10.13.0◆ (no 618 icon; set region to Global to cut ads) 10.14.10 (850964824)</li>
<li>Taobao Lite 4.16.4 (overseas)</li>
<li>Diantao 1.7.6</li>
<li>Alibaba 7.20.0 (iOS 14.7) ◆9.4.6◆</li>
<li>JD ◆9.5.0◆ (minimum for payment) 10.0.6 (fix iPhone 12 cart misalignment) 10.2.0 (iOS 16 image send) 10.2.4 (no Double-11 icon)</li>
<li>Pinduoduo 4.23.0 (iOS 15.6) 4.56.0 4.76.0 (iOS 14.5) 5.2.0 5.12.0 ◆5.30.0◆ (wallet) 5.31.1 (iOS 14 widget)</li>
<li>Weidian 5.4.7</li>
<li>Smzdm 9.8.16</li>
<li>Manmanbuy ◆3.2.40◆</li>
<li>Suning 7.7.3.8</li>
<li>Shihuo 6.54.0 (iOS 14.7)</li>
<li>IdleFish 6.2.5 (minimum usable) 6.2.9 (iOS 14.7) 6.3.7 6.4.80 6.6.60 ◆6.9.80◆ (minimum for bidding; transfers broken) 7.1.10 (iOS 15; overlay install) 7.4.10 (elder mode; phone-login only; iOS 13.7)</li>
<li>Zhuanzhuan 5.6.1</li>
<li>Xiaohongshu 6.63 (use Flex to block ads) ◆6.86◆ (iOS 14.7) 7.28 (browse history minimum) 7.40 (new emoji)</li>
<li>Meituan 11.4.401 (Meituan Youxuan unusable) 11.6.406 11.10.203 (iOS 15)</li>
<li>Taopiaopiao 10.4.1 (iOS 14 widget)</li>
<li>Ctrip 8.22 (overlay install)</li>
<li>Qianniu 8.13.0 9.3.0</li>
</ul>
<p><strong>Finance</strong></p>
<ul>
<li>Alipay 10.1.35 10.2.8 (minimum where bank card list works) ◆10.2.10◆ (iOS 14 widget; mini-programs OK) 10.2.15 10.2.38 (fast cold start) 10.2.53 (can remove Life channel; remove all homepage cards) 10.2.59 (can disable homepage recommendations) 10.2.76 (elder mode)</li>
<li>UnionPay ◆8.0.7◆ (minimum for transfers)</li>
<li>Shark Ledger Pro 2.0 (no community bloat)</li>
</ul>
<p><strong>Entertainment</strong></p>
<ul>
<li>Bilibili 6.1.3 6.61.0 (dynamic avatar minimum; need i4Tools download)</li>
<li>Bilibili HD 2.3 (last with toggleable startup animation)</li>
<li>Bilibili Concept 2.13.2 2.15.4 2.4 6.48.0 (global mini-window)</li>
<li>bilibili-弹幕動畫戲劇線上看 2.7.0 (TW region; no game center, mall, live, startup ads; vertical videos fail; 837359696) ◆3.0.3◆ (dark-mode hot switch; live; long-press speed; 841150268) 3.0.4</li>
<li>Douyin 15.0.0 (840791014; requires overlay install) 16.5.0 (playback speed)</li>
<li>Douyin Lite 15.0.0 16.8.0 (playback speed)</li>
<li>TikTok 1.2.2 (last unblocked region; cannot register/login; TW region 823491616)</li>
<li>YouTube 15.28.2 16.05.9 (CC subtitle button)</li>
<li>Kuaishou 6.11.8 9.8.50</li>
<li>iQIYI 5.7.1 (no pre-roll ads) 7.0.1 (login without SMS) 8.12.5 (download 3 videos at once) 9.7.0 (Cinema) 9.8.0 (last version supporting web QR login on secondary device)</li>
<li>Tencent Video 7.8.0 (iOS 14.7) 8.2.48</li>
<li>Youku 6.12.0 (no ads) 7.5.5 (iOS 14.7)</li>
<li>Douyu 4.920</li>
<li>Huya 6.5.1</li>
<li>Yunting ◆5.8.0◆ (no ads) 6.0.1 (no launch ads)</li>
<li>NetEase Cloud Music 2.7.1 3.1.1 (no lossless) 3.7.5 4.0.1 (iOS 14.5) 4.1.2 (last without video; supports new ncm format) ◆4.2.2◆ (first full screen; adds launch ads) 4.3.1 (minimum for Bilibili SIM free traffic) 4.3.2 4.3.5 (old UI last) 5.5.0 (iOS 15.6) 5.6.0 (classic player last) 5.6.3 (iOS 14.5) 5.7.0 (iOS 15.3, iPhone 13) 5.8.1 (overlay install) 6.4.7 (first dark mode) 6.5.2 7.0.0 (iOS 15) 7.2.0 (Listen Together first) 7.2.10 (lyric pinyin) 7.3.01 (top-right spinning disc) 7.3.20 (iOS 14 widget) 8.0.10 (custom bottom tabs; PiP video)</li>
<li>QQ Music 8.8.5 8.9.9 (web login after uninstalling QQ) 9.2.8 (no live/launch ads) 9.3 (iOS 14.7) 9.7 10.12 (no update popup)</li>
<li>Bodi Music 1.2.6 (free; import external playlists)</li>
<li>MOO Music 1.6.5 (simple UI) 2.3.2 (iOS 15.1; earlier versions had clear-history bug)</li>
<li>Kugou Music 3.9.4 4.0.7 7.0.6 8.8.6 9.7.6</li>
<li>Kuwo Music 4.9.2</li>
<li>Xiami 6.1.8</li>
<li>Quanmin K Ge 3.7.6</li>
<li>Changba 8.2</li>
<li>Ximalaya ◆6.6.15◆ 7.0.8</li>
<li>QingTing FM 6.2.6 (no audio ads)</li>
</ul>
<p><strong>Reading</strong></p>
<ul>
<li>Toutiao 3.1.1 6.0.3 (no ads; iOS 11) 6.2.9 (first with chat emoji) 6.6.0 (can block ads on jailbreak) 7.0.5 7.0.9 7.9.2 (dark mode) 7.9.6 (long-press speed)</li>
<li>Tencent News 5.1.6</li>
<li>The Paper 8.1.7 (widget; no hot list)</li>
<li>WeRead 4.3.0 (dark mode) 5.0.4 (widget) 5.4.0 (Apple Pencil)</li>
<li>Qidian 4.7.0 (first landscape; block updates with Flex) 5.0.1</li>
<li>Zhuishushenqi 2.23.1 (no coins; chase-mode) 2.25.1 (switch sources) 2.24.24 (switch sources)</li>
<li>iReader Pro 6.3.0</li>
<li>Shuqi 3.9.10 (no horizontal ads)</li>
<li>BiQuGe 5.5 (no ads/popups)</li>
<li>Xiangse Guige 2.33.0</li>
<li>NetEase Comics 4.2.0 (use Flex3 membership patch)</li>
</ul>
<p><strong>Education</strong></p>
<ul>
<li>Notability 10.6 (last free version)</li>
<li>Chaoxing Study 4.5.6</li>
<li>Baidu Chinese ◆2.0◆ (minimum usable; 820243885) 2.1.0</li>
<li>Tencent Translate 3.1 (basic only)</li>
<li>50-On Origins ◆1.3.5◆ (last before paywall)</li>
<li>Sports World Campus 3.1.2 (can reject updates minimum)</li>
<li>Perfect Campus 5.3.1 (Alipay recharge minimum)</li>
<li>Driving Test Coach 7.6.4 (iOS 14.5)</li>
<li>Jiaxiao Yidian Tong 6.1.0 (images display; minimum) 6.1.7 (no update popups; no video lessons; overlay to refresh question bank) 8.1.0 (no paid popups on wrong answers) 9.1.0 (can refresh bank) 9.3.1 10.2.0 (last without launch ads)</li>
</ul>
<p><strong>Tools</strong></p>
<ul>
<li>Baidu 12.13.0.10</li>
<li>Amap 9.05.2 (minimum working search) 10.55.0 (last with old voice) 10.80.0 (swipe-back)</li>
<li>Baidu Maps 8.6.5 (no ads) 10.24.5 (full screen) 15.2.5 (dark mode)</li>
<li>Hello Bike 5.74 (only version without jailbreak detection; iOS 14.5) 6.1.5 (UnionPay) 6.2.0 (no bar on logo)</li>
<li>Netease Dashen 2.5.0 2.8.0 (no launch ads; QR login works)</li>
<li>Baidu Netdisk 6.6.0 (upload video without VIP) 6.7.3 (rename extensions/open unknown shares) 6.9.4 7.0.0 8.13.1 (no launch ads) 10.1.70 (messages normal)</li>
<li>Tianyi Cloud 4.5.0 (last free video upload; daily sign-in adds space)</li>
<li>Weipan 3.3.2 3.4.3</li>
<li>Youdao Note 5.7.1 (few ads) 5.9.8 (note + collaboration coexist)</li>
<li>Evernote 9.3.9</li>
<li>WPS Office 9.0.0 (no ads) 10.14.0 (iPhone 13 Pro/iOS 15 search &amp; replace without crash)</li>
<li>Outlook 4.2210.3 (no meeting room booking, etc.)</li>
<li>JiSpeed 5.16.0 (iOS 15)</li>
<li>Meiyan Camera 9.4.00 (minimum usable)</li>
<li>Meitu Xiuxiu 6.0.5 7.0.1</li>
<li>FiLMiC Pro ◆6.19.7◆ (last pre-subscription; compatible with IAP tweak; 851609129)</li>
<li>Halide Mark II ◆1.17.3◆ (last paid version; 837845559)</li>
<li>Sogou Input 2.2.1 (no search) 4.0.0 4.4.0 5.0.1 (clipboard) 7.2.6 (iOS 14.7) 10.22</li>
<li>Baidu Input 6.0.2 (super skins; no clipboard) 7.1.1 (no voice input)</li>
<li>iFly Input 6.0 8.0.2000</li>
<li>UC Browser 10.5.5 (no headlines; cache video) 10.7.11 (cache video) 11.3.1 (cache video, download files)</li>
<li>QQ Browser 6.1.1 (cache video) 6.3 (can disable headlines) 8.2.1 (first free-traffic version)</li>
<li>Quark Browser 2.2.9 2.3.1.913 (iOS 15.6)</li>
<li>Alook 8.2 9.6 11.5</li>
<li>Speedtest China by Ookla 4.2.10 (839306602)</li>
<li>DAMA (image privacy blur) 1.1.27 (bug unlocks premium; 850202162)</li>
<li>Pixelmator Photo 2.0.12 (last before subscription; 850784840)</li>
<li>Pin 3.2.2 (last with full Labs) 3.15.1</li>
<li>Keep 5.18.0 7.5.3</li>
<li>Mi Fit 4.0.3 (minimum login)</li>
<li>Strava 23.0.0</li>
<li>Widgy Widgets 1.7 (iOS 14.5)</li>
<li>Autohome 9.10.6 (vehicle detail pages fail to load)</li>
<li>Didi 5.1 (first bike version) 5.2.20 (iOS 14.5)</li>
<li>Caiyun Weather 6.0.4 (dark mode) 6.0.5 (iOS 14 widget) 6.0.7 6.1.1</li>
<li>Caiyun Weather Pro 5.0.10 (last before paid)</li>
<li>BaiMiao 2.1.6 (no membership limits, no ads)</li>
<li>Documents by Readdle (CN) 5.4 (audio/video sniffing, m3u8 download)</li>
<li>TV Assistant 5.5.0 (audio/video download, file export)</li>
</ul>
<h2 id="grab-old-versions">Grab Old Versions</h2>
<h3 id="mobile-trollstore">Mobile (TrollStore)</h3>
<ol>
<li>Search “新有趣工具箱” in WeChat to install TrollStore online.</li>
<li>Download <a href="https://share.initnil.com/d/With_TorllStore/DowngradeApp%28With_TrollStore%29_1.1-6.ipa" target="_blank" rel="noopener">DowngradeApp</a>.</li>
<li>Open TrollStore and install.</li>
</ol>
<h3 id="desktop">Desktop</h3>
<p>If the “i4Tools Lite” catalog lacks the version you want, capture it with iTunes on desktop. iTunes (v12.6.5.3) download: <a href="https://support.apple.com/zh-cn/HT208079" target="_blank" rel="noopener">Apple Support</a>. Packet-capture tool (release post: <a href="https://www.52pojie.cn/thread-1284776-1-1.html" target="_blank" rel="noopener">52pojie</a>): <a href="https://wwx.lanzoui.com/iBE4Emzgbkj" target="_blank" rel="noopener">Lanzou</a>.</p>
<p>Steps:</p>
<ol>
<li>Install iTunes v12.6.5.3 (built-in App Store).</li>
<li>Open iTunes and sign in with Apple ID.</li>
<li>Click the third-row “♫ Music” tile, click “Edit Menu”, check “Apps”, click “Done”, then click “Apps” to switch view.</li>
<li>Download the capture tool. Create a folder for the <code>.exe</code> files, e.g., <code>D:\Program Files\iOS-old-apps</code> (the program creates data files alongside it).</li>
<li>Open the capture tool, enter the app name, press Enter to search.</li>
<li>Double-click the version you want.</li>
<li>Click “Start intercept”.</li>
<li>In iTunes, enter the app name in the top-right search box.</li>
<li>Click “Store” -&gt; “Search in iTunes Store for …”.</li>
<li>Under the correct device tab (iPhone/iPad), click “Get”/“Download”.</li>
<li>After download, click “Library” (third row).</li>
<li>Right-click the app icon -&gt; “Show in Windows Explorer” to find the <code>.ipa</code>.</li>
<li>Back up the package for later use.</li>
<li>Install [i4Tools] (“爱思助手”).</li>
<li>Open i4Tools -&gt; Apps/Games -&gt; Import Install to sideload the <code>.ipa</code>.</li>
</ol>
<p>Notes:</p>
<ul>
<li>App packages are tied to the Apple ID used to download them. To share, the recipient must log into that Apple ID in App Store before importing via desktop.</li>
<li>Once an app is added to the iTunes download queue you can stop intercepting and move on to the next.</li>
</ul>
<h2 id="block-in-app-update-prompts">Block In-App Update Prompts</h2>
<ol>
<li>Jailbreak.</li>
<li>Install <a href="https://apt.cydiabc.top/" target="_blank" rel="noopener">AppSync Unified</a> and <a href="https://yttxcs.com/" target="_blank" rel="noopener">Filza File Manager</a>.</li>
<li>Open Filza.</li>
<li>Go to the app install directory <code>/private/var/containers/Bundle/Application/xxx</code>.</li>
<li>Search <code>info.plist</code> and open the largest one.</li>
<li>Expand <code>Root</code> and set the version number to the latest release. If the version is <code>x.x.x</code> but the string is <code>x.x.x.x</code>, change the first three segments, leave the last.</li>
</ol>
<h2 id="tips--faqs">Tips &amp; FAQs</h2>
<h3 id="disable-auto-updates">Disable Auto-Updates</h3>
<p>Go to Settings -&gt; App Store and turn off <strong>Automatic Downloads: App Updates</strong>.</p>
<h3 id="app-is-larger-than-app-store-install">App is larger than App Store install</h3>
<p>For apps installed via desktop i4Tools, go to Settings -&gt; General -&gt; iPhone Storage, tap <strong>Offload App</strong> then <strong>Reinstall App</strong> to shrink size. Apps installed with i4Tools Lite or with <code>iTunesMetadata.plist</code> removed cannot be shrunk.</p>
<h3 id="app-removed-from-sale">App removed from sale</h3>
<p>If the captured version shows “no longer available,” register a new Apple ID and grab once after first logging into iTunes—the pulled version can still be captured.</p>
<h3 id="downgrade-tim-to-the-first-release-104">Downgrade TIM to the first release (1.0.4)</h3>
<ol>
<li>Use old iTunes to capture these four: 3.1.1, 2.5.1, 1.1.6, 1.0.4.</li>
<li>In i4Tools, overlay-install in order: 3.1.1 → 2.5.1 → 1.1.6 → 1.0.4.</li>
<li>Run the app once after each overlay.</li>
<li>If a version crashes, reopen a few times.</li>
<li>After downgrading to 1.0.4, go to Settings -&gt; General -&gt; iPhone Storage, tap <strong>Offload App</strong> then <strong>Reinstall</strong> to reduce size.</li>
</ol>
<h3 id="contributors">Contributors</h3>
<ul>
<li>⑨RealZJMM怪我丑 (Plex)</li>
<li>某年某月某日</li>
<li>Sunshine</li>
<li>1053083281</li>
<li>酌酒饮孤单</li>
<li>康晓锋</li>
<li>iuuan</li>
<li>偏执又可爱的me</li>
<li>那時明月</li>
<li>阿立</li>
<li>启示录</li>
</ul>
<h2 id="repost-notice">Repost Notice</h2>
<p><a href="https://qianling.pw/ios-app/" target="_blank" rel="noopener">View the original</a></p>
<p>All credit to the original author; this is just a mirrored record.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Capture Kuaishou Speed Edition Cookies</title>
      <link>https://vccv.cc/en/article/ksjsb-cookie.html</link>
      <pubDate>Tue, 02 Aug 2022 10:45:10 +0000</pubDate>
      <guid>https://vccv.cc/en/article/ksjsb-cookie.html</guid>
      <description>A tutorial on grabbing Kuaishou Speed Edition account cookies. Suitable for non-root Android and iOS users alike. If you need related tools, feel free to reach out.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>This is a pure tutorial compiled and tested by me. Any similarity to other guides is coincidental.</p>
<p>If you need related apps, search and download yourself or contact me (comments, etc.).</p>
<p>Let’s dive in.</p>
<h2 id="prep">Prep</h2>
<p>If you’ve never registered Kuaishou Speed Edition or never withdrawn cash, first register on a real device and <strong>bind WeChat</strong> (Settings -&gt; Account &amp; Security -&gt; WeChat) to make withdrawals easier.</p>
<p>If this is a second account and you plan to bind Alipay, also log in on a real device first. Alipay can only be bound during withdrawal, so keep the real-device session logged in. After you capture the packet in a VM (BlackBox or VMOS Pro) and send it to me, I’ll run coins until it’s withdrawable; then you withdraw on the real device via Alipay.</p>
<h2 id="android-guide">Android guide</h2>
<h2 id="blackbox">BLACKBOX</h2>
<p>This method uses BlackBox for packet capture—simpler and faster, and my preferred approach.</p>
<h3 id="install-apps">Install apps</h3>
<p>Install BlackBox64 or BlackBox32, HttpCanary, and the “Yellow Chicken anti-disconnect” module.</p>
<p>If your Kuaishou Speed Edition app is 32-bit, use BlackBox32; if 64-bit, use BlackBox64. If you don’t know, install both and see which one can add the app.</p>
<h3 id="configure-blackbox">Configure BlackBox</h3>
<ol>
<li>
<p>Install Kuaishou Speed Edition on the real device. Open BlackBox, tap the bottom-right <strong>+</strong> to add the app.</p>
<blockquote>
<p>If you can’t find Kuaishou Speed Edition in the picker, switch BlackBox32/64.</p>
</blockquote>
</li>
<li>
<p>Tap the three dots top-right -&gt; Settings, enable <strong>Xposed Framework</strong>, <strong>Hide Xposed Framework</strong>, and <strong>Hide Root</strong>.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp" data-caption="Settings">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152512767_hu_c7a9e59184a968c2.webp 480w, /en/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp 524w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="524"
                    height="1008"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152512767_hu_c7a9e59184a968c2.webp 480w, /en/article/ksjsb-cookie/image-20220803152512767_hu_f84700c0228c4432.webp 524w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Settings"
                    
                />
            </picture>
        </a></p>
<p><a href="/en/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp" data-caption="Enable options">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152538456_hu_3d50ab9a96374d90.webp 480w, /en/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp 504w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="504"
                    height="922"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152538456_hu_3d50ab9a96374d90.webp 480w, /en/article/ksjsb-cookie/image-20220803152538456_hu_7dd5fee908d8d05e.webp 504w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Enable options"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>Open Module Management, tap <strong>+</strong>, add the Yellow Chicken anti-disconnect module, and <strong>check</strong> it.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp" data-caption="Add module">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152602866_hu_c76e4c558436e29b.webp 480w, /en/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp 520w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="520"
                    height="950"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803152602866_hu_c76e4c558436e29b.webp 480w, /en/article/ksjsb-cookie/image-20220803152602866_hu_16b1da84c8f545d0.webp 520w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Add module"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>Restart BlackBox twice (open/close a couple of times).</p>
</li>
</ol>
<h3 id="target-app">Target app</h3>
<p>In HttpCanary, go to <strong>Settings -&gt; Target apps</strong>, tap <strong>+</strong>, choose your virtual app BlackBox (32 or 64—pick the one you’re using).</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-caption="Target app">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="418"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Target app"
                    
                />
            </picture>
        </a></p>
<h3 id="url-keyword">URL keyword</h3>
<p>Back on the main page, tap the search icon, scroll to the bottom, choose <strong>URL keyword</strong>, and enter <code>salt</code>.</p>
<p>This step is crucial—enter it exactly. If HttpCanary is killed in the background, you must re-enter the keyword.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-caption="URL keyword salt">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="474"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="URL keyword salt"
                    
                />
            </picture>
        </a></p>
<h3 id="start-capture">Start capture</h3>
<p>On the main page, tap the bottom-right <strong>paper plane</strong> icon to start capturing.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp" data-caption="Start capture">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803153019696_hu_1cf64d0cb37126e7.webp 480w, /en/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp 570w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="570"
                    height="1072"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803153019696_hu_1cf64d0cb37126e7.webp 480w, /en/article/ksjsb-cookie/image-20220803153019696_hu_cac1f6a1c0fbb6ad.webp 570w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Start capture"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>If prompted to install a cert, you can skip or install. If you fail to capture later, installing is fine (I captured without installing).</p>
</blockquote>
<h3 id="log-into-kuaishou">Log into Kuaishou</h3>
<p>In BlackBox, open Kuaishou Speed Edition (the one inside BlackBox, not the real device). Make sure it’s the <strong>first launch</strong> and you’re logged out. Log in with phone + SMS. After login, go to Settings -&gt; Account &amp; Security -&gt; WeChat to <strong>bind WeChat</strong>, or wait to bind WeChat/Alipay during withdrawal.</p>
<blockquote>
<p>If entering the phone/OTP does nothing, kill BlackBox and retry.</p>
<p>If you capture nothing or can’t pass security checks, uninstall the Kuaishou app inside BlackBox, kill related apps, re-add, start HttpCanary, and log in again.</p>
</blockquote>
<h3 id="capture-success">Capture success</h3>
<p>If all went well, return to HttpCanary—you should see captured traffic.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp" data-caption="Captured data">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803153132284_hu_d06ff7f2442687ab.webp 480w, /en/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp 518w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="518"
                    height="1122"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803153132284_hu_d06ff7f2442687ab.webp 480w, /en/article/ksjsb-cookie/image-20220803153132284_hu_a076390434985bf6.webp 518w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Captured data"
                    
                />
            </picture>
        </a></p>
<h3 id="save-request">Save request</h3>
<p>Open any request, go to Request, tap the top-right save icon, choose <strong>Save request</strong>.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-caption="Save request">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /en/article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1399"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /en/article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Save request"
                    
                />
            </picture>
        </a></p>
<h3 id="send-the-file">Send the file</h3>
<p>Files are saved under <code>HttpCanary-&gt;download</code>. Send the latest file (use a file manager). There may be two files: one ending with <code>header</code> and one with <code>raw</code>. Send the <strong>header</strong> file.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-caption="Find header file">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /en/article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /en/article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Find header file"
                    
                />
            </picture>
        </a></p>
<h3 id="cleanup">Cleanup</h3>
<p>After capturing, you can close all apps. Do <strong>not</strong> log out of the Kuaishou account, or the data becomes invalid. Just leave the apps alone.</p>
<h3 id="create-a-second-vm">Create a second VM</h3>
<p>If you need a second account, <strong>do not log out the first</strong>. Create another virtual space and repeat the steps in BlackBox.</p>
<p>Swipe left on BlackBox home to switch spaces:</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp" data-caption="Account 1">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803182922295_hu_b99994bf1b753fdf.webp 480w, /en/article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp 720w, /en/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="886"
                    height="1848"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803182922295_hu_b99994bf1b753fdf.webp 480w, /en/article/ksjsb-cookie/image-20220803182922295_hu_bb35ba13e65d8d69.webp 720w, /en/article/ksjsb-cookie/image-20220803182922295_hu_e02035aa4a3f6f7f.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Account 1"
                    
                />
            </picture>
        </a></p>
<p><a href="/en/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp" data-caption="Account 2">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803182943032_hu_65757c6d51e85e4e.webp 480w, /en/article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp 720w, /en/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="886"
                    height="1849"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803182943032_hu_65757c6d51e85e4e.webp 480w, /en/article/ksjsb-cookie/image-20220803182943032_hu_80b150de8f1c3ab6.webp 720w, /en/article/ksjsb-cookie/image-20220803182943032_hu_60c294744779da46.webp 886w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Account 2"
                    
                />
            </picture>
        </a></p>
<p>Other steps are the same.</p>
<blockquote>
<p>Note:</p>
<p>The second account must use a different phone number and withdrawal method. If you only have one WeChat, capture and send the data first; after I process the coins, bind Alipay during withdrawal.</p>
</blockquote>
<h2 id="vmos-pro">VMOS PRO</h2>
<p>This method uses VMOS Pro. It’s more complex but isolates from the real device and suits multiple accounts.</p>
<h3 id="install-apps-1">Install apps</h3>
<p>Install HttpCanary (specific version), VMOS Pro (virtual machine with root), and MT Manager (file manager).</p>
<p>HttpCanary must support exporting system certs; I use <strong>v9.2.8.1</strong>.</p>
<h3 id="export-certificate">Export certificate</h3>
<p>Open HttpCanary -&gt; <strong>Settings -&gt; SSL certificate settings -&gt; Export HttpCanary root certificate -&gt; System Trusted (.0)</strong>.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp" data-caption="Export certificate">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_84e04bb009ad92b7.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_c1a9f8f1f61b0755.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1394"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_84e04bb009ad92b7.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e4982c7f459368ad.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_c1a9f8f1f61b0755.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659413729910_hu_e5c24953fade25cf.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Export certificate"
                    
                />
            </picture>
        </a></p>
<p>Note the path, typically <code>HttpCanary/cert</code>.</p>
<h3 id="create-vm">Create VM</h3>
<p>Open VMOS Pro and pick the second template—it defaults to Android 7.1.2.</p>
<p><a href="/en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp" data-caption="Create VM">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_c1c6202bd293b962.webp 480w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp 720w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_77c7137508c445f1.webp 960w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2400"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp"
                    srcset="/en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_c1c6202bd293b962.webp 480w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_eaad758c0f6a9758.webp 720w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_77c7137508c445f1.webp 960w, /en/article/ksjsb-cookie/27CF6E70110624196EC27197E5CF15C9_hu_b35b2f05e9bded5e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Create VM"
                    
                />
            </picture>
        </a></p>
<h3 id="import-files">Import files</h3>
<p>Inside the VM, tap the dock <strong>Add</strong> icon and import Kuaishou Speed Edition, MT Manager, and the <strong>cert file</strong> from above. They’ll auto-install in the VM.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp" data-caption="Import files">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_cb34be6e00d4ac92.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_5406949d50d1240b.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2340"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_cb34be6e00d4ac92.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_4812168dfb68cabf.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_5406949d50d1240b.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411129188_hu_3595fccf2ebd974.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Import files"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>Important: ensure you imported the cert. If <code>VMOSfiletransferstation</code> later appears empty, you forgot the cert!</p>
<p><a href="/en/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp" data-caption="Import cert">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803112457171_hu_286b39b1cc5501f0.webp 480w, /en/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp 540w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="540"
                    height="321"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220803112457171_hu_286b39b1cc5501f0.webp 480w, /en/article/ksjsb-cookie/image-20220803112457171_hu_4d74b4f4f2fc880d.webp 540w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Import cert"
                    
                />
            </picture>
        </a></p>
</blockquote>
<h3 id="get-root">Get root</h3>
<p>In VM settings, enable <strong>Superuser</strong>. A <strong>Superuser</strong> app should appear, meaning root access is active.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp" data-caption="Get root">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_6345a00d4f97eb06.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_5f4ca67b647f6b78.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_6345a00d4f97eb06.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_396fde2c2f13d199.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_5f4ca67b647f6b78.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411356354_hu_25c5754a659f5275.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Get root"
                    
                />
            </picture>
        </a></p>
<h3 id="grant-permissions">Grant permissions</h3>
<p>Open <strong>MT Manager</strong> inside the VM. When prompted, allow Superuser (check “remember”).</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp" data-caption="Allow request">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_d9ba8509921f081d.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_1f8fe0800b555f8c.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp 1070w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1070"
                    height="2113"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_d9ba8509921f081d.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_4eb7b4961e0e0aa9.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_1f8fe0800b555f8c.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411649769_hu_93380f20826e70fe.webp 1070w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Allow request"
                    
                />
            </picture>
        </a></p>
<h3 id="move-the-cert">Move the cert</h3>
<p>In MT Manager, left pane: <code>VMOSfiletransferstation</code>; right pane: <code>system</code>. If there’s no <code>system</code> folder, root access failed—redo the previous step.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp" data-caption="Choose folders">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_10bfc95e1418422c.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_2d9b105cefb2f3c3.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="805"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_10bfc95e1418422c.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_1310ff4feea64b39.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_2d9b105cefb2f3c3.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659411790619_hu_187659adfe773a22.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Choose folders"
                    
                />
            </picture>
        </a></p>
<p>On the right, go to <code>system-&gt;etc-&gt;security-&gt;cacerts</code>. On the left, open <code>VMOSfiletransferstation</code> to find the cert file. Long-press the cert on the left and <strong>Copy</strong>—it will appear on the right. Different filenames are normal.</p>
<p>Long-press the cert file on the left and tap <strong>Copy</strong>. It should appear on the right. Filename differences are normal.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp" data-caption="Copy cert">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_c30f1ea2295dbb83.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8f2c4fe5420cef8f.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1492"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_c30f1ea2295dbb83.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8519b62f103c0cfe.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_8f2c4fe5420cef8f.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412262964_hu_e854dbb7e0f31a61.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Copy cert"
                    
                />
            </picture>
        </a></p>
<h3 id="target-app-1">Target app</h3>
<p><strong>Back on the real device</strong>, open HttpCanary -&gt; <strong>Settings -&gt; Target apps</strong>, tap <strong>+</strong>, choose VMOS Pro.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp" data-caption="Target app">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="418"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_17209a37eb2f3036.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_f389452182878994.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_c193a31b46c665d1.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412738397_hu_705e98f0304ceb4c.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Target app"
                    
                />
            </picture>
        </a></p>
<h3 id="url-keyword-1">URL keyword</h3>
<p>On the main page, tap the search icon, scroll to the bottom, choose <strong>URL keyword</strong>, and enter <code>salt</code>.</p>
<p>This is critical—enter it correctly.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp" data-caption="URL keyword salt">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="474"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_1fb9e3dab54df35b.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_6c9e280b6c138746.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_d46fd542b6617bdd.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412524498_hu_be7c1b5bca8b147d.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="URL keyword salt"
                    
                />
            </picture>
        </a></p>
<h3 id="start-capture-1">Start capture</h3>
<p>Return to the main page and tap the bottom-right <strong>paper plane</strong> to start.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp" data-caption="Start capture">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_5a5fad7fddf3d30.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_f9da78105dad4773.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="2254"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_5a5fad7fddf3d30.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_3b5e1780ac1be344.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_f9da78105dad4773.webp 960w, /en/article/ksjsb-cookie/qq_pic_merged_1659412828818_hu_2251f3ddbbc94688.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Start capture"
                    
                />
            </picture>
        </a></p>
<blockquote>
<p>If you’re rooted, you can move the cert directly on the real device—no VM needed. The “Install root certificate to capture SSL data” banner is normal for non-root users; ignore it.</p>
</blockquote>
<h3 id="log-into-kuaishou-1">Log into Kuaishou</h3>
<p>Inside the VM, open Kuaishou Speed Edition for the <strong>first time</strong> (logged out). Log in with phone + SMS. After login, go to Settings -&gt; Account &amp; Security -&gt; WeChat to <strong>bind WeChat</strong>, or bind during withdrawal.</p>
<blockquote>
<p>If login fails or buttons do nothing, kill all related apps and retry, or try later. Another trick: while logged in, close the VM, wait (even 30 minutes), then start HttpCanary, start the VM, and open Kuaishou—the packet may be captured instantly.</p>
</blockquote>
<h3 id="capture-success-1">Capture success</h3>
<p>If all went well, HttpCanary should show three entries of ~2.8kB each.</p>
<p><a href="/en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp" data-caption="Captured data">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_7b18d82d048f1b03.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp 864w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="864"
                    height="633"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp"
                    srcset="/en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_7b18d82d048f1b03.webp 480w, /en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_40777dac2f12c60c.webp 720w, /en/article/ksjsb-cookie/qq_pic_merged_1659413807817_hu_e7d56485bcebf894.webp 864w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Captured data"
                    
                />
            </picture>
        </a></p>
<h3 id="save-request-1">Save request</h3>
<p>Open any entry, go to Request, tap save top-right, choose <strong>Save request</strong>.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp" data-caption="Save request">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /en/article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="1399"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122359062_hu_45f48a2adb5fe56.webp 480w, /en/article/ksjsb-cookie/image-20220802122359062_hu_27aa16a521e0eb10.webp 720w, /en/article/ksjsb-cookie/image-20220802122359062_hu_acbc1c605a5d93a6.webp 960w, /en/article/ksjsb-cookie/image-20220802122359062_hu_2c25f683dc9a3083.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Save request"
                    
                />
            </picture>
        </a></p>
<h3 id="send-the-file-1">Send the file</h3>
<p>Files live in <code>HttpCanary-&gt;download</code>. Send the latest file. You may see two files: one ending with <code>header</code>, one with <code>raw</code>. Send the <strong>header</strong> file.</p>
<p><a href="/en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-fancybox="gallery" data-src="/en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp" data-caption="Find header file">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /en/article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="573"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp"
                    srcset="/en/article/ksjsb-cookie/image-20220802122429599_hu_86c3c5ba6eaf7407.webp 480w, /en/article/ksjsb-cookie/image-20220802122429599_hu_5f0b62e0efbac338.webp 720w, /en/article/ksjsb-cookie/image-20220802122429599_hu_6334694aeccbb8.webp 960w, /en/article/ksjsb-cookie/image-20220802122429599_hu_b1904840dd03472e.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Find header file"
                    
                />
            </picture>
        </a></p>
<h2 id="ios-guide">iOS guide</h2>
<blockquote>
<p>My iOS setup:</p>
<p>Jailbroken, iOS 14.2.1</p>
<p>Tools: Crane (jailbreak tweak for multi-instance), Thor (paid sniffer), Stream (free sniffer)</p>
</blockquote>
<p>To be continued.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Fancybox for Images in the Twikoo Comment Section</title>
      <link>https://vccv.cc/en/article/fancybox-twikoo.html</link>
      <pubDate>Wed, 13 Jul 2022 14:38:25 +0000</pubDate>
      <guid>https://vccv.cc/en/article/fancybox-twikoo.html</guid>
      <description>Early this year I documented how to add Fancybox to the Hexo cactus theme. Later I switched the comment system to Twikoo. While upgrading today I saw a post about integrating Twikoo with lightGallery to enlarge comment images. Since I already use Fancybox, I decided to wire Twikoo up to Fancybox instead.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>In <a href="https://vccv.cc/article/fancybox-cactus.html" target="_blank" rel="noopener">this post</a> I explained how to add Fancybox to the cactus theme. I later swapped my comment system to <a href="https://twikoo.js.org/" target="_blank" rel="noopener">Twikoo</a>. While upgrading today I stumbled across: <a href="https://www.imaegoo.com/2021/twikoo-lightgallery/" target="_blank" rel="noopener">Integrate Twikoo with lightGallery to zoom comment images</a>. Since Fancybox is already installed, I might as well hook Twikoo to Fancybox.</p>
<h2 id="process">Process</h2>
<p>Following the author’s idea, locate the <code>twikoo.init</code> code and modify it. I’ll focus on what changed rather than pasting the original.</p>
<p>Here’s the final code:</p>
<h3 id="final-result">Final result</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">twikoo</span><span class="p">.</span><span class="nx">init</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// envId: &#39;abcdef&#39;,
</span></span></span><span class="line"><span class="cl">  <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="nx">onCommentLoaded</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">commentContents</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="s1">&#39;tk-content&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">commentContents</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">commentItem</span> <span class="o">=</span> <span class="nx">commentContents</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">imgEls</span> <span class="o">=</span> <span class="nx">commentItem</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;img&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">imgEl</span> <span class="o">=</span> <span class="nx">imgEls</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="c1">// Skip emoji, only wrap normal images
</span></span></span><span class="line"><span class="cl">          <span class="k">if</span> <span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">className</span> <span class="o">!=</span> <span class="s1">&#39;tk-owo-emotion&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-fancybox&#39;</span><span class="p">,</span> <span class="s1">&#39;gallery&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-caption&#39;</span><span class="p">,</span> <span class="s1">&#39;Comments: &#39;</span><span class="o">+</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;alt&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">            <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Below is how I arrived here—use the idea even if your theme code differs.</p>
<h3 id="read-the-original-code">Read the original code</h3>
<p>For reference, here’s the original snippet:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">twikoo</span><span class="p">.</span><span class="nx">init</span><span class="p">({</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// envId: &#39;abcdef&#39;,
</span></span></span><span class="line"><span class="cl">  <span class="c1">// ...
</span></span></span><span class="line"><span class="cl">  <span class="nx">onCommentLoaded</span><span class="o">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="kd">var</span> <span class="nx">commentContents</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="s1">&#39;tk-content&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o">&lt;</span> <span class="nx">commentContents</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">commentItem</span> <span class="o">=</span> <span class="nx">commentContents</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">      <span class="kd">var</span> <span class="nx">imgEls</span> <span class="o">=</span> <span class="nx">commentItem</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="s1">&#39;img&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">      <span class="k">if</span> <span class="p">(</span><span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span> <span class="o">&gt;</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o">&lt;</span> <span class="nx">imgEls</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">imgEl</span> <span class="o">=</span> <span class="nx">imgEls</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">          <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;class&#39;</span><span class="p">,</span> <span class="s1">&#39;tk-lg-link&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;href&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">          <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="nx">lightGallery</span><span class="p">(</span><span class="nx">commentItem</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">selector</span><span class="o">:</span> <span class="s1">&#39;.tk-lg-link&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">share</span><span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>The idea: find images (<code>img</code>) inside the comment area (<code>tk-content</code>), wrap each with the plugin-specific <code>&lt;a&gt;</code> markup, insert it, then remove the original image.</p>
<blockquote>
<p>You can swap in other plugins by adjusting the markup:</p>
<p>lightgallery:</p>
<p><code>&lt;a class=&quot;tk-lg-link&quot; data-src=&quot;xxx.png&quot; href=&quot;xxx.png&quot;&gt;&lt;img src=&quot;xxx.png&quot; alt=&quot;xxx&quot;&gt;&lt;/a&gt;</code></p>
<p>fancybox:</p>
<p><code>&lt;a data-fancybox=&quot;gallery&quot; data-src=&quot;xxx.png&quot; data-caption=&quot;xxx&quot;&gt;&lt;img src=&quot;xxx.png&quot; alt=&quot;xxx&quot;&gt;&lt;/a&gt;</code></p>
</blockquote>
<h3 id="change-the-tags">Change the tags</h3>
<p>Copy the structure and switch attributes to Fancybox. For example, lightGallery needs <code>class=&quot;tk-lg-link&quot;</code>, whereas Fancybox needs <code>data-fancybox=&quot;gallery&quot;</code>. So replace <code>aEl.setAttribute('class', 'tk-lg-link');</code> with <code>aEl.setAttribute('data-fancybox', 'gallery');</code>, and so on.</p>
<h3 id="remove-unused-code">Remove unused code</h3>
<p>lightGallery also required:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="nx">lightGallery</span><span class="p">(</span><span class="nx">commentItem</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nx">selector</span><span class="o">:</span> <span class="s1">&#39;.tk-lg-link&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nx">share</span><span class="o">:</span> <span class="kc">false</span>
</span></span><span class="line"><span class="cl">        <span class="p">});</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Fancybox doesn’t need this, so delete it. After these changes, try it out—and you’ll hit another issue.</p>
<h3 id="comment-images-vs-emoji">Comment images vs emoji</h3>
<p>Emoji are also <code>&lt;img&gt;</code> elements (<code>class=&quot;tk-owo-emotion&quot;</code>), so the plugin was wrapping emoji too, which is unnecessary.</p>
<h3 id="handle-emoji">Handle emoji</h3>
<p>Add a simple check to skip emoji:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">className</span> <span class="o">!=</span> <span class="s1">&#39;tk-owo-emotion&#39;</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="kd">var</span> <span class="nx">aEl</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="s1">&#39;a&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-fancybox&#39;</span><span class="p">,</span> <span class="s1">&#39;gallery&#39;</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-src&#39;</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;src&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="nx">aEl</span><span class="p">.</span><span class="nx">setAttribute</span><span class="p">(</span><span class="s1">&#39;data-caption&#39;</span><span class="p">,</span> <span class="s1">&#39;Comments: &#39;</span><span class="o">+</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">getAttribute</span><span class="p">(</span><span class="s1">&#39;alt&#39;</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="nx">aEl</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">imgEl</span><span class="p">.</span><span class="nx">cloneNode</span><span class="p">(</span><span class="kc">false</span><span class="p">));</span>
</span></span><span class="line"><span class="cl">  <span class="nx">imgEl</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">aEl</span><span class="p">,</span> <span class="nx">imgEl</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="nx">imgEl</span><span class="p">.</span><span class="nx">remove</span><span class="p">();</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Make sure this condition sits inside the <strong>second for-loop</strong>.</p>
<h2 id="result">Result</h2>
<p><a href="/en/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp" data-fancybox="gallery" data-src="/en/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp" data-caption="Final effect">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/fancybox-twikoo/image-20220713153543806_hu_a768fe61115f769f.webp 480w, /en/article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp 720w, /en/article/fancybox-twikoo/image-20220713153543806_hu_bcd3e397ec76c272.webp 960w, /en/article/fancybox-twikoo/image-20220713153543806_hu_6e486905bf5d9e61.webp 1440w, /en/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp 2750w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2750"
                    height="1570"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp"
                    srcset="/en/article/fancybox-twikoo/image-20220713153543806_hu_a768fe61115f769f.webp 480w, /en/article/fancybox-twikoo/image-20220713153543806_hu_368747c6341d6d9c.webp 720w, /en/article/fancybox-twikoo/image-20220713153543806_hu_bcd3e397ec76c272.webp 960w, /en/article/fancybox-twikoo/image-20220713153543806_hu_6e486905bf5d9e61.webp 1440w, /en/article/fancybox-twikoo/image-20220713153543806_hu_9b4f75bc6ca3b21.webp 2750w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="Final effect"
                    
                />
            </picture>
        </a></p>
<p>That’s it—clean galleries without wrapping emoji.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://www.imaegoo.com/2021/twikoo-lightgallery/" target="_blank" rel="noopener">iMaeGoo</a></p>
<p><a href="https://twikoo.js.org/" target="_blank" rel="noopener">twikoo</a></p>
<p><a href="https://fancyapps.com/fancybox/" target="_blank" rel="noopener">fancybox</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Workarounds for EasyConnect on Linux</title>
      <link>https://vccv.cc/en/article/docker-easyconnect.html</link>
      <pubDate>Fri, 08 Jul 2022 15:29:12 +0000</pubDate>
      <guid>https://vccv.cc/en/article/docker-easyconnect.html</guid>
      <description>When at home on vacation and needed to use EasyConnect to connect to the school&amp;#39;s intranet, so I planned to download it and use it. But! EasyConnect is a rogue software, which is often referred to as poisonous software, so I started to look for ways to deal with it.</description>
      <content:encoded><![CDATA[<h2 id="start">Start</h2>
<p>I&rsquo;m at home on vacation and I need to use <strong>EasyConnect</strong> to connect to the school&rsquo;s intranet. I occasionally need to connect to the school&rsquo;s server or access intranet pages, so I plan to download it.</p>
<p>But! EasyConnect is a rogue software, which is often referred to as a cancerous software. I then started looking for ways to deal with it.</p>
<blockquote>
<p>Under macOS, EasyConnect primarily behaves as follows.</p>
<ol>
<li>background resident processes EasyMonitor and ECAgentProxy, both running with root privileges.</li>
<li>automatically installs root certificates, including the system root certificate and FireFox root certificate, and reinstalls them after deletion.</li>
</ol>
<p>ps: Resident processes with <em>root</em> privileges means that these processes can read and write anything; installing root certificates means that they can directly perform man-in-the-middle attacks and tamper with data at will.</p>
</blockquote>
<h2 id="method-1">Method 1</h2>
<p>This method is suitable for computers with EasyConnect already installed, with minimal tossing.</p>
<ol>
<li>
<p>use <code>sudo su</code> to obtain administrator privileges.</p>
</li>
<li>
<p>Delete (rm)</p>
<p>/Library/LaunchDaemons/com.sangfor.EasyMonitor.plist.</p>
</li>
<li>
<p>delete /Library/LaunchAgents/com.sangfor.ECAgentProxy.plist.</p>
</li>
<li>
<p>reboot the Mac.</p>
</li>
<li>
<p>Open the keychain and delete the certificate under System Keychain - System - Certificates (keyword sangfor).</p>
</li>
</ol>
<blockquote>
<p>Be sure to <em>restart the Mac before deleting the certificate</em>, as the EasyMonitor process in the background will automatically import the certificate after it has been deleted.</p>
</blockquote>
<p>This eliminates the problem with EasyConnect. However, so far it causes EasyConnect not to connect, so we need to start EasyConnect in a secure way. Two scripts can be written to achieve start and exit.</p>
<p><strong>startEasyConnect.sh</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#! /bin/bash
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">/Applications/EasyConnect.app/Contents/Resources/bin/EasyMonitor &gt; /dev/null 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</span></span><span class="line"><span class="cl">/Applications/EasyConnect.app/Contents/MacOS/EasyConnect &gt; /dev/null 2&gt;<span class="p">&amp;</span><span class="m">1</span> <span class="p">&amp;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>killEasyMonitor.sh</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#! /bin/bash
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">pkill EasyMonitor
</span></span><span class="line"><span class="cl">pkill ECAgent
</span></span><span class="line"><span class="cl">pkill ECAgentProxy
</span></span></code></pre></td></tr></table>
</div>
</div><p>Place the above two scripts under the <code>PATH</code> path and grant executable permissions to.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x startEasyConnect.sh
</span></span><span class="line"><span class="cl">chmod +x killEasyMonitor.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>When you need to use EasyConnect, execute the <code>startEasyConnect</code> command as <strong>regular user</strong> (the EasyMonitor process will not have permission to import the root certificate). After exiting EasyConnect, run <code>killEasyMonitor</code> to kill the EasyMonitor process in the background.</p>
<h2 id="method-2">Method 2</h2>
<p>Suitable for those who have not yet installed EasyConnect and have some knowledge of Docker and are not afraid of trouble. (being used)</p>
<h3 id="installing-docker">Installing Docker</h3>
<p><a href="https://docs.docker.com/desktop/windows/install/" target="_blank" rel="noopener">Windows</a></p>
<p><a href="https://docs.docker.com/desktop/mac/install/" target="_blank" rel="noopener">macOS</a></p>
<h3 id="installing-clash">Installing Clash</h3>
<p><a href="https://github.com/Fndroid/clash_for_windows_pkg/releases" target="_blank" rel="noopener">Windows</a></p>
<p><a href="https://github.com/yichengchen/clashX/releases" target="_blank" rel="noopener">ClashX</a> or <a href="https://install.appcenter.ms/users/clashx/apps/clashx-pro/distribution_groups/public" target="_blank" rel="noopener">ClashX Pro</a> versions can also be installed on macOS</p>
<h3 id="install-vnc-viewer-optional">Install VNC Viewer (optional)</h3>
<p>If you are using EasyConnect <strong>which requires</strong> a graphical interface to log in, you need to install VNC Viewer, otherwise you can skip this step.</p>
<p>If you don&rsquo;t know, you can skip this step and return to it later when you are prompted to run EasyConnect with Docker and cannot finish in the command line interface.</p>
<p>The installation of VNC Viewer is very simple, go to the <a href="https://www.realvnc.com/en/connect/download/viewer/" target="_blank" rel="noopener">Download</a> page on the official website, select the appropriate version to download, and then go all the way to the next step to complete.</p>
<h3 id="installing-a-text-editor">Installing a text editor</h3>
<p>Because it involves editing and modifying <strong>yaml</strong> files, you may need to install a <a href="https://code.visualstudio.com/" target="_blank" rel="noopener">VSCode</a>, which does not use Notepad because it does not have highlighting, does not spell words, and does not automatically format, which may cause you to have some indentation, spelling, and punctuation errors that are more It is difficult to find.</p>
<p>VSCode is free, but here is another recommended software: <strong>Sublime Text</strong> (paid).</p>
<h3 id="running-easyconnect-with-docker">Running EasyConnect with Docker</h3>
<p>First make sure that your Docker is running (try run <code>docker ps -a</code>). Open a terminal and enter different commands depending on whether you need a graphical interface or not.</p>
<blockquote>
<p>2022.12.29 Updated</p>
<p>I am an Intel model of MacBook, according to the reminder of the old brother in the comments section, the following tutorial <strong>does not apply</strong> to Apple&rsquo;s own M series chips, i.e. <strong>arm architecture</strong> machines.</p>
<p>Since I don&rsquo;t have an M-chip machine, please try compiling <strong>non-amd64</strong> branch files on your own if needed, see <a href="https://github.com/Hagb/issues/167" target="_blank" rel="noopener">issue167</a> for details. If you encounter new problems during the compilation process, you can read more issues raised by others.</p>
</blockquote>
<p><strong>Pure command line version:</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.easyconn
</span></span><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -v <span class="nv">$HOME</span>/.easyconn:/root/.easyconn -it -p 127.0.0.1:1080:1080 -p 127.0.0.1:8888:8888 -e <span class="nv">IPTABLES_LEGACY</span><span class="o">=</span><span class="m">1</span> -e <span class="nv">EC_VER</span><span class="o">=</span>7.6.3 -e <span class="nv">CLI_OPTS</span><span class="o">=</span><span class="s2">&#34;-d vpn.xxx.edu.cn -u USERNAME -p PASSWORD&#34;</span> hagb/docker-easyconnect:cli
</span></span></code></pre></td></tr></table>
</div>
</div><p>The commands are explained below.</p>
<ul>
<li>In the first line, we create a configuration file in the <code>$HOME</code> directory of the current user to save login information.</li>
<li>On the second line, we start an EasyConnect command-line version of the Docker container.
<ul>
<li><code>--device /dev/net/tun --cap-add NET_ADMIN</code> creates the virtual network device.</li>
<li><code>-it</code> returns an interactive terminal to display information.</li>
<li><code>-v</code> specifies the mount volume, where we map the configuration file in the <code>$HOME$</code> directory of the current user to the container, enabling the persistence of login information.</li>
<li><code>-p</code> specifies the port mapping of the container, you can change the port number according to the actual situation. where 1080 is the Socks5 proxy port and 8888 is the HTTP proxy port.</li>
<li><code>-e EC_VER </code> Set the value of the environment variable <code>EC_VER</code> in the container, specifying the version of Sangfor, preferably the same as the server side.</li>
<li><code>-e CLI_OPTS</code> sets the value of the environment variable <code>CLI_OPTS</code> in the container, specifying the parameters when running Sangfor. Here <code>-d</code> specifies the VPN address, <code>-u</code> specifies the user name, and <code>-p</code> specifies the user&rsquo;s password. Please <strong>modify these information yourself correctly</strong>!</li>
<li><code>-e IPTABLES_LEGACY=1</code> uses the old iptables command, mainly to maintain compatibility with WSL. On some distributions of WSL, the absence of this environment variable will prevent the VPN from functioning properly. (Optional)</li>
</ul>
</li>
</ul>
<p>Please refer to: <a href="https://github.com/Hagb/blob/master/doc/usage.md" target="_blank" rel="noopener">usage.md</a> for specific parameter settings</p>
<p><strong>GUI version:</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -ti -e <span class="nv">PASSWORD</span><span class="o">=</span>xxxx -v <span class="nv">$HOME</span>/.ecdata:/root -p 127.0.0.1:5901:5901 -p 127.0.0.1:1080:1080 hagb/docker-easyconnect:7.6.3
</span></span></code></pre></td></tr></table>
</div>
</div><p>Where <code>hagb/docker-easyconnect:7.6.3</code> means use <code>7.6.3</code> version of EasyConnect, please change the version number according to the actual situation.</p>
<blockquote>
<p>PS: When your port 5901 or 1080 is occupied by other services, you can change the port of EasyConnect that we run with docker above by using the following command (for example, the command line version is pure, the GUI version is the same);</p>
<p>127.0.0.1:<em>15901</em>:5901 and 127.0.0.1:<em>10180</em>:1080. You can change the 15901 and 10180 in 127.0.0.1:<em>15901</em>:1080 to your own unoccupied ports.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker run --device /dev/net/tun --cap-add NET_ADMIN -ti -e <span class="nv">PASSWORD</span><span class="o">=</span>xxxx -v <span class="nv">$HOME</span>/.ecdata:/root -p 127.0.0.1:15901:5901 -p 127.0.0.1:10180:1080 hagb/docker-easyconnect:7.6.3
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="graphical-vnc-viewer-connection">Graphical VNC Viewer connection</h3>
<p>After typing, open <strong>VNC Viewer</strong>, click <strong>File -&gt; New connection</strong> in the upper left corner, or <strong>right click -&gt; New connection</strong> in the blank space, or use the shortcut key <strong>Ctrl + N</strong> to create a new link, and fill in the VNC Server in the pop-up dialog box <strong>127.0.0.1:5901</strong> , Name can be left out.</p>
<p><a href="/en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp" data-fancybox="gallery" data-src="/en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp" data-caption="VNC Viewer">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_9533240000a87157.webp 480w, /en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp 583w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="583"
                    height="791"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp"
                    srcset="/en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_9533240000a87157.webp 480w, /en/article/docker-easyconnect/v2-ef2d65c9a9b6b65228529a429261160c_r_hu_4e7b534acd30c9c7.webp 583w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="VNC Viewer"
                    
                />
            </picture>
        </a></p>
<p>After clicking OK, double-click the link we just created, enter the password XXXX, and you&rsquo;re ready to connect.</p>
<blockquote>
<p>It&rsquo;s much easier to run EasyConnect in Docker without having to enter a captcha.</p>
<p>It is more convenient.</p>
<p>Also, the project itself remembers the server address you entered, so you only need to click the login button when you use it in the future.</p>
</blockquote>
<p>At this point, you&rsquo;ll have a socks5 proxy running on <strong>1080 port</strong> on your computer, and the next step is to configure Clash to forward when we need it.</p>
<h3 id="configuring-clash">Configuring Clash</h3>
<p>This section describes how you can use EasyConnect&rsquo;s VPN service when you need it.</p>
<p>First run Clash, click Profiles in the left navigation bar and you will see a default <strong>config.yaml</strong>, or you can edit other profiles if you have them. Click on the button shaped like <code>&lt; &gt;</code> to the right of the profile you want to edit, meaning edit the profile in a text editor, and add at the end.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Add a sock5 proxy with the name vpn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- {<span class="nt">&#34;name&#34;: &#34;vpn&#34;, &#34;type&#34;: &#34;socks5&#34;, &#34;server&#34;: &#34;127.0.0.1&#34;, &#34;port&#34;: </span><span class="s2">&#34;1080&#34;</span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># Add rules for ip-cidr</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- <span class="l">IP-CIDR,222.192.6.0/24,vpn</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Caution.</p>
<p>The <code>222.192.6.0/24</code> filled in here means that only the traffic accessing <code>222.192.6.xxx</code> will go through the proxy configured above, which needs to be changed according to your actual situation.</p>
<p>Of course, if you are editing your own airport configuration file, you need to add the above content under the original <code>proxies</code> and <code>rules</code>, and * cannot add these two attributes*.</p>
</blockquote>
<p>At this point, in Clash&rsquo;s General page, turn <strong>System Proxy</strong> on and you will have access to the school&rsquo;s intranet, but not to remote desktops and other features, which will require further configuration if you need to use them.</p>
<h3 id="configure-clashx">Configure ClashX</h3>
<p>Similar to the above.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- {<span class="w"> </span><span class="nt">name: &#39;vpn&#39;, type: socks5, server: 127.0.0.1, port</span><span class="p">:</span><span class="w"> </span><span class="m">1080</span><span class="w"> </span>}<span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">	</span>- <span class="s1">&#39;IP-CIDR,172.20.2.0/24,vpn&#39;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><h3 id="configuring-tun-mode">Configuring TUN mode</h3>
<p>For TUN mode, the official documentation describes it as follows.</p>
<blockquote>
<p>For software that does not follow the system proxy, TUN mode can take over its traffic and leave it to CFW. In Windows, TUN mode performs better than TAP mode.</p>
</blockquote>
<p>Applications such as browsers use the system agent, and some non-system agent applications can be set up to be handled by CFW. In short, after configuring TUN mode, our requirements are ready to be implemented. To start TUN mode, you need to do the following (<strong>MacOS users skip the first two steps</strong>):</p>
<ol>
<li>open the General page of Clash, find Home Directory, click <code>Open Folder</code> on the right to open the <code>Home Directory</code> folder.</li>
<li>Go to the website <a href="https://www.wintun.net/" target="_blank" rel="noopener">Wintun</a> and click <code>Download Wintun xxx</code> in the interface to download the zip package. Copy <code>wintun.dll</code> from the directory corresponding to <code>wintun-x.xx/wintun/bin</code> to the <code>Home Directory</code> directory according to the system version. Use the <code>amd64</code> version for <code>64</code> based processors for <code>64</code> bit operating systems, and choose the <code>arm64</code> version for M1 Macs.</li>
<li>Click Manage on the right side of Service Mode in General, and install Service Mode in the window that opens, the application will restart automatically when the installation is finished, and the Earth icon on the right side of Service Mode turns green.</li>
<li>Click <strong>settings -&gt; Profile Mixin -&gt; YAML</strong>, click <strong>Edit</strong> on the right side of <strong>YAML</strong>, enter the following content, and click the button at the bottom right to save.</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">mixin</span><span class="p">:</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">hosts</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;mtalk.google.com&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">108.177.125.188</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;services.googleapis.cn&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">74.125.203.94</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">&#39;raw.githubusercontent.com&#39;</span><span class="p">:</span><span class="w"> </span><span class="m">151.101.76.133</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">dns</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enable</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">default-nameserver</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">223.5.5.5</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">1.0.0.1</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">ipv6</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enhanced-mode</span><span class="p">:</span><span class="w"> </span><span class="l">redir-host</span><span class="w"> </span><span class="c">#fake-ip</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">nameserver</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.rubyfish.cn/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://223.5.5.5/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.pub/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fallback</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://1.0.0.1/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://public.dns.iij.jp/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">https://dns.twnic.tw/dns-query</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">fallback-filter</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">geoip</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span><span class="nt">ipcidr</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">240.0.0.0</span><span class="l">/4</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">0.0.0.0</span><span class="l">/32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">127.0.0.1</span><span class="l">/32</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">domain</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.google.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.facebook.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.twitter.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.youtube.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.xn--ngstr-lra8j.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.google.cn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.googleapis.cn</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="l">+.gvt1.com</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">tun</span><span class="p">:</span><span class="w"> 
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">enable</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">stack</span><span class="p">:</span><span class="w"> </span><span class="l">gvisor</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">dns-hijack</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">      </span>- <span class="m">198.18.0.2</span><span class="p">:</span><span class="m">53</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">macOS-auto-route</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="nt">macOS-auto-detect-interface</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w"> </span><span class="c"># 自动检测出口网卡</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><ol start="5">
<li>Return to the general page to turn on Mixin, and then click connections to find that all connections are in TUN mode, at which point we have completed all configurations.</li>
</ol>
<p>For more detailed configuration, please refer to the <a href="https://docs.cfw.lbyczf.com/contents/tun.html" target="_blank" rel="noopener">TUN mode</a> page of the official documentation.</p>
<h3 id="filtering-applications">Filtering applications</h3>
<p>Related rules can be found in.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;officeVpnProxy&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;socks5&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">server</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;127.0.0.1&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">port</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;10180&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxy-groups</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;programs&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="l">select</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">proxies</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;DIRECT&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="s2">&#34;PROXY&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="c"># programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,vpnkit.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,vpnkit-bridge.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.dev-envs.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.backend.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.extensions.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.proxy.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.service,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,com.docker.wsl-distro-proxy.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,Docker Desktop.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,docker.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,wsl.exe,programs</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span>- <span class="l">PROCESS-NAME,wslhost.exe,programs</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Note: The ports should correspond to the ports you configured in the previous docker configuration.</p>
</blockquote>
<h3 id="rebooting">Rebooting</h3>
<p>When you close the terminal window or reboot your computer and want to start Docker again, we just need to start the appropriate container and click Login in VNC Viewer (if you don&rsquo;t use the graphical interface, you only need to start the container).</p>
<p>To start the container, you don&rsquo;t need to type the command above to create the container, because the command means create the container, download the image, start and enter the container, we have already created the container, we just need to start it later. So, we first need to know what containers we have, and then start the corresponding containers on it.</p>
<p>First, look at the containers we already have</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker ps -a
</span></span></code></pre></td></tr></table>
</div>
</div><p>You should get similar output, and if this is your first time using Docker, you should only have one container</p>
<p><a href="/en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-fancybox="gallery" data-src="/en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp" data-caption="docker container">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2010"
                    height="102"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp"
                    srcset="/en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_ef10729183ff2e30.webp 480w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d466bcf537e6ea85.webp 720w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_d708a6bdd75c67f5.webp 960w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_6f6a876e8f0cd3d8.webp 1440w, /en/article/docker-easyconnect/v2-31c51548fc67de83039eeedf10bf28c5_r_hu_eabb254bfa5029bd.webp 2010w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="docker container"
                    
                />
            </picture>
        </a></p>
<p>When you want to turn it on again after the computer has restarted, just type.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker start 81f
</span></span></code></pre></td></tr></table>
</div>
</div><p>The <code>81f</code> is the <code>ID</code> of the container I want to start, which is the value of the first column, it&rsquo;s a long value, usually you only need to enter the first few digits, or you can change it with the <code>docker rename</code> command.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">docker rename OLDNAME NEWNAME
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="uninstalling-easyconnect">Uninstalling EasyConnect</h2>
<p>As I said before, one of the rogue things about EasyConnect is that it is very difficult to uninstall, but I have come up with a method based on information from the Internet and my own experience.</p>
<p>First, find the EasyConnect installation directory and double-click it to run the uninstaller, then you will see that the directory is not completely deleted, there are still a lot of files, so let&rsquo;s perform the following steps.</p>
<ol>
<li>select all Shift + Delete, if you encounter the one that does not give the deletion will be skipped, then there will still be many files left.</li>
<li>Disconnect and restart the computer, come to the installation directory, change the names of all the folders, change them to whatever you want, restart again</li>
<li>Select all the folders that have just been renamed Shift + Delete, if this time still can not delete the folder cut to another place and then delete</li>
<li>restart the computer, administrator privileges to open the command line (if you do not have the usual command line tools can Win + X select <strong>Windows PowerShell (Administrator)</strong>)</li>
<li>enter the command <code>netsh winsock reset</code> and enter</li>
</ol>
<p>The last two steps to reset winsock are very important, if not performed will likely be a variety of clients can not connect to the network situation.</p>
<p>If you still have the <strong>sanfor</strong> service after uninstallation, you can refer to <a href="https://www.zhihu.com/question/333699380/answer/2358761655" target="_blank" rel="noopener">this article</a> to try to solve it.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/Hagb/docker-easyconnect" target="_blank" rel="noopener">docker-easyconnect</a></p>
<p><a href="https://soulike.tech/article/64" target="_blank" rel="noopener">Soulike</a></p>
<p><a href="https://zhuanlan.zhihu.com/p/389894063" target="_blank" rel="noopener">Jortana</a></p>
<p><a href="https://naiv.fun/Ops/sangfor-in-docker.html" target="_blank" rel="noopener">Nativus</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Yabai: Tiling Window Manager for Mac</title>
      <link>https://vccv.cc/en/article/mac-tiling-yabai.html</link>
      <pubDate>Thu, 19 May 2022 12:03:26 +0000</pubDate>
      <guid>https://vccv.cc/en/article/mac-tiling-yabai.html</guid>
      <description>Long-time Linux users should be no stranger to i3wm, which differs significantly from Mac and Windows operating systems like the floating (float) desktop, which is called the tiling (tiling) desktop. When I learned about the open source project yabai for Mac, I couldn&amp;#39;t wait to start using it.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>Long-time Linux users should be familiar with <a href="https://i3wm.org/" target="_blank" rel="noopener">i3wm</a>, which is significantly different from the floating (float) desktops of Mac and Windows operating systems, which are called tiling desktops. When I learned about the open source project <a href="https://github.com/koekeishiya/yabai" target="_blank" rel="noopener">yabai</a> for Mac, I couldn&rsquo;t wait to start using it.</p>
<h2 id="installation">Installation</h2>
<blockquote>
<p>Equipment status:</p>
<p><a href="https://zhuanlan.zhihu.com/p/90508170" target="_blank" rel="noopener">Homebrew is installed</a> (You can refer to the official website)</p>
<p><a href="https://github.com/koekeishiya/yabai/wiki/Disabling-System-Integrity-Protection" target="_blank" rel="noopener">Closed SIP</a></p>
<p>Monterey12.4</p>
</blockquote>
<p>It is best to refer to <a href="https://github.com/koekeishiya/yabai/wiki/Installing-yabai-%28latest-release%29" target="_blank" rel="noopener">Official Documents</a> for installation, after all, the official one is the latest and most accurate.</p>
<p>The following is a record of your own process, which is available for your reference.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Install yabai</span>
</span></span><span class="line"><span class="cl">brew install koekeishiya/formulae/yabai
</span></span><span class="line"><span class="cl">sudo yabai --install-sa
</span></span><span class="line"><span class="cl"><span class="c1"># Start yabai</span>
</span></span><span class="line"><span class="cl">brew services start yabai
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Install skhd</span>
</span></span><span class="line"><span class="cl">brew install koekeishiya/formulae/skhd
</span></span><span class="line"><span class="cl"><span class="c1"># Start skhd</span>
</span></span><span class="line"><span class="cl">brew services start skhd
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">########### macOS Big Sur or Monterey More Steps ###########</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">sudo visudo -f /private/etc/sudoers.d/yabai
</span></span><span class="line"><span class="cl"><span class="c1"># Change &lt;user&gt; to you own username</span>
</span></span><span class="line"><span class="cl"><span class="c1"># yuesir ALL = (root) NOPASSWD: /usr/local/bin/yabai --load-sa</span>
</span></span><span class="line"><span class="cl">&lt;user&gt; <span class="nv">ALL</span> <span class="o">=</span> <span class="o">(</span>root<span class="o">)</span> NOPASSWD: /usr/local/bin/yabai --load-sa
</span></span><span class="line"><span class="cl"><span class="c1"># Add to .yabairc</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">yabai -m signal --add <span class="nv">event</span><span class="o">=</span>dock_did_restart <span class="nv">action</span><span class="o">=</span><span class="s2">&#34;sudo yabai --load-sa&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>yabai can be used with <a href="https://github.com/koekeishiya/skhd" target="_blank" rel="noopener">skhd</a>, the option <strong>Secure Keyboard Entry</strong> must be disabled (off by default).</p>
<p>After the system starts yabai and skhd for the first time, macOS will prompt for permission to access the secondary functions. After adding permissions to <strong>System Preferences-&gt;Installability and Privacy-&gt;Privacy</strong>, execute the following command.</p>
<p><a href="/en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp" data-fancybox="gallery" data-src="/en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp" data-caption=" Authorization assistance functions ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_f95f04c5b6aa4bcb.webp 480w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp 720w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_fb3d69dd55d3b947.webp 960w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp 1408w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1408"
                    height="1246"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp"
                    srcset="/en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_f95f04c5b6aa4bcb.webp 480w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_7a56cdff6bd28bbe.webp 720w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_fb3d69dd55d3b947.webp 960w, /en/article/mac-tiling-yabai/1161505-20220306151719494-1937640907_hu_48189a4b6857e765.webp 1408w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Authorization assistance functions "
                    
                />
            </picture>
        </a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Restart</span>
</span></span><span class="line"><span class="cl">brew services restart yabai
</span></span><span class="line"><span class="cl">brew services restart skhd
</span></span></code></pre></td></tr></table>
</div>
</div><p>This is still not working properly, and you still need to configure the relevant files yourself.</p>
<h2 id="configuration">Configuration</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Create yabai config</span>
</span></span><span class="line"><span class="cl">touch ~/.yabairc
</span></span><span class="line"><span class="cl">chmod +x ~/.yabairc
</span></span><span class="line"><span class="cl"><span class="c1"># Create skhd config</span>
</span></span><span class="line"><span class="cl">touch ~/.skhdrc
</span></span><span class="line"><span class="cl">chmod +x ~/.skhdrc
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="yabairc-example">.yabairc <a href="https://www.cnblogs.com/tdg-yyx/p/15972309.html" target="_blank" rel="noopener">Example</a>：</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span><span class="lnt">38
</span><span class="lnt">39
</span><span class="lnt">40
</span><span class="lnt">41
</span><span class="lnt">42
</span><span class="lnt">43
</span><span class="lnt">44
</span><span class="lnt">45
</span><span class="lnt">46
</span><span class="lnt">47
</span><span class="lnt">48
</span><span class="lnt">49
</span><span class="lnt">50
</span><span class="lnt">51
</span><span class="lnt">52
</span><span class="lnt">53
</span><span class="lnt">54
</span><span class="lnt">55
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="cp">#!/usr/bin/env sh
</span></span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 这里参考了 yabai 的 wiki 。具体步骤下面讲</span>
</span></span><span class="line"><span class="cl">sudo yabai --load-sa
</span></span><span class="line"><span class="cl">yabai -m signal --add <span class="nv">event</span><span class="o">=</span>dock_did_restart <span class="nv">action</span><span class="o">=</span><span class="s2">&#34;sudo yabai --load-sa&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口布局 bsp: 平铺 float: 浮动</span>
</span></span><span class="line"><span class="cl">yabai -m config layout                       bsp
</span></span><span class="line"><span class="cl"><span class="c1"># 默认拆分规则 first_child second_child</span>
</span></span><span class="line"><span class="cl">yabai -m config window_placement             second_child
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口间距设置</span>
</span></span><span class="line"><span class="cl">yabai -m config top_padding                  <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config bottom_padding               <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config left_padding                 <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config right_padding                <span class="m">5</span>
</span></span><span class="line"><span class="cl">yabai -m config window_gap                   <span class="m">4</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 自动平衡所有窗口始终占据相同的空间</span>
</span></span><span class="line"><span class="cl">yabai -m config auto_balance                 off
</span></span><span class="line"><span class="cl"><span class="c1"># 如果禁用自动平衡，此项属性定义的是新窗口占用的空间量。0.5意为旧窗口占用50%</span>
</span></span><span class="line"><span class="cl">yabai -m config split_ratio                 0.50
</span></span><span class="line"><span class="cl"><span class="c1"># 鼠标修饰键 意思就是按着这个键就可以使用鼠标单独修改窗口大小了</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_modifier               fn
</span></span><span class="line"><span class="cl"><span class="c1"># fn + 左键 移动</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_action1                move
</span></span><span class="line"><span class="cl"><span class="c1"># fn + 右键 </span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_action2                resize
</span></span><span class="line"><span class="cl"><span class="c1"># 焦点跟随鼠标 默认off: 关闭  autoraise:自动提升 autofocus: 自动对焦</span>
</span></span><span class="line"><span class="cl">yabai -m config focus_follows_mouse          autofocus
</span></span><span class="line"><span class="cl"><span class="c1"># 设置鼠标是否跟随当前活动窗口 默认 off: 关闭 on: 开启</span>
</span></span><span class="line"><span class="cl">yabai -m config mouse_follows_focus          on
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动窗口问题在顶部</span>
</span></span><span class="line"><span class="cl">yabai -m config window_topmost               on
</span></span><span class="line"><span class="cl"><span class="c1"># 修改窗口阴影 on: 打开 off: 关闭 float: 只显示浮动窗口的阴影</span>
</span></span><span class="line"><span class="cl">yabai -m config window_shadow                float
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 窗口透明度设置</span>
</span></span><span class="line"><span class="cl">yabai -m config window_opacity               on
</span></span><span class="line"><span class="cl"><span class="c1"># 配置活动窗口不透明度</span>
</span></span><span class="line"><span class="cl">yabai -m config active_window_opacity        1.0             
</span></span><span class="line"><span class="cl">yabai -m config normal_window_opacity        0.9
</span></span><span class="line"><span class="cl">yabai -m config window_opacity_duration      0.0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 在主显示器上的每个空间顶部添加 20 填充 底部添加 0 填充</span>
</span></span><span class="line"><span class="cl"><span class="c1"># yabai -m config external_bar main:20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 在所有显示器上的每个空间顶部添加 0 填充 底部添加 0 填充</span>
</span></span><span class="line"><span class="cl">yabai -m config external_bar all:0:5
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 规则 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 打开系统偏好设置，不使用平铺模式</span>
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^系统偏好设置</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^提醒事项</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">yabai -m rule --add <span class="nv">app</span><span class="o">=</span><span class="s2">&#34;^关于本机</span>$<span class="s2">&#34;</span> <span class="nv">manage</span><span class="o">=</span>off
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;yabai configuration loaded..&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="skhdrc-example">.skhdrc Example：</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># ================================ 窗口设置 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># focus window : 激活窗口快捷键  h: 左  j: 下  k: 右 l: 上 </span>
</span></span><span class="line"><span class="cl">alt - h : yabai -m window --focus west
</span></span><span class="line"><span class="cl">alt - j : yabai -m window --focus south
</span></span><span class="line"><span class="cl">alt - k : yabai -m window --focus north
</span></span><span class="line"><span class="cl">alt - l : yabai -m window --focus east 
</span></span><span class="line"><span class="cl"><span class="c1"># 交换窗口位置</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - h : yabai -m window --swap west
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - j : yabai -m window --swap south
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - k : yabai -m window --swap north
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + alt - l : yabai -m window --swap east
</span></span><span class="line"><span class="cl"><span class="c1"># 移动窗口位置</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - h : yabai -m window --warp west
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - j : yabai -m window --warp south
</span></span><span class="line"><span class="cl"><span class="c1"># 因与IDEA shift + cmd + K push code 冲突，故注释了此快捷键</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - k : yabai -m window --warp north</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - l : yabai -m window --warp east
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动窗口设置 参考了Magent默认设置。因为之前用习惯了。。。。</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 恢复原始窗口大小</span>
</span></span><span class="line"><span class="cl">ctrl + alt - <span class="m">0</span> : yabai -m space --balance
</span></span><span class="line"><span class="cl"><span class="c1"># 把浮动窗口左右平分整个屏幕  rows:cols:start-x:star-y:width:height  m行:n列:x:y:w:h</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 最大化</span>
</span></span><span class="line"><span class="cl">ctrl + alt - <span class="k">return</span> : yabai -m window --grid 1:1:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - up     : yabai -m window --grid 2:1:0:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏左</span>
</span></span><span class="line"><span class="cl">ctrl + alt - left   : yabai -m window --grid 1:2:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏右</span>
</span></span><span class="line"><span class="cl">ctrl + alt - right  : yabai -m window --grid 1:2:1:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 2分屏下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - down   : yabai -m window --grid 2:1:0:1:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏左上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - u : yabai -m window --grid 2:2:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏右上</span>
</span></span><span class="line"><span class="cl">ctrl + alt - i : yabai -m window --grid 2:2:0:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏左下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - j : yabai -m window --grid 2:2:1:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 4分屏右下</span>
</span></span><span class="line"><span class="cl">ctrl + alt - k : yabai -m window --grid 2:2:1:1:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏左1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - d : yabai -m window --grid 1:3:0:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏左2</span>
</span></span><span class="line"><span class="cl">ctrl + alt - e : yabai -m window --grid 1:3:0:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏中1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - f : yabai -m window --grid 1:3:1:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏右2</span>
</span></span><span class="line"><span class="cl">ctrl + alt - t : yabai -m window --grid 1:3:1:0:2:1
</span></span><span class="line"><span class="cl"><span class="c1"># 3分屏右1</span>
</span></span><span class="line"><span class="cl">ctrl + alt - g : yabai -m window --grid 1:3:3:0:1:1
</span></span><span class="line"><span class="cl"><span class="c1"># 9分屏居中</span>
</span></span><span class="line"><span class="cl">ctrl + alt - c : yabai -m window --grid 3:3:1:1:1:1
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动/不浮动窗口 float / unfloat window and center on screen</span>
</span></span><span class="line"><span class="cl">alt - t : yabai -m window --toggle float<span class="p">;</span>yabai -m window --grid 4:4:1:1:2:2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">alt - r         : yabai -m space --rotate <span class="m">90</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 调整窗口大小</span>
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - left : yabai -m window --resize left:-50:0<span class="p">;</span> yabai -m window --resize right:-50:0
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - down : yabai -m window --resize bottom:0:50<span class="p">;</span> yabai -m window --resize top:0:50
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - up : yabai -m window --resize top:0:-50<span class="p">;</span> yabai -m window --resize bottom:0:-50
</span></span><span class="line"><span class="cl">ctrl + alt + cmd - right : yabai -m window --resize right:50:0<span class="p">;</span> yabai -m window --resize left:50:0
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 重启 Yabai</span>
</span></span><span class="line"><span class="cl">cmd + alt - r : /usr/bin/env osascript <span class="o">&lt;&lt;&lt;</span> <span class="s2">&#34;display notification \&#34;正在重启 Yabai\&#34; with title \&#34;Yabai\&#34;&#34;</span><span class="p">;</span> launchctl kickstart -k <span class="s2">&#34;gui/</span><span class="si">${</span><span class="nv">UID</span><span class="si">}</span><span class="s2">/homebrew.mxcl.yabai&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 多桌面配置  ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 创建一个新桌面，并把当前活动的窗口发送到新桌面，并且自动跳转到新桌面 需要jq支持 brew install jq</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - n : yabai -m space --create <span class="o">&amp;&amp;</span> <span class="nv">index</span><span class="o">=</span><span class="s2">&#34;</span><span class="k">$(</span>yabai -m query --spaces --display <span class="p">|</span> jq <span class="s1">&#39;.| length&#39;</span><span class="k">)</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> yabai -m window --space <span class="s2">&#34;</span><span class="si">${</span><span class="nv">index</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">&amp;&amp;</span> yabai -m space --focus <span class="s2">&#34;</span><span class="si">${</span><span class="nv">index</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 切换回最近的一个桌面</span>
</span></span><span class="line"><span class="cl">alt - x : yabai -m space --focus recent
</span></span><span class="line"><span class="cl"><span class="c1"># 切换回第一个桌面</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">1</span> : yabai -m space --focus <span class="m">1</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">2</span> : yabai -m space --focus <span class="m">2</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">3</span> : yabai -m space --focus <span class="m">3</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">4</span> : yabai -m space --focus <span class="m">4</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">5</span> : yabai -m space --focus <span class="m">5</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">6</span> : yabai -m space --focus <span class="m">6</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">7</span> : yabai -m space --focus <span class="m">7</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">8</span> : yabai -m space --focus <span class="m">8</span>
</span></span><span class="line"><span class="cl">alt - <span class="m">9</span> : yabai -m space --focus <span class="m">9</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 关闭当前桌面</span>
</span></span><span class="line"><span class="cl">cmd + alt - w : yabai -m space --destroy
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 把窗口发送到桌面，并跟随过去 send window to desktop and follow focus</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - z : yabai -m window --space next<span class="p">;</span> yabai -m space --focus next
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">1</span> : yabai -m window --space  1<span class="p">;</span> yabai -m space --focus <span class="m">1</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">2</span> : yabai -m window --space  2<span class="p">;</span> yabai -m space --focus <span class="m">2</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">3</span> : yabai -m window --space  3<span class="p">;</span> yabai -m space --focus <span class="m">3</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">4</span> : yabai -m window --space  4<span class="p">;</span> yabai -m space --focus <span class="m">4</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">5</span> : yabai -m window --space  5<span class="p">;</span> yabai -m space --focus <span class="m">5</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">6</span> : yabai -m window --space  6<span class="p">;</span> yabai -m space --focus <span class="m">6</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">7</span> : yabai -m window --space  7<span class="p">;</span> yabai -m space --focus <span class="m">7</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">8</span> : yabai -m window --space  8<span class="p">;</span> yabai -m space --focus <span class="m">8</span>
</span></span><span class="line"><span class="cl"><span class="nb">shift</span> + cmd - <span class="m">9</span> : yabai -m window --space  9<span class="p">;</span> yabai -m space --focus <span class="m">9</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ APPS ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># iTerm2</span>
</span></span><span class="line"><span class="cl">cmd - <span class="k">return</span> : open -a iTerm
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># ================================ 多显示器配置 ================================</span>
</span></span><span class="line"><span class="cl"><span class="c1"># focus monitora : </span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - z  : yabai -m display --focus prev</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - 3  : yabai -m display --focus 3</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># send window to monitor and follow focus</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + cmd - c  : yabai -m window --display next; yabai -m display --focus next</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + cmd - 1  : yabai -m window --display 1; yabai -m display --focus 1</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># move floating window</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + ctrl - a : yabai -m window --move rel:-20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + ctrl - s : yabai -m window --move rel:0:20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># increase window size</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + alt - a : yabai -m window --resize left:-20:0</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + alt - w : yabai -m window --resize top:0:-20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># decrease window size</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - s : yabai -m window --resize bottom:0:-20</span>
</span></span><span class="line"><span class="cl"><span class="c1"># shift + cmd - w : yabai -m window --resize top:0:20</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># set insertion point in focused container</span>
</span></span><span class="line"><span class="cl"><span class="c1"># ctrl + alt - h : yabai -m window --insert west</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle window zoom</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - d : yabai -m window --toggle zoom-parent</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - f : yabai -m window --toggle zoom-fullscreen</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle window split type</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - e : yabai -m window --toggle split</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 浮动/不浮动窗口 float / unfloat window and center on screen</span>
</span></span><span class="line"><span class="cl"><span class="c1">#alt - t : yabai -m window --toggle float;yabai -m window --grid 4:4:1:1:2:2</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># toggle sticky(+float), topmost, picture-in-picture</span>
</span></span><span class="line"><span class="cl"><span class="c1"># alt - p : yabai -m window --toggle sticky;\</span>
</span></span><span class="line"><span class="cl"><span class="c1">#           yabai -m window --toggle topmost;\</span>
</span></span><span class="line"><span class="cl"><span class="c1">#           yabai -m window --toggle pip</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="use">Use</h2>
<p>After using it for a few days, I found that skhd&rsquo;s shortcuts often conflict with application or system shortcuts, which is a bit troublesome.</p>
<p>In addition, there are more shortcut keys, you need to use more to remember familiar, I use it again for a period of time to see the situation first.</p>
<p>The effect would be something like the following:</p>
<p><a href="/en/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp" data-fancybox="gallery" data-src="/en/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp" data-caption=" Renderings ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/mac-tiling-yabai/image-20220520121029280_hu_45487547f7a8f045.webp 480w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp 720w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_1d12674daaeaaf6c.webp 960w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_d049b745022b47ff.webp 1440w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2760"
                    height="1840"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp"
                    srcset="/en/article/mac-tiling-yabai/image-20220520121029280_hu_45487547f7a8f045.webp 480w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_566e0ac6fa30cf75.webp 720w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_1d12674daaeaaf6c.webp 960w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_d049b745022b47ff.webp 1440w, /en/article/mac-tiling-yabai/image-20220520121029280_hu_13fbfc0ddb2c2fd6.webp 2760w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Renderings "
                    
                />
            </picture>
        </a></p>
<p>Looked almost well, just haven&rsquo;t played around with it, efficiency didn&rsquo;t improve much, unfortunately.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/koekeishiya/yabai" target="_blank" rel="noopener">yabai Open Source Project</a></p>
<p><a href="https://github.com/koekeishiya/skhd" target="_blank" rel="noopener">skhd Open Source Project</a></p>
<p><a href="https://www.cnblogs.com/tdg-yyx/p/15972309.html" target="_blank" rel="noopener">Toretto</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Teasing Master Takagi-san Notes</title>
      <link>https://vccv.cc/en/article/takagi-san.html</link>
      <pubDate>Sat, 26 Mar 2022 14:06:28 +0000</pubDate>
      <guid>https://vccv.cc/en/article/takagi-san.html</guid>
      <description>Takagi-san&amp;#39;s TV version is now finished, and there may not be a fourth season. Before learning that the theatrical version will be released in Japan in June, bilibili may be introduced, looking forward to it.</description>
      <content:encoded><![CDATA[<h2 id="からかい上手の高木さん">からかい上手の高木さん</h2>
<style>
    .bilibili_shortcodes {
        position: relative;
        width: 100%;
        height: 0;
        padding-bottom: 58%;
    }
    .bilibili_shortcodes iframe {
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0;
        top: 0;
        border-radius: var(--radius);
    }
</style>

<div class="bilibili_shortcodes">
    <iframe
            src="https://player.bilibili.com/player.html?bvid=BV1eS4y127Eg&page=1&high_quality=1&danmaku=0&as_wide=0"
            scrolling="no"
            border="0"
            frameborder="no"
            framespacing="0"
            allowfullscreen="true"
            sandbox="allow-top-navigation allow-same-origin allow-forms allow-scripts"
    >
    </iframe>
</div>

<h2 id="before">Before</h2>
<p>The third season of <strong>Takagi-san</strong> (Japanese: からかい上手の高木さん) anime TV ended today (3.26), and there may not be a fourth season.</p>
<p>Purposely went to catch up at 1 a.m. and felt a lot of emotions.</p>
<p>Before learning that the theatrical version will be released in Japan in June, bilibili may be introduced, looking forward to it.</p>
<p>Also, reprinting a video of the upkeeper&rsquo;s clip recapping three seasons of the show, great job.</p>
<p>Thanks to <a href="https://www.bilibili.com/video/BV1eS4y127Eg" target="_blank" rel="noopener">吕吕吕谷修</a> .</p>
]]></content:encoded>
    </item>
    <item>
      <title>Configuring Aria2 on macOS</title>
      <link>https://vccv.cc/en/article/aria2-mac.html</link>
      <pubDate>Sat, 19 Mar 2022 16:49:15 +0000</pubDate>
      <guid>https://vccv.cc/en/article/aria2-mac.html</guid>
      <description>Backed up the process of configuring aria2 under the macOS and cooperating with many plug-ins in Chrome browser to download multithreading and many other functions. Most of them are shared by GitHub authors and have been noted at the end of the article.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<h3 id="what-is-aria2">What is Aria2?</h3>
<blockquote>
<p>Aria2 is a free, cross-platform command line interface download manager that supports HTTP, HTTPS, FTP, Bittorrent and Metalink.</p>
<p>Another feature of Aria2 is that you can use JSON-RPC and XML-RPC for HTTP remote download control, and the JSON-RPC interface is available through WebSocket.</p>
</blockquote>
<p>I mainly use to download seed Bittorrent files and multithreaded downloads.</p>
<h3 id="preparation-before-configuration">Preparation before configuration</h3>
<ul>
<li>
<p>Installed <a href="https://brew.sh/index_zh-cn" target="_blank" rel="noopener">Homebrew</a> 。</p>
</li>
<li>
<p>Ability of using <strong>vim</strong> or other editors.</p>
<blockquote>
<p>Common commands:</p>
<p>Press the <em>i</em> key in the open vim interface to enter edit mode; Press the <em>Esc</em> key to exit edit mode and enter command line mode; Use the <em><strong>:wq</strong></em> command to save and exit.</p>
</blockquote>
</li>
</ul>
<h2 id="install-and-configure-aria2">Install and configure Aria2</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Install aria2 by Homebrew</span>
</span></span><span class="line"><span class="cl">brew install aria2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Create aria2.conf and aria2.session files</span>
</span></span><span class="line"><span class="cl">mkdir ~/.aria2 <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ~/.aria2
</span></span><span class="line"><span class="cl">touch aria2.conf
</span></span><span class="line"><span class="cl">touch aria2.session
</span></span></code></pre></td></tr></table>
</div>
</div><p>Edit the configuration file <strong>aria2.conf</strong> :</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">##</span> <span class="err">文件保存相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">文件的保存路径(可使用绝对路径或相对路径),</span> <span class="err">默认:</span> <span class="err">Mac下Downloads下载文件夹</span>
</span></span><span class="line"><span class="cl"><span class="err">dir=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/Downloads</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用磁盘缓存,</span> <span class="mi">0</span><span class="err">为禁用缓存,</span> <span class="err">需</span><span class="mf">1.16</span><span class="err">以上版本,</span> <span class="err">默认:</span><span class="mi">16</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">disk-cache=</span><span class="mi">32</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">文件预分配方式,</span> <span class="err">能有效降低磁盘碎片,</span> <span class="err">默认:prealloc</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">预分配所需时间:</span> <span class="err">none</span> <span class="err">&lt;</span> <span class="err">falloc</span> <span class="err">?</span> <span class="err">trunc</span> <span class="err">&lt;</span> <span class="err">prealloc</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">falloc和trunc则需要文件系统和内核支持</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">NTFS建议使用falloc,</span> <span class="err">EXT</span><span class="mi">3</span><span class="err">/</span><span class="mi">4</span><span class="err">建议trunc,</span> <span class="err">MAC</span> <span class="err">下需要注释此项</span>
</span></span><span class="line"><span class="cl"><span class="err">#file-allocation=none</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">断点续传</span>
</span></span><span class="line"><span class="cl"><span class="err">continue=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">下载连接相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最大同时下载任务数,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-concurrent-downloads=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">同一服务器连接数,</span> <span class="err">添加时可指定,</span> <span class="err">默认:</span><span class="mi">1</span><span class="err">,</span> <span class="err">最大值</span><span class="mi">16</span>
</span></span><span class="line"><span class="cl"><span class="err">max-connection-per-server=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最小文件分片大小,</span> <span class="err">添加时可指定,</span> <span class="err">取值范围</span><span class="mi">1</span><span class="err">M</span> <span class="mi">-1024</span><span class="err">M,</span> <span class="err">默认:</span><span class="mi">20</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">假定size=</span><span class="mi">10</span><span class="err">M,</span> <span class="err">文件为</span><span class="mi">20</span><span class="err">MiB</span> <span class="err">则使用两个来源下载;</span> <span class="err">文件为</span><span class="mi">15</span><span class="err">MiB</span> <span class="err">则使用一个来源下载</span>
</span></span><span class="line"><span class="cl"><span class="err">min-split-size=</span><span class="mi">10</span><span class="err">M</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务最大线程数,</span> <span class="err">添加时可指定,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#split=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">分片选择算法,有助于视频的边下边播同时兼顾减少建立连接的次数</span>
</span></span><span class="line"><span class="cl"><span class="err">stream-piece-selector=geom</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">整体下载速度限制,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-overall-download-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务下载速度限制,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-download-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">整体上传速度限制,</span> <span class="err">运行时可修改,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-overall-upload-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个任务上传速度限制,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-upload-limit=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">禁用IPv</span><span class="mi">6</span><span class="err">,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">#disable-ipv</span><span class="mi">6</span><span class="err">=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">连接超时时间,</span> <span class="err">默认:</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl"><span class="err">#timeout=</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">最大重试次数,</span> <span class="err">设置为</span><span class="mi">0</span><span class="err">表示不限制重试次数,</span> <span class="err">默认:</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#max-tries=</span><span class="mi">5</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">设置重试等待的秒数,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#retry-wait=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">进度保存相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">日志文件</span>
</span></span><span class="line"><span class="cl"><span class="err">log-level=notice</span>
</span></span><span class="line"><span class="cl"><span class="err">log=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.log</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">从会话文件中读取下载任务</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">需提前创建一个空文件否则会报错</span>
</span></span><span class="line"><span class="cl"><span class="err">input-file=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.session</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在Aria</span><span class="mi">2</span><span class="err">退出时保存`错误/未完成`的下载任务到会话文件</span>
</span></span><span class="line"><span class="cl"><span class="err">save-session=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/aria</span><span class="mi">2</span><span class="err">.session</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">定时保存会话,</span> <span class="mi">0</span><span class="err">为退出时才保存,</span> <span class="err">需</span><span class="mf">1.16</span><span class="err">.</span><span class="mi">1</span><span class="err">以上版本,</span> <span class="err">默认:</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">save-session-interval=</span><span class="mi">60</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">强制保存会话,</span> <span class="err">即使任务已经完成,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">较新的版本开启后会在任务完成后依然保留.aria</span><span class="mi">2</span><span class="err">文件</span>
</span></span><span class="line"><span class="cl"><span class="err">#force-save=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">RPC相关设置</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用RPC,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-rpc=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">允许所有来源,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-allow-origin-all=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">允许非外部访问,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-listen-all=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">RPC监听端口,</span> <span class="err">端口被占用时可以修改,</span> <span class="err">默认:</span><span class="mi">6800</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-listen-port=</span><span class="mi">6800</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">设置的RPC授权令牌</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">此处使用`openssl</span> <span class="err">rand</span> <span class="err">-base</span><span class="mi">64</span> <span class="mi">32</span><span class="err">`命令生成&lt;TOKEN&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">此次需要自行配置，将&lt;TOKEN&gt;整体替换为你的RPC“密码”</span>
</span></span><span class="line"><span class="cl"><span class="err">rpc-secret=&lt;TOKEN&gt;</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">是否启用</span> <span class="err">RPC</span> <span class="err">服务的</span> <span class="err">SSL/TLS</span> <span class="err">加密,</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用加密后</span> <span class="err">RPC</span> <span class="err">服务需要使用</span> <span class="err">https</span> <span class="err">或者</span> <span class="err">wss</span> <span class="err">协议连接</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-secure=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在</span> <span class="err">RPC</span> <span class="err">服务中启用</span> <span class="err">SSL/TLS</span> <span class="err">加密时的证书文件,</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">使用</span> <span class="err">PEM</span> <span class="err">格式时，您必须通过</span> <span class="err">--rpc-private-key</span> <span class="err">指定私钥</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-certificate=/path/to/certificate.pem</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">在</span> <span class="err">RPC</span> <span class="err">服务中启用</span> <span class="err">SSL/TLS</span> <span class="err">加密时的私钥文件</span>
</span></span><span class="line"><span class="cl"><span class="err">#rpc-private-key=/path/to/certificate.key</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">HTTP</span> <span class="err">设置</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">自定义</span> <span class="err">User</span> <span class="err">Agent</span>
</span></span><span class="line"><span class="cl"><span class="err">user-agent=Mozilla/</span><span class="mf">5.0</span> <span class="err">(Macintosh;</span> <span class="err">Intel</span> <span class="err">Mac</span> <span class="err">OS</span> <span class="err">X</span> <span class="mi">10</span><span class="err">_</span><span class="mi">15</span><span class="err">_</span><span class="mi">1</span><span class="err">)</span> <span class="err">AppleWebKit/</span><span class="mf">537.36</span> <span class="err">(KHTML,</span> <span class="err">like</span> <span class="err">Gecko)</span> <span class="err">Chrome/</span><span class="mf">80.0</span><span class="err">.</span><span class="mf">3987.85</span> <span class="err">Safari/</span><span class="mf">537.36</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">##</span> <span class="err">BT/PT下载相关</span> <span class="err">##</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">当下载的是一个种子(以.torrent结尾)时,</span> <span class="err">自动开始BT任务,</span> <span class="err">默认:</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">follow-torrent=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT监听端口,</span> <span class="err">当端口被屏蔽时使用,</span> <span class="err">默认:</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">listen-port=</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">单个种子最大连接数,</span> <span class="err">默认:</span><span class="mi">55</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-max-peers=</span><span class="mi">55</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">###</span> <span class="err">DHT</span> <span class="err">功能,</span> <span class="err">仅对</span> <span class="err">BT</span> <span class="err">生效,</span> <span class="err">PT</span> <span class="err">无效###</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">打开</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">4</span><span class="err">)</span> <span class="err">功能</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-dht=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">打开</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">6</span><span class="err">)</span> <span class="err">功能</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-dht</span><span class="mi">6</span><span class="err">=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT网络监听端口,</span> <span class="err">默认:</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-listen-port=</span><span class="mi">6881-6999</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">本地节点查找</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-enable-lpd=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">种子交换</span>
</span></span><span class="line"><span class="cl"><span class="err">enable-peer-exchange=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">4</span><span class="err">)</span> <span class="err">路由表文件路径</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-file-path=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/dht.dat</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">DHT</span> <span class="err">(IPv</span><span class="mi">6</span><span class="err">)</span> <span class="err">路由表文件路径</span>
</span></span><span class="line"><span class="cl"><span class="err">dht-file-path</span><span class="mi">6</span><span class="err">=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/dht</span><span class="mi">6</span><span class="err">.dat</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">客户端伪装,</span> <span class="err">PT需要</span>
</span></span><span class="line"><span class="cl"><span class="err">peer-id-prefix=-UT</span><span class="mi">341</span><span class="err">-</span>
</span></span><span class="line"><span class="cl"><span class="err">peer-agent=uTorrent/</span><span class="mi">341</span><span class="err">(</span><span class="mi">109279400</span><span class="err">)(</span><span class="mi">30888</span><span class="err">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">同一服务器连接数</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">每个种子限速,</span> <span class="err">对少种的PT很有用,</span> <span class="err">默认:</span><span class="mi">50</span><span class="err">K</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-request-peer-speed-limit=</span><span class="mi">50</span><span class="err">K</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">当种子的分享率达到这个数时,</span> <span class="err">自动停止做种,</span> <span class="mi">0</span><span class="err">为一直做种,</span> <span class="err">默认:</span><span class="mf">1.0</span>
</span></span><span class="line"><span class="cl"><span class="err">seed-ratio=</span><span class="mi">0</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT校验相关,</span> <span class="err">默认:</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#bt-hash-check-seed=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">继续之前的BT任务时,</span> <span class="err">无需再次校验,</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-seed-unverified=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">保存磁力链接元数据为种子文件(.torrent文件),</span> <span class="err">默认:</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-save-metadata=</span><span class="kc">true</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT</span> <span class="err">服务器地址</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">逗号分隔的</span> <span class="err">BT</span> <span class="err">服务器地址.</span> <span class="err">如果服务器地址在</span> <span class="err">--bt-exclude-tracker</span> <span class="err">选项中,</span> <span class="err">其将不会生效.</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-tracker=udp:</span><span class="c1">//tracker.coppersurfer.tk:6969/announce,udp://tracker.leechers-paradise.org:6969/announce,udp://tracker.opentrackr.org:1337/announce,udp://p4p.arenabg.com:1337/announce,udp://9.rarbg.to:2710/announce,udp://9.rarbg.me:2710/announce,udp://tracker.internetwarriors.net:1337/announce,udp://exodus.desync.com:6969/announce,udp://tracker.tiny-vps.com:6969/announce,udp://tracker.moeking.me:6969/announce,udp://retracker.lanta-net.ru:2710/announce,udp://open.stealth.si:80/announce,udp://open.demonii.si:1337/announce,udp://tracker.torrent.eu.org:451/announce,udp://tracker.cyberia.is:6969/announce,udp://denis.stalker.upeer.me:6969/announce,udp://tracker3.itzmx.com:6961/announce,udp://ipv4.tracker.harry.lu:80/announce,udp://valakas.rollo.dnsabr.com:2710/announce,udp://tracker.nyaa.uk:6969/announce,udp://retracker.netbynet.ru:2710/announce,udp://opentor.org:2710/announce,udp://explodie.org:6969/announce,http://explodie.org:6969/announce,udp://zephir.monocul.us:6969/announce,udp://xxxtor.com:2710/announce,udp://tracker.zum.bi:6969/announce,udp://tracker.yoshi210.com:6969/announce,udp://tracker.uw0.xyz:6969/announce,udp://tracker.sbsub.com:2710/announce,udp://tracker.lelux.fi:6969/announce,udp://tracker.iamhansen.xyz:2000/announce,udp://tracker.filemail.com:6969/announce,udp://tracker.dler.org:6969/announce,udp://retracker.sevstar.net:2710/announce,udp://retracker.akado-ural.ru:80/announce,udp://open.nyap2p.com:6969/announce,udp://chihaya.toss.li:9696/announce,udp://bt2.archive.org:6969/announce,udp://bt1.archive.org:6969/announce,udp://bt.okmp3.ru:2710/announce,https://tracker.nanoha.org:443/announce,http://tracker.torrentyorg.pl:80/announce,http://tracker.opentrackr.org:1337/announce,http://tracker.internetwarriors.net:1337/announce,http://tracker.bt4g.com:2095/announce,http://t.nyaatracker.com:80/announce,http://retracker.sevstar.net:2710/announce,http://pow7.com:80/announce,http://mail2.zelenaya.net:80/announce,http://h4.trakx.nibba.trade:80/announce,udp://tracker4.itzmx.com:2710/announce,udp://tracker2.itzmx.com:6961/announce,udp://tracker.zerobytes.xyz:1337/announce,udp://tracker.swateam.org.uk:2710/announce,udp://tr.bangumi.moe:6969/announce,udp://qg.lorzl.gq:2710/announce,udp://opentracker.i2p.rocks:6969/announce,udp://bt2.54new.com:8080/announce,https://tracker.opentracker.se:443/announce,https://tracker.lelux.fi:443/announce,http://www.loushao.net:8080/announce,http://vps02.net.orel.ru:80/announce,http://tracker4.itzmx.com:2710/announce,http://tracker3.itzmx.com:6961/announce,http://tracker2.itzmx.com:6961/announce,http://tracker1.itzmx.com:8080/announce,http://tracker01.loveapp.com:6789/announce,http://tracker.zerobytes.xyz:1337/announce,http://tracker.yoshi210.com:6969/announce,http://tracker.nyap2p.com:8080/announce,http://tracker.lelux.fi:80/announce,http://tracker.bz:80/announce,http://opentracker.i2p.rocks:6969/announce,http://open.acgnxtracker.com:80/announce
</span></span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT</span> <span class="err">排除服务器地址</span>
</span></span><span class="line"><span class="cl"><span class="err">bt-exclude-tracker=</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">启用后台进程</span>
</span></span><span class="line"><span class="cl"><span class="err">daemon=</span><span class="kc">false</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">部分事件hook,</span> <span class="err">调用第三方命令:/path/to/command</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT下载完成(如有做种将包含做种，如需调用请务必确定设定完成做种条件)</span>
</span></span><span class="line"><span class="cl"><span class="err">on-bt-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载完成</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载错误</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-error=</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">代理</span> <span class="err">仅支持</span> <span class="err">HTTP</span> <span class="err">协议</span>
</span></span><span class="line"><span class="cl"><span class="err">#all-proxy=http:</span><span class="c1">//127.0.0.1:1087
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>Considerations for this profile are as follows:</p>
<ul>
<li>RPC mode is enabled by default.</li>
<li>The RPC authorization token has been set, please change it to your own.</li>
<li>BT tracker has been added.</li>
</ul>
<h2 id="set-to-self-boot">Set to self-boot</h2>
<h3 id="create-a-users-startup-file">Create a user&rsquo;s startup file</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">vim ~/Library/LaunchAgents/aria2.plist
</span></span></code></pre></td></tr></table>
</div>
</div><p>Write as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-xml" data-lang="xml"><span class="line"><span class="cl"><span class="cp">&lt;?xml version=&#34;1.0&#34; encoding=&#34;UTF-8&#34;?&gt;</span>
</span></span><span class="line"><span class="cl"><span class="cp">&lt;!DOCTYPE plist PUBLIC &#34;-//Apple//DTD PLIST 1.0//EN&#34; &#34;http://www.apple.com/DTDs/PropertyList-1.0.dtd&#34;&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;plist</span> <span class="na">version=</span><span class="s">&#34;1.0&#34;</span><span class="nt">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;dict&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>KeepAlive<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>Label<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>aria2<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>ProgramArguments<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;array&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&lt;string&gt;</span>/usr/local/bin/aria2c<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;/array&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>RunAtLoad<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;true/&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;key&gt;</span>WorkingDirectory<span class="nt">&lt;/key&gt;</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&lt;string&gt;</span>/Users/YOUR-OWN-USERNAME/Downloads<span class="nt">&lt;/string&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/dict&gt;</span>
</span></span><span class="line"><span class="cl"><span class="nt">&lt;/plist&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Note:</p>
<p>Be sure to change the user name of the <em>WorkingDirectory</em> directory to your own user name.</p>
</blockquote>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Check plist files</span>
</span></span><span class="line"><span class="cl">plutil ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Chmod file</span>
</span></span><span class="line"><span class="cl">chmod <span class="m">644</span> ~/Library/LaunchAgents/aria2.plist
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="add-and-enable-self-startup-files">Add and enable self-startup files</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Add</span>
</span></span><span class="line"><span class="cl">launchctl load ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Delete</span>
</span></span><span class="line"><span class="cl">launchctl unload ~/Library/LaunchAgents/aria2.plist
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Start</span>
</span></span><span class="line"><span class="cl">launchctl start aria2
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Stop</span>
</span></span><span class="line"><span class="cl">launchctl stop aria2
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>Note:</p>
<p>If you have previously added aria2 startup files, remember to delete the startup items and then add them again!</p>
</blockquote>
<h2 id="add-automatic-update-bt-tracker-function">Add automatic update BT tracker function</h2>
<h3 id="create-a-trackers-list-aria2sh-script">Create a trackers-list-aria2.sh script</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.aria2/trackers-list-aria2.sh
</span></span><span class="line"><span class="cl">vim ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>The script reads as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/bash
</span></span></span><span class="line"><span class="cl"><span class="c1"># 文件名 trackers-list-aria2.sh</span>
</span></span><span class="line"><span class="cl"><span class="c1"># aria2 设置文件路径</span>
</span></span><span class="line"><span class="cl"><span class="nv">CONF</span><span class="o">=</span><span class="si">${</span><span class="nv">HOME</span><span class="si">}</span>/.aria2/aria2.conf
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># 设置选择的 trackerlist （可选 all_aria2.txt, best_aria2.txt, http_aria2.txt）</span>
</span></span><span class="line"><span class="cl"><span class="nv">trackerfile</span><span class="o">=</span>all_aria2.txt
</span></span><span class="line"><span class="cl"><span class="c1"># downloadfile=https://raw.githubusercontent.com/ngosang/trackerslist/master/${trackerfile}</span>
</span></span><span class="line"><span class="cl"><span class="nv">downloadfile</span><span class="o">=</span>https://trackerslist.com/<span class="si">${</span><span class="nv">trackerfile</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">list</span><span class="o">=</span><span class="k">$(</span>curl -fsSL <span class="si">${</span><span class="nv">downloadfile</span><span class="si">}</span><span class="k">)</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> ! grep -q <span class="s2">&#34;bt-tracker&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span> <span class="p">;</span> <span class="k">then</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 添加 bt-tracker 服务器信息......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\nbt-tracker=</span><span class="si">${</span><span class="nv">list</span><span class="si">}</span><span class="s2">&#34;</span> &gt;&gt; <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">else</span>
</span></span><span class="line"><span class="cl">    <span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 更新 bt-tracker 服务器信息.....\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">    sed -i <span class="s1">&#39;&#39;</span> <span class="s2">&#34;s@bt-tracker.*@bt-tracker=</span><span class="si">${</span><span class="nv">list</span><span class="si">}</span><span class="s2">@g&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">CONF</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">## 重启 aria2 服务</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 停止 aria2 服务......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">launchctl stop aria2
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> -e <span class="s2">&#34;\033[34m==&gt; 启动 aria2 服务......\033[0m&#34;</span>
</span></span><span class="line"><span class="cl">launchctl start aria2
</span></span></code></pre></td></tr></table>
</div>
</div><p>Set permissions:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="set-up-the-task-scheduler-to-achieve-automatic-updates">Set up the task scheduler to achieve automatic updates</h3>
<p>Compile the current user task plan:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -e
</span></span></code></pre></td></tr></table>
</div>
</div><p>Use <strong>crontab -l</strong> command to view the current user task schedule. The contents are as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="nv">MAILTO</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span>
</span></span><span class="line"><span class="cl"><span class="m">0</span> <span class="m">18</span> * * * ~/.aria2/trackers-list-aria2.sh
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>2022/05/27 update:</p>
<p>Add <em>MAILTO = &ldquo;&rdquo;</em> configuration to avoid <em>You have new mail</em> prompts.</p>
<p>If such notification has already occurred, enter <code>mail</code> to view and eliminate it.</p>
</blockquote>
<p>Or you can command directly:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="o">(</span>crontab -l 2<span class="p">&amp;</span>&gt; /dev/null<span class="p">;</span> <span class="nb">echo</span> <span class="s2">&#34;0 18 * * * ~/.aria2/trackers-list-aria2.sh&#34;</span><span class="o">)</span> <span class="p">|</span> crontab
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>The above indicates:</p>
<p>Automatically update BT tracker and restart aria2 service at 6: 00 p.m. every day.</p>
<p>Cancel the scheduled task:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -e
</span></span></code></pre></td></tr></table>
</div>
</div><p>Then delete the content manually, or run it directly:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">crontab -l 2<span class="p">&amp;</span>&gt; /dev/null<span class="p">|</span> sed <span class="s2">&#34;/trackers-list-aria2.sh/d&#34;</span> <span class="p">|</span> crontab
</span></span></code></pre></td></tr></table>
</div>
</div></blockquote>
<h3 id="add-download-notification">Add Download-Notification</h3>
<p>Final effect: when the download is complete, a prompt box will pop up in the upper right corner of the screen to display the file name of the completed download, and voice broadcast: &ldquo;there is a file that has been downloaded, please check it!&rdquo;</p>
<p><a href="/en/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp" data-fancybox="gallery" data-src="/en/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp" data-caption=" An example of aria2 prompt box under macOS ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/aria2-mac/image-20220319180124115_hu_143c9d9257067920.webp 480w, /en/article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp 720w, /en/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp 744w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="744"
                    height="180"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp"
                    srcset="/en/article/aria2-mac/image-20220319180124115_hu_143c9d9257067920.webp 480w, /en/article/aria2-mac/image-20220319180124115_hu_299aa375bd663ec0.webp 720w, /en/article/aria2-mac/image-20220319180124115_hu_20eb603bc0fd28b8.webp 744w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" An example of aria2 prompt box under macOS "
                    
                />
            </picture>
        </a></p>
<h3 id="create-a-download-complete-hooksh-script">Create a download-complete-hook.sh script</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">touch ~/.aria2/download-complete-hook.sh
</span></span><span class="line"><span class="cl">vim ~/.aria2/download-complete-hook.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>The script reads as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl"><span class="cp">#!/bin/sh
</span></span></span><span class="line"><span class="cl"><span class="c1"># 文件名 download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 给aria2 RPC添加一个下载完成通知 for macOS</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 变量 3 表示下载完成文件的路径</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 具体提示框设置可参考`https://code-maven.com/display-notification-from-the-mac-command-line`。</span>
</span></span><span class="line"><span class="cl"><span class="c1"># 不支持设置自定义图标</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nv">fname</span><span class="o">=</span><span class="sb">`</span>basename <span class="nv">$3</span><span class="sb">`</span>
</span></span><span class="line"><span class="cl">osascript <span class="s">&lt;&lt;EOF
</span></span></span><span class="line"><span class="cl"><span class="s">display notification &#34;$fname 已经下载完成！&#34; with title &#34;【下载完成】&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">say &#34;有个文件下载完成，请查收！&#34;
</span></span></span><span class="line"><span class="cl"><span class="s">EOF</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Set permissions:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">chmod +x ~/.aria2/download-complete-hook.sh
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="add-hook-settings">Add Hook Settings</h3>
<blockquote>
<p>The <em>aria2.conf</em> configuration file above already contains the following, and those who use the above file can skip this section directly.</p>
</blockquote>
<p>Add the following to the <strong>aria2.conf</strong> :</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="err">#</span> <span class="err">BT下载完成(如有做种将包含做种，如需调用请务必确定设定完成做种条件)</span>
</span></span><span class="line"><span class="cl"><span class="err">on-bt-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span><span class="line"><span class="cl"><span class="err">#</span> <span class="err">下载完成</span>
</span></span><span class="line"><span class="cl"><span class="err">on-download-complete=$</span><span class="p">{</span><span class="err">HOME</span><span class="p">}</span><span class="err">/.aria</span><span class="mi">2</span><span class="err">/download-complete-hook.sh</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="aria2-web-ui">Aria2 web UI</h2>
<p>Do not need to install, just use the browser to open: <a href="http://ariang.mayswind.net/latest/" target="_blank" rel="noopener">AriaNg UI</a> .</p>
<h3 id="prc-setting">PRC Setting</h3>
<blockquote>
<p>Set according to the PRC-related settings in the <em>aria2.conf</em> configuration file.</p>
</blockquote>
<p><a href="/en/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp" data-fancybox="gallery" data-src="/en/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp" data-caption=" AriaNg PRC Setting ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/aria2-mac/image-20220319180542315_hu_55e35000499379b5.webp 480w, /en/article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp 720w, /en/article/aria2-mac/image-20220319180542315_hu_547e522f5efb545a.webp 960w, /en/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp 1196w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1196"
                    height="856"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp"
                    srcset="/en/article/aria2-mac/image-20220319180542315_hu_55e35000499379b5.webp 480w, /en/article/aria2-mac/image-20220319180542315_hu_a38fe1c7d7b2007e.webp 720w, /en/article/aria2-mac/image-20220319180542315_hu_547e522f5efb545a.webp 960w, /en/article/aria2-mac/image-20220319180542315_hu_ad100b1b20b776b0.webp 1196w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" AriaNg PRC Setting "
                    
                />
            </picture>
        </a></p>
<h2 id="install-the-browser-download-plug-in">Install the browser download plug-in</h2>
<p><a href="https://chrome.google.com/webstore/detail/aria2-for-chrome/mpkodccbngfoacfalldjimigbofkhgjn" target="_blank" rel="noopener">Aria2 for Chrome plug-in</a></p>
<ul>
<li>Built-in an offline AriaNg version of UI</li>
<li>Integrate right-click download menu</li>
</ul>
<blockquote>
<p>The built-in offline AriaNg version also requires <em>PRC Setting</em> , otherwise you will not be able to connect successfully.</p>
</blockquote>
<h2 id="reference-only">Reference only</h2>
<h3 id="download-the-file-from-the-network-disk">Download the file from the network disk</h3>
<p><a href="https://greasyfork.org/zh-CN/scripts/436446" target="_blank" rel="noopener">网盘直链下载助手</a>: it needs to be enabled by installing script managers such as the extension plug-in <a href="https://violentmonkey.github.io/get-it/" target="_blank" rel="noopener">Violentmonkey</a> or <a href="https://www.tampermonkey.net/" target="_blank" rel="noopener">Tampermonkey</a> .</p>
<h4 id="usage">Usage</h4>
<blockquote>
<p>Use with <a href="https://chrome.google.com/webstore/detail/aria2-for-chrome/mpkodccbngfoacfalldjimigbofkhgjn" target="_blank" rel="noopener">Aria2 for Chrome Plugin-in</a> .</p>
</blockquote>
<ol>
<li>Select the file you want to download and click &ldquo;Aria download&rdquo; or &ldquo;RPC download&rdquo; on the download assistant page to push it to the Aria2 UI interface.</li>
<li>After clicking the appropriate option with the mouse, select &ldquo;send Link&rdquo;, and then confirm the download.</li>
</ol>
<p><a href="/en/article/aria2-mac/QQ20220319-175017.gif" data-fancybox="gallery" data-src="/en/article/aria2-mac/QQ20220319-175017.gif" data-caption=" Plug-in usage example ">
            <img
                width="480"
                height="176"
                style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                loading="lazy"
                decoding="async"
                src="/en/article/aria2-mac/QQ20220319-175017.gif"
                alt=" Plug-in usage example "
                
            />
        </a></p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/maboloshi/" target="_blank" rel="noopener">GitHub maboloshi</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Set Up Qinglong Panel on a Linux Server</title>
      <link>https://vccv.cc/en/article/qinglong-jd.html</link>
      <pubDate>Thu, 10 Mar 2022 13:04:37 +0000</pubDate>
      <guid>https://vccv.cc/en/article/qinglong-jd.html</guid>
      <description>In contact with the Qinglong panel deployment sign in after consulting a lot of information, found to be a simple introduction to the East and West, so the idea of writing this article was born. The tutorial is detailed and lists all the pits that you have stepped in, if there are any omissions, welcome to add!</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>Since my intention is to squeeze the value out of idle servers, this article is all about deployment with the server as the body, other devices such as N1 or Playcloud, please find your own information to deploy.</p>
<h2 id="server-selection">Server Selection</h2>
<p>Region selection.</p>
<p>It is best to choose a domestic server, so that it is safer for the Jingdong hanging, but there are network problems (connection to GitHub is unstable and troublesome), while foreign servers have no problems in this regard.</p>
<p>Select Centos 7 x64 for the system.</p>
<blockquote>
<p>Centos 7 is better compared to the Green Dragon panel. I have tested that some environment dependencies of Ubuntu system cannot be installed, which is more troublesome.</p>
</blockquote>
<h2 id="installation">Installation</h2>
<ul>
<li>
<p>Install <strong>Docker</strong>：</p>
<p>China</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">curl -fsSL https://get.docker.com <span class="p">|</span> bash -s docker --mirror Aliyun
</span></span></code></pre></td></tr></table>
</div>
</div><p>Others</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">curl -fsSL https://get.docker.com <span class="p">|</span> bash -s docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>Start Docker and set it to self-start</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">sudo systemctl start docker
</span></span><span class="line"><span class="cl">sudo systemctl <span class="nb">enable</span> docker
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>Pull Mirror</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">docker pull whyour/qinglong:latest
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>Deployment Panel</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span><span class="lnt">9
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">docker run -dit \
</span></span><span class="line"><span class="cl">-v $PWD/ql/config:/ql/config \
</span></span><span class="line"><span class="cl">-v $PWD/ql/log:/ql/log \
</span></span><span class="line"><span class="cl">-v $PWD/ql/db:/ql/db \
</span></span><span class="line"><span class="cl">-p 5600:5600 \
</span></span><span class="line"><span class="cl">--name qinglong \
</span></span><span class="line"><span class="cl">--hostname qinglong \
</span></span><span class="line"><span class="cl">--restart always \
</span></span><span class="line"><span class="cl">whyour/qinglong:latest
</span></span></code></pre></td></tr></table>
</div>
</div><blockquote>
<p>The fifth line of the port number (5600) is recommended to be modified to be safer.</p>
</blockquote>
</li>
</ul>
<h2 id="initialization">Initialization</h2>
<p>Visit <strong>IP:Port number</strong>, e.g. local address 127.0.0.1:5600 to access the Green Dragon panel installation interface.</p>
<p><a href="/en/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp" data-caption=" Initialization ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310160646421_hu_d20b495683bdbf46.webp 480w, /en/article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp 720w, /en/article/qinglong-jd/image-20220310160646421_hu_d44d6a3645478e1f.webp 960w, /en/article/qinglong-jd/image-20220310160646421_hu_eb18c1254dee5843.webp 1440w, /en/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp 1582w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1582"
                    height="1078"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp"
                    srcset="/en/article/qinglong-jd/image-20220310160646421_hu_d20b495683bdbf46.webp 480w, /en/article/qinglong-jd/image-20220310160646421_hu_41b0bf1d4c2bc5e.webp 720w, /en/article/qinglong-jd/image-20220310160646421_hu_d44d6a3645478e1f.webp 960w, /en/article/qinglong-jd/image-20220310160646421_hu_eb18c1254dee5843.webp 1440w, /en/article/qinglong-jd/image-20220310160646421_hu_f01ef1d287d5dfa1.webp 1582w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Initialization "
                    
                />
            </picture>
        </a></p>
<p>Just follow the process once.</p>
<blockquote>
<p>Notification settings there can be configured with multiple notification methods, choose the one you use most often. If not, you can also skip or Baidu Sever Sauce (simple, not recommended), Enterprise WeChat Robot (recommended for those who use Enterprise WeChat).</p>
<p><a href="/en/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp" data-caption=" Notification Settings ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310161019853_hu_2e75e6e8224ee0da.webp 480w, /en/article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp 720w, /en/article/qinglong-jd/image-20220310161019853_hu_e7de64836634f7f8.webp 960w, /en/article/qinglong-jd/image-20220310161019853_hu_42eaa0e6979b6edc.webp 1440w, /en/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp 1548w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1548"
                    height="1068"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp"
                    srcset="/en/article/qinglong-jd/image-20220310161019853_hu_2e75e6e8224ee0da.webp 480w, /en/article/qinglong-jd/image-20220310161019853_hu_90353ec5f8129422.webp 720w, /en/article/qinglong-jd/image-20220310161019853_hu_e7de64836634f7f8.webp 960w, /en/article/qinglong-jd/image-20220310161019853_hu_42eaa0e6979b6edc.webp 1440w, /en/article/qinglong-jd/image-20220310161019853_hu_d7cafd0f482253a4.webp 1548w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Notification Settings "
                    
                />
            </picture>
        </a></p>
</blockquote>
<h2 id="add-task">Add task</h2>
<p>Go to the main menu and select New Task in the upper right corner:</p>
<p><a href="/en/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp" data-caption=" Add task ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310161222686_hu_9ae779ac997b3c3c.webp 480w, /en/article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp 720w, /en/article/qinglong-jd/image-20220310161222686_hu_e7017497bccbb5dc.webp 960w, /en/article/qinglong-jd/image-20220310161222686_hu_c1cf720d400f404a.webp 1440w, /en/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1678"
                    height="1008"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp"
                    srcset="/en/article/qinglong-jd/image-20220310161222686_hu_9ae779ac997b3c3c.webp 480w, /en/article/qinglong-jd/image-20220310161222686_hu_d01561829de613b7.webp 720w, /en/article/qinglong-jd/image-20220310161222686_hu_e7017497bccbb5dc.webp 960w, /en/article/qinglong-jd/image-20220310161222686_hu_c1cf720d400f404a.webp 1440w, /en/article/qinglong-jd/image-20220310161222686_hu_8921b535e66a05cf.webp 1678w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Add task "
                    
                />
            </picture>
        </a></p>
<p>Name is arbitrary, can not be filled; command is as follows, one line, a total of nine; timing rules can fill in their own, I default here 0 0 0 * * * , which means 0 hours, 0 minutes and 0 seconds of each day.</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">ql repo https://github.com/KingRan/KR.git <span class="s2">&#34;jd_|jx_|jdCookie&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|utils|function|sign|sendNotify|ql|JDJR&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/curtinlv/JD-Script.git
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/Zy143L/wskey.git <span class="s2">&#34;wskey&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo ql repo https://github.com/smiek2121/scripts.git <span class="s2">&#34;jd_|gua_&#34;</span> <span class="s2">&#34;&#34;</span> <span class="s2">&#34;ZooFaker_Necklace.js|JDJRValidator_Pure.js|sign_graphics_validate.js|cleancart_activity.js|jdCookie.js|sendNotify.js&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/Yun-City/City.git <span class="s2">&#34;jd_|jx_|gua_|jddj_|getJDCookie&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|function|utils|sendnotify|ZooFaker_Necklace|jd_Cookie|JDJRValidator_|sign_graphics_validate|ql|magic|cleancart_activity&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/6dylan6/jdpro.git <span class="s2">&#34;jd_|jx_|jddj_&#34;</span> <span class="s2">&#34;backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|JD|function|sendNotify&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/gys619/Absinthe.git <span class="s2">&#34;jd_|jx_|jddj_|gua_|getJDCookie|wskey&#34;</span> <span class="s2">&#34;activity|backUp&#34;</span> <span class="s2">&#34;^jd[^_]|USER|utils|ZooFaker_Necklace|JDJRValidator_|sign_graphics_validate|jddj_cookie|function|ql|magic|JDJR|JD&#34;</span> <span class="s2">&#34;main&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/zero205/JD_tencent_scf.git <span class="s2">&#34;jd_|jx_|jdCookie&#34;</span> <span class="s2">&#34;backUp|icon&#34;</span> <span class="s2">&#34;^jd[^_]|USER|sendNotify|sign_graphics_validate|JDJR|JDSign|ql&#34;</span> <span class="s2">&#34;main&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">ql repo https://github.com/whyour/hundun.git <span class="s2">&#34;quanx&#34;</span> <span class="s2">&#34;tokens|caiyun|didi|donate|fold|Env&#34;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p><a href="/en/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp" data-caption=" New assignment ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310162558349_hu_a32c3e64348d8f22.webp 480w, /en/article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp 720w, /en/article/qinglong-jd/image-20220310162558349_hu_8e868643682d63f7.webp 960w, /en/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1030"
                    height="1034"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp"
                    srcset="/en/article/qinglong-jd/image-20220310162558349_hu_a32c3e64348d8f22.webp 480w, /en/article/qinglong-jd/image-20220310162558349_hu_5973386631a9e0e9.webp 720w, /en/article/qinglong-jd/image-20220310162558349_hu_8e868643682d63f7.webp 960w, /en/article/qinglong-jd/image-20220310162558349_hu_28b34a0b61a194d6.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" New assignment "
                    
                />
            </picture>
        </a></p>
<p>Once all of them are filled in, we actively run through them, select them all and click <strong>Run All</strong>. Wait a while and you will see hundreds of additional tasks.</p>
<h2 id="configuring-jingdong-cookies">Configuring Jingdong cookies</h2>
<p>Here I am using <strong>Google Chrome</strong>, visit the <em><a href="https://bean.m.jd.com/bean/signIndex.action" target="_blank" rel="noopener">Jingdong mobile login address</a></em> , open the developer mode (<strong>Shortcut key: F12</strong>), open the <strong>Network</strong> tab, follow the webpage prompts to log in to your Jingdong account, and copy the account cookie, as shown in the following figure.</p>
<p><a href="/en/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp" data-caption=" Jingdong cookie ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310163451895_hu_3453950250d867c4.webp 480w, /en/article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp 720w, /en/article/qinglong-jd/image-20220310163451895_hu_f044d4622c6eb926.webp 960w, /en/article/qinglong-jd/image-20220310163451895_hu_c5378ef5ff019761.webp 1440w, /en/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp 1662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1662"
                    height="958"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp"
                    srcset="/en/article/qinglong-jd/image-20220310163451895_hu_3453950250d867c4.webp 480w, /en/article/qinglong-jd/image-20220310163451895_hu_60f714e85df6877d.webp 720w, /en/article/qinglong-jd/image-20220310163451895_hu_f044d4622c6eb926.webp 960w, /en/article/qinglong-jd/image-20220310163451895_hu_c5378ef5ff019761.webp 1440w, /en/article/qinglong-jd/image-20220310163451895_hu_15c04ab904506340.webp 1662w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Jingdong cookie "
                    
                />
            </picture>
        </a></p>
<p>Then go back to Qinglong panel, select <strong>Environment Variables</strong> &mdash;&gt; <strong>New Variable</strong>, the name is <strong>JD_COOKIE</strong>, the value is the cookie just copied, and the auto split hold is <strong>No</strong>. Click OK to finish adding finally.</p>
<p><a href="/en/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp" data-caption=" New Variable ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310163958888_hu_348f883a8b9f5549.webp 480w, /en/article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp 720w, /en/article/qinglong-jd/image-20220310163958888_hu_1aaa3ef4f1c6f341.webp 960w, /en/article/qinglong-jd/image-20220310163958888_hu_d53543069bb792b5.webp 1440w, /en/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp 1670w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1670"
                    height="1124"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp"
                    srcset="/en/article/qinglong-jd/image-20220310163958888_hu_348f883a8b9f5549.webp 480w, /en/article/qinglong-jd/image-20220310163958888_hu_ddf1cd58dd81abdf.webp 720w, /en/article/qinglong-jd/image-20220310163958888_hu_1aaa3ef4f1c6f341.webp 960w, /en/article/qinglong-jd/image-20220310163958888_hu_d53543069bb792b5.webp 1440w, /en/article/qinglong-jd/image-20220310163958888_hu_97b6c36607162268.webp 1670w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" New Variable "
                    
                />
            </picture>
        </a></p>
<blockquote>
<ul>
<li>
<p>Some tips.</p>
<ul>
<li>
<p><del>Multiple accounts only need to have the value <em>Line feed to enter the next cookie</em> inside, you cannot create another variable.</del></p>
</li>
<li>
<p>Mutiple accounts need to switch the <em>AUTO_SPLIT</em> option to <em>YES</em> on the newest version.<a href="/en/article/qinglong-jd/image-20220602190915779_hu_ca51d9104accfef9.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220602190915779_hu_ca51d9104accfef9.webp" data-caption="auto split">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220602190915779_hu_75ed5145a134bec.webp 480w, /en/article/qinglong-jd/image-20220602190915779_hu_afbcf6f98e642a22.webp 720w, /en/article/qinglong-jd/image-20220602190915779_hu_a2e3f05b1fa5d377.webp 960w, /en/article/qinglong-jd/image-20220602190915779_hu_ca51d9104accfef9.webp 1050w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1050"
                    height="1014"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220602190915779_hu_afbcf6f98e642a22.webp"
                    srcset="/en/article/qinglong-jd/image-20220602190915779_hu_75ed5145a134bec.webp 480w, /en/article/qinglong-jd/image-20220602190915779_hu_afbcf6f98e642a22.webp 720w, /en/article/qinglong-jd/image-20220602190915779_hu_a2e3f05b1fa5d377.webp 960w, /en/article/qinglong-jd/image-20220602190915779_hu_ca51d9104accfef9.webp 1050w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt="auto split"
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>The cookie values only need to be <em>pt_key</em> and <em>pt_pin</em>, if you don&rsquo;t know how to copy and paste them all, it&rsquo;s fine.</p>
</li>
<li>
<p>Do not perform frequently to avoid black numbers.</p>
</li>
<li>
<p>Jingdong account is recommended to be bound to WeChat, the activity lottery draw to WeChat red envelope will be automatically withdrawn to WeChat wallet.</p>
</li>
</ul>
</li>
</ul>
</blockquote>
<h2 id="modify-configuration-file-optional">Modify configuration file (optional)</h2>
<p>Click <strong>Configuration file</strong>, you can modify the notification push service in it. The notification push here is the push of daily tasks, and the push set at the beginning is the login push of Qinglong panel, etc. It is recommended to set it up here, but be aware that the messages are usually particularly numerous.</p>
<h2 id="installing-dependencies">Installing Dependencies</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl"><span class="c1"># Enter</span>
</span></span><span class="line"><span class="cl">docker <span class="nb">exec</span> -it qinglong bash
</span></span><span class="line"><span class="cl"><span class="c1"># Install run</span>
</span></span><span class="line"><span class="cl">curl -fsSL https://ghproxy.com/https://raw.githubusercontent.com/shufflewzc/QLDependency/main/Shell/QLOneKeyDependency.sh <span class="p">|</span> sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>A long wait to finish is all it takes.</p>
<blockquote>
<p>If your Qinglong container is not called <em>qinglong</em>, please replace it yourself.</p>
</blockquote>
<h2 id="run">Run</h2>
<p>At this point we are finally done, we can select the number of pages as <strong>500 Article/Page</strong> and then run the batch of tasks by selecting all.</p>
<p><a href="/en/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp" data-fancybox="gallery" data-src="/en/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp" data-caption=" Number of pages ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/qinglong-jd/image-20220310165735358_hu_d4b3fbc50850cebd.webp 480w, /en/article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp 720w, /en/article/qinglong-jd/image-20220310165735358_hu_a8d3569b506aea4f.webp 960w, /en/article/qinglong-jd/image-20220310165735358_hu_1b6f66b11020a38e.webp 1440w, /en/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp 1470w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1470"
                    height="688"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp"
                    srcset="/en/article/qinglong-jd/image-20220310165735358_hu_d4b3fbc50850cebd.webp 480w, /en/article/qinglong-jd/image-20220310165735358_hu_43d8b4d25b6414.webp 720w, /en/article/qinglong-jd/image-20220310165735358_hu_a8d3569b506aea4f.webp 960w, /en/article/qinglong-jd/image-20220310165735358_hu_1b6f66b11020a38e.webp 1440w, /en/article/qinglong-jd/image-20220310165735358_hu_6dd850d67b4f09dd.webp 1470w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Number of pages "
                    
                />
            </picture>
        </a></p>
<p>The task will run automatically and regularly in the future, so you don&rsquo;t need to worry about it anymore.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/whyour/qinglong" target="_blank" rel="noopener">Qinglong Panel Open Source Projecct</a></p>
<h2 id="update">Update</h2>
<p>Update a fool-proof one-click script for the novice or those who don&rsquo;t want to fuss:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-sh" data-lang="sh"><span class="line"><span class="cl">wget -q https://raw.githubusercontents.com/shufflewzc/VIP/main/Scripts/sh/ql.sh -O ql.sh <span class="o">&amp;&amp;</span> bash ql.sh
</span></span></code></pre></td></tr></table>
</div>
</div><p>You need to pre-install <strong>wget</strong>, centos users can directly <strong>yum install wget</strong>, other systems can do it by themselves.</p>
<h2 id="update-1">Update 1</h2>
<p>Be sure to download the <strong>京东</strong>、<strong>京喜</strong>、<strong>京东极速版</strong> apps and open the following activities (some need to choose to plant or produce items to choose on their own, do not leave it empty, otherwise it is equivalent to the activity is not open), in case the script can not run the unopened activities, resulting in lower earnings.</p>
<blockquote>
<p>京东 tasks：东东农场、东东萌宠、宠汪汪、种豆得豆；</p>
<p>京喜 tasks：京喜财富岛、京喜牧场、京喜工厂；</p>
<p>京东 tasks：汪汪乐园</p>
<p>note that we need to bind the WeChat (some scripts will automatically withdraw cash to WeChat).</p>
</blockquote>
<h2 id="update-2">Update 2</h2>
<p>2022/06/02 update the mutiple accounts configuration.</p>
<h2 id="update-3">Update 3</h2>
<p>2022/06/12 update the jd-cookie web link.</p>
]]></content:encoded>
    </item>
    <item>
      <title>My iOS Jailbreak Plugins and Repo Backups</title>
      <link>https://vccv.cc/en/article/jailbreak-plugin-backup.html</link>
      <pubDate>Mon, 28 Feb 2022 11:16:02 +0000</pubDate>
      <guid>https://vccv.cc/en/article/jailbreak-plugin-backup.html</guid>
      <description>Personal jailbreak self-use plugins and jailbreak source backup directory, just in case. By the way, we recommend some conscientious authors.</description>
      <content:encoded><![CDATA[<blockquote>
<p>Model: 12mini</p>
<p>System: iOS 14.2.1</p>
<p>Software: unc0ver</p>
<p>Store: cydia + zebra</p>
</blockquote>
<h2 id="source">Source</h2>
<ul>
<li>
<p><a href="https://repo.cydiabc.top/" target="_blank" rel="noopener">小苹果</a></p>
</li>
<li>
<p><a href="https://havoc.app/" target="_blank" rel="noopener">Havoc</a></p>
</li>
<li>
<p><a href="https://opa334.github.io/" target="_blank" rel="noopener">opa334</a></p>
</li>
<li>
<p><a href="https://creaturecoding.com/repo/" target="_blank" rel="noopener">Shuffle Official</a></p>
</li>
<li>
<p><a href="http://tigisoftware.com/cydia/" target="_blank" rel="noopener">Filza Official</a></p>
</li>
<li>
<p><a href="http://cokepokes.github.io/" target="_blank" rel="noopener">AppStore++ Official</a></p>
</li>
<li>
<p><a href="http://ib-soft.net/cydia/" target="_blank" rel="noopener">iCleaner Pro Official</a></p>
</li>
<li>
<p><a href="https://lenglengyu.com/" target="_blank" rel="noopener">lenglengyu</a></p>
</li>
<li>
<p><a href="http://repo.niceios.com/" target="_blank" rel="noopener">NiceiOS</a></p>
</li>
<li>
<p><a href="http://repo.qqtlr.com/" target="_blank" rel="noopener">Hi客 Chineseization</a></p>
</li>
<li>
<p><a href="https://miro92.com/repo/" target="_blank" rel="noopener">MiRO92</a></p>
</li>
<li>
<p><a href="http://apt.thebigboss.org/repofiles/cydia/" target="_blank" rel="noopener">BigBoss</a></p>
</li>
<li>
<p><a href="https://repo.co.kr/" target="_blank" rel="noopener">A-Bypass Official</a></p>
</li>
<li>
<p><a href="https://lzsxcl.github.io/repo/" target="_blank" rel="noopener">h2 Official</a></p>
</li>
<li>
<p><a href="https://repo.chariz.com/" target="_blank" rel="noopener">Chariz</a></p>
</li>
<li>
<p><a href="http://limneos.net/repo/" target="_blank" rel="noopener">BioProtect XS Official</a></p>
</li>
<li>
<p><a href="https://udevsharold.github.io/repo/" target="_blank" rel="noopener">Bakgrunnur Official</a></p>
</li>
<li>
<p><a href="https://sharman79.github.io/Netskao/" target="_blank" rel="noopener">Netskao Backup</a></p>
<blockquote>
<p>2022.04 Updated.</p>
<p><a href="https://repo.initnil.com/" target="_blank" rel="noopener">Netskao Official</a> has reopened.</p>
</blockquote>
</li>
</ul>
<blockquote>
<p>Some self-contained sources and some development sources are not listed.</p>
</blockquote>
<h2 id="plug-in">Plug-in</h2>
<h3 id="paid-plug-ins">Paid plug-ins</h3>
<blockquote>
<p>Paid plug-ins in the case of their own ability or recommended to pay to support the author, thank them for their efforts. As the majority of paid plug-ins are outside the region, you can register PayPal bound domestic card use.</p>
</blockquote>
<ul>
<li>App Hider: Hide the app</li>
<li>iCleaner Pro: Clean up junk and troubleshoot plug-ins</li>
<li>Filza: powerful file manager, direct install deb and ipa</li>
<li>Fake GPS Pro: virtual positioning, simulated Wi-Fi</li>
<li>h2: A comprehensive plug-in</li>
<li>Snapper2 + Snapper2 CC Toggle: powerful screenshot plugin</li>
<li>NiceCaller: system call enhancement, common window calls</li>
<li>Crane: Alternative Multi-opening Plugin</li>
<li>CopyLog: Clipboard management enhancement</li>
<li>Flex 3: System Enhancement Artifact</li>
<li>InstaLauncher 2: Slide sideways to open the software</li>
<li>Aemulo: nfc enhancement, simulating non-encrypted cards added to wallets</li>
<li>Some paid plugins from Cold Rain Source</li>
</ul>
<h3 id="free-plugin">Free Plugin</h3>
<ul>
<li>AppSync Unified: Turn off system signature verification and install ipa</li>
<li>QQ Purification: QQ Enhancement</li>
<li>WeChat purification: WeChat opens Callkit and more</li>
<li>PerfectGrabber: Game mode pull down to show power time</li>
<li>PullClearNC: Pull down to clear all notifications</li>
<li>Many other software optimization plugins in Netskao</li>
<li>Shuffle: Setting up plug-in categorization</li>
<li>StoreSwitcher 2: App Store quick account switching</li>
<li>AppStore++: App Store enhancement, mainly download old versions</li>
<li>VideoAdsSpeed: for those who can&rsquo;t block ads and disguise speeding up skipping</li>
<li>Choicy, A-Bypass, Shadow: Blocking Jailbreak</li>
<li>Eyeplugs: notification blocking, similar to the Android game mode in the message do not disturb</li>
<li>Safari Plus: Bring your own browser enhancements</li>
<li>Tranzlo: translation plugin, free and powerful</li>
<li>CrackTool4: Crack part of the paid plug-ins</li>
<li>CyDown: cydia enhancements and paid plugins crack</li>
<li>Shortmoji 2: Native Input Method Enhancement</li>
</ul>
<h2 id="to-be-updated">To be updated</h2>
<p>The list of plugins will be updated all the time, and the quality plugins I use will be updated and uploaded from time to time.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Adding Fancybox Image Zoom to the Cactus Theme</title>
      <link>https://vccv.cc/en/article/fancybox-cactus.html</link>
      <pubDate>Sun, 20 Feb 2022 15:24:12 +0000</pubDate>
      <guid>https://vccv.cc/en/article/fancybox-cactus.html</guid>
      <description>Install fancybox to hexo theme cactus some experience for your reference. fancybox can solve the problem of cactus theme images can not be enlarged, thanks to fancyapps to make a contribution.</description>
      <content:encoded><![CDATA[<h2 id="causes">Causes</h2>
<p>This blog theme cactus does not have a picture enlargement function, when looking at the tutorial pictures often appear too small text and can not see the situation clearly. After searching, I found this plugin <strong>fancybox</strong> which works well.</p>
<h2 id="installation">Installation</h2>
<p>The following image is the official website of fancyapps, you can see that in addition to fancybox there are other Javascript UI libraries.</p>
<p><a href="/en/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp" data-fancybox="gallery" data-src="/en/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp" data-caption=" fancyapps official website ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/fancybox-cactus/image-20220220160055554_hu_6c6ecba71d7111b.webp 480w, /en/article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp 720w, /en/article/fancybox-cactus/image-20220220160055554_hu_c1c80007e98c2141.webp 960w, /en/article/fancybox-cactus/image-20220220160055554_hu_3e9192a60ae72d62.webp 1440w, /en/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp 1920w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1920"
                    height="864"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp"
                    srcset="/en/article/fancybox-cactus/image-20220220160055554_hu_6c6ecba71d7111b.webp 480w, /en/article/fancybox-cactus/image-20220220160055554_hu_70fe02693bddef39.webp 720w, /en/article/fancybox-cactus/image-20220220160055554_hu_c1c80007e98c2141.webp 960w, /en/article/fancybox-cactus/image-20220220160055554_hu_3e9192a60ae72d62.webp 1440w, /en/article/fancybox-cactus/image-20220220160055554_hu_5d25dfb7b973f5ae.webp 1920w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" fancyapps official website "
                    
                />
            </picture>
        </a></p>
<h3 id="introduce">Introduce</h3>
<p>Go to <a href="https://fancyapps.com/docs/ui/installation" target="_blank" rel="noopener">Documentation for fancybox</a> and see in the <strong>Installation</strong> section that we can install via npm and bring in directly via CDN. Since this is a blog site, I choose to bring it in directly via CDN.</p>
<blockquote>
<p>You can also use standalone UMD build by downloading the files or using directly from the CDN on your page:</p>
<ul>
<li><a href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js" target="_blank" rel="noopener">https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js</a></li>
<li><a href="https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css" target="_blank" rel="noopener">https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css</a></li>
</ul>
</blockquote>
<p>In the <strong>hexo-folder/themes/cactus/layout/_partial/head.ejs</strong> file, we introduce the css file by adding the code at the end of the head tag:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">.</span><span class="nx">fancybox</span><span class="p">.</span><span class="nx">enabled</span><span class="p">)</span> <span class="p">{</span><span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl">  <span class="o">&lt;</span><span class="nx">link</span> <span class="nx">rel</span><span class="o">=</span><span class="s2">&#34;stylesheet&#34;</span> <span class="nx">href</span><span class="o">=</span><span class="s2">&#34;https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.css&#34;</span> <span class="o">/&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="p">}</span> <span class="o">%&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>In the <strong>scripts.ejs</strong> file in the same directory, we introduce the js file by adding the code directly to the last line:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c">&lt;!--</span> <span class="nx">FancyBox</span> <span class="o">--&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="k">if</span> <span class="p">(</span><span class="nx">theme</span><span class="p">.</span><span class="nx">fancybox</span><span class="p">.</span><span class="nx">enabled</span><span class="p">)</span> <span class="p">{</span><span class="o">%&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;</span><span class="nx">script</span> <span class="nx">src</span><span class="o">=</span><span class="s2">&#34;https://cdn.jsdelivr.net/npm/@fancyapps/ui@4.0/dist/fancybox.umd.js&#34;</span><span class="o">&gt;&lt;</span><span class="err">/script&gt;</span>
</span></span><span class="line"><span class="cl"><span class="o">&lt;%</span> <span class="p">}</span> <span class="o">%&gt;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>You can find that I added conditional judgments, so to add to the <strong>theme_config.yml</strong> file:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="c"># Enable FancyBox</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="nt">fancybox</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">enabled</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>As for whether to introduce it directly, it all depends on what you like.</p>
<h3 id="modify-configuration">Modify configuration</h3>
<p>Continue to look at the official documentation can be found, we just need to simply img tag <strong>&lt;img</strong> outside of a layer of a tag <strong>&lt;a</strong>, plus the tag attribute <strong>data-fancybox</strong> <strong>data-src</strong> <strong>data-caption</strong>, you can achieve the function.</p>
<p>At first I planned to introduce the js script directly to modify it, but I found it useless. Then I thought, maybe hexo will render markdown to html at the moment after the external js script takes effect? I did not go deeper into the cause, if there are big brothers know these, welcome to comment pointing!</p>
<p>So I decided to try to see if I could start directly with the renderer. Searching for the default renderer for hexo is <strong>hexo-renderer-marked</strong>. In the <strong>hexo-folder/node_modules/hexo-renderer-marked/lib/renderer.js</strong> file, search for the keyword <strong>img</strong> and find the relevant code changes as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-js" data-lang="js"><span class="line"><span class="cl"><span class="c1">// Before
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="sb">`&lt;img src=&#34;</span><span class="si">${</span><span class="nx">encodeURL</span><span class="p">(</span><span class="nx">href</span><span class="p">)</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` alt=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">title</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` title=&#34;</span><span class="si">${</span><span class="nx">title</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">lazyload</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39; loading=&#34;lazy&#34;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39;&gt;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// After
</span></span></span><span class="line"><span class="cl"><span class="kd">let</span> <span class="nx">out</span> <span class="o">=</span> <span class="sb">`&lt;a data-fancybox=&#34;gallery&#34; data-src=&#34;</span><span class="si">${</span><span class="nx">href</span><span class="si">}</span><span class="sb">&#34; data-caption=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;&gt;&lt;img src=&#34;</span><span class="si">${</span><span class="nx">encodeURL</span><span class="p">(</span><span class="nx">href</span><span class="p">)</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">text</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` alt=&#34;</span><span class="si">${</span><span class="nx">text</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">title</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="sb">` title=&#34;</span><span class="si">${</span><span class="nx">title</span><span class="si">}</span><span class="sb">&#34;`</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="nx">lazyload</span><span class="p">)</span> <span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39; loading=&#34;lazy&#34;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nx">out</span> <span class="o">+=</span> <span class="s1">&#39;&gt;&lt;/a&gt;&#39;</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="validation">Validation</h3>
<p>After executing the <strong>hexo clean &amp;&amp; hexo s</strong> preview, I found that the display is normal and the function is available, the problem is solved.</p>
<h2 id="effect">Effect</h2>
<p>Take a picture to see the effect.</p>
<p><a href="/en/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp" data-fancybox="gallery" data-src="/en/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp" data-caption=" Final Results ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/fancybox-cactus/image-20220220172801964_hu_befd40fb05313a7b.webp 480w, /en/article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp 720w, /en/article/fancybox-cactus/image-20220220172801964_hu_ea781079473b1623.webp 960w, /en/article/fancybox-cactus/image-20220220172801964_hu_5f733f016d1dc7e4.webp 1440w, /en/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp 1909w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1909"
                    height="865"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp"
                    srcset="/en/article/fancybox-cactus/image-20220220172801964_hu_befd40fb05313a7b.webp 480w, /en/article/fancybox-cactus/image-20220220172801964_hu_96736498f411a2cf.webp 720w, /en/article/fancybox-cactus/image-20220220172801964_hu_ea781079473b1623.webp 960w, /en/article/fancybox-cactus/image-20220220172801964_hu_5f733f016d1dc7e4.webp 1440w, /en/article/fancybox-cactus/image-20220220172801964_hu_332dc068081152a2.webp 1909w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Final Results "
                    
                />
            </picture>
        </a></p>
<p>It&rsquo;s so nice and satisfying hahaha.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://fancyapps.com/docs/ui/fancybox/" target="_blank" rel="noopener">Fancybox</a></p>
]]></content:encoded>
    </item>
    <item>
      <title>JetBrains Suite Activation Guide (2022)</title>
      <link>https://vccv.cc/en/article/jetbrains-activate.html</link>
      <pubDate>Thu, 06 Jan 2022 14:12:54 +0000</pubDate>
      <guid>https://vccv.cc/en/article/jetbrains-activate.html</guid>
      <description>This activation method is valid for all JetBrains family buckets, including IDEA, PyCharm, GoLand, WebStorm, etc., for personal learning reference only! If you have previously installed an older version, it is recommended to uninstall and reinstall and start fresh.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<blockquote>
<p>Valid for the entire JetBrains family of buckets, including IDEA, PyCharm, GoLand, WebStorm, etc.</p>
<p><strong>For personal use only</strong>!</p>
</blockquote>
<p>Before the tutorial, if you have installed an older version, I recommend to <strong>uninstall and reinstall</strong> to start.</p>
<table>
  <thead>
      <tr>
          <th>IDE</th>
          <th>Official Website Address</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>IDEA</td>
          <td><a href="https://www.jetbrains.com/idea/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/idea/download/other.html</a></td>
      </tr>
      <tr>
          <td>PyCharm</td>
          <td><a href="https://www.jetbrains.com/pycharm/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/pycharm/download/other.html</a></td>
      </tr>
      <tr>
          <td>GoLand</td>
          <td><a href="https://www.jetbrains.com/go/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/go/download/other.html</a></td>
      </tr>
      <tr>
          <td>WebStorm</td>
          <td><a href="https://www.jetbrains.com/webstorm/download/other.html" target="_blank" rel="noopener">https://www.jetbrains.com/webstorm/download/other.html</a></td>
      </tr>
  </tbody>
</table>
<h2 id="update-3">Update 3</h2>
<p>Regardless of the software, it is recommended to use the latest version of 2021.3._. After testing, this version is the easiest to operate and the most stable.</p>
<p>After activation, please turn off automatic update checking in the settings (keyword: update).</p>
<h2 id="2021version-23-and-later">2021.Version 2.3 and later</h2>
<blockquote>
<p>As of January 6, 2022, the latest version for Mac is 2021.3.1.</p>
</blockquote>
<p>Starting with version 2021.2.3, the Jetbrains trial policy was updated: mandatory account login, trial period tied to account. At this time, we achieve activation by means of network interception.</p>
<h3 id="mac-version">Mac version</h3>
<p>Because I am using the Mac version, the tutorial will be relatively more detailed.</p>
<ol>
<li>
<p>New download the IDE you need, if you have installed the unlimited trial, modified the hosts, please first <strong>Uninstall the old version and install it again</strong> , otherwise it can not be activated.</p>
<p>The following is an example of PyCharm.</p>
</li>
<li>
<p>Once installed, open it first, go to the activation page, <strong>Do not close</strong>, and then proceed with the following steps.</p>
</li>
<li>
<p>Download <a href="https://yuesir.lanzouo.com/ig1O9yg1uxe" target="_blank" rel="noopener">ja-netfilter.zip</a> and unzip it to a location you can find.</p>
<blockquote>
<p>2022.04.17 Updated:</p>
<p>For the latest 2022.1 version of <a href="https://yuesir.lanzoum.com/iNlyJ03cykid" target="_blank" rel="noopener">ja-netfilter.zip</a> .</p>
</blockquote>
</li>
<li>
<p>Open Access, click on <strong>Applications</strong> on the left side to find <strong>PyCharm</strong>, right click on the <strong>PyCharm</strong> icon and click on <strong>Show package contents</strong> .</p>
</li>
<li>
<p>Go to the <strong>Contents/bin</strong> directory and use a text editor to open the <strong>pycharm.vmoptions</strong> file.</p>
<blockquote>
<p>Recommended download for editing using <em>Sublime Text</em>.</p>
</blockquote>
</li>
<li>
<p>Add <code>-javaagent:/ABUSOLUTE-PATH/ja-netfilter.jar</code> at the end, remember to change it to your own <strong>Absolute path</strong> and save the file.</p>
</li>
<li>
<p>Exit PyCharm with the shortcut <strong>Command + Q</strong> .</p>
</li>
<li>
<p>Reopen, select <strong>Activate PyCharm</strong> and then click <strong>Activation Code</strong> .</p>
<blockquote>
<p>2022.04.17 Updated:</p>
<p>Another activation option is available here, which is even simpler.</p>
<p><a href="/en/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp" data-fancybox="gallery" data-src="/en/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp" data-caption=" License server activation method ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/jetbrains-activate/image-20220417181002264_hu_8c0dfc348fc4301a.webp 480w, /en/article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp 720w, /en/article/jetbrains-activate/image-20220417181002264_hu_c5491ebaf2cf597b.webp 960w, /en/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp 1098w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1098"
                    height="398"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp"
                    srcset="/en/article/jetbrains-activate/image-20220417181002264_hu_8c0dfc348fc4301a.webp 480w, /en/article/jetbrains-activate/image-20220417181002264_hu_82c115f112b70435.webp 720w, /en/article/jetbrains-activate/image-20220417181002264_hu_c5491ebaf2cf597b.webp 960w, /en/article/jetbrains-activate/image-20220417181002264_hu_4813fca1bca94c43.webp 1098w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" License server activation method "
                    
                />
            </picture>
        </a></p>
<p>Select the <em>License Server</em> method (license server), enter the server address: <em><a href="https://jetbra.in" target="_blank" rel="noopener">https://jetbra.in</a></em> , and activate it.</p>
</blockquote>
</li>
<li>
<p>Copy the activation code below and paste it into the input box in the activation window and click <strong>Activate</strong>. Over!</p>
</li>
<li>
<p>Other: If you have not tried JetBrains products, you do not need to use the following activation code, just select Register Account to try when you open the IDE at <strong>Step 2</strong>, and the subsequent steps remain the same.</p>
</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">IFB45W18MX-eyJsaWNlbnNlSWQiOiJJRkI0NVcxOE1YIiwibGljZW5zZWVOYW1lIjoi5rC45LmF5r+A5rS7IHd3d8K3YWppaHVvwrdjb20iLCJhc3NpZ25lZU5hbWUiOiIiLCJhc3NpZ25lZUVtYWlsIjoiIiwibGljZW5zZVJlc3RyaWN0aW9uIjoiIiwiY2hlY2tDb25jdXJyZW50VXNlIjpmYWxzZSwicHJvZHVjdHMiOlt7ImNvZGUiOiJEUE4iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRCIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJQUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiSUkiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTQyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJHTyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiRE0iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJTRiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJEUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUEMiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJDTCIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiV1MiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJEIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSUzAiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IlJNIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJBQyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjpmYWxzZX0seyJjb2RlIjoiUlNWIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IkRDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOmZhbHNlfSx7ImNvZGUiOiJSU1UiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6ZmFsc2V9LHsiY29kZSI6IkRQIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBEQiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQV1MiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFNJIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBQUyIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQQ1dNUCIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQR08iLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUFBDIiwicGFpZFVwVG8iOiIyMDIyLTAyLTA0IiwiZXh0ZW5kZWQiOnRydWV9LHsiY29kZSI6IlBSQiIsInBhaWRVcFRvIjoiMjAyMi0wMi0wNCIsImV4dGVuZGVkIjp0cnVlfSx7ImNvZGUiOiJQU1ciLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX0seyJjb2RlIjoiUlMiLCJwYWlkVXBUbyI6IjIwMjItMDItMDQiLCJleHRlbmRlZCI6dHJ1ZX1dLCJtZXRhZGF0YSI6IjAxMjAyMjAxMDVQUEFNMDAwMDA1IiwiaGFzaCI6IjI5NjkzNjI3LzA6LTIwNjkyMjgzNDciLCJncmFjZVBlcmlvZERheXMiOjcsImF1dG9Qcm9sb25nYXRlZCI6ZmFsc2UsImlzQXV0b1Byb2xvbmdhdGVkIjpmYWxzZX0=-MEkjEOAC1dEQpMqlge5gs64YYPdP1gNn0miz12/3xTQQ+bk8qMymnwKk/rCNNH8xe3DLneF+YMm0Orvz6QTTW12KeQ1uOPoOnBjDFvsjoT4NtzhXgVDYJ0lQlTapJFPTCyqfuir1RHw08SLPjAxFrQROVkR315E3oHCdmz8ZEB/sahLK081cgxrqFznXtLrSi17ZaCDvbO/0dhChY1dur6SnjOMTShytrRKc4w6/wn1lbfncBVL7pPMwzSOAgA5NPToC3uxDzEJh3Hhpip8okaa28dohFherPzHR9/jT2yh3Gyh2NraqoNtQTFoPwxkOYahKEw06jWrISRA1mH57tw==-MIIETDCCAjSgAwIBAgIBDTANBgkqhkiG9w0BAQsFADAYMRYwFAYDVQQDDA1KZXRQcm9maWxlIENBMB4XDTIwMTAxOTA5MDU1M1oXDTIyMTAyMTA5MDU1M1owHzEdMBsGA1UEAwwUcHJvZDJ5LWZyb20tMjAyMDEwMTkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDCP4uk4SlVdA5nuA3DQC+NsEnZS9npFnO0zrmMWcz1++q2UWJNuGTh0rwi+3fUJIArfvVh7gNtIp93rxjtrQAuf4/Fa6sySp4c32MeFACfC0q+oUoWebhOIaYTYUxm4LAZ355vzt8YeDPmvWKxA81udqEk4gU9NNAOz1Um5/8LyR8SGsSc4EDBRSjcMWMwMkYSauGqGcEUK8WhfplsyF61lKSOFA6VmfUmeDK15rUWWLbOMKgn2cxFA98A+s74T9Oo96CU7rp/umDXvhnyhAXSukw/qCGOVhwKR8B6aeDtoBWQgjnvMtPgOUPRTPkPGbwPwwDkvAHYiuKJ7Bd2wH7rAgMBAAGjgZkwgZYwCQYDVR0TBAIwADAdBgNVHQ4EFgQUJNoRIpb1hUHAk0foMSNM9MCEAv8wSAYDVR0jBEEwP4AUo562SGdCEjZBvW3gubSgUouX8bOhHKQaMBgxFjAUBgNVBAMMDUpldFByb2ZpbGUgQ0GCCQDSbLGDsoN54TATBgNVHSUEDDAKBggrBgEFBQcDATALBgNVHQ8EBAMCBaAwDQYJKoZIhvcNAQELBQADggIBAB2J1ysRudbkqmkUFK8xqhiZaYPd30TlmCmSAaGJ0eBpvkVeqA2jGYhAQRqFiAlFC63JKvWvRZO1iRuWCEfUMkdqQ9VQPXziE/BlsOIgrL6RlJfuFcEZ8TK3syIfIGQZNCxYhLLUuet2HE6LJYPQ5c0jH4kDooRpcVZ4rBxNwddpctUO2te9UU5/FjhioZQsPvd92qOTsV+8Cyl2fvNhNKD1Uu9ff5AkVIQn4JU23ozdB/R5oUlebwaTE6WZNBs+TA/qPj+5/wi9NH71WRB0hqUoLI2AKKyiPw++FtN4Su1vsdDlrAzDj9ILjpjJKA1ImuVcG329/WTYIKysZ1CWK3zATg9BeCUPAV1pQy8ToXOq+RSYen6winZ2OO93eyHv2Iw5kbn1dqfBw1BuTE29V2FJKicJSu8iEOpfoafwJISXmz1wnnWL3V/0NxTulfWsXugOoLfv0ZIBP1xH9kmf22jjQ2JiHhQZP7ZDsreRrOeIQ/c4yR8IQvMLfC0WKQqrHu5ZzXTH4NO3CwGWSlTY74kE91zXB5mwWAx1jig+UXYc2w4RkVhy0//lOmVya/PEepuuTTI4+UJwC7qbVlh5zfhj8oTNUXgN0AOc+Q0/WFPl1aw5VV/VrO8FCoB15lFVlpKaQ1Yh+DVU8ke+rt9Th0BCHXe0uZOEmH0nOnH/0onD
</span></span></code></pre></td></tr></table>
</div>
</div><h3 id="windows-version">Windows version</h3>
<p><del><strong>Step 4</strong> is different from the Mac version, others are similar:</del></p>
<ul>
<li><del>Next, find the <strong>vmoptions</strong> file in the IDE installation directory. Whether you are using <strong>IDEA</strong>, <strong>WebStorm</strong>, <strong>PyCharm</strong> or something else, the file name is <strong>xxxxx.vmoptions</strong> .</del></li>
</ul>
<ol>
<li>
<p>Perform steps 1-2 of the tutorial under Mac.</p>
</li>
<li>
<p>Clear any previously used activation methods.</p>
</li>
<li>
<p>Download <a href="https://yuesir.lanzouo.com/iGxtCzqu98d" target="_blank" rel="noopener">Activation Script</a> and unzip it.</p>
<ul>
<li>
<p><strong>scripts</strong>: Scripts for automatic installation and uninstallation of cracked patches (including scripts for Windows, Mac and Linux systems) are placed.</p>
<blockquote>
<p>For the problem of not finding the <em>idea.vmoptions</em> file, this time it is much easier to introduce the patch directly by running the script.</p>
</blockquote>
</li>
<li>
<p><strong>vmoptions</strong> : JetBrains products are placed in the <strong>xxx.vmoptions</strong> The new version 2021.3.2 we can refer directly to this folder under <strong>xxx.vmoptions</strong> configuration file.</p>
</li>
</ul>
</li>
<li>
<p>Click to run the <strong>install-current-user.vbs</strong> script to install the crack patch for the current user.</p>
<blockquote>
<p><strong>install-all-users.vbs</strong> Installed for all users, not recommended.</p>
</blockquote>
</li>
<li>
<p>If a prompt pops up, click OK and wait a few seconds.</p>
</li>
<li>
<p>Perform steps 7-10 of the tutorial for Mac.</p>
<blockquote>
<p>After successful activation, the patch folder cann&rsquo;t be moved or deleted, because the script will not find the corresponding file, and the activation will be invalid. So, just leave it in the dust, and don&rsquo;t move it.</p>
</blockquote>
</li>
</ol>
<h3 id="linux-version">Linux version</h3>
<p>Refer to the Windows version activation tutorial.</p>
<p>Step 4 Click Run <strong>install.sh</strong> script to install it.</p>
<h2 id="2021version-22-and-earlier">2021.Version 2.2 and earlier</h2>
<p>2021.2.2 and before versions, we can achieve permanent use by unlimited reset trial period patch.</p>
<ol>
<li>
<p>Installing plug-ins</p>
<p>Offline installation method:</p>
<p>1.1、Download the plug-in
<a href="https://plugins.zhile.io/files/ide-eval-resetter-2.1.6.zip" target="_blank" rel="noopener">Download Address</a></p>
<p>1.2、Install the plug-in</p>
<p>Download the plug-in zip package directly and drag the zip package directly into the IDE window to install the plug-in. If you can&rsquo;t drag and drop the installation, you can manually install the plugin at <strong>(Install Plugin From Disk&hellip;)</strong> in <strong>Settings/Preferences&hellip; -&gt; Plugins</strong> and the plugin will prompt for successful installation.</p>
<hr>
<p>Online installation method:</p>
<p>Just search <strong>IDE Eval Reset</strong> to install it.</p>
</li>
<li>
<p>Using the plug-in</p>
<ul>
<li>
<p>After successful installation of the plugin, there will be an additional <strong>Eval Reset</strong> button under <strong>Help</strong>. Generally, when the IDE window is cut out or cut back (window loses/gains focus) it will trigger an event to detect if it has not been reset for a long time (25 days) and give you a notification to choose. (The first time you install it, you will be prompted directly)</p>
</li>
<li>
<p>The main interface of the plugin can also be called up manually at</p>
<p>If the IDE does not have the project open, click on the menu in the Welcome screen: <strong>Get Help -&gt; Eval Reset</strong>. If the IDE has opened the project, click on the menu: <strong>Help -&gt; Eval Reset</strong>. The main screen of the plug-in is brought up with 2 buttons and 1 checkbox.</p>
<ul>
<li>button: <strong>Reload</strong> is used to refresh the information displayed on the screen.</li>
<li>button: <strong>Reset</strong> Clicking on it will ask if you want to reset the trial information and restart the IDE. Select Yes to perform the reset and restart the IDE to take effect, or No to do nothing.</li>
<li>Check the box: <strong>Auto reset before per restart</strong> . When checked, the trial information will be automatically reset every time you restart/quit the IDE.</li>
</ul>
</li>
</ul>
</li>
</ol>
<h2 id="success-screenshot">Success Screenshot</h2>
<p><a href="/en/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp" data-fancybox="gallery" data-src="/en/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp" data-caption=" Success Screenshot ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/jetbrains-activate/image-20220106145338969_hu_993e5a3a53f3ebf1.webp 480w, /en/article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp 720w, /en/article/jetbrains-activate/image-20220106145338969_hu_9f46997733b7929c.webp 960w, /en/article/jetbrains-activate/image-20220106145338969_hu_c1505e101444bc8d.webp 1440w, /en/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp 1600w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1600"
                    height="952"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp"
                    srcset="/en/article/jetbrains-activate/image-20220106145338969_hu_993e5a3a53f3ebf1.webp 480w, /en/article/jetbrains-activate/image-20220106145338969_hu_eccf4e1ef82f8c89.webp 720w, /en/article/jetbrains-activate/image-20220106145338969_hu_9f46997733b7929c.webp 960w, /en/article/jetbrains-activate/image-20220106145338969_hu_c1505e101444bc8d.webp 1440w, /en/article/jetbrains-activate/image-20220106145338969_hu_edd18a07a6b28679.webp 1600w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Success Screenshot "
                    
                />
            </picture>
        </a></p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/ja-netfilter/ja-netfilter" target="_blank" rel="noopener">GitHub pengzhile</a></p>
<p><a href="https://www.macwk.com/article/jetbrains-crack" target="_blank" rel="noopener">MacWk Pertim</a></p>
<h2 id="update">Update</h2>
<p>I have tested (under Mac environment), after upgrading to the latest version <strong>2021.3.2</strong>, the first method still works, only <strong>Repeat steps 4-7</strong> is needed, you can upgrade with no worries.</p>
<p>The official countermeasures seem to have been added under Windows, and the file can no longer be found in the user directory, so this time I have updated the corresponding part of the tutorial.</p>
<p>Also. After successful activation, it is recommended not to upgrade the new version, it works just fine, you say.</p>
<h2 id="update-1">Update 1</h2>
<p>2021.3.3 was updated successfully.</p>
<p><a href="/en/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp" data-fancybox="gallery" data-src="/en/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp" data-caption=" 2021.3.3 version ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/jetbrains-activate/image-20220321174826134_hu_7274ef00ec0eeb37.webp 480w, /en/article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp 720w, /en/article/jetbrains-activate/image-20220321174826134_hu_2ab388fe21a934.webp 960w, /en/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp 1142w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1142"
                    height="824"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp"
                    srcset="/en/article/jetbrains-activate/image-20220321174826134_hu_7274ef00ec0eeb37.webp 480w, /en/article/jetbrains-activate/image-20220321174826134_hu_88a4e646906e43d2.webp 720w, /en/article/jetbrains-activate/image-20220321174826134_hu_2ab388fe21a934.webp 960w, /en/article/jetbrains-activate/image-20220321174826134_hu_efa92de8610b570a.webp 1142w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" 2021.3.3 version "
                    
                />
            </picture>
        </a></p>
<h2 id="update-2">Update 2</h2>
<p>Mac version 2022.1, the previous failed, updated the article.</p>
<p><a href="/en/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp" data-fancybox="gallery" data-src="/en/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp" data-caption=" 2022.1 version ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/jetbrains-activate/image-20220417180532192_hu_800fa942902bc438.webp 480w, /en/article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp 720w, /en/article/jetbrains-activate/image-20220417180532192_hu_e61e1dc769ba8c61.webp 960w, /en/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp 1096w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1096"
                    height="786"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp"
                    srcset="/en/article/jetbrains-activate/image-20220417180532192_hu_800fa942902bc438.webp 480w, /en/article/jetbrains-activate/image-20220417180532192_hu_e98ee31821d98912.webp 720w, /en/article/jetbrains-activate/image-20220417180532192_hu_e61e1dc769ba8c61.webp 960w, /en/article/jetbrains-activate/image-20220417180532192_hu_21b70f2b31f23c5a.webp 1096w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" 2022.1 version "
                    
                />
            </picture>
        </a></p>
]]></content:encoded>
    </item>
    <item>
      <title>Tweaking the PassBy Jailbreak Plugin for iOS</title>
      <link>https://vccv.cc/en/article/passby-fix.html</link>
      <pubDate>Sat, 01 Jan 2022 23:19:51 +0000</pubDate>
      <guid>https://vccv.cc/en/article/passby-fix.html</guid>
      <description>I have heard about some smart unlocking plugins like IntelligentPass 4 and PassBy, and I found the &amp;#34;pain point&amp;#34; of these plugins: the Bluetooth unlocking feature is disabled. By modifying the source code of PassBy, we can solve this problem sideways.</description>
      <content:encoded><![CDATA[<h2 id="preface">Preface</h2>
<p>I had heard about a plug-in for <strong>Smart Unlock</strong> called IntelligentPass 4. I found its official source and purchased it for $2.99 and discovered the &ldquo;pain point&rdquo; of such plug-ins, which is also the pain point of such plug-ins that can unlock by identifying secure Bluetooth devices.</p>
<blockquote>
<p>Since iOS7 you can not get the MAC address of the Bluetooth device directly from the API, you can only use the UUID to identify the device, it should be noted that the same device does not show the same UUID on different phones, so it can not be used for unique identification.</p>
</blockquote>
<p>But what I needed most was to use the Bluetooth auto-unlock feature in it, and after my constant attempts, that type of plugin was unable to discover my Amazfit watch device.</p>
<blockquote>
<p>By the way, after finding out that the plugin didn&rsquo;t work for me, I immediately contacted the author of the plugin source by email to get help or a refund. But!!! No one gave a shit about me. I then went to Reddit and found out that this plugin store is not reputable and has no after sales service. Remember to avoid the pit, my $2.99 ah 😭.</p>
</blockquote>
<p>At this point, I found the open source project <strong>PassBy</strong> again and my eyes turned to it.</p>
<h2 id="solution">Solution</h2>
<p>On the issue of the project I found that there were also people who had such problems:</p>
<p><a href="/en/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp" data-fancybox="gallery" data-src="/en/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp" data-caption=" Question ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/passby-fix/image-20220114222356631_hu_f6918e820686c46a.webp 480w, /en/article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp 720w, /en/article/passby-fix/image-20220114222356631_hu_f65ffe0d7d6a8ed6.webp 960w, /en/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1080"
                    height="624"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp"
                    srcset="/en/article/passby-fix/image-20220114222356631_hu_f6918e820686c46a.webp 480w, /en/article/passby-fix/image-20220114222356631_hu_991d11ffee9bdac0.webp 720w, /en/article/passby-fix/image-20220114222356631_hu_f65ffe0d7d6a8ed6.webp 960w, /en/article/passby-fix/image-20220114222356631_hu_3ca9883ad27c45f5.webp 1080w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Question "
                    
                />
            </picture>
        </a></p>
<p>Fortunately, PassBy is an open source plugin, and I saw some insights mentioned in the comments under that issue earlier:</p>
<p><a href="/en/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp" data-fancybox="gallery" data-src="/en/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp" data-caption=" Comments ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/passby-fix/image-20220114222622805_hu_62ce23611d1ea808.webp 480w, /en/article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp 720w, /en/article/passby-fix/image-20220114222622805_hu_65d24a05875338.webp 960w, /en/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1030"
                    height="546"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp"
                    srcset="/en/article/passby-fix/image-20220114222622805_hu_62ce23611d1ea808.webp 480w, /en/article/passby-fix/image-20220114222622805_hu_a609b63d68d8eb7d.webp 720w, /en/article/passby-fix/image-20220114222622805_hu_65d24a05875338.webp 960w, /en/article/passby-fix/image-20220114222622805_hu_562fe41fa07d40d2.webp 1030w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Comments "
                    
                />
            </picture>
        </a></p>
<p>He says the <strong>BluetoothManager</strong> header used to get the Bluetooth device, can we get it by creating a version without <strong>if(name)</strong>.</p>
<p>Since then, I think I can modify the source code myself and add the name of the device I need inside the judgment. It can&rsquo;t get my device, so I&rsquo;ll add it myself and think it should still work 😂.</p>
<h3 id="build-environment">Build environment</h3>
<p>After cloning the source code locally, I found that it was built via <strong>theos</strong>, so as a first step I had to set up the environment so that I could compile the plugin proper. theos&rsquo; <a href="https://theos.dev/docs/" target="_blank" rel="noopener">Official Documents</a>is very detailed, and I&rsquo;m on a Mac, so I followed its introduction about Mac systems to install.</p>
<p><a href="https://theos.dev/docs/installation-macos" target="_blank" rel="noopener">Installation instructions for macOS</a>.</p>
<h3 id="compilation">Compilation</h3>
<p>After I built it, I tried to compile it first, but I found that PassBy needs <strong>iOS SDK</strong> version 13.3, but I didn&rsquo;t find it in the official SDK provided by theos. Luckily, I found <a href="https://github.com/SniperGER/iOS13-Private-SDK" target="_blank" rel="noopener">SniperGER provides the iOS 13.3 SDK</a> in Google.</p>
<blockquote>
<p>Copy the SDK folder(s) in sdks to $THEOS/sdks and the folder(s) in include to $THEOS/include.</p>
</blockquote>
<h3 id="modify-source-code">Modify source code</h3>
<p>Opened the <strong>Tweak.xm</strong> file (I used Sublime Text) and found the main function <strong>isUsingBT</strong> that controls this piece of Bluetooth functionality by searching for the keyword <strong>bluetooth</strong>, the original code is as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">BOOL</span> <span class="nf">isUsingBT</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">useGracePeriodOnBT</span> <span class="o">&amp;&amp;</span> <span class="n">allowedBTs</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">NSArray</span> <span class="o">*</span> <span class="n">connectedDevices</span> <span class="o">=</span> <span class="p">[[</span><span class="n">BluetoothManager</span> <span class="n">sharedInstance</span><span class="p">]</span> <span class="n">connectedDevices</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="n">BluetoothDevice</span> <span class="o">*</span> <span class="n">bluetoothDevice</span> <span class="k">in</span> <span class="n">connectedDevices</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">NSString</span> <span class="o">*</span> <span class="n">deviceName</span> <span class="o">=</span> <span class="p">[</span><span class="n">bluetoothDevice</span> <span class="n">name</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">NO</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Because I was not familiar with the <strong>objective-c</strong> language, and did not go to the system to learn it, so I only relied on a little bit of learned C language to look at the bottom, and found that indeed, as mentioned above, the <strong>BluetoothManager</strong> header file used, where the most important logic is as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>It stores the name of your allowed secure Bluetooth device <strong>deviceName</strong> into <strong>allowedBTs</strong> and I also found that it stores the data <strong>sha1</strong> value of <strong>devicename</strong> into the <strong>passbybt.plist</strong> file eventually:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="cp">#define BT_PLIST_PATH   &#34;/var/mobile/Library/Preferences/com.giorgioiavicoli.passbybt.plist&#34;
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>So I modified the <strong>isUsingBT()</strong> function as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="k">static</span> <span class="kt">BOOL</span> <span class="nf">isUsingBT</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">useGracePeriodOnBT</span> <span class="o">&amp;&amp;</span> <span class="n">allowedBTs</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">NSArray</span> <span class="o">*</span> <span class="n">connectedDevices</span> <span class="o">=</span> <span class="p">[[</span><span class="n">BluetoothManager</span> <span class="n">sharedInstance</span><span class="p">]</span> <span class="n">connectedDevices</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="n">BluetoothDevice</span> <span class="o">*</span> <span class="n">bluetoothDevice</span> <span class="k">in</span> <span class="n">connectedDevices</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">NSString</span> <span class="o">*</span> <span class="n">deviceName</span> <span class="o">=</span> <span class="p">[</span><span class="n">bluetoothDevice</span> <span class="n">name</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">deviceName</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">deviceName</span> <span class="n">length</span><span class="p">]</span> <span class="o">&amp;&amp;</span> <span class="p">[</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="n">deviceName</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">            <span class="k">if</span> <span class="p">([</span><span class="n">allowedBTs</span> <span class="nl">containsObject</span><span class="p">:</span><span class="n">SHA1</span><span class="p">(</span><span class="s">@&#34;Amazfit GTS 2&#34;</span><span class="p">)])</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">                <span class="k">return</span> <span class="nb">YES</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="nb">NO</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><p>Note: I need to add the device name <strong>Amazfit GTS 2</strong>, please modify it according to your personal situation!</p>
<h3 id="modify-file">Modify file</h3>
<p>Above you see that it is storing the data <strong>sha1</strong> value of the device name in the file <strong>passbybt.plist</strong>. We found this file in the iPhone using <strong>Filza</strong> and found that it is indeed so, it is in a dictionary format.</p>
<table>
  <thead>
      <tr>
          <th>sha1</th>
          <th>bool</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>063dc8e6c26233fc20a129a31403a642ea1095c4</td>
          <td>true</td>
      </tr>
      <tr>
          <td>811e9e206b053a4e02c74155bfa27b6c84e7dcad</td>
          <td>true</td>
      </tr>
  </tbody>
</table>
<p>We can use the following web tool to generate the corresponding sha1 value for the device name and then add a new key-value pair: <a href="https://passwords-generator.org/sha1-hash-generator" target="_blank" rel="noopener">SHA-1 Hash Generator</a> .</p>
<blockquote>
<p>2022.12.15 Updates.</p>
<p>Thanks to Vivian Chen for sending me an email alerting me that the site for generating sha1-hash is not working and for providing a new site, thanks again!</p>
<p><a href="/en/article/passby-fix/image-20221215103030016_hu_7beb9fad79fd290c.webp" data-fancybox="gallery" data-src="/en/article/passby-fix/image-20221215103030016_hu_7beb9fad79fd290c.webp" data-caption=" Generate sha1 values ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/passby-fix/image-20221215103030016_hu_21bb29344f793585.webp 480w, /en/article/passby-fix/image-20221215103030016_hu_55627c11214fc1e4.webp 720w, /en/article/passby-fix/image-20221215103030016_hu_b9052d6e73d95757.webp 960w, /en/article/passby-fix/image-20221215103030016_hu_797110e48e4978ab.webp 1440w, /en/article/passby-fix/image-20221215103030016_hu_7beb9fad79fd290c.webp 2176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="2176"
                    height="862"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/passby-fix/image-20221215103030016_hu_55627c11214fc1e4.webp"
                    srcset="/en/article/passby-fix/image-20221215103030016_hu_21bb29344f793585.webp 480w, /en/article/passby-fix/image-20221215103030016_hu_55627c11214fc1e4.webp 720w, /en/article/passby-fix/image-20221215103030016_hu_b9052d6e73d95757.webp 960w, /en/article/passby-fix/image-20221215103030016_hu_797110e48e4978ab.webp 1440w, /en/article/passby-fix/image-20221215103030016_hu_7beb9fad79fd290c.webp 2176w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Generate sha1 values "
                    
                />
            </picture>
        </a></p>
<p><del>Special Updates.</del></p>
<p><del>The Lowercase hash option on the web page must be checked to convert all hash values to lowercase, always remember!!!</del></p>
</blockquote>
<p><a href="/en/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp" data-fancybox="gallery" data-src="/en/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp" data-caption=" Generate sha1 values ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/passby-fix/image-20220113161956969_hu_d611d5133f5c3092.webp 480w, /en/article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp 720w, /en/article/passby-fix/image-20220113161956969_hu_4395c656f00f8add.webp 960w, /en/article/passby-fix/image-20220113161956969_hu_d912e897c2b8a9aa.webp 1440w, /en/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp 1706w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1706"
                    height="716"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp"
                    srcset="/en/article/passby-fix/image-20220113161956969_hu_d611d5133f5c3092.webp 480w, /en/article/passby-fix/image-20220113161956969_hu_7a1225ddc2061578.webp 720w, /en/article/passby-fix/image-20220113161956969_hu_4395c656f00f8add.webp 960w, /en/article/passby-fix/image-20220113161956969_hu_d912e897c2b8a9aa.webp 1440w, /en/article/passby-fix/image-20220113161956969_hu_69313b056d793ea5.webp 1706w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Generate sha1 values "
                    
                />
            </picture>
        </a></p>
<h3 id="packaged-and-install">Packaged and Install</h3>
<p>Create a new terminal in the PassBy project folder and enter the command <strong>make package</strong> to package the deb file and open it with Filza to install it.</p>
<p>Note: If the installation with <strong>Zebra</strong> does not work, modify the version number, open the <strong>control</strong> file in the root directory of PassBy, modify <strong>Version</strong> and then package and install it.</p>
<h2 id="results">Results</h2>
<p>After testing, I was able to unlock and use my Amazfit GTS 2 properly. Since I&rsquo;m not familiar with Obejective-c language, I&rsquo;m satisfied that I was able to solve the problem successfully, although the steps are still troublesome.</p>
<h2 id="thanks">Thanks</h2>
<p><a href="https://github.com/giorgioiavicoli/PassBy" target="_blank" rel="noopener">Github PassBy</a></p>
<p><a href="https://github.com/theos/theos" target="_blank" rel="noopener">Github theos</a></p>
<h2 id="update-1">Update 1</h2>
<p>I found after using the plugin for a while that my phone would have an extra two or three seconds of black screen when lit. Sure enough, on GitHub this just found that someone also mentioned this problem, limited to my technical inability to know what this problem is and how to solve it, so I gave up on this plug-in.</p>
<p><a href="/en/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp" data-fancybox="gallery" data-src="/en/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp" data-caption=" Black screen bug ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/passby-fix/image-20220114234532701_hu_7c442400687dff2d.webp 480w, /en/article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp 720w, /en/article/passby-fix/image-20220114234532701_hu_b7633c0019d7c373.webp 960w, /en/article/passby-fix/image-20220114234532701_hu_b01ed813954dd79c.webp 1440w, /en/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp 1642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1642"
                    height="1068"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp"
                    srcset="/en/article/passby-fix/image-20220114234532701_hu_7c442400687dff2d.webp 480w, /en/article/passby-fix/image-20220114234532701_hu_57f4f19bda8c5a3a.webp 720w, /en/article/passby-fix/image-20220114234532701_hu_b7633c0019d7c373.webp 960w, /en/article/passby-fix/image-20220114234532701_hu_b01ed813954dd79c.webp 1440w, /en/article/passby-fix/image-20220114234532701_hu_3ab16f9b9b3fd6b3.webp 1642w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Black screen bug "
                    
                />
            </picture>
        </a></p>
<h2 id="update-2">Update 2</h2>
<p>If there is a failure to compile error, prompting <strong>File Not Found</strong>, do the following as prompted in the compilation section.</p>
<blockquote>
<p>Copy the SDK folder(s) in sdks to $THEOS/sdks and the folder(s) in include to $THEOS/include.</p>
</blockquote>
<p>This operation is also shown in the SDK author&rsquo;s ReadME file on GitHub, please read it in detail.</p>
<h2 id="update-3">Update 3</h2>
<p>In view of my technical inability, according to the article so modified, security aspects seem to be some problems, and I do not know how to improve.</p>
<p>If you don&rsquo;t mind and don&rsquo;t know how to compile, you can leave a message in the comments section at <strong>Equipment name</strong> and I will compile it for you.</p>
<p>After installation, the device does not appear inside the device list of the plugin settings, i.e. it does not change. Just remember <em><strong>In the passbybt.plist file, change the value to true for on and false for off</strong></em> .</p>
]]></content:encoded>
    </item>
    <item>
      <title>Beautifying Code Blocks in the Cactus Theme</title>
      <link>https://vccv.cc/en/article/cactus-codeblock-beautify.html</link>
      <pubDate>Mon, 27 Dec 2021 15:42:28 +0000</pubDate>
      <guid>https://vccv.cc/en/article/cactus-codeblock-beautify.html</guid>
      <description>I do not like cactus&amp;#39;s original codeblock style very much. Because I used to use wordpress theme, which has the style of imitation mac. But cactus does not have the style settings for the code block, so I decided to do it myself and revamp the theme!</description>
      <content:encoded><![CDATA[<h2 id="antecedents">Antecedents</h2>
<p>I do not like cactus&rsquo;s original codeblock style very much. Because I used to use wordpress theme, which has the style of imitation mac. But cactus does not have the style settings for the code block, so I decided to do it myself and revamp the theme!</p>
<h2 id="after">After</h2>
<p>I&rsquo;m glad I found a tutorial on the internet, although it&rsquo;s not a handy tutorial exclusively for cactus, but after a period of time, I managed to solve it hahaha 😂 I&rsquo;d like to thank the original author here.</p>
<p>As usual, share it to those who come later, so as not to waste time by repeatedly building the wheel.</p>
<ol>
<li>
<p>It is recommended to browse through the original tutorial: <a href="https://blog.imlete.cn/article/Hexo-add-CodeBlock.html" target="_blank" rel="noopener">Hexo-Add codeblock borders</a> .</p>
</li>
<li>
<p>The following modifications are specific to the cactus theme and are for reference only.</p>
<ul>
<li>
<p>Find the <strong>style.styl</strong> file for the topic in the <strong>source/css</strong> directory and modify the corresponding location of the code as follows:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-styl" data-lang="styl"><span class="line"><span class="cl"><span class="o">//</span> <span class="nt">Code</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">codeFrame&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">theme&#39;</span>
</span></span><span class="line"><span class="cl"><span class="kp">@import</span> <span class="err">&#39;_highlight</span><span class="o">/</span><span class="err">d</span><span class="k">if</span><span class="err">f&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">...................</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">.</span><span class="nc">highlight</span>
</span></span><span class="line"><span class="cl">	<span class="py">margin</span><span class="p">:</span> <span class="err">2rem</span> <span class="err">0</span> <span class="err">0</span> <span class="err">0</span>
</span></span></code></pre></td></tr></table>
</div>
</div></li>
<li>
<p>In the same location of the above file <code>.highlight</code>code block will</p>
<p><code>border-radius: 4px</code> Deletion.</p>
<p><code>background: $color-background-code</code> Delete.</p>
</li>
<li>
<p>Same as above add properties to <code>.btn-copy</code> <code>top: 0.2rem</code>.</p>
</li>
</ul>
</li>
<li>
<p>Finally I deleted all the original files from the <strong>_highlight</strong> folder, leaving only the three new files.</p>
<p><a href="/en/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp" data-fancybox="gallery" data-src="/en/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp" data-caption=" Modify file ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227223103409_hu_e920f01a04b58691.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp 826w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="826"
                    height="160"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227223103409_hu_e920f01a04b58691.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227223103409_hu_a6e4c1760b8282e5.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227223103409_hu_c40c003fe9ef374b.webp 826w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Modify file "
                    
                />
            </picture>
        </a></p>
</li>
<li>
<p>Attention：</p>
<ul>
<li>The third step in the original tutorial I found I could just skip because the code related to the cactus code block is in the <strong>style.styl</strong> file.</li>
<li>To change the different highlighting styles for code blocks, simply change the <strong>diff.styl</strong> file.</li>
</ul>
</li>
</ol>
<h2 id="final-results">Final Results</h2>
<p>Before modification:</p>
<p><a href="/en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp" data-fancybox="gallery" data-src="/en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp" data-caption=" Before modification ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227223503492_hu_f153146d43e07c05.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ed3c7df325d83143.webp 960w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_f1c7b33e28419c69.webp 1440w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1850"
                    height="1152"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227223503492_hu_f153146d43e07c05.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_eb81d9b489aaae8d.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ed3c7df325d83143.webp 960w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_f1c7b33e28419c69.webp 1440w, /en/article/cactus-codeblock-beautify/image-20211227223503492_hu_ec63987de62c4a13.webp 1850w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Before modification "
                    
                />
            </picture>
        </a></p>
<p>After modification:</p>
<p><a href="/en/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp" data-fancybox="gallery" data-src="/en/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp" data-caption=" After modification ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227172137422_hu_1c07735fa98b8cf0.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_f75fbcd42f511de7.webp 960w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_69758693d2b0250b.webp 1440w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp 1876w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1876"
                    height="904"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp"
                    srcset="/en/article/cactus-codeblock-beautify/image-20211227172137422_hu_1c07735fa98b8cf0.webp 480w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_f5e380d3c5491f3b.webp 720w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_f75fbcd42f511de7.webp 960w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_69758693d2b0250b.webp 1440w, /en/article/cactus-codeblock-beautify/image-20211227172137422_hu_520db2d451274999.webp 1876w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" After modification "
                    
                />
            </picture>
        </a></p>
<p>I am personally satisfied with the drop, the color scheme all depends on your own play haha.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Play Genshin Impact on Jailbroken iOS Devices</title>
      <link>https://vccv.cc/en/article/ios-jailbreak-genshin.html</link>
      <pubDate>Thu, 23 Dec 2021 22:29:23 +0000</pubDate>
      <guid>https://vccv.cc/en/article/ios-jailbreak-genshin.html</guid>
      <description>On 2021-12-22 14:00, the Genshin Imapct began to detect jailbreak devices, prompting &amp;#34;data exception, please re-login&amp;#34;. I searched for keywords on GitHub and found a shield jailbreak plugin and modified it to work properly on the iOS.</description>
      <content:encoded><![CDATA[<h2 id="update-3">Update 3</h2>
<p>After the feedback in the comment section, as of 2022/07/16 the latest version of the iOS version, the shielding plug-in in the article download link can still be used normally.</p>
<p>In view of the unstable update of the BigBoss source, it is recommended to use the first version of the plug-in inside the article download link.</p>
<h2 id="what-happened">What happened</h2>
<p>On 2021-12-22 at 14:00, the Genshin Impact on the iOS also started to detect the jailbroken device, prompting &ldquo;Data abnormal, please log in again&rdquo;.</p>
<p><a href="/en/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp" data-fancybox="gallery" data-src="/en/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp" data-caption=" Official Warning ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ios-jailbreak-genshin/img_hu_179a1059803b7455.webp 480w, /en/article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp 720w, /en/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp 910w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="910"
                    height="430"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp"
                    srcset="/en/article/ios-jailbreak-genshin/img_hu_179a1059803b7455.webp 480w, /en/article/ios-jailbreak-genshin/img_hu_ad2d159bda1d13a0.webp 720w, /en/article/ios-jailbreak-genshin/img_hu_f4c27533f76c2544.webp 910w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Official Warning "
                    
                />
            </picture>
        </a></p>
<h2 id="after">After</h2>
<p>I searched for keywords on GitHub and found a foreign brother who had released a jailbreak plugin six days ago.</p>
<p>BUT!!!</p>
<p>The original author mistakenly misspelled the name of the Genshin Impact&rsquo;s package in China as follows:</p>
<p><a href="/en/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp" data-fancybox="gallery" data-src="/en/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp" data-caption=" Error Code ">
            <picture>
                <source
                    type="image/webp"
                    srcset="/en/article/ios-jailbreak-genshin/error_hu_22262c7272ea2bc1.webp 480w, /en/article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp 720w, /en/article/ios-jailbreak-genshin/error_hu_c60ac2fefdf9df27.webp 960w, /en/article/ios-jailbreak-genshin/error_hu_65f656b816e1bc6a.webp 1440w, /en/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp 1734w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                >
                <img
                    width="1734"
                    height="136"
                    style="width: 100%; height: auto; max-height: 36rem; object-fit: contain;"
                    loading="lazy"
                    decoding="async"
                    src="/en/article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp"
                    srcset="/en/article/ios-jailbreak-genshin/error_hu_22262c7272ea2bc1.webp 480w, /en/article/ios-jailbreak-genshin/error_hu_14d482f6e42c3e2a.webp 720w, /en/article/ios-jailbreak-genshin/error_hu_c60ac2fefdf9df27.webp 960w, /en/article/ios-jailbreak-genshin/error_hu_65f656b816e1bc6a.webp 1440w, /en/article/ios-jailbreak-genshin/error_hu_c2f469cfa55717da.webp 1734w"
                    sizes="(min-width: 768px) 720px, calc(100vw - 2rem)"
                    alt=" Error Code "
                    
                />
            </picture>
        </a></p>
<h2 id="solution">Solution</h2>
<p>Original code:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">{ Filter = { Bundles = ( &#34;com.miHoYo.GenshinImpact&#34;, &#34;com.miHoYo.Yanshen&#34; ); }; }
</span></span></code></pre></td></tr></table>
</div>
</div><p>Correction to:</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">{ Filter = { Bundles = ( &#34;com.miHoYo.GenshinImpact&#34;, &#34;com.miHoYo.Yuanshen&#34; ); }; }
</span></span></code></pre></td></tr></table>
</div>
</div><p>I unpacked and modified the deb package packed by the original author and recompiled it for distribution, doing a small and insignificant thing.</p>
<h2 id="results">Results</h2>
<p>By my test, the Genshin Impact national service has been able to run normally, the international service to be tested.</p>
<blockquote>
<p>Test Equipment:</p>
<p>Model: 12mini</p>
<p>iOS version: 14.2.1</p>
<p>Jailbreak software: unc0ver</p>
</blockquote>
<h2 id="download">Download</h2>
<p><a href="https://yuesir.lanzouo.com/iejurxwygaf" target="_blank" rel="noopener">Lanzou Cloud</a></p>
<h2 id="thanks">Thanks🙏</h2>
<p><a href="https://github.com/iVoider/GenshinJailbreakBypass" target="_blank" rel="noopener">Github iVoider</a></p>
<h2 id="update-1">Update 1</h2>
<p>The author has uploaded a maintenance plugin on BigBoss source called <strong>原神（国服）屏蔽越狱</strong> . It has been tested and works fine, please go ahead and download and install it directly.</p>
<h2 id="update-2">Update 2</h2>
<p>The plugin has been renamed to <strong>原神防越狱检测</strong> .</p>
]]></content:encoded>
    </item>
    <item>
      <title>Python Notebook Quickstart</title>
      <link>https://vccv.cc/en/article/python-notebook.html</link>
      <pubDate>Tue, 05 Oct 2021 22:59:01 +0000</pubDate>
      <guid>https://vccv.cc/en/article/python-notebook.html</guid>
      <description>The blogger&amp;#39;s personal python learning notebook, recording the key points encountered in the learning process. python programming from the beginning to the ground!</description>
      <content:encoded><![CDATA[<blockquote>
<p>Life is not easy, exams too.</p>
</blockquote>
<ul>
<li>Python Programming from Beginning to Practice is Python 3.5, while in Python 3.6 the internal algorithm of dict was rewritten, hence <strong>3.6 dict is ordered, prior to this version it was unordered</strong>. <a href="https://legacy.python.org/dev/peps/pep-0468/" target="_blank" rel="noopener">Reference Links</a></li>
<li>String formatting <code>f'Results of the {event}'</code></li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
