<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Vinking]]></title><description><![CDATA[愿星光永远偏爱你的梦境]]></description><link>https://www.vinking.top</link><image><url>https://cdn.vinking.top/avatar.webp</url><title>Vinking</title><link>https://www.vinking.top</link></image><generator>Yohaku (https://github.com/Innei/Yohaku)</generator><lastBuildDate>Fri, 01 May 2026 11:17:27 GMT</lastBuildDate><atom:link href="https://www.vinking.top/feed" rel="self" type="application/rss+xml"/><pubDate>Fri, 01 May 2026 11:17:27 GMT</pubDate><language><![CDATA[zh-CN]]></language><item><title><![CDATA[从快捷指令到 App：一次在免费开发者账号下实现 HealthKit 授权的踩坑记录]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cdn.vinking.top/o9nk09MfoW1fcOK.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/XEyqibYJ2iLluLc.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/ERMTumG3I5dbB75.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/posts/codes/healthkit-authorization-free-apple-developer-account">https://www.vinking.top/posts/codes/healthkit-authorization-free-apple-developer-account</a></blockquote><div><p>以前写过一篇文章，使用快捷指令实现将健身记录同步到博客的个人状态中。</p><p style="padding:6px 12px;border-left:2px solid #C56473;background:#C5647350;font-style:italic;font-weight:500">Not support render this content in RSS render</p><p>但是实际上用下来感觉非常的难受，一方面由于快捷指令太长了，一旦需要对其中部分的信息进行调整，操作会非常非常的麻烦；另一方面，苹果的自动化并没有固定时间自动执行的选项，为了覆盖一整天的定时同步，需要创建五六个自动化任务。整体显得非常笨重且繁琐。所以在过年的这段时间写了一个应用，使用 HKObserverQuery + 小组件定时任务来实现数据的后台自动推送。</p><p>::: masonry
<img height="2556" src="https://cdn.vinking.top/o9nk09MfoW1fcOK.webp" width="1179"/>
<img height="2556" src="https://cdn.vinking.top/XEyqibYJ2iLluLc.webp" width="1179"/>
<img height="2556" src="https://cdn.vinking.top/ERMTumG3I5dbB75.webp" width="1179"/>
:::</p><p>但由于我使用的是免费的苹果开发者账户，只能将应用手动打包为 ipa 文件，然后通过 SideStore 进行安装。导致即使声明了 HealthKit entitlements，安装后也不会弹出健康数据授权页面，也就无法访问任何健康数据。网上找了一圈也没什么好的解决方案，一度以为只能每周连接 Xcode 重新构建到手机来给应用续命了。</p><p>后面无意中翻到 Reddit 的这个 <a href="https://www.reddit.com/r/AltStore/comments/1mnnvtd/issue_with_app_ids_not_expiring">帖子</a> ，评论区里有人提到一个思路：通过修改应用的 Bundle ID，让它使用另一个已经存在 App ID 来通过替身的方式绕开 App ID 未过期导致无法安装新应用的问题。</p><p>经过尝试，这个方法也适用于解决通过 SideStore 安装的应用无法弹出健康数据授权的问题。具体做法是：通过将 Xcode 项目里的 Bundle ID 改成与最初通过 SideStore 安装该应用时相同的 App ID，然后在 Xcode 里连接真机运行一次，让 Xcode 给这个 App ID 注册 HealthKit capability ，这时候打开应用就可以正常弹出健康数据授权页面并且完成数据的授权。</p><p>最后将应用重新构建为 ipa，再用 SideStore 安装后，就能在已授权状态下访问到 HealthKit 数据。这种方法可以在一定程度上绕开苹果免费开发者账户侧载应用不弹授权页面的限制。</p><p><del>当然通过这种方式完成的授权能否长期保持还有待进一步观察。如果后续有新的结果，我会再更新。</del> 该方法确认可以长期使用。</p></div><p style="text-align:right"><a href="https://www.vinking.top/posts/codes/healthkit-authorization-free-apple-developer-account#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/posts/codes/healthkit-authorization-free-apple-developer-account</link><guid isPermaLink="true">https://www.vinking.top/posts/codes/healthkit-authorization-free-apple-developer-account</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Mon, 02 Mar 2026 07:54:59 GMT</pubDate></item><item><title><![CDATA[获取《明日方舟：终末地》的抽卡记录]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cdn.vinking.top/R1secGzm8IL0qt7.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/posts/codes/how-to-obtain-gacha-records-in-arknights-endfield">https://www.vinking.top/posts/codes/how-to-obtain-gacha-records-in-arknights-endfield</a></blockquote><div><p>今天《明日方舟：终末地》正式开启公测了。抽空体验了一段时间之后，想着将抽卡数据导入进我自己的<a href="https://astrionyx.vinking.top/">抽卡分析应用</a>中。但是可能是游戏刚开服的缘故，找了一轮都没能找到导出抽卡数据的工具，最终只能自己动手实现这个功能。下面分享主要思路，如果你需要实现这个功能希望对你有所帮助。</p><h2 id="url-">URL 里都有什么</h2><p>首先，和其他游戏一样，我们可以通过抓包软件抓取这样的抽卡记录链接：</p><pre class="language-text lang-text"><code class="language-text lang-text">https://ef-webview.hypergryph.com/api/record/char?lang=zh-cn&amp;seq_id={seqId}&amp;pool_type={poolType}&amp;token={token}&amp;server_id={serverId}
</code></pre>
<p><img alt="抽卡记录链接" height="351" src="https://cdn.vinking.top/R1secGzm8IL0qt7.webp" width="1030"/></p><hr/><h3 id="">角色池</h3><p>针对角色池，我们主要关注 <code>pool_type</code> 和 <code>seq_id</code> 这两个参数：</p><p><code>pool_type</code> 是卡池枚举值，目前仅能取如下卡池之一：</p><ul><li>启程寻访（新手池）：<code>E_CharacterGachaPoolType_Beginner</code></li><li>基础寻访（常驻池）：<code>E_CharacterGachaPoolType_Standard</code></li><li>特许寻访（限定池）：<code>E_CharacterGachaPoolType_Special</code></li></ul><p>而与原神，鸣潮等游戏不同，终末地的抽卡记录链接通常带有 <code>seq_id</code> 参数。</p><pre class="language-json lang-json"><code class="language-json lang-json">// seq_id=26&amp;pool_type=E_CharacterGachaPoolType_Standard
{
  &quot;code&quot;: 0,
  &quot;data&quot;: {
    &quot;list&quot;: [
      //...
      {
        &quot;poolId&quot;: &quot;standard&quot;,
        &quot;poolName&quot;: &quot;基础寻访&quot;,
        &quot;charId&quot;: &quot;chr_0019_karin&quot;,
        &quot;charName&quot;: &quot;秋栗&quot;,
        &quot;rarity&quot;: 4,
        &quot;isFree&quot;: false,
        &quot;isNew&quot;: false,
        &quot;gachaTs&quot;: &quot;1769073164712&quot;,
        &quot;seqId&quot;: &quot;21&quot;
      }
    ],
    &quot;hasMore&quot;: false
  },
  &quot;msg&quot;: &quot;&quot;
}

// pool_type=E_CharacterGachaPoolType_Beginner
{
  &quot;code&quot;: 0,
  &quot;data&quot;: {
    &quot;list&quot;: [
      {
        &quot;poolId&quot;: &quot;beginner&quot;,
        &quot;poolName&quot;: &quot;启程寻访&quot;,
        &quot;charId&quot;: &quot;chr_0022_bounda&quot;,
        &quot;charName&quot;: &quot;萤石&quot;,
        &quot;rarity&quot;: 4,
        &quot;isFree&quot;: false,
        &quot;isNew&quot;: false,
        &quot;gachaTs&quot;: &quot;1769072324787&quot;,
        &quot;seqId&quot;: &quot;20&quot; //该卡池最新的抽卡记录
      },
      // ...
    ],
    &quot;hasMore&quot;: true
  },
  &quot;msg&quot;: &quot;&quot;
}

</code></pre>
<p>通过观察上面两个不同卡池的记录，我们可以发现 <code>seq_id</code> 参数的一些特征：</p><ol start="1"><li><code>seq_id (seqId)</code> 是一个 <strong>账号级的</strong>、<strong>跨子卡池的</strong>、<strong>不同类型卡池互相独立的</strong> 递增序号，所有角色子卡池的抽卡记录共享同一条 <code>seq_id (seqId)</code> 序列，而武器子卡池的抽卡记录共享另一条 <code>seq_id (seqId)</code> 序列。在同一卡池类型（所有角色池或者所有武器池）下，即使我们更换子卡池的类型也不会让 <code>seq_id (seqId)</code> 重新开始计数。</li><li><code>seq_id (seqId)</code> 数字越大，时间越晚、数据越新。</li><li>当请求的链接不带 <code>seq_id</code> 参数的时候会返回该卡池最新的五条记录（即 <code>seqId</code> 最大的五条记录）。</li></ol><p>根据这些特征我们可以知道：<strong>在游戏里的抽卡记录展示页中，我们从第一页开始往后翻（从新记录到旧记录）的过程就是抽卡记录链接 <code>seq_id</code> 参数递减的过程。</strong></p><p>在链接返回的抽卡记录中，还会带有一个 <code>hasMore</code> 参数。其代表的是当前返回结果的最小 <code>seqId</code> 之下是否还有数据，反映的是是否还能翻下一页。</p><hr/><h3 id="">武器池</h3><p>武器池的 API 与角色池有所不同。武器池需要通过两个 API 来获取数据：</p><h4 id="">获取武器池列表</h4><p>首先需要通过下面的链接获取用户存在抽卡记录的武器池列表：</p><pre class="language-text lang-text"><code class="language-text lang-text">https://ef-webview.hypergryph.com/api/record/weapon/pool?lang=zh-cn&amp;token={token}&amp;server_id={serverId}
</code></pre>
<p>返回的数据结构：</p><pre class="language-json lang-json"><code class="language-json lang-json">{
  &quot;code&quot;: 0,
  &quot;data&quot;: [
    { &quot;poolId&quot;: &quot;weponbox_1_0_1&quot;, &quot;poolName&quot;: &quot;熔铸申领&quot; },
    { &quot;poolId&quot;: &quot;weaponbox_constant_2&quot;, &quot;poolName&quot;: &quot;星声申领&quot; }
    // ...
  ],
  &quot;msg&quot;: &quot;&quot;
}
</code></pre>
<p>这里可以看到武器池分为两种类型：</p><ul><li><strong>武器限定池</strong>：<code>poolId</code> 格式为 <code>weponbox_*</code>（如 <code>weponbox_1_0_1</code>），对应当期 UP 武器</li><li><strong>武器常驻池</strong>：<code>poolId</code> 格式为 <code>weaponbox_constant_*</code>（如 <code>weaponbox_constant_2</code>）</li></ul><blockquote><p>题外话：这里有意思的是武器限定池的 <code>poolId</code> 的前缀拼写错误为了 <code>wepon</code>，不知道是不是历史遗留问题。</p></blockquote>
<h4 id="">获取武器抽卡记录</h4><p>获取具体武器池的抽卡记录链接与角色池抽卡记录链接格式有所不同，武器池的抽卡记录链接将 <code>pool_id</code> 参数代替了 <code>pool_type</code> 参数：</p><pre class="language-text lang-text"><code class="language-text lang-text">https://ef-webview.hypergryph.com/api/record/weapon?lang=zh-cn&amp;seq_id={seqId}&amp;pool_id={poolId}&amp;token={token}&amp;server_id={serverId}
</code></pre>
<p>其返回的数据结构为：</p><pre class="language-json lang-json"><code class="language-json lang-json">{
  &quot;code&quot;: 0,
  &quot;data&quot;: {
    &quot;list&quot;: [
      {
        &quot;poolId&quot;: &quot;weponbox_1_0_1&quot;,
        &quot;poolName&quot;: &quot;熔铸申领&quot;,
        &quot;weaponId&quot;: &quot;wpn_funnel_0010&quot;,
        &quot;weaponName&quot;: &quot;骑士精神&quot;,
        &quot;weaponType&quot;: &quot;E_WeaponType_Wand&quot;,
        &quot;rarity&quot;: 6,
        &quot;isNew&quot;: true,
        &quot;gachaTs&quot;: &quot;1769238381938&quot;,
        &quot;seqId&quot;: &quot;47&quot;
      },
      // ...
    ],
    &quot;hasMore&quot;: true
  },
  &quot;msg&quot;: &quot;&quot;
}
</code></pre>
<p>武器记录的字段与角色记录略有不同：</p><ul><li><code>weaponId</code>：武器 ID</li><li><code>weaponName</code>：武器名称</li><li><code>weaponType</code>：武器类型（<code>E_WeaponType_Sword</code>、<code>E_WeaponType_Wand</code> 等）</li></ul><p>武器池的 <code>seq_id</code> 特性与角色池相同，所有武器子卡池共享同一条 <code>seqId</code> 序列。</p><hr/><p>至此，我们已经基本搞清楚了《明日方舟：终末地》抽卡记录链接的逻辑。</p><h2 id="">主要思路</h2><p>根据上面的介绍，我们能构想出通过一个有效的终末地抽卡记录链接来获取全部卡池所有记录的方法：</p><h3 id="">角色池</h3><ol start="1"><li>首先带上随便一个卡池的 <code>pool_type</code>，并且不带 <code>seq_id</code> 发起一次请求，获取该卡池最大 <code>seqId</code> 的最新的抽卡记录。</li><li>后续使用返回数据中最小 <code>seqId</code> 作为游标，遍历该卡池的所有记录，直至后续抽卡数据被服务器清理或着到了该卡池的第一次抽卡 <code>hasMore === false</code> 停止。</li><li>切换为另一个卡池的 <code>pool_type</code>，继续重复第一步的操作即可。</li></ol><h3 id="">武器池</h3><ol start="1"><li>首先调用武器池列表 API 获取用户有数据的武器池。</li><li>遍历每个武器池，使用 <code>pool_id</code> 参数获取记录。</li><li>根据 <code>poolId</code> 判断卡池类型：包含 <code>constant</code> 的为常驻池，否则为限定池。</li></ol><h3 id="">代码实现</h3><pre class="language-typescript lang-typescript"><code class="language-typescript lang-typescript">// 获取角色池记录
async function fetchCharacterRecords(token: string, serverId: string) {
  const poolTypes = [
    &quot;E_CharacterGachaPoolType_Beginner&quot;,
    &quot;E_CharacterGachaPoolType_Standard&quot;,
    &quot;E_CharacterGachaPoolType_Special&quot;,
  ];
  const allRecords = [];

  for (const poolType of poolTypes) {
    let cursor = null;
    let hasMore = true;

    while (hasMore) {
      const seqIdParam = cursor !== null ? `&amp;seq_id=${cursor}` : &quot;&quot;;
      const url = `https://ef-webview.hypergryph.com/api/record/char?lang=zh-cn${seqIdParam}&amp;pool_type=${poolType}&amp;token=${encodeURIComponent(token)}&amp;server_id=${serverId}`;
      
      const response = await fetch(url);
      const { data } = await response.json();

      if (data?.list?.length &gt; 0) {
        allRecords.push(...data.list);
        hasMore = data.hasMore;
        
        if (hasMore) {
          const seqIds = data.list.map(item =&gt; Number(item.seqId));
          cursor = Math.min(...seqIds);
          await new Promise(resolve =&gt; setTimeout(resolve, 300));
        }
      } else {
        hasMore = false;
      }
    }
  }

  return allRecords;
}

// 获取武器池记录
async function fetchWeaponRecords(token: string, serverId: string) {
  const allRecords = [];
  const poolListUrl = `https://ef-webview.hypergryph.com/api/record/weapon/pool?lang=zh-cn&amp;token=${encodeURIComponent(token)}&amp;server_id=${serverId}`;
  const poolListResponse = await fetch(poolListUrl);
  const { data: weaponPools } = await poolListResponse.json();

  if (!weaponPools?.length) return allRecords;

  for (const pool of weaponPools) {
    let cursor = null;
    let hasMore = true;

    while (hasMore) {
      const seqIdParam = cursor !== null ? `&amp;seq_id=${cursor}` : &quot;&quot;;
      const url = `https://ef-webview.hypergryph.com/api/record/weapon?lang=zh-cn${seqIdParam}&amp;pool_id=${pool.poolId}&amp;token=${token}&amp;server_id=${serverId}`;
      
      const response = await fetch(url);
      const { data } = await response.json();

      if (data?.list?.length &gt; 0) {
        allRecords.push(...data.list);
        hasMore = data.hasMore;
        
        if (hasMore) {
          const seqIds = data.list.map(item =&gt; Number(item.seqId));
          cursor = Math.min(...seqIds);
          await new Promise(resolve =&gt; setTimeout(resolve, 300));
        }
      } else {
        hasMore = false;
      }
    }
  }

  return allRecords;
}
</code></pre>
<p>这样我们就实现了获取《明日方舟：终末地》的全部卡池所有记录。</p></div><p style="text-align:right"><a href="https://www.vinking.top/posts/codes/how-to-obtain-gacha-records-in-arknights-endfield#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/posts/codes/how-to-obtain-gacha-records-in-arknights-endfield</link><guid isPermaLink="true">https://www.vinking.top/posts/codes/how-to-obtain-gacha-records-in-arknights-endfield</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Thu, 22 Jan 2026 21:13:15 GMT</pubDate></item><item><title><![CDATA[一份小小的 2025 年 AI 年度使用报告]]></title><description><![CDATA[<p>当前内容无法于 RSS 阅读器中正确渲染，请往：<a href="https://www.vinking.top/posts/daily/ai_report_2025">https://www.vinking.top/posts/daily/ai_report_2025</a></p>]]></description><link>https://www.vinking.top/posts/daily/ai_report_2025</link><guid isPermaLink="true">https://www.vinking.top/posts/daily/ai_report_2025</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Wed, 31 Dec 2025 05:01:47 GMT</pubDate></item><item><title><![CDATA[悲报：要被榨干了！]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cdn.vinking.top/xlGDHu44ucvTNz2.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/44SdOfkPkkaF20M.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/notes/23">https://www.vinking.top/notes/23</a></blockquote><div><p><strong>【 战斗速报！】</strong> 各位早上好 中午好 晚上好，从前天开始持续遭遇多个脚本的恶意攻击。今天早上到达了小高峰，几小时就受到了 20w+ 的恶意请求，已经刷掉近 10GB 的流量。目前已经将这些 IP 段拉入黑名单：</p><pre class=""><code class="">182.34.4.0/24
180.119.118.0/23
140.75.192.0/24
121.233.200.0/24
61.147.92.0/24
120.238.245.0/24
58.222.45.0/24
218.90.199.0/24
</code></pre>
<p>由于这些请求基本上是每 5 分钟消耗 100 MB 左右的流量，所以并没有触发 CDN 设置的 5 分钟 200MB 封顶限制，加上周末早上在睡大觉，导致本月的 CDN 免费额度已经被消耗了一半以上</p><p>如果后续继续被攻击到 CDN 免费额度耗尽，会将境内的流量全部解析到<a href="https://shiro.vinking.top/">境外的线路</a>躲一阵子，届时会出现不限于网站打开时间大幅拉长，部分地区无法访问等情况，请各位谅解。</p><p>最后请脚本大佬手下留情</p><p><img alt="已经一滴都没有了" height="256" src="https://cdn.vinking.top/xlGDHu44ucvTNz2.webp" width="256"/></p><h2 id="">后续</h2><p>鉴于恶意攻击仍在零星持续，目前已经着手编写并且启用了自动检测并更新 CDN 黑名单的脚本，这次大概能睡一个好觉了。</p><p><img height="313" src="https://cdn.vinking.top/44SdOfkPkkaF20M.webp" width="584"/></p></div><p style="text-align:right"><a href="https://www.vinking.top/notes/23#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/notes/23</link><guid isPermaLink="true">https://www.vinking.top/notes/23</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Sat, 05 Jul 2025 08:36:46 GMT</pubDate></item><item><title><![CDATA[Astrionyx - 鸣潮抽卡分析工具及其细节]]></title><description><![CDATA[<p>当前内容无法于 RSS 阅读器中正确渲染，请往：<a href="https://www.vinking.top/posts/codes/astrionyx-wuwa-gacha-analysis">https://www.vinking.top/posts/codes/astrionyx-wuwa-gacha-analysis</a></p>]]></description><link>https://www.vinking.top/posts/codes/astrionyx-wuwa-gacha-analysis</link><guid isPermaLink="true">https://www.vinking.top/posts/codes/astrionyx-wuwa-gacha-analysis</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Fri, 30 May 2025 02:44:21 GMT</pubDate></item><item><title><![CDATA[句点]]></title><description><![CDATA[<div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/notes/22">https://www.vinking.top/notes/22</a></blockquote><div><p>最近压力太大了。</p><p>趁着 Steam 特卖节看了好多游戏，买了《灾厄堡垒》和《超灵秘法社》，都没能沉下心来好好玩。 也似乎只能玩得下 Gal （大概是不用动脑吧</p><p>草稿箱里有好几篇文章都是只写了开头，有时候半夜突然坐起来打开电脑，光标在空白处闪烁三分钟，又默默合上笔记本。</p><p>或许该接受生活长出点青苔，就像接受有些故事线不必强行推进。</p></div><p style="text-align:right"><a href="https://www.vinking.top/notes/22#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/notes/22</link><guid isPermaLink="true">https://www.vinking.top/notes/22</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Fri, 21 Mar 2025 13:31:25 GMT</pubDate></item><item><title><![CDATA[将苹果的健身记录同步到博客展示]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cdn.vinking.top/g2EvuIOL5NGvcJo.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/ih67w63XjrzZA8z.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/eB9pK0g0E8HlDjp.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/p0hU3X6MFbPc0ql.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/FKZ376cb9Dn1d9l.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status">https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status</a></blockquote><div><h3 id="">前言</h3><p>在 Shiro 主题中有一个 <a href="https://mx-space.js.org/docs/themes/shiro/extra#%E4%B8%AA%E4%BA%BA%E7%8A%B6%E6%80%81%E5%B1%95%E7%A4%BA">「个人状态展示」</a> 功能，可以展示一些自定义的状态。</p><p>为了充分利用这个功能，想将手机的健身圆环的数据同步展示在个人状态里，效果如下：</p><p><img alt="效果图" height="164" src="https://cdn.vinking.top/g2EvuIOL5NGvcJo.webp" width="379"/></p><p>最初计划通过编写 JavaScript 脚本并借助 Scriptable 应用来实现这个想法。然而经过尝试后发现，Scriptable 并不支持 HealthKit，从而无法获取到健康数据。在苹果设备上，应用需要通过 HealthKit 的 API 才能访问健康数据，而 <a href="https://x.com/scriptableapp/status/1317876804472999936">Scriptable 曾尝试集成 HealthKit但是被苹果商店拒绝</a>。所以只能退而求其次，使用苹果自带的快捷指令来实现这一功能。</p><blockquote><p>2026.3.1 更新，由于快捷指令的限制太多，目前已经更换为自己编写的 App + SideStore自签来实现自动推送</p></blockquote>
<h3 id="">状态展示的设置</h3><p>通过手动设置个人状态展示，可以在控制台中看到页面通过 <code>POST</code> 的方式向 <code>https://{后端服务器}/api/v2/serverless/shiro/status</code> 发送了一个请求：</p><p><img alt="个人状态展示请求" height="412" src="https://cdn.vinking.top/ih67w63XjrzZA8z.webp" width="1331"/></p><p>请求的请求体包含下面这样格式的 JSON：</p><pre class="language-json lang-json"><code class="language-json lang-json">{
    &quot;emoji&quot;: &quot;😴&quot;, // 头像右下角的 Emoji
    &quot;desc&quot;: &quot;消耗0千卡能量 锻炼0分钟 站立0小时&quot;, // 展开后的描述
    &quot;ttl&quot;: 60 // 状态的持续时间，单位为秒
}
</code></pre>
<p>为了完成更新个人状态的操作，需要先获取访问令牌并且构建请求头 <code>Authorization: bearer {token}</code> 用于验证用户权限。</p><p>访问令牌有两种获得方法，第一种是每次设置状态前先发起一次登录请求，在登录请求返回的 JSON 里就能获得一个 <code>xxxxx.xxxxxxxx</code> 格式的访问令牌。</p><p>另一种是通过在后台 <strong>设定</strong> -&gt; <strong>安全</strong> -&gt; <strong>API Token</strong> 里新建一个 <code>xxxxxxxxxxxxxx</code> 格式的访问令牌，这里推荐这种方式。</p><p>拿到访问令牌后，控制台里验证一下：</p><pre class="language-js lang-js"><code class="language-js lang-js">const token = &quot;xxxxxxxxx&quot;;
fetch(&quot;https://server.vinking.top/api/v2/serverless/shiro/status&quot;, {
  method: &quot;POST&quot;,
  headers: {
    &quot;Content-Type&quot;: &quot;application/json&quot;,
    Authorization: token,
  },
  body: JSON.stringify({
    emoji: &quot;✌️&quot;,
    desc: &quot;测试&quot;,
    ttl: 60,
  }),
})
  .then((response) =&gt; {
    if (response.ok) {
      return response.text().then(() =&gt; {
        console.log(`用户状态设置成功，状态码: ${response.status}`);
      });
    }
  })
  .catch((error) =&gt; console.error(&quot;用户状态设置错误:&quot;, error));
</code></pre>
<p>成功设置状态。</p><p><img alt="设置成功" height="132" src="https://cdn.vinking.top/eB9pK0g0E8HlDjp.webp" width="222"/></p><h3 id="">设计快捷指令</h3><p>要实现自动同步健康数据到个人状态展示，需要设计一个能获取健康数据、构建请求并调用 API 的快捷指令，设计思路如下：</p><p style="padding:6px 12px;border-left:2px solid #C56473;background:#C5647350;font-style:italic;font-weight:500">Not support render this content in RSS render</p>
<!-- -->
<p>在将流程图转换为快捷指令的过程中有几个需要注意的坑：</p><ol start="1"><li>如果某类数据当天没有记录（如未锻炼），快捷指令会<strong>返回空值而不是 0</strong>。需要提前设置一个初始值 0 以避免后续拼接描述文本出现问题。</li><li>如果想要数据与苹果健康的健身记录面板数据一致，需特别注意「站立 x 小时」（Stand Hours）的统计方式。它反映的是<strong>达标次数</strong>，而非实际站立时长。其计算逻辑为：每个小时内，只要累计站立时间达到或超过 1 分钟，即算作 1 小时达标。例如，08:00 - 08:01 站立，09:30 - 09:31 站立，会被记录为 2 小时达标。相比之下，快捷指令获取的「站立分钟数」（Stand Time）是每次站立的实际分钟数。因此，若要统计「站立 x 小时」，需通过<strong>计数</strong>的方式统计每小时是否达标，而非直接累加站立分钟数。使用指令表达如下：</li></ol><p><img alt="统计达标次数" height="600" src="https://cdn.vinking.top/p0hU3X6MFbPc0ql.webp" width="310"/></p><ol start="3"><li>当接口成功设置状态时，仅返回 <code>204</code> 状态码且不返回任何内容，加上快捷指令本身不支持直接对 HTTP 状态码进行详细判断，因此只能通过判断返回文件的大小是否为 0 来确认设置是否成功。</li></ol><p>由于快捷指令太长了，所以放<a href="https://www.icloud.com/shortcuts/8ea3b57527394aa4aa5ef046c1a2ecf0">快捷指令</a>。</p><p>快捷指令完整流程如下（超级长图警告）：</p><p><img src="https://cdn.vinking.top/FKZ376cb9Dn1d9l.webp"/></p></div><p style="text-align:right"><a href="https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status</link><guid isPermaLink="true">https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Mon, 24 Feb 2025 19:13:03 GMT</pubDate></item><item><title><![CDATA[2025 没有新年游戏环节]]></title><description><![CDATA[<link rel="preload" as="image" href="https://image.vinking.top/fJVbVtd3ZPIg5Ps.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/posts/confetti/2025-no-new-year-game">https://www.vinking.top/posts/confetti/2025-no-new-year-game</a></blockquote><div><div><p>首先很遗憾的是，<strong>今年没有新年游戏环节</strong>。</p><p>博客上次更新还在两个月前，期间断断续续写了很多草稿，都因为忙于工作上的事情而被迫搁置，其中当然也包括 25 年的新年游戏。目前游戏处于一个半成品中的半成品状态（甚至并没有确定完整的玩法😭），所以在这里公开今年新年游戏里一个比较有意思的想法。</p><h2 id="">游戏灵感💡</h2><p>克里普托斯（Kryptos）是一座位于美国弗吉尼亚州中央情报局总部广场上的雕塑，由 James Sanborn 设计建造，于 1990 年 11 月 3 日完工。该雕塑的名字来源于希腊语“隐藏”，主题为“情报收集”。雕塑上刻有 865 个字符，这些字符被分为四段密文，每段采用不同的加密方法。</p><ul><li>第一段：已被破译，内容为“Between subtle shading and the absence of light lies the nuance of iqlusion”。其中“iqlusion”是故意拼错的“illusion”。</li><li>第二段：已被破译，得到经纬度 38°57′6.5″N 77°8′44″W。</li><li>第三段：已被破译，描述 Howard Carter 打开埃及法老图坦卡蒙陵墓时的情景。</li><li>第四段：至今仍未被完全破译。<a href="#1"><sup>1</sup></a></li></ul><p>其中雕塑第二段使用的是维吉尼亚密码（Vigenère cipher）进行加密的。<a href="#2"><sup>2</sup></a></p><h2 id="">游戏想法</h2><p>本次新年游戏会分为两个阶段</p><ul><li>游戏第一阶段的谜题尚没有想好，玩家解谜完成后将会得到一串字符串并且可以领取第一阶段的红包奖励🧧。</li><li>游戏第二阶段会给出一个维吉尼亚密码表（当然，并不会说明这是一个维吉尼亚密码表）以及一段密文。玩家需要将第一阶段得到的字符串作为的明文倒推出密钥，这个密钥就是游戏的最终结果同时可以领取第二阶段的红包奖励🧧。</li></ul><p>另外附上一个自己写的<a href="https://kryptos-six.vercel.app/">校验小工具</a>，希望有助于你的理解。</p><p>如果你有更好的想法或者建议，请跟我细说细说✌️</p><p>最后：</p><p style="color:#ff57a0" class="text-3xl">恭贺新禧，新年快乐</p><p style="color:#ff57a0;font-weight:bold">愿你的未来纯净明朗，像你此刻的可爱目光。</p><p><img height="100" src="https://image.vinking.top/fJVbVtd3ZPIg5Ps.webp" width="100"/></p><h3 id="">推荐观看</h3><p><a href="https://www.lemmi.no/p/the-unbreakable-kryptos-code">[Video]The Unbreakable Kryptos Code</a></p><h3 id="">参考文献</h3></div><footer><div id="1">1<!-- -->: &quot;Kryptos&quot; <em>Wikipedia</em>. Wikimedia Foundation, January 28, 2025. <a href="https://en.wikipedia.org/wiki/Kryptos">https://en.wikipedia.org/wiki/Kryptos</a>.</div><div id="2">2<!-- -->: &quot;The Unbreakable Kryptos Code.&quot; <em>Lemmi.no</em>. January 28, 2025. <a href="https://www.lemmi.no/p/the-unbreakable-kryptos-code">https://www.lemmi.no/p/the-unbreakable-kryptos-code</a>.</div></footer></div><p style="text-align:right"><a href="https://www.vinking.top/posts/confetti/2025-no-new-year-game#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/posts/confetti/2025-no-new-year-game</link><guid isPermaLink="true">https://www.vinking.top/posts/confetti/2025-no-new-year-game</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Mon, 27 Jan 2025 20:19:45 GMT</pubDate></item><item><title><![CDATA[将 SSL 证书同步到多吉云 CDN]]></title><description><![CDATA[<link rel="preload" as="image" href="https://image.vinking.top/UOO6W0N4.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/XhDtQ0MKSoUbdaW.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/lLvnFK30YCWTBd4.webp?imageMogr2/thumbnail/!80p"/><link rel="preload" as="image" href="https://cdn.vinking.top/dZKph0WwJNn3Rws.webp?imageMogr2/thumbnail/!80p"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn">https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn</a></blockquote><div><p>前两个月由于腾讯云 CDN 不支持欠费立刻暂停服务换到了多吉云 CDN。</p><p> <img alt="但是！" height="120" src="https://image.vinking.top/UOO6W0N4.webp" width="120"/></p><p>目前 宝塔/1Panel 的免费 SSL 证书都只有 90 天的有效期，虽然可以自动续签，但是续签后还是需要频繁手动更新 CDN 的证书，非常麻烦。</p><p>好在多吉云提供了对应的 API，使得我们可以通过脚本的方式自动实现同步 SSL 证书到多吉云 CDN。</p><p> <img height="272" src="https://cdn.vinking.top/XhDtQ0MKSoUbdaW.webp" width="533"/></p><h2 id="">功能</h2><ul><li>🔑 动态生成多吉云 API 访问令牌</li><li>📤 一键式证书上传与管理</li><li>🌐 多域名智能证书绑定</li><li>🗑️ 旧证书清理功能（可选）</li><li>⏰ 无缝衔接 Let&#x27;s Encrypt 自动续期</li><li>✅ 双平台支持（宝塔/1Panel）</li></ul><p style="padding:6px 12px;border-left:2px solid #C56473;background:#C5647350;font-style:italic;font-weight:500">Not support render this content in RSS render</p><h2 id="">快速开始</h2><ol start="1"><li>获取多吉云 API 密钥：
<ul><li>登录多吉云控制台</li><li>进入「用户中心」→「密钥管理」</li><li>创建新密钥对</li></ul></li><li>确认证书路径：
<ul><li>宝塔面板：<code>/www/server/panel/vhost/ssl/域名目录/</code></li><li>1Panel 可跳过</li></ul></li></ol><h2 id="">配置指南</h2><p>编辑脚本中的以下参数：</p><pre class="language-bash lang-bash"><code class="language-bash lang-bash"># 多吉云 AccessKey 和 SecretK
ACCESS_KEY=&quot;your_access_key_here&quot;   # 替换为你的AccessKey
SECRET_KEY=&quot;your_secret_key_here&quot;  # 替换为你的SecretKey

# 证书路径配置
FULLCHAIN_PATH=&quot;/path/to/fullchain.pem&quot;  # 全链证书路径
PRIVKEY_PATH=&quot;/path/to/privkey.pem&quot;      # 私钥路径

# 域名配置
DOMAINS=(&quot;example.com&quot; &quot;cdn.example.com&quot; &quot;www.example.com&quot;)  # 需要绑定的域名列表

# 旧证书处理策略
DELETE_OLD_CERT=false  # true=自动删除旧证书 | false=保留历史证书
</code></pre>
<h2 id="">部署指南</h2><h3 id="1panel">1Panel</h3><ol start="1"><li>进入证书管理界面</li><li><p>创建/编辑证书：</p><ul><li>启用「自动续签」</li><li>启用「推送证书到本地目录」</li><li>选择目录</li><li>启用「申请后执行脚本」</li><li>粘贴本脚本内容</li><li>修改证书路径为：</li></ul><pre class="language-sh lang-sh"><code class="language-sh lang-sh"># 证书路径
FULLCHAIN_PATH=&quot;./fullchain.pem&quot;
PRIVKEY_PATH=&quot;./privkey.pem&quot;
</code></pre>
</li></ol><p><img alt="1Panel 证书设置" height="511" src="https://cdn.vinking.top/lLvnFK30YCWTBd4.webp?imageMogr2/thumbnail/!80p" width="759"/></p><h3 id="">宝塔</h3><ol start="1"><li>创建定时任务：
<ul><li>任务类型：Shell 脚本</li><li>任务名称：随意</li><li>执行周期：每月 1 号 01:30 执行一次</li><li>执行用户：root</li><li>脚本内容：粘贴本脚本内容</li></ul></li></ol><p><img alt="宝塔定时任务" height="473" src="https://cdn.vinking.top/dZKph0WwJNn3Rws.webp?imageMogr2/thumbnail/!80p" width="788"/></p><ol start="2"><li>配合自动续签 Let’s Encrypt 证书定时任务 <code>/www/server/panel/pyenv/bin/python /www/server/panel/class/acme_v2.py –renew=1</code> 理论上可以实现放养多吉云 CDN 的证书。</li></ol><p>保存后执行一次任务，如果显示下面信息即已经完成证书的同步：</p><pre class=""><code class="">证书上传成功！
证书ID：12345
证书已成功绑定到 www.vinking.top
证书已成功绑定到 vinking.top
证书ID 12344 删除成功。
----------------------------------------------------------------------------
★[2024-12-26 16:01:29] Successful
----------------------------------------------------------------------------
</code></pre>
<h2 id="">代码思路</h2><h3 id="---accesstoken">获取密钥 &amp; 生成 <code>AccessToken</code></h3><p>多吉云的 API 具有验证机制，使用前需要在控制台的 <a href="https://console.dogecloud.com/user/keys">密钥管理</a> 获取 <code>AccessKey</code> 以及 <code>SecretKey</code>，然后根据 <code>AccessKey</code> 和 <code>SecretKey</code>生成 <code>AccessToken</code> 。</p><p> <code>AccessToken</code> 的生成过程是将请求地址和请求内容拼接后，使用 <code>SecretKey</code> 进行 <code>HMAC-SHA1</code> 加密，然后将得到的加密值与 <code>AccessKey</code> 用冒号连接起来。具体的生成算法可以参考文档 <a href="https://docs.dogecloud.com/cdn/api-access-token?id=%e7%ae%97%e6%b3%95">验证机制</a> 。</p><pre class="language-sh lang-sh"><code class="language-sh lang-sh"># 多吉云 AccessKey 和 SecretKey
ACCESS_KEY=&quot;xxxx&quot;
SECRET_KEY=&quot;xxxxxx&quot;

function generateAccessToken() {
    local apiPath=&quot;$1&quot;
    local body=&quot;$2&quot;
    local signStr=$(echo -e &quot;${apiPath}\n${body}&quot;)
    local sign=$(echo -n &quot;$signStr&quot; | openssl dgst -sha1 -hmac &quot;$SECRET_KEY&quot; | awk &#x27;{print $NF}&#x27;)
    local accessToken=&quot;$ACCESS_KEY:$sign&quot;

    echo &quot;$accessToken&quot;
}
 </code></pre>
<p>生成了 <code>AccessToken</code> 后，只需要在请求头中加上 <code>Authorization: TOKEN &lt;AccessToken&gt;</code> 即可通过验证。</p><h3 id="--">找到宝塔的域名证书 &amp; 上传证书</h3><p>在 <code>/www/server/panel/vhost/ssl/</code> 目录下，可以找到宝塔所有以域名命名的文件夹，文件夹内包含这个域名对应的<strong>完整证书链</strong> <code>fullchain.pem</code> 以及<strong>私钥</strong> <code>privkey.pem</code>。</p><p>这里推荐给域名及其所有子域名使用同一个泛域名证书，可以实现一次性将域名及其所有子域名完成证书同步。</p><p>以域名 <code>vinking.top</code> 为例，完整证书链文件和私钥文件的目录如下：</p><pre class=""><code class="">FULLCHAIN_PATH=&quot;/www/server/panel/vhost/ssl/vinking.top/fullchain.pem&quot;
PRIVKEY_PATH=&quot;/www/server/panel/vhost/ssl/vinking.top/privkey.pem&quot;
</code></pre>
<p>获取到域名证书后，需要通过 POST 的方式向 <code>https://api.dogecloud.com/cdn/cert/upload.json</code> 提交证书内容。上传成功后需要获取证书 ID，以便将刚才上传的证书绑定到域名。</p><p>参考文档 <a href="https://docs.dogecloud.com/cdn/api-cert-upload">上传证书</a> 、 <a href="https://docs.dogecloud.com/cdn/api-cert-bind">绑定证书</a> 。</p><pre class="language-sh lang-sh"><code class="language-sh lang-sh"># 宝塔面板 Let&#x27;s Encrypt 证书路径
FULLCHAIN_PATH=&quot;/www/server/panel/vhost/ssl/vinking.top/fullchain.pem&quot;
PRIVKEY_PATH=&quot;/www/server/panel/vhost/ssl/vinking.top/privkey.pem&quot;

# 证书备注名
CURRENT_DATE=$(date +&quot;%y/%m/%d&quot;)
NOTE=&quot;Certificate $CURRENT_DATE&quot;

# 需要绑定的域名列表
DOMAINS=(&quot;xxxxx.com&quot; &quot;cdn.xxxxx.com&quot; &quot;www.xxxxx.com&quot;)

# 上传证书到多吉云
function uploadCert() {
    local note=&quot;$1&quot;
    local certFile=&quot;$2&quot;
    local privateKeyFile=&quot;$3&quot;
    local certContent=$(&lt;&quot;$certFile&quot;)
    local privateKeyContent=$(&lt;&quot;$privateKeyFile&quot;)
    local encodedCert=$(echo &quot;$certContent&quot; | jq -sRr @uri)
    local encodedPrivateKey=$(echo &quot;$privateKeyContent&quot; | jq -sRr @uri)
    local body=&quot;note=$note&amp;cert=$encodedCert&amp;private=$encodedPrivateKey&quot;
    local accessToken=$(generateAccessToken &quot;/cdn/cert/upload.json&quot; &quot;$body&quot;)
    local response=$(curl -s -X POST &quot;https://api.dogecloud.com/cdn/cert/upload.json&quot;  \
         -H &quot;Authorization: TOKEN $accessToken&quot; \
         -H &quot;Content-Type: application/x-www-form-urlencoded&quot; \
         --data &quot;$body&quot;)

    local code=$(echo &quot;$response&quot; | jq -r &#x27;.code&#x27;)

    if [ &quot;$code&quot; -eq 200 ]; then
        echo &quot;证书上传成功！&quot;
        local certId=$(echo &quot;$response&quot; | jq -r &#x27;.data.id&#x27;)
        echo &quot;证书 ID：$certId&quot;
        bindCert &quot;$certId&quot;
    else
        local errMsg=$(echo &quot;$response&quot; | jq -r &#x27;.msg&#x27;)
        echo &quot;证书上传失败，错误代码：$code，错误信息：$errMsg&quot;
    fi
}

# 绑定证书
function bindCert() {
    local certId=&quot;$1&quot;
    local responses=()

    for domain in &quot;${DOMAINS[@]}&quot;; do
        (
            local body=&quot;id=$certId&amp;domain=$domain&quot;
            local accessToken=$(generateAccessToken &quot;/cdn/cert/bind.json&quot; &quot;$body&quot;)
            local response=$(curl -s -X POST &quot;https://api.dogecloud.com/cdn/cert/bind.json&quot;  \
                 -H &quot;Authorization: TOKEN $accessToken&quot; \
                 -H &quot;Content-Type: application/x-www-form-urlencoded&quot; \
                 --data &quot;$body&quot;)
            local code=$(echo &quot;$response&quot; | jq -r &#x27;.code&#x27;)

            if [ &quot;$code&quot; -eq 200 ]; then
                echo &quot;证书已成功绑定到 $domain&quot;
            else
                local errMsg=$(echo &quot;$response&quot; | jq -r &#x27;.msg&#x27;)
                echo &quot;绑定证书到 $domain 失败，错误代码：$code，错误信息：$errMsg&quot;
            fi
        ) &amp;
    done

    wait
}
</code></pre></div><p style="text-align:right"><a href="https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn</link><guid isPermaLink="true">https://www.vinking.top/posts/codes/auto-sync-ssl-certificates-to-dogecloud-cdn</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Tue, 19 Nov 2024 10:32:56 GMT</pubDate></item><item><title><![CDATA[旅游]]></title><description><![CDATA[<link rel="preload" as="image" href="https://cdn.vinking.top/qYRIec6WJSMpKZ3.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/Ys4PggcvE8wx1h5.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/7unkjNwq6RJLDFl.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/4ZRHRnRl7qXTSoP.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/37w7YfTCC8oWlf6.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/Ev1Rh2RoPoGdOuH.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/XX0bBSwtj8jRnj9.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/iQvuBZuIB5PzXEr.webp"/><link rel="preload" as="image" href="https://cdn.vinking.top/EiW1FhEnlk9vxvD.webp"/><div><blockquote>此渲染由 Yohaku API 生成，或存排版之虞，最佳体验请往：<a href="https://www.vinking.top/notes/21">https://www.vinking.top/notes/21</a></blockquote><div><p>最终还是决定去珠海旅游了。</p><h2 id="5-">5 号</h2><p>早上打顺风车出发，以为 5 号人会比较少，两个多小时应该能到了，没想到早上八点上车下午两点才到，果断给回程买了高铁票。</p><p>下午到酒店整理完后就去「爱情邮局」那边拍照，不得不说国庆是真的多人啊，路上堵车，到了也堵人，再加上早上坐车坐得整个人都懵懵的，所以基本上都在吃吃吃。</p><div data-live-photo="true" data-photo-src="https://cdn.vinking.top/u6NKvRmlybBIn90.webp" data-video-src="https://cdn.vinking.top/YKUK6G1jI7eMeUc.mov" style="height:320px"></div><h2 id="67-">6，7 号</h2><p>6 号的时候长隆的酒店就恢复到正常价格了，所以就订了长隆的「迎海酒店公寓」，一千两百块钱两张门票 + 一晚酒店 + 早餐自助餐。</p><p>酒店到长隆海洋王国大概有三四公里，但是每三十分钟会有一班免费的接驳车送去海洋王国，所以问题不大。</p><p>::: masonry
<img height="1440" src="https://cdn.vinking.top/qYRIec6WJSMpKZ3.webp" width="1920"/>
<img height="2560" src="https://cdn.vinking.top/Ys4PggcvE8wx1h5.webp" width="1920"/>
<img height="1440" src="https://cdn.vinking.top/7unkjNwq6RJLDFl.webp" width="1920"/>
<img height="1440" src="https://cdn.vinking.top/4ZRHRnRl7qXTSoP.webp" width="1920"/>
<img height="1440" src="https://cdn.vinking.top/37w7YfTCC8oWlf6.webp" width="1920"/>
<img height="1440" src="https://cdn.vinking.top/Ev1Rh2RoPoGdOuH.webp" width="1920"/>
<img height="1440" src="https://cdn.vinking.top/XX0bBSwtj8jRnj9.webp" width="1920"/>
:::</p><p>临走的时候买了一个小熊挂件、一个小丑企鹅纪念币还有一个能趴在肩上的海豹🦭。</p><p>::: masonry
<img height="2560" src="https://cdn.vinking.top/iQvuBZuIB5PzXEr.webp" width="1920"/>
<img height="2560" src="https://cdn.vinking.top/EiW1FhEnlk9vxvD.webp" width="1920"/>
:::</p><p><strong>该回家上班了</strong></p><script src="https://cdn.apple-livephotoskit.com/lpk/1/livephotoskit.js"></script><h2 id="">题外话</h2><p>最近微信推出了发送苹果实况图片的功能， 而 Web 也可以使用苹果提供的 LivePhotosKit 来实现</p><p style="padding:6px 12px;border-left:2px solid #C56473;background:#C5647350;font-style:italic;font-weight:500">Not support render this content in RSS render</p><p>首先引入 <code>LivePhotosKit</code> JS</p><pre class="language-html lang-html"><code class="language-html lang-html">&lt;script src=&quot;https://cdn.apple-livephotoskit.com/lpk/1/livephotoskit.js&quot;&gt;&lt;/script&gt;
</code></pre>
<p>再创建一个 <code>&lt;div&gt;</code> 元素即可:</p><pre class="language-html lang-html"><code class="language-html lang-html">&lt;div
    data-live-photo
    data-photo-src=&quot;https://...&quot;
    data-video-src=&quot;https://...&quot;
    style=&quot;width: 320px; height: 320px&quot;&gt;            
&lt;/div&gt;
</code></pre>
<p>其中 <code>data-photo-src</code> 是导出的图片、 <code>data-video-src</code> 是导出的视频。</p></div><p style="text-align:right"><a href="https://www.vinking.top/notes/21#comments">览毕，何不一言？</a></p></div>]]></description><link>https://www.vinking.top/notes/21</link><guid isPermaLink="true">https://www.vinking.top/notes/21</guid><dc:creator><![CDATA[Vinking]]></dc:creator><pubDate>Tue, 08 Oct 2024 03:11:03 GMT</pubDate></item></channel></rss>