Latest Learning

Stuff I learned recently.

kitty 默认不支持 Fcitx 的输入,但是在 fctix5 下可以通过使用命令 GLFW_IM_MODULE=ibus kitty 启用的 kitty 来输入中文。

链接:https://github.com/kovidgoyal/kitty/issues/5549#issuecomment-1264867941

一直不太明白为什么会有 “月背” 这个概念,心里想着:难道月亮会有一面一直在背面?

查了下,确实是这样,由于 潮汐锁定 的原因,月亮公转和自转的周期是一致的,在地球看来,其实就是一直一个面对着。但是这不代表背面没有阳光,只是相对于地球而已。

这个是用于 Nano Banana 的 prompt. 来源 linuxdo

{
  "task": "portrait_restoration",
  "language": "zh-CN",
  "prompt": {
    "subject": {
      "type": "human_portrait",
      "identity_fidelity": "match_uploaded_face_100_percent",
      "no_facial_modification": true,
      "expression": "natural",
      "eye_detail": "sharp_clear",
      "skin_texture": "ultra_realistic",
      "hair_detail": "natural_individual_strands",
      "fabric_detail": "rich_high_frequency_detail"
    },
    "lighting": {
      "exposure": "bright_clear",
      "style": "soft_studio_light",
      "brightness_balance": "even",
      "specular_highlights": "natural_on_face_and_eyes",
      "shadow_transition": "smooth_gradual"
    },
    "image_quality": {
      "resolution": "8k",
      "clarity": "high",
      "noise": "clean_low",
      "artifacts": "none",
      "over_smoothing": "none"
    },
    "optics": {
      "camera_style": "full_frame_dslr",
      "lens": "85mm",
      "aperture": "f/1.8",
      "depth_of_field": "soft_shallow",
      "bokeh": "smooth_natural"
    },
    "background": {
      "style": "clean_elegant",
      "distraction_free": true,
      "tone": "neutral"
    },
    "color_grading": {
      "style": "cinematic",
      "saturation": "rich_but_natural",
      "white_balance": "accurate",
      "skin_tone": "natural_true_to_subject"
    },
    "style_constraints": {
      "no_cartoon": true,
      "no_beauty_filter": true,
      "no_plastic_skin": true,
      "no_face_reshaping": true,
      "no_ai_face_swap": true
    }
  },
  "negative_prompt": [
    "cartoon",
    "anime",
    "cgi",
    "painterly",
    "plastic skin",
    "over-smoothing",
    "over-sharpening halos",
    "heavy skin retouching",
    "face reshaping",
    "identity drift",
    "face swap",
    "beauty filter",
    "uncanny",
    "washed out",
    "color cast",
    "blown highlights",
    "crushed shadows",
    "banding",
    "jpeg artifacts",
    "extra fingers",
    "deformed eyes",
    "asymmetrical face",
    "warped features"
  ],
  "parameters": {
    "fidelity_priority": "identity",
    "detail_priority": "eyes_skin_hair_fabric",
    "realism_strength": 0.95,
    "sharpening": "micro_contrast_only",
    "skin_retention": "keep_pores_and_microtexture",
    "recommended_denoise": "low_to_medium"
  }
}

git clonegit fetch 的时候,git 会在本地创建一些”快照”,记录远程仓库的最新状态,但这些不是真正的分支,当远端的 branch 删除之后,本地还会留着。

解决方法 1

git fetch --prune

解决方法 2

直接配置全局的 gitconfig 即可:

git config --global fetch.prune true

获取远端分支

Fetch the latest changes from the default remote upstream repository (if set)

git fetch

查看所有分支

List all branches (local and remote; the current branch is highlighted by *):

git branch --all

删除远端分支

git push origin --delete <branch_name>

删除本地分支

git branch -d <branch_name>

direnv 配合 rbw 平常用起来很好用,还不用担心密钥硬编码到代码中泄露。

export TF_VAR_ntfy_token=$(rbw get ntfy_github_action_token)
export TF_VAR_gmail_token=$(rbw get gmail_github_action_token)

⚠️ 重要注意

我在 macos 下配合 rbw 会有很大延迟 (解锁之后使用 rbw get 有时候会有接近 10s 的延迟),我研究发现是因为 rbw 的获取 ttyname() 有性能问题。

请在 .zshrc 中添加以下环境变量来解决这个问题:

export RBW_TTY=$(tty)

配置后响应时间可缩短到 1 秒内。

相关:修复 macos 下使用 rbw 获取密钥卡顿]

一个 curl 请求的例子:

curl -X POST 'https://api.github.com/repos/zhaochunqi/til-pages/dispatches' \
  --header 'Content-Type: application/json' \
  --header 'Accept: application/vnd.github.v3+json' \
  --header 'Authorization: Bearer github_pat_xxxxx' \
  --header 'X-GitHub-Api-Version: 2022-11-28' \
  --data '{"event_type": "til-updated"}'

其中 github_pat_xxxxx 是 github 的 token,可以在 github token 页面生成。使用 fine-grained token, token 权限需要有 Contents: Read and write.

til-updated 是 github action 的事件类型,可以在 github action 的配置文件中定义。

on:
  repository_dispatch:
    types: [til-updated]

这样就可以通过 curl 请求触发 github action 了。

使用命令 source_env 可以在当前目录的 .envrc 文件中引用其他目录的 .envrc 文件。

使用具体情况可参考:

目录如下:
 tree -al A
drwxr-xr-x@  - zhaochunqi 14 Dec 15:02 A
.rw-r--r--@ 56 zhaochunqi 14 Dec 15:02 ├── .envrc
drwxr-xr-x@  - zhaochunqi 14 Dec 15:02 └── B
.rw-r--r--@ 57 zhaochunqi 14 Dec 15:02     └── .envrc

A/.envrc 文件内容如下:

export A="this is A"
export B="this is B from A folder"

A/B/.enrc 文件内容如下:

source_env ../.envrc
export B="This is B from B folder"

在 A 目录下执行 direnv allow 后,进入 B 目录,执行 direnv allow 后,可以看到如下输出:

Desktop/A/B 
 echo $A
this is A

Desktop/A/B 
 echo $B
This is B from B folder

可以看到,在 B 目录下,可以访问到 A 目录下的环境变量,并且 B 目录下的环境变量覆盖了 A 目录下的环境变量。这正是我们想要的。

使用 https://github.com/marketplace/actions/create-pull-request 的时候遇到无法创建 pr 的问题,需要做如下配置:

1. 检查仓库设置

请访问:如:https://github.com/zhaochunqi/dns/settings/actions (替换成你自己的) 找到 “Workflow permissions” 部分,确保:

  • ✅ 选择 “Read and write permissions”
  • ✅ 勾选 “Allow GitHub Actions to create and approve pull requests”

2. workflow 中添加

permissions:
  contents: write
  pull-requests: write
  1. 需要一个 Discord 的 Webhook 地址,可以通过在 Discord 的频道中创建一个 Webhook 来获取。如:https://discord.com/api/webhooks/1111111111111/xxxxxxxxxxxxxxxxxxxxxxxxxxxx
  2. 需要安装 webhook 插件,在 Jellyfin 的插件商店中搜索 webhook 即可找到。

配置方法:

勾选你要的 play 的一些事件,然后填写你的 Webhook 地址,然后在 template 处添加:

{
    "content": "{{MentionType}}",
    "avatar_url": "{{ServerUrl}}/Users/{{UserId}}/Images/Primary",
    "username": "{{NotificationUsername}}",
    "embeds": [
        {
            "author": {
                {{#if_equals ItemType 'Episode'}}
                    "name": "Playback Started • {{{SeriesName}}} S{{SeasonNumber00}}E{{EpisodeNumber00}} ~ {{{Name}}}",
                {{else}}
                    "name": "Playback Started • {{{Name}}} ({{Year}})",
                {{/if_equals}}

                "url": "{{ServerUrl}}/web/#/details?id={{ItemId}}&serverId={{ServerId}}"
            },
            
            "thumbnail":{
                "url": "{{ServerUrl}}/Items/{{ItemId}}/Images/Primary"
            },

            "description": "> {{{Overview}}}\n\n``[{{PlaybackPosition}}/{{RunTime}}]``",

            "color": "3394611",

            "footer": {
                "text": "{{{ServerName}}}",
                "icon_url": "{{AvatarUrl}}"
            },

            "timestamp": "{{Timestamp}}"
        }
    ]
}

随便播放一个视频,你可以看到 Discord 频道中有消息了。如果没有成功,记得到 Jellyfin 的日志中查看错误信息。(不要随便勾选一些事件或者忽略 template 之类的选项)

Traefik 底层使用的是 lego 库来处理 ACME (Let’s Encrypt) 协议。在标准的 DNS-01 验证流程中,Traefik 会严格遵循 “创建 -> 验证 -> 清理” 的生命周期。所以如果有 _acme-challenge 之类的 dns 记录存在,除非正在签发过程中,否则是可以删除掉的。

签发流程:LIVE EDITOR

flowchart TD
    Start["开始 DNS-01 挑战"]
    
    Start --> GetInfo["获取挑战信息<br/>GetChallengeInfo()"]
    GetInfo --> CNAMECheck{"检查 CNAME"}
    
    CNAMECheck -->|有 CNAME| FollowCNAME["跟随 CNAME 链<br/>getChallengeFQDN()"]
    CNAMECheck -->|无 CNAME| UseFQDN["使用原始 FQDN"]
    
    FollowCNAME --> EffectiveFQDN["获得 EffectiveFQDN"]
    UseFQDN --> EffectiveFQDN
    
    EffectiveFQDN --> Present["创建 TXT 记录<br/>Present()"]
    
    Present --> ProviderCheck{"DNS 提供商类型"}
    
    ProviderCheck -->|标准提供商| StandardProvider["标准 DNS 提供商<br/>直接创建 TXT 记录"]
    ProviderCheck -->|ACME-DNS| ACMEDNSProvider["ACME-DNS 提供商"]
    
    ACMEDNSProvider --> AccountCheck{"检查账户"}
    AccountCheck -->|账户存在| UpdateTXT["更新 TXT 记录"]
    AccountCheck -->|账户不存在| CreateAccount["创建新账户"]
    
    CreateAccount --> CNAMERequired["返回 ErrCNAMERequired<br/>需要手动创建 CNAME"]
    CNAMERequired --> ManualCNAME["手动创建 CNAME 记录"]
    ManualCNAME --> UpdateTXT
    
    StandardProvider --> Propagation["等待 DNS 传播"]
    UpdateTXT --> Propagation
    
    Propagation --> Polling["轮询检查<br/>wait.For()"]
    Polling --> Validate{"验证成功?"}
    
    Validate -->|是| CertIssued["证书签发成功"]
    Validate -->|否| Timeout{"超时?"}
    
    Timeout -->|是| Error["签发失败"]
    Timeout -->|否| Polling
    
    CertIssued --> Cleanup["清理 DNS 记录<br/>CleanUp()"]
    Error --> Cleanup
    
    Cleanup --> DeleteTXT["删除 TXT 记录"]
    DeleteTXT --> End["流程结束"]
    
    %% 样式
    classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px
    classDef process fill:#e1f5fe,stroke:#01579b,stroke-width:2px
    classDef decision fill:#fff3e0,stroke:#e65100,stroke-width:2px
    classDef error fill:#ffebee,stroke:#c62828,stroke-width:2px
    classDef success fill:#e8f5e8,stroke:#2e7d32,stroke-width:2px
    
    class GetInfo,FollowCNAME,UseFQDN,EffectiveFQDN,Present,StandardProvider,UpdateTXT,Propagation,Polling,Cleanup,DeleteTXT process
    class CNAMECheck,ProviderCheck,AccountCheck,Validate,Timeout decision
    class CNAMERequired,ManualCNAME,Error error
    class CertIssued,End success

nixos 更新 flake

flakes 的设计初衷是“重现性”(Reproducibility),而不是“实时性”。

获取最新的分支构建信息

# 只更新 nixpkgs 这个 input
nix flake update nixpkgs

# 或者更新所有 inputs
nix flake update

注意,建议更新所有 inputs,不然可能会出现 nixpkgs 和 home-manager 版本不一致的问题