阳光开朗马乙己

Can't solve the problem? Solve the person who raises the problem! Write English blogs in the future.

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-26-21-36-56-kongyiji/

求和!李姐万岁!用ChatGPT写GitBook布局锤子便签配色的WordPress主题

我早期在Github写《Chrome插件英雄榜》连载的时候,用的是GitBook的自动构建功能,也就是在Github仓库,按照一定的规范存储markdown格式文章和配置文件,GitBook就会自动构建一本书,供读者阅读。

GitBook阅读体验确实不错,在PC版,左侧是目录,右侧是正文内容,点击左侧目录,就可以切换右侧的正文内容,在移动版,目录则收到一个抽屉布局中,点击左上角图标可以唤出抽屉,点击抽屉里的目录,可以切换主屏幕的内容

后来,GitBook开源版不再更新,开始专注商业付费版(限制存储空间),我于是开始寻找免费的替代品。最终选择了WordPress

WordPress是一个很成功的产品,2003年发布至今,实现了开源与商业化的平衡,免费版一直更新,成就了丰富的插件以及主题生态,开发者们可以通过开发WordPress插件主题,获取收益,也可以用爱发电,发布免费的主题和插件,由于WordPress代码开源,自然也没有类似苹果税的概念

世界上三分之一的网站都由WordPress构建,WordPress支持完整强大的后台管理,支持评论功能,支持全站搜索,搜索引擎都会对WordPress网站做优化,网站SEO变得简单!垃圾评论过滤,评论邮件提醒,网站缓存优化,Google广告接入,提供Rss订阅等常见功能,都能通过免费稳定的插件轻松获取

既要又要是人类的本性,我切换到WordPress后,又开始想念GitBook优秀的布局设计,同时又想要锤子便签一样舒适的配色阅读体验,但没有找到现成的主题,于是我打算自己写一个,但WordPress主题需要用到PHP语法,于是我让ChatGPT帮忙写PHP,ChatGPT写PHP很优秀,活儿好不粘人,让我有了做甲方的感觉

WordPress PHP

主题写完了初版,主题暂定名称为《求和!李姐万岁! GitBook For WordPress》目前已经发布到 https://fangyuanxiaozhan.com (方圆小站)运行使用,方圆小站完全由白嫖的Github Actions 运行时进行管理,管理脚本开源地址 https://github.com/zhaoolee/WordPressXMLRPCTools 脚本的目的是用Hexo的方式管理WordPress「使用Github Actions自动更新文章到WordPress」

主题

主题封面图

screenshot

效果演示

  • 宽窄屏自适应

Gitbook

如果你们的重点放在蒂法上,来这里 https://fangyuanxiaozhan.com/p/2023-01-08-13-50-22-ff7/ 服务器带宽有限,图片加载稍慢,可能需要多等一会儿(如果有便宜带宽的服务器推荐,评论区可以推荐一波)

  • 支持搜索

支持搜索

(我觉得爱丽丝建模真不错,ff7重制版第二弹2023年赶快出!)

关于主题《求和!李姐万岁! GitBook For WordPress》

主题开源在Github: https://github.com/zhaoolee/gitbook-for-wordpress

  • 侧边栏按时间倒序显示已发布文章
  • 目录切换文章,侧边栏自动将当前文章滚动到侧边栏顶部
  • 移动端与PC端自适应布局
  • 支持评论
  • 支持搜索
  • 底部预留备案号位置

后续计划的更新

  • 支持按照专题自动生成多级目录
  • 持续打磨样式,优化代码结构
  • 写一份WordPress免费插件推荐列表

不要因为走的太远,就忘了当初为什么出发

不要因为走的太远-就忘了当初为什么出发

写博客最大的乐趣在于分享,博客应该是:有趣想法生成器,个人项目分享器,优质内容发射器;而不是废话连篇生成器,广告生成器,带货生成器...

在2023年,为WordPress写主题,让个人独立博客更易读易用,看起来是性价比很低的事,但按照我的折腾经验,在个人域名写独立博客,比内容平台发内容要爽的多,因为可以写想写的内容,随时向互联网发布自己的观点,而不是今天发布的内容可见,明天可能就变成知识的荒原

《求和!李姐万岁! GitBook For WordPress》主题用了罗老师的头像做素材,最后放一句罗老师的上古语录:希望那些喜欢用 「枪打出头鸟」 这样的道理教训年轻人,并且因此觉得自己很「成熟」的中国人有一天能够明白这样一个事实: 有的鸟来到世间,是为了做它认为正确的事,而不是专门躲枪子儿的。如果没被干掉就继续彪悍嚣张下去,如果被干掉了老子就认了

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-26-13-04-25-gitbook-for-wordpress/

在独立域名持续创作博客,是最简单的长线投资

我很喜欢看博客, 尤其是兴趣使然的独立博主写的博客, 博客是很好的灵感来源。比如我看到《大数据已死》这篇文章, 就会了解到通过分离存储和计算, 大数据作为单一问题就不存在了,变成了海量存储和大型计算两个问题, 而且这两个问题各自都能通过独立扩展,进行解决。

我很喜欢写博客, 因为博客能促进人思考, 每天上班工作, 如果没有写博客的习惯, 很容易就会被工作所淹没,工作中的思考也很难被记录下来。

博客比书籍发布内容更快,而且是免费的! 有些领域变化非常快,在有人写书之前,博客有时是唯一的信息来源。Stable diffusion 模型出现后的第二天,人们就已经在写博客了,书籍永远不会那么快。而书籍和论文则被锁定在付费墙之后, 加之自媒体经济产生大量垃圾书籍, 买书像是抽盲盒。

持续创作博客是最简单的长期投资,我2016年开始在简书写博客,用免费开源的WordPress做个人网站,在Github更新各种个人开源项目,这些时间如果用来玩游戏,刷短视频,也便荒废掉了,写(技术)博客则是把时间储蓄了起来,提升专业水平,帮助一些人,也收获一些朋友。

实践比转发更有乐趣,2023年3月,各种非人非狗的媒体为了流量,在它人的苦难面前,开始自我治愈,还开始调侃鲁迅先生笔下的孔乙己,如果鲁迅先生还拿的动笔,肯定要提笔锤爆这群标榜中肯的无良媒体,有人在转发反驳的观点,但我感觉还是亲自骂一骂才过瘾,亲自骂一骂才能有更多的语料,为无良媒体的早日倒闭丢一块飞砖。

水滴石穿,为未来做准备,内容平台自我阉割的越来越厉害,中文互联网就变得只剩下一种声音,如果想发出不同的声音,请准备一个独立的域名,独立域名的内容可以被搜索引擎抓取,随着域名年龄的增长,上传内容的增多,自己认可的声音,也可以通过古老的域名向互联网布道,优质的域名,本身是资产。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-18-15-27-38-read-book/

程序员学哪一门语言更不容易失业

今天,大学室友微信群在聊一个很经典的话题,程序员学哪一门语言更不容易失业

有人认为PHP已经到了黄昏,有人认为Go语言可以和Java掰一下手腕,有人认为没有什么是一行sql解决不了的,有人认为 Python和Java永远是主流,能干到头秃… (有研究表明,程序员与秃头并没有太大的相关性,研究并不一定准)

我的观点是,javascript和 Node.js配合,更不容易失业,JS这门语言应用极为广泛,几乎什么都能做,Web小程序(React),App开发(React Native),桌面应用(Electron)都可以用js写,是万金油一般的存在。

JS这门语言易上手,上限很高,从业者众多,依赖包生态也极为丰富,神库众多,即使你的水平一般,也能借助各种神库,写出健康的代码,保持健康的发量

JS深度绑定Web生态,JS是Web生态的基石,Web是互联网的基石,互联网技术越发展,JS的内容层次就越丰富,同时也意味着,JS程序员要不断学习,才不会被后浪拍在沙滩上,说穿了,想要不失业,就要不断学习

JS是最接近前端的语言,前端是最接近用户的,如果想要证明自己的编程实力,可以自己搞开源项目,而JS很适合搞开源项目,一个周末写个油猴子增强插件不是梦~

在2023年,很多人在喊前端已死,我认为初级水平的前端可以被机器取代,但JS程序的基数极为庞大,如果拥有对JS程序调优的能力,那就不容易失业,如果能用ChatGPT这类工具提升开发效率,那反而会让我们的工作更轻松。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-24-25-js/

摄影天然适合程序员

程序员的脑力劳动远大于体力劳动,写个人博客是很好的爱好,但脑力不足的时候,摄影是程序员天然的生活调味剂。

  • 摄影增加运动量,提升程序员的体力,多走多拍才有好照片,摄影给久坐的程序员一个锻炼的机会,努力锻炼,保持健康,活得久比什么都重要。

  • 摄影教会程序员做减法,提升程序员审美,微软的程序大多功能丰富,毫无设计感,而好的摄影作品讲求明确主体,突出主题,简化画面,懂得做减法的程序员能前往更高的境界。

  • 摄影扩大程序员折腾的范围,找到更多可玩的领域,Adobe全家桶,相机raw解码软硬件,照片原片的存储备份,不同焦段原副厂镜头的选购,走山访海旅行计划的制定,游戏摄影配套插件工具的优化,都能扩大程序员的折腾范围,这些恰好都和程序相关。

  • 摄影是一门下限很低,上限极高的学科,如果一门知识的上限很低,便不可持续,而摄影的上限很高,即使到了70岁,我们只要出门打开取景器,就可能拍出比以往作品都更好的照片,持续向上发展的兴趣,能给程序员更好的人生体验。

  • 摄影容易交到朋友,扩大程序员的社交范围,程序员大量的时间都被工作占据,交朋友的时间很少,而摄影这项爱好,能让我们通过同城摄影群,交到各行各业的朋友。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-11-43-programmer-photography/

我为什么喜欢用锤子便签

锤子便签配色舒服,适合阅读,锤子便签用户界面一直是暖色,背景与文字的配色都很舒服,无论是创作者还是阅读者,都有很好的观感。

锤子便签免费且没有广告,锤子便签没有搞订阅制,也没有广告,属于真正小而美的软件。

锤子便签有Web版!我认为一个工具良不良心,支持web是很重要的指标,支持web就意味着可以在任何可以安装浏览器的设备使用,即使你是Linux用户。

锤子便签支持多端同步,无论是安卓,iOS,还是PC web版都能顺利同步进度,对于拥有碎片化时间的人,我们可以在床上用iPhone或安卓手机写,起床后可以用PC或Mac接着写。

锤子便签生成的图片分辨率很不错,锤子便签生成的图片适合发布在各种社交媒体,文字不失真,排版工整细致,图片适合阅读,也方便下载存档。

锤子便签默认字体很周正,适合发正式的通知,非衬线字体适合发通知,锤子便签字体很适合发布通知内容。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-03-16-16-04-56-smartisan-notes/

建议Apple推出新表带:你大爷永远是你大爷!公园唱歌老大爷才是Apple Watch的核心用户

在深圳莲花山公园闲逛,遇到一位老大爷唱歌,周围很多阿姨围观,仔细观察,发现老大爷的手表是Apple Watch!

深圳莲花山公园Apple Watch老大爷其一

深圳莲花山公园Apple Watch老大爷其二

老大爷或许才是Apple Watch的核心用户,关注自身健康,喜欢手表,退休金充裕,配合iPad 可以组个K歌全家桶,而且Apple Watch 还支持电子木鱼App,没事可以敲两下,功德加一

建议库克出个老大爷专属表带,表带名为:「你大爷永远是你大爷」(手动狗头)

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-23-12-51-18-apple-watch/

独立博客永不为奴

2023年2月,微信公众号图文推送样式,逐渐向小红书看齐,于是我体验了一下小红书的发文功能。

总体来说,小红书发文体验比公众号编辑器好很多,公众号编辑器,无论是网页版还是app版,体验都很烂,外链图片经常转存失败,图片转存失败后,其余内容也强制无法保存。

微信公众号目前的问题

新申请的公众号一律没有评论功能,没有评论,就无法建立创作者与读者之间的交流

推送倾向展示量大而多的公众号,一些追求品质的年更月更创作者,无法将内容传递给粉丝

公众号审核规则不透明,每个平台的审核规则都不透明,小红书也是如此,我在小红书昵称定为老法师昭昭都被判定违规,想要完整表达自己的观点,还是得有自己的域名,独立博客永不为奴

公众号内容生态完全封闭,创作者无法向广阔的互联网展示自己的内容,用人话说,就是内容再好,别人也搜不到。

公众号已发布的内容无法修改(准确说,只能修改正文的几个字),配合无评论功能的限制,内容一旦发布,即使发现了严重错误,也无法修改,只能删除,而公众号每天还有群发限制,及时改错的想法基本凉凉… 小红书在这方面就做的很好,甚至可以修改封面图!

小红书用起来不爽的几个点

小红书完全不支持外链,小红书将个人博客的外链视为引流违规行为,所以小红书无法做连续的合集内容,只能做碎片化的内容。

小红书的审核规则很随意,一张图放到推文内容中可以,但设置为个人页背景封面就判定违规。

小红书会ban掉海外IP访问,国内创作的内容,无论是什么语种的内容,都只能自产自销,有点无聊…

独立博客永不为奴

我认为,能把自己的想法完整表达出来,并传播出去,应该是创作者的基本权利,而内容上了公共平台,能不能发,能发哪一部分,就由不得创作者了

创作者利用公共平台,放大自己的影响力,而公共平台也在驯化创作者,最后创作者变成了不愿思考,只研究流量规则的自媒体。

上周,阮一峰老师的博客,受到了入侵,恢复内容用了两三天;我的个人博客(文末)最近也不断收到大量的垃圾评论,长期消耗本就不富裕的服务器资源。

个人独立博客越来越难做,但也越来越有吸引力,当所有平台都在捂创作者的嘴时,能有一个名为个人独立博客的方式,还能允许我自由表达,如同黑屋子开了一扇窗,我会感到很欣慰,独立博客永不为奴!

兽人永不为奴

微信公众号创造了内容孤岛,ChatGPT这类产品,会是将孤岛连接到开放互联网的航路。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-23-12-30-38-blog/

ChatGPT是一个理解自然语言的工具箱

ChatGPT的话题在2023年2月格外火热,以聊天对话的形式,为人类提供大量的专业知识。

万能的神ChatGPT

ChatGPT 擅长产出符合逻辑的答案,人类的逻辑能力其实并不好。作为一个开发工程师,我发现代码80%的BUG,都是程序逻辑有问题,即使是常年写码的工程师,也会写出逻辑有问题的程序,ChatGPT非常适合排查代码片段,辅助工程师写出逻辑正确的代码,在这方面, ChatGPT最大的竞品是Github Copilot

Github Copilot

ChatGPT拟人化的问答模式,非常适合当老师。学会一门知识,本身是枯燥的,如果把知识转换为ChatGPT问答的形式,将会极大提升课堂的趣味性,玩过RPG游戏的人,要进行大量的问答,这些问答往往是几个固定的问题,再给几个固定的选项,如果将知识转换为RPG游戏的形式,并给予极大的问答自由度,学生就变成了玩家。

ChatGPT适合仿制3A游戏,3A游戏需要大量的人力,海量的资金投入,巨长的开发周期;引入ChatGPT,游戏开发者只需定义玩法,ChatGPT就可以生成中规中矩的罐头游戏,罐头游戏并非贬义词,市面上绝大多数游戏都是没什么特色的罐头游戏,ChatGPT能生成罐头游戏,反而让开发者们,更有时间去研究特色玩法。

ChatGPT适合生成产品发布会,因为发布会的套路都是固定的;ChantGPT也适合做直播,因为直播的套路也是固定的;ChatGPT最适合做的是公务员,我们一直谈法制,但不好搞,ChatGPT代替法官来判案,代替律师来辩护,会让罪与罚更容易一一对应。

ChatGPT 会员终于开放了,支持万事达,Visa,每月20美元,开通后有两个模型可选,开通会员后,会默认使用提升回答速度的版本,当然也可以选择普通速度的Legacy版本。

ChatGPT会员可选两个模型

买ChatGPT PLUS会员并不容易,需要用海外信用卡支付,我办了Depay的海外万事达卡,特色是支持USDT充值,如果50美元开卡,可以免月租;如果需要海外信用卡,可以通过我的邀请链接开卡 https://depay.depay.one/web-app/register-h5?invitCode=620375&lang=zh-cn

ChatGPT非常适合写脚本,但小概率会出现类型错误,变量名的语义和实际进行的操作产生了误差(命名不规范坑人也坑ChatGPT)

ChatGPT生成代码错误

ChatGPT可以帮忙写很多前端样式,对汉语描述的理解非常到位,我们还可以不断追加要求,要求ChatGPT对代码进行改写,真的是理想的乙方

ChatGPT写样式

ChatGPT改写代码

让ChatGPT用Node.js写一个同步脚本

  • 输入需求
写一个基于rsync命令同步服务器目录(比如 /opt)到本地目录(比如 ~/cloud-backup/ )的Node.js每日定时备份脚本;

支持配置登陆用户, 和登录服务器信息, 服务器IP, 登录端口, 登录用户, 无需配置密码, 默认使用ssh key登录;

每天的备份目录用YYYY-MM-DD日期格式命名,如果从服务器同步的文件夹为 `/opt/` , 则在本地的存放位置为 `${用户目录}/cloud-backup/YYYY-MM-DD/opt/` ,传输速度限制为每秒100KB,如果同步失败, 则1分钟后自动重试, 只保留最近14天的备份, 过期的备份自动删除;

如果本地文件夹不存在,则自动创建;

同步过程中, 打印同步文件进度的log; log同步输出到脚本同级目录下的log.txt文件, log.txt只保存最近14天的log, 过期的log自动删除;

将功能点细分为函数, 便于后续扩展;

列出以上脚本依赖包相关的 package.json

我需要使用pm2守护运行这个脚本,请给出pm2凌晨2点25分运行脚本的方法

ChatGPT输出代码

const { exec } = require("child_process");
const { format } = require("date-fns");
const fs = require("fs");
const path = require("path");
const { promisify } = require("util");

const execAsync = promisify(exec);

const SSH_KEY_PATH = process.env.SSH_KEY_PATH || "~/.ssh/id_rsa";
const SYNC_FOLDER = "/opt";
const BACKUP_FOLDER = `${process.env.HOME}/cloud-backup`;

const SSH_CONFIG = {
  host: "example.com",
  port: 22,
  username: "example",
};

const MAX_SPEED = 100; // KB/s
const RETRY_INTERVAL = 60 * 1000; // 1 minute
const MAX_BACKUPS = 14;

const now = new Date();
const backupFolderName = format(now, "yyyy-MM-dd");
const backupFolderPath = path.join(BACKUP_FOLDER, backupFolderName);
const logFilePath = path.join(__dirname, "log.txt");

async function syncWithRetry() {
  let success = false;
  while (!success) {
    try {
      await sync();
      success = true;
    } catch (err) {
      console.error(err);
      console.log(`Sync failed, retrying in ${RETRY_INTERVAL / 1000} seconds...`);
      await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
    }
  }
}

async function sync() {
  const command = `rsync -a --progress --max-size=${MAX_SPEED}K --delete -e "ssh -i ${SSH_KEY_PATH}" ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} ${backupFolderPath}`;
  console.log(`Syncing ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} to ${backupFolderPath}...`);
  await execAsync(command);
  console.log("Sync finished.");
}

async function removeExpiredBackups() {
  const backupFolders = await fs.promises.readdir(BACKUP_FOLDER);
  const expiredBackups = backupFolders
    .filter((folder) => folder !== backupFolderName)
    .sort()
    .slice(0, -MAX_BACKUPS);
  await Promise.all(
    expiredBackups.map((folder) =>
      fs.promises.rm(path.join(BACKUP_FOLDER, folder), { recursive: true, force: true })
    )
  );
}

async function removeExpiredLogs() {
  const logs = await fs.promises.readdir(__dirname);
  const expiredLogs = logs
    .filter((log) => log.endsWith(".log") && log !== `${backupFolderName}.log`)
    .sort()
    .slice(0, -MAX_BACKUPS);
  await Promise.all(expiredLogs.map((log) => fs.promises.rm(path.join(__dirname, log))));
}

async function createBackupFolder() {
  try {
    await fs.promises.mkdir(backupFolderPath, { recursive: true });
    console.log(`Created backup folder: ${backupFolderPath}`);
  } catch (err) {
    if (err.code !== "EEXIST") {
      throw err;
    }
  }
}

async function main() {
  await createBackupFolder();
  await syncWithRetry();
  await removeExpiredBackups();
  await removeExpiredLogs();

  const logText = `Synced ${SSH_CONFIG.username}@${SSH_CONFIG.host}:${SYNC_FOLDER} to ${backupFolderPath} at ${new Date().toISOString()}\n`;
  await fs.promises.appendFile(logFilePath, logText);
}

main().catch((err) => console.error(err));

如果输出中断,我们可以要求ChatGPT继续上次的输出,而不用重新生成

继续输出

内容输出

然而,ChatGPT 还是漏了package.json的输出,我们可以要求ChatGPT对package.json内容重新输出

image-20230219152951399

前面我们明确要求了ChatGPT进行函数式编程,如果我们需要优化某个函数的输出,可以直接让ChatGPT继续修改

继续修改

运行ChatGPT修改后的脚本

运行结果

修改后的脚本可以顺利完成同步任务,由于rsync可以自动跳过已同步的文件,当天,多次运行同步脚本,也可以快速进行增量同步。

让ChatGPT推荐一些WordPress主题

WordPress主题推荐

如果我们有自己的WordPress网站,个人服务器带宽有限,首屏打开速度不理想,也可以让ChatGPT给出一些轻量化主题推荐

小结

2023年,用中文在搜索引擎(Google, Bing, baidu)查点儿东西(凯恩斯陷阱),大概率都会指向知乎,但知乎产品又做的非常粪坑,强迫用户装App, App各种无厘头的弹窗广告,搞的推荐和热榜话题简直是兢兢业业的给用户喂shi

凯恩斯陷阱

ChatGPT确实可以当搜索引擎来用,用中文问内容,几乎是有问必答,而且干净无废话,不懂还可以追问,一言以蔽之,搜索引擎本身也不生产内容,和ChatGPT一样,都是内容的搬运工,但ChatGPT和搜索引擎的用户体验简直是天壤之别,而且ChatGPT还可以通过加入新数据,不断成长,搜索引擎确实应该努努力了,一个无法持续优化的搜索引擎,是无法和ChatGPT竞争的。

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-12-11-51-20-chatgpt-tools/

zhaoole推荐值得玩的主机游戏

塞尔达旷野之息

异度神剑2

异度神剑3

女神异闻录5皇家版

最终幻想7重置版

本文永久更新地址:

https://fangyuanxiaozhan.com/p/2023-02-12-11-23-42-game/