解决 Planet 或者 Kubo 中 ENS (`.eth`) 域名无法更新的问题

TL;DR

IPFS_PATH="$HOME/Library/Containers/xyz.planetable.Planet/Data/Library/Application Support/ipfs/" $(find /Applications/Planet.app/Contents/Resources/ -name "ipfs-$(uname -m)-*.bin" | head -n 1) config --json DNS.Resolvers '{"eth.": "https://dns.eth.limo/dns-query"}'`

只需要将 Planet 使用的 IPFS 配置文件里的 DNS.Resolvers 设置成 eth.limo 就可以了,具体可以参考 eth.limo文档

对普通的 IPFS (比如 IPFS Desktop),直接用上面提到的文档里的命令

ipfs config --json DNS.Resolvers '{"eth.": "https://dns.eth.limo/dns-query"}'

就可以了。如果只安装了 IPFS Desktop,需要替换成对应的 IPFS 命令行。

 
Docker Desktop 被识别成恶意软件
 

使用 Mac 作为家庭服务器(通过以太网连接到网络)可能会遇到的一个问题是,系统错误地认为网络中的主机名冲突,然后将设备重新命名为 设备名 (2) (主机名则会变成 <hostname>-2)。

这个问题只会在系统上存在多个活跃的网络服务时出现,关闭 Wi-Fi 理论上就可以避免,但使用许多“连续互通”功能需要启用 Wi-Fi。

 
关于 macOS 上的的网络磁盘挂载

macOS 的网络磁盘挂载做得确实烂,性能和可靠性均不如 Windows。

在一些情况下(比如使用 Cryptomator 挂载 OneDrive 上的保险库)甚至会导致整个系统出现异常(典型的症状是 Finder 无响应、任何进程一旦访问网络资源就会卡死)1,其原因可能是内核中的代码出现了死锁。

  1. OneDrive on demand causes cryptomator to freeze - Help / Desktop App - Cryptomator Community

 

Mac mini + 2.5GbE USB网卡做服务器。

用台式机主板2.5GbE网卡上传文件,平均速度大约220 MB/s。使用MacBook连接到Wi-Fi 6 (5 GHz, 80 MHz)上传,峰值速度大约40 MB/s。

 

Spotlight 😅

 

Mac mini M4 的接口还是过于贫瘠了点,只有3个雷电口,一个给屏幕一个给系统盘,这就只剩下一个了。要是有4个雷电口就好多了……

 

Emmm……至少目前手动聚合好像是可以的,自动还是不工作……

 

聚合似乎又可以了,也有可能是我的这个Planet有问题……

 

聚合似乎还会出现问题,Planet重启之后就无法正常聚合了

看了下源码也也没发现啥问题,倒是知道了为啥tag不会正常更新,因为就没有做更新:https://github.com/Planetable/Planet/blob/b9c039150ec83cccd980e305a86a04a395cb866c/Planet/Entities/MyPlanetModel%2BAggregate.swift#L303

 

终于把最近一年半+按点赞排序的前5页都备份了😣
242/757

 
Web3 博客评论区的最终方案

就像短博文里说的那样,使用 giscus 配合 Planet 批量设置评论区还是有一点麻烦的。

其实主要问题是用户可能通过不同的 IPFS 网关访问,这就导致了不管是 URL 还是 pathname 都不可靠。帖子的标题确实可行,但可能出现没有标题的短博文这种情况。

一开始的选择是如果没有标题那么就用 JS 把 og:title 写入成发帖时间,可以实现功能,但会有两个问题,如果后期加上了标题、或者发帖时间被修改(Planet 似乎有一个 bug 是编辑帖子的时候时间有概率会变成现在),而手动设置时间则无法设置“秒”,出现这两种情况的话,之前的评论就不会显示了。

使用标题还有另一个需要处理的问题就是标题本身发生变化的情况。

所以最终还是决定用 JS 将所有文章的 Open Graph Title 全部动态替换成 Post ID(反正读取这玩意的服务都不会去跑 JS),最终代码如下,似乎只能放在 header 的 Custom Code 里才能生效:

适用于 Plain 模板:

<script>
(function() {
  // --- Step 1: Compare og:site_name to the actual page title
  const siteNameTag = document.querySelector('meta[property="og:site_name"]');
  const siteName = siteNameTag ? siteNameTag.getAttribute('content').trim() : '';
  const pageTitle = document.title.trim();

  // --- Step 2: If they differ, update og:title with the last part of the pathname
  if (siteName !== pageTitle) {
    let path = window.location.pathname;
    // Remove trailing slash if any
    if (path.endsWith('/')) {
      path = path.slice(0, -1);
    }
    // Extract the last segment of the path
    const lastPart = path.substring(path.lastIndexOf('/') + 1);

    // Update <meta property="og:title" ...>
    const ogTitleTag = document.querySelector('meta[property="og:title"]');
    if (ogTitleTag) {
      ogTitleTag.setAttribute('content', lastPart);
      console.log(`Updated og:title to "${lastPart}"`);
    }
  }

  // --- Step 3: Create the wrapper <div> elements
  const outerDiv = document.createElement('div');
  outerDiv.style.display = 'flex';
  outerDiv.style.alignItems = 'center';
  outerDiv.style.padding = '0px 20px';

  const innerDiv = document.createElement('div');
  innerDiv.style.flex = '1';
  innerDiv.style.width = '100%';
  innerDiv.style.maxWidth = '700px';
  innerDiv.style.margin = '20px auto';

  // --- Step 4: Load the Giscus script
  // (You could also wrap this in a <div> if desired, as in prior examples)
  const giscusScript = document.createElement('script');
  giscusScript.src = "https://giscus.app/client.js";
  giscusScript.setAttribute('data-repo', "extrawdw-code/blog-giscus");
  giscusScript.setAttribute('data-repo-id', "R_kgDONkfVTg");
  giscusScript.setAttribute('data-category', "General");
  giscusScript.setAttribute('data-category-id', "DIC_kwDONkfVTs4ClpWU");
  giscusScript.setAttribute('data-mapping', "og:title");
  giscusScript.setAttribute('data-strict', "1");
  giscusScript.setAttribute('data-reactions-enabled', "1");
  giscusScript.setAttribute('data-emit-metadata', "0");
  giscusScript.setAttribute('data-input-position', "top");
  giscusScript.setAttribute('data-theme', "preferred_color_scheme");
  giscusScript.setAttribute('data-lang', "en");
  giscusScript.setAttribute('data-loading', "lazy");
  giscusScript.setAttribute('crossorigin', "anonymous");
  giscusScript.async = true;

  // Append script inside the inner div
  innerDiv.appendChild(giscusScript);

  // Then append the inner div to the outer div
  outerDiv.appendChild(innerDiv);

  // Insert script into <head> or near end of <body>
  document.addEventListener('DOMContentLoaded', function() {
    document.body.appendChild(outerDiv);
  });
})();
</script>

适用于 Sepia 模板:

<script>
(function() {
  // --- Step 1: Compare og:site_name to the actual page title
  const siteNameTag = document.querySelector('meta[property="og:site_name"]');
  const siteName = siteNameTag ? siteNameTag.getAttribute('content').trim() : '';
  const pageTitle = document.title.trim();

  // --- Step 2: If they differ, update og:title with the last part of the pathname
  if (siteName !== pageTitle) {
    let path = window.location.pathname;
    // Remove trailing slash if any
    if (path.endsWith('/')) {
      path = path.slice(0, -1);
    }
    // Extract the last segment of the path
    const lastPart = path.substring(path.lastIndexOf('/') + 1);

    // Update <meta property="og:title" ...>
    const ogTitleTag = document.querySelector('meta[property="og:title"]');
    if (ogTitleTag) {
      ogTitleTag.setAttribute('content', lastPart);
      console.log(`Updated og:title to "${lastPart}"`);
    }
  }

  // --- Step 3: Create the wrapper <div> elements
  const outerDiv = document.createElement('div');
  outerDiv.style.display = 'flex';
  outerDiv.style.alignItems = 'center';
  outerDiv.style.padding = '0px 20px';

  const innerDiv = document.createElement('div');
  innerDiv.style.flex = '1';
  innerDiv.style.width = '100%';
  innerDiv.style.maxWidth = '700px';
  innerDiv.style.margin = '20px auto';

  // --- Step 4: Load the Giscus script
  // (You could also wrap this in a <div> if desired, as in prior examples)
  const giscusScript = document.createElement('script');
  giscusScript.src = "https://giscus.app/client.js";
  giscusScript.setAttribute('data-repo', "extrawdw-code/blog-giscus");
  giscusScript.setAttribute('data-repo-id', "R_kgDONkfVTg");
  giscusScript.setAttribute('data-category', "General");
  giscusScript.setAttribute('data-category-id', "DIC_kwDONkfVTs4ClpWU");
  giscusScript.setAttribute('data-mapping', "og:title");
  giscusScript.setAttribute('data-strict', "1");
  giscusScript.setAttribute('data-reactions-enabled', "1");
  giscusScript.setAttribute('data-emit-metadata', "0");
  giscusScript.setAttribute('data-input-position', "top");
  giscusScript.setAttribute('data-theme', "preferred_color_scheme");
  giscusScript.setAttribute('data-lang', "en");
  giscusScript.setAttribute('data-loading', "lazy");
  giscusScript.setAttribute('crossorigin', "anonymous");
  giscusScript.async = true;

  // Append script inside the inner div
  innerDiv.appendChild(giscusScript);

  // Then append the inner div to the outer div
  outerDiv.appendChild(innerDiv);

  // Finally, place this wrapper inside the div with id="main-container"
  document.addEventListener('DOMContentLoaded', function() {
    const container = document.getElementById("main-container");
    if (container) {
      container.appendChild(outerDiv);
    } else {
      console.warn('Could not find a container with id="main-container".');
    }
  });
})();
</script>

外边套的俩 div 是参考的站长的网站设计。

最终效果如下:

Screenshot 2025-01-01 at 14.46.06 Screenshot 2025-01-01 at 14.45.24

在聚合站点的时候,只要打开“重用原始ID”的选项就可以让评论也“同步”过去。

p.s.:Planet 在聚合站点且保留 ID 的情况下,Bug 太多了……经常出现原帖被当成聚合过来的帖子,然后无法编辑需要重启的情况。

 

给没有标题的微帖子弄了下评论,会自动将评论时间设置为 Open Graph 标题让 giscus,并为 Sepia 主题做了一些优化:

<script>
(function() {
  // Step 1: Check if the <title> element is empty
  const pageTitle = document.title.trim();
  if (pageTitle.length === 0) {
    const metaPublishedTime = document.querySelector('meta[property="article:published_time"]');
    if (metaPublishedTime) {
      const publishedTimeValue = metaPublishedTime.getAttribute('content');
      
      // Update the og:title meta tag
      const ogTitleTag = document.querySelector('meta[property="og:title"]');
      if (ogTitleTag) {
        const newTitle = `Post on ${publishedTimeValue}`;
        ogTitleTag.setAttribute('content', newTitle);

        // Log the updated title
        console.log('Updated OG title:', newTitle);
      }
    }
  }

  // Step 2: Create the wrapper <div> elements
  const outerDiv = document.createElement('div');
  outerDiv.style.display = 'flex';
  outerDiv.style.alignItems = 'center';
  outerDiv.style.padding = '0px 20px';

  const innerDiv = document.createElement('div');
  innerDiv.style.flex = '1';
  innerDiv.style.width = '100%';
  innerDiv.style.maxWidth = '700px';
  innerDiv.style.margin = '20px auto';

  // Step 3: Create the Giscus script element
  const giscusScript = document.createElement('script');
  giscusScript.src = "https://giscus.app/client.js";
  giscusScript.setAttribute('data-repo', "extrawdw-code/microblog-giscus");
  giscusScript.setAttribute('data-repo-id', "R_kgDONkstKg");
  giscusScript.setAttribute('data-category', "General");
  giscusScript.setAttribute('data-category-id', "DIC_kwDONkstKs4ClqCg");
  giscusScript.setAttribute('data-mapping', "og:title");
  giscusScript.setAttribute('data-strict', "1");
  giscusScript.setAttribute('data-reactions-enabled', "1");
  giscusScript.setAttribute('data-emit-metadata', "0");
  giscusScript.setAttribute('data-input-position', "top");
  giscusScript.setAttribute('data-theme', "preferred_color_scheme");
  giscusScript.setAttribute('data-lang', "en");
  giscusScript.setAttribute('data-loading', "lazy");
  giscusScript.setAttribute('crossorigin', "anonymous");
  giscusScript.async = true;

  // Append script inside the inner div
  innerDiv.appendChild(giscusScript);

  // Then append the inner div to the outer div
  outerDiv.appendChild(innerDiv);

  // Finally, place this wrapper inside the div with id="container"
  document.addEventListener('DOMContentLoaded', function() {
    const container = document.getElementById("main-container");
    if (container) {
      container.appendChild(outerDiv);
    } else {
      console.warn('Could not find a container with id="container".');
    }
  });
})();
</script>
 

似乎发现了 Planet 的一个 bug:如果被聚合的博客发生了更新,Sepia 主题生成的首页里的正文并不会被更新,手动重建或完全重建也不行,必须要重新启动 Planet 后再重建才会更新。

编辑:而且标签的修改似乎不会在聚合的时候同步。

 

目前会将多个设备的微型博客聚合在一起,也就是这里

 

Planet: ipns://k51qzi5uqu5dlygiqo7ib0tpdm8t4spn6w1su6b8o6zwhax7jwu2qkt2x7avg4

 

Planet: ipns://k51qzi5uqu5dm3nnu5exl810kts24sqeh4xmis7jpsf0iiml77ysg61cpv4n36

 

在笔记本上创建了一个 Planet 并且将其聚合到位于 Mac mini 的“主”微博 Planet。

Planet: ipns://k51qzi5uqu5dkd1qdqw2dyr5hry9wfuxhy11xltnif380ismqoyahvj27oyzgt

 
Commenting is Live!

Powered by giscus.

Prev
Page 2 of 4
Next