普通视图

Received yesterday — 2025年6月16日

2025年3款免费开源虚拟物品自助发卡、自动售货系统及独角数卡搭建教程

2025年6月16日 14:56

开源发卡系统
开源发卡系统

发卡系统

  • w-hehe/hmyk: 红盟云卡 卡密商城 自动发卡商城平台 虚拟商品出售。独立版开源,使用ThinkPHP开发,持续更新!可转售可二开可套牌可商用
  • lizhipay/acg-faka文档): 个人发卡源码,发卡系统,二次元发卡系统,二次元发卡源码,发卡程序,动漫发卡,PHP发卡源码,异次元发卡
    • 主题路径:app/View/User/Theme/
    • 支付系统,拥有强悍的插件扩展能力,现目今已经支持全网任意平台,任意支付渠道。
    • 云更新,如果系统升级新版本,你无需进行繁琐操作,只需要在你的店铺后台就可以无缝完成升级。
    • 商品销售,支持商品配图、会员价、游客价、邮件通知、卡密预选(用户可以预选自己想购买的那个账号或者卡号)、API对接、强制登录购买、强悍的自定义控件功能、限时秒杀、批发优惠、优惠卷、等众多功能。
    • 分站系统,前台用户可以开通分站,分站可以独立运行,也可以卖主站商品,有点类似商业店铺了。
    • 会员系统,会员/商户融为一体,支持会员等级,以及商户等级完全自定义,以及商品可自定义会员等级对应价格。
    • 推广/代理系统,拥有三级分销返佣功能,注册账号即实现自动发展下级。
    • 共享店铺系统,可以在后台直接对接别人的店铺,通过扣除余额来进行无感知进货。
    • 应用商店,拥有众多插件以及模板,让你的店铺变得格外强大。
    • 界面美观,完美支持PC和手机,真正的内外二次元文化。
    • 强悍的扩展能力,你可以通过本程序在几分钟之内快速的实现你任意想实现的在线购物功能,例子如下:
    • 游戏方面,物品购买即时到玩家背包
    • 商业软件余额充值
    • 商业软件自动授权
    • 论坛/社区VIP自动开通
    • 只要你想得到,没有做不到。
  • assimon/dujiaoka: 🦄独角数卡(自动售货系统)-开源站长自动化售货解决方案、高效、稳定、快速!🚀🚀🎉🎉
    • 支付宝当面付
    • 支付宝PC支付
    • 支付宝手机支付
    • payjs微信扫码.
    • Paysapi(支付宝/微信).
    • 码支付(QQ/支付宝/微信)
    • 微信企业扫码支付
    • Paypal支付(默认美元)
    • V免签支付
    • 全网易支付支持(通用彩虹版)
    • stripe

独角数卡部署教程

部署前置条件

  • 你需要一台内存512M或以上为最佳的vps或云服务器(推荐:RackNerd
  • 其次你的服务器操作系统要为 linux 内核

宝塔安装

宝塔面板官网:bt.cn。(宝塔面板开心版

必装环境

接下来我们安装一下下图六个软件:

宝塔必装软件
宝塔必装软件

最好是编译安装哦,性能更好。
🙋由于在之前版本很多同学不会使用supervisor,所以2.0.+版本我们会采用较为简单的堡塔应用管理器来实现守护进程。

PHP环境确认

一、 删除PHP的禁用函数

(ps:宝塔默认会禁用一些 php 的函数,导致 artisan 命令无法正确运行)

点击【软件商店】->【PHP设置】->【禁用函数列表】 将以下函数删除!!
putenvproc_openpcntl_signalpcntl_alarm

宝塔面板 -PHP禁用函数列表
宝塔面板 -PHP禁用函数列表

二、安装装PHP必要的两个扩展

点击【软件商店】->【PHP设置】->【安装扩展】
安装以下三个扩展:
fileinforedisopcache(可选安装,性能加强)

宝塔面板 - PHP安装扩展.png
宝塔面板 - PHP安装扩展.png

新建一个网站

一、在宝塔里新建一个网站用于运行本项目

宝塔面板 - 新建一个网站.png
宝塔面板 - 新建一个网站.png

二、上传我们的项目代码

请选择xxx_build.tar.gz压缩包。⚠️一定要选择带build字样的包,才有依赖!独角数卡发行版本下载地址:独角数卡各发行版本

三、设置项目伪静态和运行目录

解压项目代码后,我们点击网站的设置,设置运行目录:

宝塔面板 - 设置网站运行目录.png
宝塔面板 - 设置网站运行目录.png

设置伪静态:

宝塔面板 - 伪静态.png
宝塔面板 - 伪静态.png

开始安装

一、访问你的网站域名,进入安装流程

二、按实际情况填写网站配置信息

宝塔面板 - 安装页面
宝塔面板 - 安装页面

配置守护进程

注意,很多人嫌麻烦不配置这一步,那你出了问题别哔哔!⚠ ⚠ ⚠
注意,很多人嫌麻烦不配置这一步,那你出了问题别哔哔!⚠ ⚠ ⚠
注意,很多人嫌麻烦不配置这一步,那你出了问题别哔哔!⚠ ⚠ ⚠

堡塔应用管理器是我们用来管理laravel队列进程的工具。

很多同学喜欢问可不可以不执行这一步。

现在我明确的告诉你,不可以!请按照教程来,不然可以选择不使用。🙅‍♀️

没有它的话你的程序执行会异常!

如果不喜欢使用堡塔应用管理器,那么使用1.x版本supervisor也是可以的,两个必须选一个! 必选题!

一、堡塔应用管理器配置教程

进入宝塔控制面板: 步骤:【软件商店】->【堡塔应用管理器设置】->【添加应用】 如图:

宝塔面板 - 守护进程配置
宝塔面板 - 守护进程配置

  • 名称:随意,如dujiao
  • 应用环境: 选择php7.4
  • 启动文件: 网站根目录 + /artisan
  • 执行目录: 网站根目录
  • 启动参数: queue:work

保存即可!如果遇到没有自己的php版本怎么办?或者系统有多个php版本,但是应用环境没有自己想要的那个php版本怎么办?请看下一步新增应用环境

新增应用环境

宝塔面板 - 新增应用环境
宝塔面板 - 新增应用环境

环境名称可以随便填。

启动文件一般是 /www/server/php/72/bin/php

⚠️注意哦,我这里是72就是php7.2,你可能是73或者74。按照自己来,我这里只是举例!

二、supervisor配置教程

步骤:【软件商店】->【Supervisor设置】->【添加守护进程】 如图:

宝塔面板 - 守护进程配置
宝塔面板 - 守护进程配置

命令参考:

/www/server/php/74/bin/php /www/wwwroot/dujiaoka/artisan queue:work
  • 名称:随意填写
  • 启动用户:选择 www
  • 运行目录:选择程序根目录
  • 启动命令:/www/server/php/你的php版本/bin/php /www/wwwroot/你的网站根目录/artisan queue:work

请注意你自己的php版本和网站根目录。不要瞎抄照着我的写? 注意命令之间的空格。

  •  
Received before yesterday

RSSHub 搭建指南打造个性化资讯中心

2025年3月7日 00:00

RSSHub 可以根据我们的需求生成个性化的 RSS 订阅源,让我们轻松地获取到各种平台的最新资讯。本文将详细介绍 RSSHub 搭建过程,快速搭建起属于自己的资讯中心。

RSSHub 的简介

RSSHub 是一个轻量、易于扩展 RSS 生成器,它基于 Node.js 开发,支持多种平台和类型订阅源,包括但不限于微博、知乎、B 站、GitHub 等。

通过简单的配置和路由规则,我们就能生成自己想要的 RSS 订阅链接,随时随地获取最新内容更新。

搭建前的准备

在开始搭建 RSSHub 之前,我们需做一些准备工作。需一台服务器,可以是云主机,也可以是本地的计算机。服务器需要具备公网 IP 地址,以便我们能够从外部访问搭建好的 RSSHub 服务。

RSSHub 基于 Docker 部署,因此需要在服务器上安装 Docker 环境。

RSSHub 支持缓存中间件,如 Redis。

为方便访问和使用,建议注册一个域名,并将其解析到服务器的 IP 地址上。

RSSHub 的搭建步骤

将下面的内容保存为 docker-compose.yml 文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
services:
rsshub:
# two ways to enable puppeteer:
# * comment out marked lines, then use this image instead: diygod/rsshub:chromium-bundled
# * (consumes more disk space and memory) leave everything unchanged
image: diygod/rsshub
restart: always
ports:
- "1200:1200"
environment:
NODE_ENV: production
CACHE_TYPE: redis
REDIS_URL: "redis://redis:6379/"
PUPPETEER_WS_ENDPOINT: "ws://browserless:3000" # marked
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"]
interval: 30s
timeout: 10s
retries: 3
depends_on:
- redis
- browserless # marked

browserless: # marked
image: browserless/chrome # marked
restart: always # marked
ulimits: # marked
core: # marked
hard: 0 # marked
soft: 0 # marked
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/pressure"]
interval: 30s
timeout: 10s
retries: 3

redis:
image: redis:alpine
restart: always
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 30s
timeout: 10s
retries: 5
start_period: 5s

volumes:
redis-data:

使用下面命令来启动 RSSHub 服务:

1
docker-compose up -d

如需拉取新版 RSSHub 的镜像,可使用下面的命令:

1
docker-compose pull

如需停止服务,可使用下面的命令:

1
docker-compose down

如果不喜欢使用 Docker Compose 部署,可使用下面的命令运行有 Puppeteer 依赖的 RSSHub 服务:

1
docker run -d --name rsshub -p 1200:1200 diygod/rsshub:chromium-bundled

可使用下面的命令运行无 Puppeteer 依赖的 RSSHub 服务:

1
docker run -d --name rsshub -p 1200:1200 diygod/rsshub

为 Follow 添加实例

如果使用 Follow 调用 RSSHub 示例,需在 docker-compose.yml 中添加一些变量。其中 FOLLOW_OWNER_USER_ID 是指您的关注账户 ID 或用户名;FOLLOW_DESCRIPTION 指实例描述;FOLLOW_PRICE 指实例月费,如设为 0 表示免费;FOLLOW_USER_LIMIT 指实例用户限制,将其设置为 0 或 1 可将实例设为私有,留空则表示无限制;ACCESS_KEY 指访问密钥:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
services:
rsshub:
image: diygod/rsshub:chromium-bundled
restart: always
ports:
- "1200:1200"
environment:
NODE_ENV: production
FOLLOW_OWNER_USER_ID=杜老师说
FOLLOW_DESCRIPTION=大带宽境外服务器
FOLLOW_PRICE=1
FOLLOW_USER_LIMIT=1000
ACCESS_KEY=ubzG7H3t9TJaFp
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:1200/healthz"]
interval: 30s
timeout: 10s
retries: 3

登录 Follow 后,点击头像,选择 RSSHub 项。在显示页面中,点添加新实例。依次输入 RSSHub 的地址,访问密钥,最后点击添加即可:

  •  

图片为啥用 Base64 格式进行传输

2025年2月17日 00:00

在互联网的世界里,图片传输是再平常不过的事情了,而 Base64 格式常常出现在这一过程中。那为啥图片要用 Base64 格式来传输呢?这背后有不少门道。本文将介绍 Base64 格式的应用场景和优点,以及一些应用场景下的缺点。

Base64 是什么

Base64 是种用 64 个可打印字符来表示二进制数据的编码方法。这 64 个字符含大小写字母各 26 个,还有 10 个数字以及两个符号。

例如,当我们看到一串像 SGVsbG8gV29ybGQh 这样的字符,这就是 Base64 编码后的结果,其实代表了 Hello World!

易于文本传输

在很多网络传输场景中,尤其是早期的网络应用,传输通道主要被设计为传输文本数据。

因为文本数据格式相对简单、统一,而且不容易出现乱码等问题。

而图片是二进制的数据,直接传输二进制数据可能会因为不同系统、不同软件对二进制数据的处理方式不同而出现问题。

Base64 把图片的二进制数据转换成了文本形式。这样一来,通过电子邮件、网页表单等主要以文本传输为主的渠道时,图片就可以顺利跟着文本一起传输了。

比如,在发送带有图片附件的电子邮件,邮件系统会把图片转换成 Base64 格式,然后和邮件的正文一起发送。

接收方收到邮件后,邮件客户端再把 Base64 格式的数据转换回图片,这样我们就能看到图片。

兼容性好

不同的操作系统和不同的软件应用对数据处理方式可能存在差异。Base64 编码后的文本数据在各种平台都能被正确识别和处理。

例如,一个在 Windows 系统上生成的 Base64 编码的图片数据,在 Linux 服务器上也能轻松解码并还原成图片,不用担心因为平台不同而出现数据损坏或者无法读取的情况。

几乎所有的编程语言都有内置的库或者函数来处理 Base64 编码和解码。这使得开发人员在开发涉及图片传输的应用程序时,能够很方便使用 Base64 格式。

比如,在一个基于 Python 的 Web 应用,开发人员可以使用库轻松地将图片文件读取并编码为 Base64 格式,然后通过网络发送给服务器或客户端。

方便在网页中嵌入图片

在网页设计中,如果一个网页中有大量的小图标或小图片,每次加载这些图片都需要发送一个 HTTP 请求。

这不仅会增加服务器的负担,还会影响网页加载速度。

而将这些小图片转换为 Base64 格式后,可以直接将 Base64 编码的数据嵌入到 HTML 或 CSS 文件中。

这样浏览器在加载 HTML 或 CSS 文件的时候,就可以直接读取到图片数据,而不需要单独发送 HTTP 请求去获取图片,从而提高了网页的加载效率。

嵌入 Base64 格式的图片还可以简化网页的结构。不需要在网页文件目录中单独存放这些小图片文件,减少了文件管理复杂性。

对于一些简单的网页应用或前端框架,这种方式非常实用。

安全性的考虑

虽然 Base64 编码不能算是真正的加密方法,但它在一定程度上可起到隐藏信息的作用。

因为对于不了解 Base64 编码的人来说,看到一串 Base64 编码的数据可能不知道它代表的是图片内容。

在一些对安全性要求不是特别高的场景下,可作为一种简单的保护措施。

比如,在一些内部文档分享系统中,把图片转换 Base64 格式传输,可防止非授权用户轻易地获取到原始图片文件。

在某些情况下,直接传输二进制图片文件可能会带来安全风险,如图片文件可能被恶意篡改,包含恶意代码。

将图片转换为 Base64 格式后,这些恶意代码在 Base64 编码文本环境中很难被执行,从而降低安全风险。

缺点

不过,Base64 传输图片也有其缺点。比如,Base64 编码后数据量比原始的二进制图片数据要大,大概会增加百分之三十三左右的大小。

所以在传输大图片或者对带宽要求很高的场景,可能需要权衡下是否使用 Base64 格式。

  •  

本博出现图碎问题说明

2025年2月11日 00:00

近期本博访问时出现了图碎问题,经排查系 CDN 回源失败导致的。有小伙伴可能会说,保证成功就可以修复了,其实没有那么简单。本文简单描述下存储节点数据流,顺便科普一下如何清理单站数据缓存。

数据流向

通过下图可以看出,图片文件保存在主机上,通过转换处理为 WebP 格式文件,经由 CDN 回源并实现访问加速:

问题分析

登录 CDN 管理后台查看其日志,发现出现超时记录。

超时原因一般两种,一种是因线路问题导致回源超时,一种是因主机没有及时返回数据造成。

本地图片经由 WebP 中间件处理,再回源给 CDN 做反代,经查是 WebP 服务突然宕机导致 CDN 未收到响应数据导致超时。

除超时问题外,因无返回数据导致 CDN 响应 404,而服务器设置 404 默认跳转至主站首页,这就导致好多小伙伴频繁刷新页面依然不显示图片。

解决方案

目前已关闭 CDN,流量直接回源至源主机,缺点就是会影响访问的速度。带调试维护后会重新挂上 CDN。

WebP 图片转换是为了减少图片体积,进而减轻带宽压力「轻量级服务器有流量的限制」因此不能暂停使用,已修改其参数,尽量保障响应的成功率。

如之前有访问记录,会留下 404 跳转缓存,需要清理相关数据。

有小伙伴分享了两种清理缓存的方法,需要的小伙伴可以参考操作。

清理缓存

首先进入到浏览器的开发者工具,一般浏览器点击F12即可,进入更多设置,勾选 Disable cache while DevTools is open 项:

或者切换到网络标签页,勾选禁用缓存,刷新页面即可「注意保持开发者工具一直处于开启的状态」

  •  

Hugo 渲染超时问题的解决笔记

2025年2月5日 00:00

hehe 童鞋选择将所有的站点托管到杜老师这「是收费的」这样就可以专心维护网站的内容,也不用费心思在运维上。在做站点迁移时遇到了 Hugo 框架的一个报错,原因是使用 Hugo 搭建相册网站需要遍历大量图片,而在生成站点文件时出现了超时问题,本文记录解决方法。

报错信息

1
2
3
ERROR render of "page" failed: "/home/runner/work/photo/photo/themes/gallery/layouts/_default/single.html:3:5": execute of template failed: template: _default/single.html:3:5: executing "main" at <partial "gallery.html" .>: error calling partial: partial "gallery.html" timed out after 30s. This is most likely due to infinite recursion. If this is just a slow template, you can try to increase the 'timeout' config setting.
Total in 60412 ms
Error: error building site: render: failed to render pages: render of "page" failed: "/home/runner/work/photo/photo/themes/gallery/layouts/_default/single.html:3:5": execute of template failed: template: _default/single.html:3:5: executing "main" at <partial "gallery.html" .>: error calling partial: partial "gallery.html" timed out after 30s. This is most likely due to infinite recursion. If this is just a slow template, you can try to increase the 'timeout' config setting.

注意:杜老师是通过 GitHub Actions 来部署,逻辑是先准备 Hugo 的运行环境,再根据站点的数据渲染站点文件。在生成站点文件时出现如上错误信息。

解决思路

从错误信息看,Hugo 网站在渲染页面时出现了问题,具体是 gallery.html 这个 partial 文件在执行时超时了,并且怀疑是由于无限递归导致的。

首先检查 gallery.html 中代码。无限递归问题可能是 gallery.html 中调用了自身,或者在调用其它 partial 时形成了循环。仔细检查文件,确保没有递归调用自己或其它可能导致循环的部分。

其次检查数据结构。如果 gallery.html 中依赖某些数据结构,可能是数据结构中存在循环引用。例如,某个对象或者列表在渲染时不断递归调用。

再次增加超时时间。如果确认不是无限递归问题,而是模板渲染确实很慢,可以尝试增加超时时间。在 Hugo 的配置文件中,增加 timeout 配置项,如 timeout = '60000'

然后优化模板性能。如果模板渲染确实很慢,可能是模板的代码过于复杂。可以尝试优化模板代码,减少不必要循环和复杂逻辑。

接着调试模板。使用 Hugo 的调试工具来逐步检查模板的执行过程。可通过在模板中添加日志输出来帮助调试。

再者检查依赖插件。如果网站使用第三方插件或依赖,可能是插件导致了问题。尝试禁用插件,看看能否解决问题。

最后检查 Hugo 的版本。确保使用的 Hugo 版本是最新的。旧版本可能存在已知的 bug,而新版本可能已修复了这些问题。

  •  

宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)

2024年11月6日 16:06

V免签支付系统介绍

V免签(PHP) 是基于 Thinkphp5.1 + mysql 实现的一套免签支付程序,主要包含以下特色:

  1. 收款即时到账,无需进入第三方账户,收款更安全
  2. 提供示例代码简单接入
  3. 超简单 Api 使用,提供统一 Api 实现收款回调
  4. 免费、开源,无后门风险
  5. 支持监听店员收款信息,可使用支付宝微信小号/模拟器挂机,方便 iOS 用户
  6. 免 root,免 xp 框架,不修改支付宝/微信客户端,防封更安全

V免签官方源码:https://github.com/szvone/vmqphp

V免签安卓监控端:https://github.com/szvone/VmqApk

演示环境基于 宝塔面板 搭建,使用 nginx1.18、php7.4、mysql5.6 已实测该环境正常搭建可用

  • V免签的运行环境为PHP版本 >=5.6。

宝塔面板-V免签支付系统搭建教程
宝塔面板-V免签支付系统搭建教程

宝塔面板部署V免签支付系统教程

  1. 下载V免签压缩包,上传至服务器并解压

  2. 关闭防跨站攻击,设置运行目录为 public 并保存

宝塔面板-网站目录-运行目录
宝塔面板-网站目录-运行目录

  1. 设置伪静态为thinkphp并保存

宝塔面板-伪静态设置
宝塔面板-伪静态设置

  1. 设置默认文档,将index.html放在第一行并保存(这里改完顺序,点击添加就是保存)

宝塔面板-默认文档设置
宝塔面板-默认文档设置

  1. 打开网站路径/config/database.php ,设置好你的 mysql 账号密码并保存

V免签支付系统数据库设置
V免签支付系统数据库设置

  1. 导入数据库文件 vmq.sql 到服务器里

数据库导入V免签数据文件
数据库导入V免签数据文件

  1. 至此网站搭建完毕,请访问后自行修改配置信息!默认后台账号和密码均为 admin

V免签支付系统演示图

前台演示图

V免签支付系统前台演示图
V免签支付系统前台演示图

后台演示图

V免签支付系统后台演示
V免签支付系统后台演示

V免签支付系统后台演示-系统设置
V免签支付系统后台演示-系统设置

V免签支付系统后台演示-监控端设置
V免签支付系统后台演示-监控端设置

V免签监控端设置

V 免签监控端:该软件是基于 V 免签开发一款免 root 和框架 Android 收款监听软件,功能为监听支付宝和微信收款消息与服务端进行交互,若匹配当前时间段服务端有同金额订单将会把收到的金额消息进行回调!达到监听通知栏收款消息回调完成支付业务。该版本主要修复了原版监控的支付宝和微信不回调的 BUG,优化代码写法。删除沉余代码加快启动速度,增加电池白名单权限,使软件在电池优化时不会被杀掉!增加 Log 监听回调面板与店员监听。V免签现已更新 PC 端监控。

下载地址

付费图片
付费图片
限时优惠
宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)
为尊重作者劳动成果,此处内容已隐藏,请购买查看内容
10
限时特惠
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
已有0人解锁查看
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
付费阅读
已售 0
隐藏内容

V免签Android监控端设置

使用Android手机安装APK,点击扫码配置 - 扫描V免签监控端设置的二维码即可配置完成

V免签二开源码

运行环境 Nginx1.1.5 以上 PHP5.6-7.3 Mysql5.6以上

  1. 网站目录->运行目录 设置为public并保存
  2. 伪静态 设置为thinkphp并保存
  3. 打开网站目录 config/database.php ,设置好您的mysql账号密码
  4. 导入数据库文件(位于根目录)pay.sql到您的数据库
  5. 至此网站搭建完毕,请访问/houtai后自行修改配置信息!默认后台账号admin和密码123456
  6. 后台登录入口在route/route.php,找到’houtai’修改即可
  7. 在后台里设置首页跳转地址,不设置跳转到默认地址
  8. 配置邮箱信息和支付宝商户号
  9. 使用免挂或者软件监控,使用免挂需要配置回调监控
  10. 建议把当前站点的网站防火墙关了,以防被拦截

下载地址:包含源码与监控挂机软件

付费图片
付费图片
限时优惠
宝塔面板-V免签支付系统搭建教程:个人开发者收款解决方案(含2开源码)
为尊重作者劳动成果,此处内容已隐藏,请购买查看内容
10
限时特惠
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
已有0人解锁查看
输入邮箱即可查询订单,跳转支付则为未查询到订单(邮箱只用于订单使用,不会发送内容到邮箱,虚拟产品售出不退!!!)
付费阅读
已售 0
隐藏内容

V免签WordPress插件

V免签WordPress插件

  • ✅关闭订单(2024年11月4日)

  • ✅收款返回文章页面,并显示隐藏内容(2023年11月4日)

  • ✅界面上面的文字可以自定义(2023年11月4日)

  • ✅金额可以在文章中自定义设置,如果不设置则显示默认金额(2023年11月7日)

  • ✅订单显示在后台(2023年11月7日)

  • ✅支付金额可以自动填入(2023年11月9日)@格子老师

  • ✅3款主题切换

V免签代部署服务

有源码不会装?懒癌发作,手不听使唤?瞌睡上头思想无法集中?昨晚酒还没醒?

如果您有以上疑难杂症,点这里就对了,发挥你的钞能力,一键解君愁!

服务内容:

  • 您无需准备以上所需源码,提出要求就好!
  • 带安装对接以上支付接口!
  • 您只需提供服务器信息、域名信息、收款二维码即可!

v免签 代安装搭建服务

  •  

Artalk 评论工具登录功能使用及反馈收集

2024年5月15日 00:00

Artalk 默认只需填写昵称和邮箱即可发表评论,无需验证邮箱。但有时候,我们希望用户能够使用社交账号登录,以减少用户填写信息的时间,或者提高用户信息的真实性,故此杜老师决定开启社交登录来实现这一目的。

写在最前

作为 Artalk 的内测用户,杜老师第一时间启用了社交登录功能。

近期也会收到一部分小伙伴反馈,说看到登录按键后不太习惯。

这里说明一下启用邮箱密码登录功能后仍然可跳过邮箱验证,登录弹窗底部显示跳过按钮,点击后评论框顶部恢复为显示原有的昵称、邮箱、网址。

另外已经向 Artalk 作者反馈相关建议,期待后期升级更多功能。

同时希望小伙伴们积极提供建议,这边都会第一时间反馈给 Artalk 作者,以满足大家的需求。

本站后期也会对接各大社交平台,目前仅支持用邮箱登录。

食用教程

在启用邮箱密码登录后,评论框顶部的昵称邮箱输入框将隐藏,发送按钮将显示为登录按钮。当用户点击登录按钮后,会弹出一个登录框,用户可输入邮箱和密码登录,登录成功即可发表评论:

用户可以通过邮箱注册账号,将向用户邮箱发送一封带有验证码的邮件。验证码有效期为 10 分钟,验证码发送频率限制 1 分钟一次:

登录后如果检测到相同邮箱下有多个不同用户名的账号,将会弹出账号合并工具,用户可选择保留其中一个用户名,该邮箱下的所有评论等数据合并到保留账号下,而原有的账号将被删除,评论显示的用户名将会变更为保留用户名:

用户发表的评论将展示「邮箱已被验证」标识:

支持同时启用多种登录方式,用户可以选择任意一种方式登录:

如果只启用了唯一一种登录,如 GitHub 登录,将直接弹出 GitHub 授权登录页面:

  •  

同款说说页面部署代码分享

2024年5月12日 00:00

在一帮小伙伴的帮助下,杜老师终于完成了对说说页面的美化。对此颇有感概,不会前端是真不行,但就是学不会。该代码匹配 Volantis,可自适应夜间模式,感兴趣的可以尝试部署,有问题就不要问了,杜老师也不会~

特性

  1. 统计用户所发说说条数;

  2. 显示用户头像;

  3. 显示用户昵称;

  4. 显示平台的用户名;

  5. 支持大图显示;

  6. 可一键至说说广场进行评论。

效果

正常的浏览效果如下图:

夜间模式的浏览效果如下图:

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<link href="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/css/style.css" rel="stylesheet" type="text/css">
<link href="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/css/highlight.github.min.css" rel="stylesheet" type="text/css">
{% p center logo large, 点图片可放大! %}
<section id="main" class="container">
<div class="total">Total <span id="total">0</span> Memos 🎉</div>
<div id="memos" class="memos">
</div>
</section>
<script type="text/javascript">
var memos = {
host: 'https://s.dusays.com/',
limit: '10',
creatorId: '1',
domId: '#memos',
username: 'penn',
name: 'Teacher Du',
}
</script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/lazyload.min.js?v=17.8.3"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/marked.min.js?v=11.1.1"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/view-image.min.js?v=2.0.2"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/moment.min.js?v=2.30.1"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/moment.twitter.js"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/highlight.min.js?v=11.9.0"></script>
<script type="text/javascript" src="https://npm.onmicrosoft.cn/penndu@13.0.0/memos/js/main.js"></script>
<script>hljs.highlightAll();</script>

注意:如果不是 Volantis 主题需删除{% p center logo large, 点图片可放大! %}所在行。

使用

请根据需求修改对应的内容:

参数说明
host域名
limit每页显示条数
creatorId用户的 ID
domId显示位置
username广场的用户名
name昵称
  •  

说说广场资源转存至缤纷云

2024年3月28日 00:00

杜老师最近太忙了,平时也是撒手掌柜,很少管理旗下平台,除非遇到问题才会第一时间解决。恰好昨天下午得空看了一下说说广场,没想到超过了百人。图片加载速度好慢,就想着托管到其它平台!

什么是 S3

S3 存储是亚马逊推出的一种对象存储服务。提供了一个高度可扩展、可靠且安全的数据存储解决方案,用于存储和管理各种类型的数据对象,例如文件、图像、视频、文档。

使用了 S3 存储,用户可以通过 API 或与 S3 兼容的工具来上传、下载、检索、管理数据对象。S3 还支持数据版本控制、生命周期管理、数据备份和恢复等功能。

Bitiful 缤纷云

缤纷云的界面是非常简洁的,而且还挺好看,概述页面可以看到资源的使用量:

缤纷云每月会赠送 50G 的存储容量,CDN 流量 10G,API 请求 10 万次。具体费用可见官方文档:

整合说说

下面说说整合过程。首先注册登录到缤纷云,切换到对象存储 AccessKey 页面,点击右侧的添加 Key,根据流程填写对应内容即可:

进入到 Memos 后台,点击设置——存储——创建,参考下图输入相关内容「杜老师做了些调整,如果效果不太理想,可以在评论区留言询问」

使用体验

有一说一,加载速度还是非常快的,毕竟是专业的存储加 CDN。不过并发请求貌似有些问题,每次批量加载都会出现很多请求失败问题。不过还好不影响前端的调用:

  •  

Docker 搭建轻量高颜值个人导航页面

2024年3月19日 00:00

最近拜访博客圈的小伙伴时,发现很多博主习惯在主页内加一个导航页。之前杜老师也在纠结是否要添加,其实是因为没找到心仪的导航页。恰好近期在网上闲逛时,发现了这款轻量高颜值的导航页,分享给需要的小伙伴们!

工具介绍

Flare 是一款轻量、快速、美观个人导航页面,适用于 HomeLab 或其它注重私密的场景。

可支持 Docker 一键部署,维护方便。

无任何数据库依赖。应用数据完全开放透明。

支持在线编辑。支持 x86 及常见的 ARM 设备。应用资源消耗很低。

工具特点

服务资源消耗极低,可以跑在任何规格的机器上。

程序页面性能较好,渲染速度更快,支持同时渲染大量书签。

使用声明的配置来进行导航内容管理,无需担心数据迁移问题。

简化了天气数据的获取方式,不再需要申请天气网站的 API_KEY,避免不必要的成本开销。

内置大量风格统一、高质量的矢量图标,确保界面长期耐看。

默认使用免登陆的模式,避免了 HomeLab、本地使用的用户有额外登录操作。

工具部署

启动应用非常简单,如果您习惯使用 Docker,可以执行:

1
docker run -d -p 5005:5005 -v `pwd`/app:/app soulteary/flare

如果您习惯使用 docker-compose,只需要执行 docker-compose up -d

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
version: '3.6'

services:
flare:
image: soulteary/flare
restart: always
# 默认无需添加任何参数,如有特殊需求
# 可阅读文档 https://github.com/soulteary/docker-flare/blob/main/docs/advanced-startup.md
command: flare
# 启用账号登陆模式
# command: flare --nologin=0
# environment:
# 如需开启用户登陆模式,需要先设置 `nologin` 启动参数为 `0`
# 如开启 `nologin`,未设置 FLARE_USER,则默认用户为 `flare`
# - FLARE_USER=flare
# 指定你自己的账号密码,如未设置 `FLARE_USER`,则会默认生成密码并展示在应用启动日志中
# - FLARE_PASS=your_password
# 是否开启“使用向导”,访问 `/guide`
# - FLARE_GUIDE=1
ports:
- 5005:5005
volumes:
- ./app:/app

效果截图

部署完成之后,访问服务器 5005 端口,就能看到下面的界面啦:

在 Flare 启动之后,您可以随时访问/guide,获取 Flare 基础界面功能的介绍:

为满足随时随地编辑的需求,程序新增了在线编辑的页面。地址是/editor

为了减少不必要的地址记忆负担,程序新增一个帮助页面,默认展示所有程序内的工具页面。地址是/help

  •  

杜老师的网站访问速度快吗

2024年1月16日 00:00

闲着没事分析了一下博客的留言,在四万多条留言里,其中有超过一百条说杜老师博客访问速度喜人,想了解下如何做的。今天为小伙伴们分享一下杜老师说的架构,以及优化建议~

数据分布

当您访问杜老师说,正在阅读一篇图文搭配教程,并准备留言时。您正在访问如下四个资源库:

资源解释

网站源码。杜老师使用 Hexo 静态框架,这意味着该网站的所有页面都是预先生成的静态 HTML 文件,而不是动态生成的。访问该网站时,直接获取这些静态网页资源,而不需要再查询数据库。这种做法可以极大减少响应延迟,从而提高网站的加载速度和性能:

图片外链。大量图片托管与去不图床同节点服务器中,方便管理同时,通过自建 CDN 节点加速了访问速度,同时避免与源码站同服务器导致抢占带宽。之所以与去不图床外链地址不同,是因为加入了 WebP 自动转换中间件,节约流量同时,提升加载速度,等同变相增加线路带宽:

评论系统。采用 Artalk 评论系统 Docker 部署方式,其使用 Go 语言构建后端,快速处理数据同时,还使用异步处理的方式,加速评论提交过程。同时采用 Redis 预缓存,Artalk 启动后直接将数据缓存至内存,无需再查询数据库,可以极大减少响应延迟:

开源镜像。全站的 JS 及部分 CSS 资源均引用开源镜像站,感谢 Zkeq 童靴提供公益 CDN 加速平台,既稳定又高速。同时号召小伙伴们不要滥用公益资源,细水长流才能长长久久,境内可用的公益资源越来越少了,希望该平台可长久运营:

优化建议

  1. 主机选择。境外主机的平均带宽比境内的主机高,但境外主机延迟都不低,且数据中心的距离越远,则丢包率越高。故在不考虑带宽情况下,尽量选择境内主机,唯一的限制就是备案了,这是一个硬性门槛,各位站长酌情考量;

  2. 程序选择。静态的肯定比动态的框架快,但有些小伙伴偏爱 WordPress/Typecho 这类的框架,可以安装静态生成插件,进而减少数据库的查询次数,变相减少响应延迟。还要注意的是,不要安装太多插件,因为每次加载页面都会遍历所有插件,插件越多遍历时间越久;

  3. 服务优化。经调查小伙伴们用的云主机普遍配置较低,建议选择 Nginx 作引擎,可以的话推荐使用编译安装最新版本,这个杜老师做过测试的,编译的更稳定且效率高。MySQL 最好 5.7 版本,8.0+适用分布式,性能提升是通过牺牲配置实现的,主机 6G 以下的无法发挥 8.0+版本的性能优势。PHP 肯定是版本越高越好,但需要程序支持才可以。主机内存充足的情况下可以通过 Redis/Memcached 缓存减少数据库查询次数「优先选 Redis」

  4. 站外调用。条件允许的情况下,尽可能的调用站外资源,如 JS/CSS,减少服务器请求数量的同时,还可以避免与网站同服务器导致抢占带宽。墙裂推荐杜老师的去不图床,各大动态博客框架都有对应插件,方便上传管理,自建 CDN 保障稳定及速度。头一次在文章里挂广告推自己的图床,还有一点脸红~

文章推荐

优化云主机的性能确实是一个重要的考虑因素,尤其是在托管大量图片和资源时。很多小伙伴喜欢用某塔面板,很久前杜老师写了一篇《云主机的极致优化》感兴趣的可以看下。虽然文章比较久远,但依旧有参考价值。

只有榨干云主机的性能,才能将性能最大化。关于安装所需的软件和服务,确实需要注意不要过度配置。每个额外的服务或应用程序都可能增加服务器的负担并可能导致性能下降。因此,仔细评估每个应用程序的必要性和其对系统资源影响是很重要的。

比如去不图床安装了 WAF,则每次访问时,先通过 WAF 过滤,才会进行请求处理,经测试会产生 100 毫秒左右的延迟。这是一个值得注意的点,尤其是对于高流量的网站或对性能要求较高的应用。虽然 WAF 可提供安全保护,但这种延迟可能对用户体验产生影响。

如果您感觉杜老师说访问速度不快,那就当杜老师上面的都没说~

  •  

友情链接的那些事

2023年10月9日 00:00

首先打个欠条,之前答应写一篇 OpenWrt 教程,奈何杜老师突然因工作安排出差,身边没有实验设备,故只要推迟更新了。这篇文章主要聊一下杜老师对友情链接的看法,其中一些策略可能会影响到后期友链运营!

先聊成绩

本博客创建于 2019 年 7 月 10 日,截止该文章发布时,已存在的友链 166 条,其中全站链接 27 条,首页链接 13 条,余下皆为内页链接。

而这 166 条链接,除了继承菜鸟博客那不超过十条友链之外,其余都是被动链接「由他站主动发起的友链申请」

当然其中还有一些友链,是友站建立好后未声明,后期回访时主动发现的,这类站点杜老师会及时上链,保障互动~

友链鼎盛时期,则达到了 207 条,部分站点的友链因无故断链、无法访问等情况而下链。

回顾前文

友链较多,维护起来也很麻烦。

杜老师会定期检查每个友链对应站点可访问性,及本站的友链是否存在,是否更换展示位置等等。

虽说有脚本工具的帮助,但因为博客框架及主题的多样性,很多站点仍需手动检测,这样就占用了杜老师很多时间和精力。

为此杜老师曾编写一篇友链规则文章《关于友情链接的一些事》里面详细描述了杜老师对友链的要求。

遇到问题

杜老师可以很自信的说,没有几个人按照该规则申请链接!

一上来就丢链接的仍然很多,不过比较友善的是都提前做好了杜老师说链接。

不过突然关站、故障博客比比皆是,杜老师每每遇到都会发邮件通知,并提供相关的技术支持,有些博主因上学等一些原因无法及时处理,导致站点长时间的不可访问,搞的杜老师只要做下链处理。

这里很多小伙伴会有所疑问,为什么一遇到不可访问,就立即下链呢?简单为大家介绍下某度引擎索引机制。

杜老师说权重尚可,每天都会吸引数千蜘蛛爬取数据,而遇到无法访问资源时,蜘蛛会降低杜老师说的权重,且对无法访问资源的 URL 做降权甚至是 K 站处理。所以说立即下链是保护站点一种方式。

当然大家找不到自己的链接,也不需要担心,在友链申请页面说明情况就好了,杜老师看到后,也会第一时间恢复上链。

一些想法

不知道有多少的小伙伴做过来源分析,会发现绝大多数的访问流量,都来自于其他博主。大众访客一般都会通过社交平台获取所需要的数据,我们这类博客只有同为博客圈的站长才会乐此不疲。

而互访就是最有效活跃博客的方式了。杜老师添加很多的友链,会定期采集各站的最新文章,尽可能的第一时间送上热评,在活跃气氛的同时,也在其它站点留下本站一丝身影。这也是为什么经常有小伙伴会说:怎么哪里都有杜老师呢?

但是久而久之,杜老师发现很多站点的博主互动性差「从不回访」有些站点久不更新。所以杜老师决定后期会调整友链策略,达到硬性的要求后再考虑做友链。同时屏蔽部分互动性差站点资源采集,这样可以有更多的精力仔细拜读大佬们的文章,以留下更多的热评。

之后建站时间低于一年的请不要主动申请链接,杜老师不清楚您建站是一时兴起,还是长远打算。

一个月及以上未更新的博客也请不要主动申请链接,且已友链的可能会随时下链,杜老师不清楚您是没有时间还是跑路。

第一次来本站的小伙伴也请高抬贵手不要主动申请链接,本站不是您宣传的平台,请不要降低了杜老师互访的热情,谢谢!

  •  

杜老师说方向调整

2023年9月2日 00:00

最近一直在水文章,偶尔还会托更。除了最近比较忙碌之外,更多的是不知道该更新点啥。和小伙伴聊了一下,决定调整一下杜老师的主题方向,也希望大家可以提一些建议!

语音部分

需要手动点击播放:

文字部分

今天,这个博文就以语音的形式去发布。然后,会将这个语音转换成文字的形式,方便喜欢看文字的小伙伴去浏览阅读。懒得看字,您可通过听语音的形式。

杜老师今天为大家分享内容,主要是想说下,杜老师说调整了一下主题的方向。原因比较简单:实在不知道该写点什么好了。

大家应该知道,杜老师说每三天会更新一次。会给大家伙分享一些技术方面的内容,有的时候会根据一些小伙伴的兴趣和建议,分享一些跟杜老师生活相关事情。

但是最近,一直在拖更且水文,很多小伙伴已经开始抱怨了。当然有一部分原因,是因为杜老师还是比较懒的,拖延症吧!

今天这个文章本来想打字说明的,但是懒得打字,打算录音,然后通过一些工具将音频转换成文字的形式跟小伙伴们进行分享。并且在此之前,也没有说先写文稿,然后再去录制,所以说会有很多的废话或者是口头语之类,这个也希望大家理解吧。

我们的话题说回来,说下方向。之前也给各位小伙伴介绍过,杜老师说是个人的技术博客,主要就是为我的学员去分享技术文章,让他们在上课的过程中,不需要把过多的精力放在记录笔记上。这样他们上课可以认真听课,下课可以在我的博客上获得笔记。

后期我已经不做培训讲师的这个工作,转向了公司的另外一个讲师,算是。职责上发生了一些变化。所以说就导致了并不需要将我自己的博客推向我的学员,这个平台就单纯的变成一个技术、资源,还有就是生活类分享的一个平台。

未来打算做一些简单的调整。因为分享一些,比如说运维方向的一些知识,很多小伙伴们可能不是特别的感兴趣。甚至是不需要,很多小伙伴们来了之后都是表示不明觉厉,他们遇到的问题更多是喜欢直接在评论区下面留言,然后获得直接帮助。

这种方式是很高效。所以说感觉没有必要去分享这类资源。当然以后有些更好的技术或者是服务的话,也会给各位小伙伴们进行这种教程上分享,主要还是想着改成这种,比如说一些有趣的工具,或是生活类的。

所以说未来主题的方向,会逐渐面向生活类,面向有趣工具,或者是一些实用性的东西来分享。会发现很多小伙伴,都是跟杜老师一样,是博主是站长,他们希望通过这一类的资源,尽可能的去丰盈自己的博客,然后带来更多流量。

使得自己博客的功能更加的健全,所以未来可能更加注重这个方向。但是有一点就是杜老师作为一个单纯的运维工程师,并不会开发代码也不会前端。

所以大家可以看到,杜老师说是非常的简洁。并没有一些酷炫的效果,只不过在功能方面,相对来说够用。也是要感谢之前有很多小伙伴对杜老师的帮助,在这里呢,就不一指名道谢了。

最后想说一下关于未来主题方向,这个也是杜老师刚刚想到的,跟其他的小伙伴也聊过,然后他们也给杜老师提供了一些建议。

当然这些还是比较片面,也希望能看到此文章一些小伙伴,给杜老师提供更多建议,这个平台的受众是访客。希望能迎合着访客的兴趣口味去经营杜老师说。

后期还是会继续保持着每三天一更的频次,尽可能的不要再出现水文了。实在懒得打字。那我就发语音。

实际上发语音比打字要轻松的多,毕竟杜老师做这方面的工作多年了吧,所以很多话都是在嘴边,不需要过脑直接就可以说出来的。

并不需要太多文稿,可以跟大家聊半天,只不过有些小伙伴应该也听出来,杜老师的口音还是比较重的,尤其是平翘舌不分。

表达的时候就会出现这种特别的情绪所在,导致大家可能听着有些别扭,这个我慢慢去调整,慢慢纠正,但是做这个行业比较久,回想一下,杜老师已经当老师十年之久,所以说不太容易改。

除了资源还有生活分享之外。未来还会推出一些公益性的活动,大家在这块如果有什么需求的话,也可在评论区留言,我看到一些比较合理的需求,也会加入到托管的项目,但是大家请不要太过于期待。

我们还是需要有一定的成本保障,目前的去不图床啊,它本身是一个公益,奈何后期有大量的恶意用户,包括受到过一些攻击造成了巨大的运营成本。

所以没办法最终改成了收费,很多小伙伴也找我细聊。有些小伙伴注意到,我们博客圈里还是有一些就是年纪比较轻,对于他们来说,可能一个月的零花钱也没有多少,但是更多的还是一些成年人,对于他们来说,这都不到一包烟的价格,所以他们还是建议我提升去不图床的价格。

但是思前想后还是没有合理定价标准,所以目前还是保持现状。目前这个阶段,杜老师的工资收入可以很好的支撑住去不图床成本。

后期在不超过一定阈值的情况下,杜老师就算是亏本也会持续运营,不能支撑住的时候,会提前跟各位小伙伴们说的,绝对不会突然跑路,请小伙伴放心。

好了,前前后后叭叭了差不多十分钟了,我们今天聊到这里,后期大家如果对这种语音形式感兴趣的话,也请留言告诉给杜老师。拜拜!

  •  

杜老师说旗下服务调整回源策略

2023年8月6日 00:00

经常光顾本站的小伙伴都很清楚,杜老师使用家中服务器对外提供服务。因家用宽带会封禁 80 等端口,借助 CDN 的端口回源功能,可使用户通过域名直接访问杜老师说旗下服务,但经常会遇到回源问题。点击进入本文听杜老师细聊!

回源问题

首先我们使用去不图床举例,说明下之前的网络连接拓扑。

内网的服务器是树莓派,映射端口分别为 80 和 443,通过软路由转换为可用端口,再使用 CDN 端口回源反代加速。

优点是网络节点少,效率较高。缺点是家用带宽会变动地址,需要经常调整 CDN 的回源地址。

之前杜老师通过 DDNS,加 DNSPod 付费服务「TTL 最低值」解决回源地址变动问题。

但是会有一段时间无法访问,原因还是出现在回源地址的解析上面。

新地址获得后,需要等待一段时间,才会同步到 DDNS。而 CDN 本地解析缓存时间较长,导致无法及时获取到新地址,就造成了回源失败。

内网穿透

为了加快地址变更后的回源生效速度,杜老师决定改为使用内网穿透的方式解决这一问题。

内网穿透是种网络技术,它允许局域网内的设备通过互联网与外部网络通信。这种技术通常用于家庭、办公室或其它内部网络环境,其中设备的 IP 地址是私有的,无法直接与公共互联网通信。

内网穿透的基本原理是通过在公共互联网上创建一个代理服务器,该服务器充当内部网络与外部网络之间的中介。当内部网络中的设备需与外部网络通信时,它会将数据发到代理服务器,然后由代理服务器将数据转发到目标设备。同样,当外部设备需与内部设备通信时,代理服务器会将数据发送到内部设备。

内网穿透的主要应用场景包括:远程访问、远程办公、游戏服务器及私有云服务等。

工具选择

在众多内网穿透工具中,杜老师选择 frp。

frp 是一个专注于内网穿透的高性能的反向代理应用,支持 TCP/UDP/HTTP/HTTPS 等多种协议,且支持 P2P 通信。可以将内网服务以安全、便捷的方式通过具有公网 IP 节点的中转暴露到公网。

工具特点

  1. 客户端服务端通信支持 TCP/QUIC/KCP 以及 Websocket 多种协议;

  2. 采用 TCP 连接流复用,在单个连接间承载更多请求,节省连接建立时间,降低请求延迟;

  3. 代理组间负载均衡;

  4. 端口复用,多个服务通过同一个服务端端口暴露;

  5. 支持 P2P 的通信形式,流量不经过服务器中转,充分利用带宽资源;

  6. 多个原生支持的客户端插件,便于独立使用 frp 客户端完成某些工作;

  7. 高度扩展的服务端插件系统,易于结合自身需求进行功能扩展;

  8. 服务端和客户端 UI 页面。

服务部署

从官网页面下载软件包,解压其中的 frps 及 frps.ini 文件,并上传至服务端/opt/目录「可上传至任意目录,但影响到下面服务配置路径」编辑 frps.ini 文件并添加 token 项「等号右侧的值可自定义,与客户端相同」

1
2
3
[common]
bind_port = 7000
token = dusays.com

使用 systemd 控制 frps 的运行状态及配置开机自启,运行命令 vim /etc/systemd/system/frps.service 并添加下面代码,即可通过 systemctl start frps 启动 frp,使用命令 systemctl enable frps 配置 frps 开机自启:

1
2
3
4
5
6
7
8
9
10
11
12
13
[Unit]
# 服务名称,可自定义
Description = frp server
After = network.target syslog.target
Wants = network.target

[Service]
Type = simple
# 启动frps的命令,需修改为您的frps的安装路径
ExecStart = /opt/frps -c /opt/frps.ini

[Install]
WantedBy = multi-user.target

客户部署

从官网页面下载软件包,解压其中的 frpc 及 frpc.ini 文件,并上传至客户端/opt/目录「可上传至任意目录,但影响到下面进程守护管理器的运行路径」编辑 frpc.ini 文件并添加以下内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[common]
server_addr = 123.123.123.123
server_port = 7000
token = dusays.com

[web]
type = tcp
local_ip = 127.0.0.1
local_port = 80
remote_port = 8780

[web2]
type = tcp
local_ip = 127.0.0.1
local_port = 443
remote_port = 8443

杜老师使用的宝塔面板,安装了进程守护管理器插件,按照如下的配置即可运行客户端:

  •  

来自杜老师的求助信息

2023年7月16日 00:00

眼看着博客的周年庆就快过去了,杜老师一直心想着大改框架,但是苦于找不到一款好程序,在此发布求助信息,希望小伙伴们可以帮忙推荐一些程序,满足杜老师的框架需求。

目前现状

目前 Hexo 的插件加 Volantis 附加功能可以满足杜老师说呈现需求,现期正在静候 Volantis 新版本更新,短期内不会有较大变动。不过有个比较大的问题,就是页面生成时间太长,平均每次部署都需要十分钟:

手中资源

目前杜老师具有 WordPress 两款付费主题,分别是知更鸟和大前端「知更鸟见下图」

具有 Typecho 一款付费主题,是 handsome「handsome 见下图」

具有 Halo 一款付费主题,是 PandaPro「PandaPro 见下图」

还有一些其它资源,在这里就不一一说明了「大前端见下图」

选型问题

WordPress 是杜老师之前用过的框架,其臃肿性被杜老师鄙夷,所以打算不再使用这款框架。

Typecho 是目前观望一款框架,程序轻量、主题完善、插件健全,如果实在没得选可能用该款。

Halo 是杜老师十分看好的一款框架,但其无法自定义 URL,加上数据的保存形式暂不做选择。

除以上几款外,其它程序暂未发现心仪主题,但考虑 Hexo 部署时间太长,不得已也要取舍了!

框架需求

  1. 首先支持高定制 URL,即可以设置每篇文章的访问地址,为的是使现有文章访问地址不变「必选」

  2. 高度兼容 Markdown 的语法,可以更加方便导入 Hexo 的文章,当然不支持没关系,大不了逐一复制也可以;

  3. 如支持数据库,希望可选数据库支持 MySQL,可以直接修改数据,不要那种 blob 类型的;

  4. 如是静态框架,希望可以技术成熟,满足上述要求同时还能快速部署。如是动态框架,希望可以是轻量级。以上均不考虑付费问题!

  •  

下一代静态博客框架 Valaxy

2023年6月1日 00:00

杜老师一直在找 Hexo 替代框架,因为杜老师说博客文章量比较多,站点页面生成速度太慢,经晓雨童靴的推荐,了解到 Valaxy 框架。本文介绍 Valaxy 的特点,以及部署方式,感兴趣的小伙伴可以尝试下!

框架介绍

Valaxy 的目标是成为新一代静态博客框架与生成器。提供更好热更新与用户加载体验、更强大更便捷自定义开发可能性。支持配置、文章的热更新,而不像 Hexo 一样重新加载页面。

它与 Hexo 相比开发体验和速度上都更胜一筹,且与 VitePress/VuePress 相比拥有更多针对博客的集成功能,譬如文章列表钩子、自动路由、组件注册、可覆盖的布局与主题等。

Valaxy 基于 Vite 提供热更新与打包功能,基于 Vue 实现视图等客户端的功能。因此 Valaxy 兼容并可自由使用 Vite 与 Vue 生态所有插件。

Valaxy 已经默认集成 Open Graph 的 SEO 优化。需要注意的是,对于许多搜索引擎来说,它们可能只青睐 SSG 构建模式。

部署过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
penn@penn-PC:~/Desktop$ sudo npm i -g pnpm
请输入密码:
验证成功

added 1 package in 13s

1 package is looking for funding
run `npm fund` for details
penn@penn-PC:~/Desktop$ npm init valaxy
Need to install the following packages:
create-valaxy@0.14.30
Ok to proceed? (y)

🌌 Valaxy v0.14.30

Project name: … valaxy-blog
📁 /home/penn/Desktop/valaxy-blog

Scaffolding project in valaxy-blog ...
Done.

✔ Install and start it now? … yes
✔ Choose the agent › pnpm
Downloading registry.npmjs.org/typescript/4.8.4: 11.9 MB/11.9 MB, done
Packages: +435
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Packages are hard linked from the content-addressable store to the virtual store.
Content-addressable store is at: /home/penn/.local/share/pnpm/store/v3
Virtual store is at: node_modules/.pnpm
node_modules/.pnpm/vue-demi@0.14.5_vue@3.3.4/node_modules/vue-demi: Running postinstall script, done in 119ms
Progress: resolved 457, reused 0, downloaded 435, added 435, done
node_modules/.pnpm/esbuild@0.17.19/node_modules/esbuild: Running postinstall script, done in 73ms

dependencies:
+ valaxy 0.14.30
+ valaxy-theme-yun 0.14.30

devDependencies:
+ typescript 4.8.4 (5.1.3 is available)

 WARN  Issues with peer dependencies found
.
├─┬ valaxy 0.14.30
│ └─┬ vite-ssg 0.22.2
│ └── ✕ unmet peer critters@^0.0.16: found 0.0.17 in valaxy
└─┬ valaxy-theme-yun 0.14.30
└─┬ valaxy-addon-waline 0.1.0
└── ✕ unmet peer valaxy@latest: found 0.14.30

Done in 1m 34.2s

> valaxy-blog@0.14.30 dev /home/penn/Desktop/valaxy-blog
> valaxy

ℹ Resolve valaxyConfig from /home/penn/Desktop/valaxy-blog/valaxy.config.ts 03:31:05
ℹ Resolve siteConfig from /home/penn/Desktop/valaxy-blog/site.config.ts 03:31:05
ℹ Resolve valaxy.config.ts from theme(yun) 03:31:05
ℹ Resolve addons: 03:31:06

🌌 Valaxy v0.14.30

🪐 theme > yun
📁 /home/penn/Desktop/valaxy-blog

Preview > http://localhost:4859/
Network > http://192.168.36.141:4859/

shortcuts > restart | open | edit

注意:官方推荐使用 pnpm 来部署,所以杜老师第一步安装了 pnpm。另外在 Choose the agent 一步,需要选 pnpm。完成 Valaxy 的部署后会自动运行,默认端口号 4859。

博客更新

如需发布文章,进入到博客根目录的 pages/posts,新建.md 文件就行了,内容结构如下:

1
2
3
4
5
6
7
8
9
10
11
---
title: Title
hide: true
excerpt_type: text
---

这是摘要

<!-- more -->

这是正文

参数作用详见下表:

参数作用阈值
title文章标题暂无
hide临时隐藏某篇文章当设置为 true 或 all 时,文章仍然会被渲染,可以直接访问链接进行查看。但不会被显示在展示的文章卡片与归档中;当设置为 index 时,将只在首页隐藏归档中仍然展示。
excerpt_type预览列表摘要渲染类型md 展示原始 Markdown;html 以 HTML 的形式展示;text 以纯文本的形式展示。

从 Hexo 迁移

Hexo 博客目录与 Valaxy 博客目录对应的关系如下,将相关的内容复制至对应文件夹即可:

用途HexoValaxy
文章source/_postspages/posts
页面sourcepages
静态资源sourcepublic

托管部署

  1. GitHub Pages: 在创建模版项目时,已内置文件 .github/workflows/gh-pages.yml 以实现 GitHub Actions 的自动部署工作流。

  2. Netlify: 已内置 netlify.toml。

  3. Vercel: 将 Framework Preset 设置为 Other,并更改 Build and Output Settings,将 Output Directory 设置为 dist 后点击 Deploy。

  4. Cloudflare Pages: 点击创建应用程序——连接到 Git,然后选择点击开始设置,将构建输出目录设置为 dist 后添加一个环境变量。变量名称设置为 NODE_VERSION,阈值为 16.0,最后点击保存并部署就行了。

使用体验

杜老师将已发布的 590 篇文章迁移到 Valaxy,仅需 20 秒即可生成站点页面文件,而通过 Hexo 则需要 8 分钟「大概是因为杜老师说使用了太多插件」

不过毕竟是新型的框架,目前主题及插件比较少,并不足以满足杜老师的使用需求,想折腾的小伙伴可以尝试下,杜老师也在坐等着更多模板。

  •  

说说广场代码分享

2023年4月23日 00:00

首先感谢下林木木童鞋,参考他的代码才有此篇教程,效果可以参考本博说说广场。杜老师不擅长前端,如有更好样式,欢迎在评论区提出建议。本教程样式不兼容所有博客模板,如有错位等问题的出现,可在评论区中留言!

准备工作

此篇教程兼容各类博客框架,不管用的是 Hexo/Hugo/Typecho/WordPress 都可直接使用。

若无服务器可以不用搭建 Memos,借助现有平台「如杜老师的 https://s.dusays.com」注册账户即可。

广场代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<script>
if (typeof Lately === 'undefined') {
const script = document.createElement('script');
script.src = 'https://jsd.onmicrosoft.cn/gh/Tokinx/Lately/lately.min.js';
script.onload = () => {
Lately.init({ target: '.bbs-date' });
};
document.head.appendChild(script);
} else {
Lately.init({ target: '.bbs-date' });
}
const urls = [
{home:"https://s.dusays.com/",host:"https://s.dusays.com/",apiV1:'v1/',creatorId:"1",comment:'',imgsrc:"https://cravatar.cn/avatar/28b57baa4e8f13fe4292ccb2de267e30"},
{home:"https://s.dusays.com/",host:"https://s.dusays.com/",apiV1:'v1/',creatorId:"70",comment:'',imgsrc:"https://bu.dusays.com/2023/07/13/64b00b0a2586c.png"}
]
var bbDom = document.querySelector('#bbs');
var load = '<div id="load" onclick="nextFetch()" ><button class="load-btn button-load">加载更多</button></div>'
var loading = '<div class="loader"><svg class="circular" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="2" stroke-miterlimit="10"/></svg></div>'
var bbsDatas = [],bbsData = {},nextDatas = [],nextData = {},limit = 2
var page = 1,offset = 0,nextLength = 0,nextDom='',bbUrlNow = '',imgsrcNow = '',hostNow = '',creIdNow = '',commentNow = '',twiEnvNow='',artEnvNow='',artSiteNow=''
bbDom.innerHTML = loading
allUrls()
function allUrls(){
var myHtml = ''
for(var i=0;i < urls.length;i++){
myHtml += '<div class="bbs-urls bbs-url" onclick="urlsNow(this)" data-hostid="'+urls[i].host+"u/"+urls[i].creatorId+'" data-host="'+urls[i].host+'" data-apiV1="'+urls[i].apiV1+'" data-creatorId="'+urls[i].creatorId+'" data-imgsrc="'+urls[i].imgsrc+'" data-comment="'+urls[i].comment+'" data-home="'+urls[i].home+'" data-twienv="'+urls[i].twiEnv+'" data-artenv="'+urls[i].artEnv+'" data-artsite="'+urls[i].artSite+'" data-index="'+i+'"><img src="'+urls[i].imgsrc+'" alt=""></div>'
}
myHtml += '<div class="bbs-urls urls-button" onclick="urlsNow(this)" data-type="random"><svg t="1665928089691" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2562" width="32" height="32"><path d="M913.2 672l98.8 57.1c5.3 3.1 5.3 10.8 0 13.9l-43.4 25L710.4 924c-2.7 1.5-6-0.4-6-3.5V772c0-2.2-1.8-4-4-4H544c-70.4 0-134.4-28.8-180.8-75.2-11.1-11.1-21.2-23.2-30.1-36.1-6.4-9.2-20-9.1-26.4 0.1C260.5 723.9 183.1 768 96 768h-48c-26.5 0-48-21.5-48-48s21.5-48 48-48h48c42.5 0 82.6-16.7 112.9-47.1 30.4-30.4 47.1-70.5 47.1-112.9s-16.7-82.6-47.1-112.9C178.6 368.7 138.4 352 96 352h-48c-26.5 0-48-21.5-48-48s21.5-48 48-48h48c70.4 0 134.4 28.8 180.8 75.2 11.1 11.1 21.2 23.2 30.1 36.1 6.4 9.2 20 9.1 26.4-0.1 46.3-67 123.6-111.1 210.8-111.1H700.4c2.2 0 4-1.8 4-4V103.4c0-3.1 3.3-5 6-3.5l258.2 156 43.4 25.1c5.3 3.1 5.3 10.8 0 13.9L913.2 352 710.4 476c-2.7 1.5-6-0.4-6-3.5V356c0-2.2-1.8-4-4-4H544c-42.5 0-82.6 16.7-112.9 47.1-30.4 30.4-47.1 70.5-47.1 112.9 0 42.5 16.7 82.6 47.1 112.9C461.4 655.3 501.5 672 544 672H700.4c2.2 0 4-1.8 4-4V551.4c0-3.1 3.3-5 6-3.5L913.2 672z" p-id="2563" fill="#f5f5f5"></path></svg></div>'
myHtml += '<div class="bbs-urls urls-button"><a href="https://s.dusays.com/"><svg t="1665929410343" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6308" width="32" height="32"><path d="M906.212134 565.732986 565.732986 565.732986 565.732986 906.212134C565.732986 926.013685 541.666486 959.972 511.97312 959.972 482.297674 959.972 458.213254 926.013685 458.213254 906.212134L458.213254 565.732986 117.734106 565.732986C97.950475 565.732986 63.97424 541.666486 63.97424 511.97312 63.97424 482.279754 97.950475 458.213254 117.734106 458.213254L458.213254 458.213254 458.213254 117.734106C458.213254 97.950475 482.297674 63.97424 511.97312 63.97424 541.666486 63.97424 565.732986 97.950475 565.732986 117.734106L565.732986 458.213254 906.212134 458.213254C925.995765 458.213254 959.972 482.279754 959.972 511.97312 959.972 541.666486 925.995765 565.732986 906.212134 565.732986Z" p-id="6309" fill="#f5f5f5"></path></svg></a></div>'
myHtml = '<div id="bbs-urls">'+myHtml+'</div>'
bbDom.insertAdjacentHTML('beforebegin', myHtml);
}
function nextFetch(){
document.querySelector("button.button-load").textContent= '加载中……';
updateHTMl(nextDatas)
if(nextLength < 10){
document.querySelector("button.button-load").remove()
return
}
getNextList()
};
function urlsNow(e){
var domUrls = document.querySelectorAll('#bbs-urls .bbs-urls')
if(e.classList.contains('url-now')){
domUrls[e.getAttribute("data-index")].classList.remove("url-now")
fetchBBser()
}else{
domUrls.forEach(function(value,index){ domUrls[index].classList.remove("url-now")})
var btn = document.querySelector('button.button-load')
if(btn){btn.remove()}
page = 1,offset = 0
bbDom.innerHTML = loading
var type = e.getAttribute("data-type")
if(type == 'random'){
var num = Math.round(Math.random() * (urls.length-1))
hostNow = urls[num].host
creIdNow = urls[num].creatorId
imgsrcNow = urls[num].imgsrc
commentNow = urls[num].comment
twiEnvNow = urls[num].twiEnv
artEnvNow = urls[num].artEnv
artSiteNow = urls[num].artSite
homeNow = urls[num].home
apiV1Now = urls[num].apiV1
domUrls[num].classList.add("url-now")
}else{
domUrls[e.getAttribute("data-index")].classList.add("url-now")
hostNow = e.getAttribute("data-host")
creIdNow = e.getAttribute("data-creatorId")
imgsrcNow = e.getAttribute("data-imgsrc")
commentNow = e.getAttribute("data-comment")
twiEnvNow = e.getAttribute("data-twienv")
artEnvNow = e.getAttribute("data-artenv")
artSiteNow = e.getAttribute("data-artsite")
homeNow = e.getAttribute("data-home")
apiV1Now = e.getAttribute("data-apiV1")
}
bbUrlNow = hostNow+"api/"+apiV1Now+"memo?creatorId="+creIdNow+"&rowStatus=NORMAL&limit=10"
fetch(bbUrlNow).then(res => res.json()).then( resdata =>{
var arrData = resdata || ''
if(resdata.data){
arrData = resdata.data
}
bbDom.innerHTML = ''
bbsDatas.length = 0
for(var j=0;j < arrData.length;j++){
var resValue = arrData[j]
bbsData = {
memoId: resValue.id,
updatedTs: resValue.updatedTs,
creatorId:resValue.creatorId,
creator: resValue.creatorName || resValue.creator.nickname || resValue.creator.name,
imgsrc: imgsrcNow,
content: resValue.content,
resourceList: resValue.resourceList,
url:hostNow,
twiEnv:twiEnvNow,
artEnv:artEnvNow,
artSite:artSiteNow,
home:homeNow,
comment: commentNow
}
bbsDatas.push(bbsData)
}
updateHTMl(bbsDatas)
bbDom.insertAdjacentHTML('afterend', load);
var nowLength = bbsData.length
if(nowLength < 10){
document.querySelector("button.button-load").remove()
return
}
page++
offset = 10*(page-1)
getNextList()
});
}
}
function getNextList(){
var bbUrl = bbUrlNow+"&offset="+offset;
fetch(bbUrl).then(res => res.json()).then( resdata =>{
var arrData = resdata || ''
if(resdata.data){
arrData = resdata.data
}
nextDom = arrData
nextLength = nextDom.length
page++
offset = 10*(page-1)
if(nextLength < 1){
document.querySelector("button.button-load").remove()
return
}
nextDatas.length = 0
for(var j=0;j < nextDom.length;j++){
var resValue = nextDom[j]
nextData = {
updatedTs: resValue.updatedTs,
creatorId:resValue.creatorId,
creator: resValue.creatorName || resValue.creator.nickname || resValue.creator.name,
imgsrc: imgsrcNow,
content: resValue.content,
resourceList: resValue.resourceList,
url:hostNow,
twiEnv:twiEnvNow,
artEnv:artEnvNow,
artSite:artSiteNow,
comment:commentNow,
memoId: resValue.id,
home:homeNow,
}
nextDatas.push(nextData)
}
})
}
const withTimeout = (millis, promise) => {
const timeout = new Promise((resolve, reject) =>
setTimeout( () => reject(`Timed out after ms.`),millis));
return Promise.race([
promise,
timeout
]);
};
const fetchBBser = async () => {
const results = await Promise.allSettled(urls.map(
url => withTimeout(2000,
fetch(url.host+"api/"+url.apiV1+"memo?creatorId="+url.creatorId+"&rowStatus=NORMAL&limit="+limit).then(response => response.json()).then(resdata => {
var qsLive = ".bbs-urls.bbs-url[data-hostid='"+url.host+"u/"+url.creatorId+"']"
document.querySelector(qsLive).classList.add("liveon");
var arrData = resdata || ''
if(resdata.data){
arrData = resdata.data
}
return arrData
})
)
)).then(results=> {
bbDom.innerHTML = ''
for(var i=0;i < results.length;i++){
var status = results[i].status
if(status == "fulfilled"){
var resultsRes = results[i].value
for(var j=0;j < resultsRes.length;j++){
var resValue = resultsRes[j]
var dateNow = new Date()
var dateDiff = dateNow.getTime() - (resValue.updatedTs * 1000);
var dayDiff = Math.floor(dateDiff / (24 * 3600 * 1000));
if(dayDiff < 10 ){
bbsData = {
memoId: resValue.id,
updatedTs: resValue.updatedTs,
creatorId:resValue.creatorId,
creator: resValue.creatorName || resValue.creator.nickname || resValue.creator.name,
imgsrc: urls[i].imgsrc,
content: resValue.content,
resourceList: resValue.resourceList,
home:urls[i].home,
url:urls[i].host,
comment:urls[i].comment,
twiEnv:urls[i].twiEnv || '',
artEnv:urls[i].artEnv || '',
artSite:urls[i].artSite || ''
}
bbsDatas.push(bbsData)
}
}
}
}
bbsDatas.sort(compare("updatedTs"));
updateHTMl(bbsDatas)
})
}
fetchBBser()
function compare(p){
return function(m,n){
var a = m[p];
var b = n[p];
return b - a;
}
}
function uniqueFunc(arr){
const res = new Map();
return arr.filter((item) => !res.has(item.creator) && res.set(item.creator, 1));
}
function updateHTMl(data){
var result="",resultAll="";
const TAG_REG = /#([^\s#]+)/;
const IMG_REG = /\!\[(.*?)\]\((.*?)\)/g;
BILIBILI_REG = /<a.*?href="https:\/\/www\.bilibili\.com\/video\/((av[\d]{1,10})|(BV([\w]{10})))\/?".*?>.*<\/a>/g;
NETEASE_MUSIC_REG = /<a.*?href="https:\/\/music\.163\.com\/.*id=([0-9]+)".*?>.*<\/a>/g;
QQMUSIC_REG = /<a.*?href="https\:\/\/y\.qq\.com\/.*(\/[0-9a-zA-Z]+)(\.html)?".*?>.*?<\/a>/g;
QQVIDEO_REG = /<a.*?href="https:\/\/v\.qq\.com\/.*\/([a-z|A-Z|0-9]+)\.html".*?>.*<\/a>/g;
YOUKU_REG = /<a.*?href="https:\/\/v\.youku\.com\/.*\/id_([a-z|A-Z|0-9|==]+)\.html".*?>.*<\/a>/g;
YOUTUBE_REG = /<a.*?href="https:\/\/www\.youtube\.com\/watch\?v\=([a-z|A-Z|0-9]{11})\".*?>.*<\/a>/g;
marked.setOptions({
breaks: true,
smartypants: false,
langPrefix: 'language-'
});
const renderer = new marked.Renderer();
const linkRenderer = renderer.link;
renderer.link = (href, title, text) => {
const localLink = href.startsWith(`${location.protocol}//${location.hostname}`);
const html = linkRenderer.call(renderer, href, title, text);
return localLink ? html : html.replace(/^<a /, `<a target="_blank" rel="noreferrer noopener nofollow" `);
};
marked.use({ renderer });
for(var i=0;i < data.length;i++){
var memos = data[i].url
var memoId = data[i].memoId
var memoUrl = memos + "m/" + memoId
var comment = data[i].comment
var twiEnv = data[i].twiEnv
var artEnv = data[i].artEnv
var artSite = data[i].artSite
var bbContREG = data[i].content
.replace(TAG_REG, "<span class='tag-span'>#$1</span> ")
.replace(IMG_REG, '')
bbContREG = marked.parse(bbContREG)
.replace(BILIBILI_REG, "<div class='video-wrapper'><iframe src='//www.bilibili.com/blackboard/html5mobileplayer.html?bvid=$1&as_wide=1&high_quality=1&danmaku=0' scrolling='no' border='0' frameborder='no' framespacing='0' allowfullscreen='true'></iframe></div>")
.replace(NETEASE_MUSIC_REG, "<meting-js auto='https://music.163.com/#/song?id=$1'></meting-js>")
.replace(QQMUSIC_REG, "<meting-js auto='https://y.qq.com/n/yqq/song$1.html'></meting-js>")
.replace(QQVIDEO_REG, "<div class='video-wrapper'><iframe src='//v.qq.com/iframe/player.html?vid=$1' allowFullScreen='true' frameborder='no'></iframe></div>")
.replace(YOUKU_REG, "<div class='video-wrapper'><iframe src='https://player.youku.com/embed/$1' frameborder=0 'allowfullscreen'></iframe></div>")
.replace(YOUTUBE_REG, "<div class='video-wrapper'><iframe src='https://www.youtube.com/embed/$1' title='YouTube video player' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture' allowfullscreen title='YouTube Video'></iframe></div>")
var IMG_ARR = data[i].content.match(IMG_REG) || '',IMG_ARR_Grid='';
if(IMG_ARR){
var IMG_ARR_Length = IMG_ARR.length,IMG_ARR_Url = '';
if(IMG_ARR_Length !== 1){var IMG_ARR_Grid = " grid grid-"+IMG_ARR_Length}
IMG_ARR.forEach(item => {
let imgSrc = item.replace(/!\[.*?\]\((.*?)\)/g,'$1')
IMG_ARR_Url += '<figure class="gallery-thumbnail"><img class="img thumbnail-image" loading="lazy" decoding="async" src="'+imgSrc+'"/></figure>'
});
bbContREG += '<div class="resimg'+IMG_ARR_Grid+'">'+IMG_ARR_Url+'</div>';
}
var tagArr = data[i].content.match(TAG_REG);
var bbContTag = '';
if (tagArr) {
bbContTag = String(tagArr[0]).replace(/[#]/g, '');
} else {
bbContTag = '动态';
};
if(data[i].resourceList && data[i].resourceList.length > 0){
var resourceList = data[i].resourceList;
var imgUrl='',resUrl='',resImgLength = 0;
for(var j=0;j < resourceList.length;j++){
var restype = resourceList[j].type.slice(0,5);
var resexlink = resourceList[j].externalLink
var resLink = '',fileId=''
if(resexlink){
resLink = resexlink
}else{
fileId = resourceList[j].publicId || resourceList[j].filename
resLink = memos+'o/r/'+resourceList[j].id+'/'+fileId
}
if(restype == 'image'){
imgUrl += '<figure class="gallery-thumbnail"><img class="img thumbnail-image" src="'+resLink+'"/></figure>'
resImgLength = resImgLength + 1
}
if(restype !== 'image'){
resUrl += '<a target="_blank" rel="noreferrer" href="'+resLink+'">'+resourceList[j].filename+'</a>'
}
}
if(imgUrl){
var resImgGrid = ""
if(resImgLength !== 1){var resImgGrid = " grid grid-"+resImgLength}
bbContREG += '<div class="resimg'+resImgGrid+'">'+imgUrl+'</div>'
}
if(resUrl){
bbContREG += '<div class="resour">'+resUrl+'</div>'
}
}
var EnvNow = ''
if(twiEnv && twiEnv != "undefined"){
EnvNow = twiEnv.replace(/https\:\/\/.*\.(.*)\..*/,'$1')
}
if(artEnv && artEnv != "undefined"){
EnvNow = artEnv.replace(/https\:\/\/.*\.(.*)\..*/,'$1')
}
result += '<li class="'+EnvNow+'memo-'+memoId+'"><div class="bbs-avatar"><a href="'+data[i].home+'" target="_blank" rel="noopener noreferrer"><img src="'+data[i].imgsrc+'" alt=""></a><a href="'+memoUrl+'" target="_blank" rel="noopener noreferrer" class="bbs-creator">'+data[i].creator+'</a><span class="bbs-dot">·</span><span class="bbs-date">'+new Date(data[i].updatedTs * 1000).toLocaleString()+'</span>'
var comSVG = '<span class="bbs-coment-svg"><svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="24"><path d="M816 808H672c-4.8 0-8 1.6-11.2 4.8l-80 80c-36.8 36.8-97.6 36.8-136 0l-80-80c-3.2-3.2-6.4-4.8-11.2-4.8h-144c-70.4 0-128-57.6-128-128V232c0-70.4 57.6-128 128-128h608c70.4 0 128 57.6 128 128v448C944 750.4 886.4 808 816 808zm0-64c35.2 0 64-28.8 64-64V232c0-35.2-28.8-64-64-64H208c-35.2 0-64 28.8-64 64v448c0 35.2 28.8 64 64 64h144c20.8 0 41.6 8 56 24l80 80c12.8 12.8 32 12.8 44.8 0l80-80c14.4-14.4 35.2-24 56-24H816zM320 408c27.2 0 48 20.8 48 48v32c0 27.2-20.8 48-48 48s-48-20.8-48-48v-32c0-27.2 20.8-48 48-48zm192 0c27.2 0 48 20.8 48 48v32c0 27.2-20.8 48-48 48s-48-20.8-48-48v-32c0-27.2 20.8-48 48-48zm192 0c27.2 0 48 20.8 48 48v32c0 27.2-20.8 48-48 48s-48-20.8-48-48v-32c0-27.2 20.8-48 48-48z" /></svg></span>'
var outSVG = '<span class="bbs-coment-svg"><svg class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="20" height="20"><path d="M864 640a32 32 0 0 1 64 0v224.096A63.936 63.936 0 0 1 864.096 928H159.904A63.936 63.936 0 0 1 96 864.096V159.904C96 124.608 124.64 96 159.904 96H384a32 32 0 0 1 0 64H192.064A31.904 31.904 0 0 0 160 192.064v639.872A31.904 31.904 0 0 0 192.064 864h639.872A31.904 31.904 0 0 0 864 831.936V640zm-485.184 52.48a31.84 31.84 0 0 1-45.12-.128 31.808 31.808 0 0 1-.128-45.12L815.04 166.048l-176.128.736a31.392 31.392 0 0 1-31.584-31.744 32.32 32.32 0 0 1 31.84-32l255.232-1.056a31.36 31.36 0 0 1 31.584 31.584L924.928 388.8a32.32 32.32 0 0 1-32 31.84 31.392 31.392 0 0 1-31.712-31.584l.736-179.392L378.816 692.48z"/></svg></span>'
if(comment == '1'){
if(twiEnv && twiEnv != 'undefined'){
result += '<a data-id="'+memoId+'" data-twienv="'+twiEnv+'" data-path="'+memoUrl+'" onclick="loadTwikoo(this)" onmouseenter="insertTwikoo(this)" href="javascript:void(0)" rel="noopener noreferrer">'+comSVG+'</a></div><div class="bbs-content"><div class="bbs-text">'+bbContREG+'</div><div class="item-comment twikoo-'+memoId+' d-none"><div id="'+EnvNow+'twikoo-'+memoId+'"></div></div></div></li>'
}else if(artEnv && artEnv != 'undefined'){
result += '<a data-id="'+memoId+'" data-artenv="'+artEnv+'" data-artsite="'+artSite+'" data-path="'+memoUrl+'" onclick="loadArtalk(this)" href="javascript:void(0)" rel="noopener noreferrer">'+comSVG+'</a></div><div class="bbs-content"><div class="bbs-text">'+bbContREG+'</div><div class="item-comment '+EnvNow+'artalk-'+memoId+' d-none"></div></div></li>'
}else{
result += '<a href="'+memoUrl+'" target="_blank" rel="noopener noreferrer">'+outSVG+'</a></div><div class="bbs-content"><div class="bbs-text">'+bbContREG+'</div></div></li>'
}
}else{
result += '</div><div class="bbs-content"><div class="bbs-text">'+bbContREG+'</div></div></li>'
}
}
var bbBefore = "<section class='bbs-timeline'><ul class='list'>"
var bbAfter = "</ul></section>"
resultAll = bbBefore + result + bbAfter
bbDom.insertAdjacentHTML('beforeend', resultAll);
var btn = document.querySelector('button.button-load')
if(btn){
btn.textContent= '加载更多';
}
window.ViewImage && ViewImage.init('.bbs-content img')
window.Lately && Lately.init({ target: '.bbs-date' });
}
</script>

注意:如需增加站点,可增加 const urls 字段,注意格式。

样式代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<style>
#bbs{padding: 2rem 0;}
#bbs-urls{margin-top: 2rem;}
.bbs-urls{display:inline-block;background: #4a4b50;border-radius:10%;margin:0 .6rem 0 0;padding:4px;width:3.4rem;height:3.4rem;cursor: pointer;vertical-align: text-bottom;}
.bbs-urls img{border-radius:50%;width:100%;height:100%;}
.bbs-urls.url-now{background:#42b983;transition: 0.6s;}
.urls-button svg.icon{padding:10px;width:100%;height: 100%;}
.bbs-timeline ul {margin:0;padding: 0;}
.bbs-timeline ul li{list-style-type:none;position:relative;}
.bbs-timeline{max-width:1200px;margin:0 auto;}
.bbs-avatar{position: relative;}
.bbs-avatar img{width:24px;height:24px;border-radius:50%;margin-right:1rem;}
div.bbs-avatar > img {
display: inline-block;
margin: 0 10px 0 0;
}
.bbs-creator,.bbs-date,.bbs-dot{position:relative;top:-5px;}
.bbs-dot{font-weight: 800;margin:0 .5rem;}
.bbs-content {margin-bottom: 3rem;}
.bbs-text,.resour{background: var(--color-block);border-radius: 8px;font-size: 1em;padding:10px 14px;position: relative;}
.resour{font-size: 0.9rem;margin-top: 2px;padding: 5px 14px;}
.bbs-text{overflow:hidden;max-height:90vh;}
.bbs-text blockquote{font-family: KaiTi,STKaiti,STFangsong;margin:0 0 0 1rem;padding:.25rem 2rem;position: relative;border-left:0 none;}
.bbs-text blockquote::before{line-height: 2rem;content: "“";font-family: Georgia, serif;font-size: 28px;font-weight: bold;position: absolute;left: 10px;top:5px;}
.bbs-text p{margin:0;}
.bbs-text pre p{display: inline-block;}
.bbs-text pre p:empty{display: none;}
.tag-span{color: #42b983;}
#load button.load-btn{width:100%;padding:8px 0;background: var(--color-block);}
#bb-footer{letter-spacing:8px;margin:5rem auto 1rem;text-align:center;}
.dark .bbs-text,.dark .resour{background:#4a4b50;}
.dark .bbs-text p{color:#fafafa;}
.loader {position: relative;margin:3rem auto;width: 100px;}
.loader::before {content: '';display: block;padding-top: 100%;}
.circular {animation: rotate 2s linear infinite;height: 100%;transform-origin: center center;width: 100%;position: absolute;top: 0;bottom: 0;left: 0;right: 0;margin: auto;}
.path {stroke-dasharray: 1, 200;stroke-dashoffset: 0;animation: dash 1.5s ease-in-out infinite, color 6s ease-in-out infinite;stroke-linecap: round;}
@keyframes rotate {100% {transform: rotate(360deg);}}
@keyframes dash {
0% {stroke-dasharray: 1, 200;stroke-dashoffset: 0;}
50% {stroke-dasharray: 89, 200;stroke-dashoffset: -35px;}
100% {stroke-dasharray: 89, 200;stroke-dashoffset: -124px;}
}
@keyframes color {
100%,0% {stroke: #d62d20;}40% {stroke: #0057e7;}66% {stroke: #008744;}80%,90% {stroke: #ffa700;}
}
.bbs-content p > img{cursor:pointer;border:1px solid #3b3d42;}
.bbs-content p:has(img.img){display: inline-block;}
.bbs-text p > img {display: block;}
.bbs-text p > img:first-child:nth-last-child(n+2),.bbs-text p > img:first-child:nth-last-child(n+2) ~ img {display: inline-block;}
.bbs-content p > img.square{height:180px;width:180px;object-fit:cover;}
.resimg.grid{
display: grid;
grid-template-columns: repeat(3,1fr);
grid-template-rows:auto;
gap: 4px;
width: calc(100%* 2 / 3);
box-sizing: border-box;
margin: 4px 0 0;
}
.resimg.grid-2{
grid-template-columns: repeat(2, 1fr);
width: 80%;
}
.resimg.grid-4{
grid-template-columns: repeat(2, 1fr);
width: calc(80% * 2 / 3);
}
.resimg.grid figure.gallery-thumbnail {
position: relative;
width: 100%;
height: 0;
padding-top: 100%;
cursor: zoom-in;
}
.resimg figure{
text-align: left;
max-height:50%;
}
.resimg figure img{
max-height:50vh;
}
.resimg.grid figure, figcaption {
margin: 0 !important;
}
.resimg.grid figure.gallery-thumbnail > img.thumbnail-image {
position: absolute;
left: 0;
top: 0;
display: block;
width: 100%;
height: 100%;
object-fit: cover;
object-position: 50% 50%;
}
.video-wrapper{position:relative;padding-bottom:55%;width:100%;height:0}
.video-wrapper iframe{position:absolute;height:100%;width:100%;}
</style>

注意:上面的样式杜老师做了微调,效果可见本站说说广场,如不满意也可自行调整。

展示代码

1
2
3
4
<div id="bbs"></div>
<script type="text/javascript" src="https://jsd.onmicrosoft.cn/npm/marked@4.3.0/marked.min.js"></script>
<script type="text/javascript" src="https://jsd.onmicrosoft.cn/gh/Tokinx/ViewImage/view-image.min.js"></script>
<script type="text/javascript" src="https://jsd.onmicrosoft.cn/gh/Tokinx/Lately/lately.min.js"></script>

注意:根据自身需求修改对应代码,如有任何问题,可随时在评论区中留言!

  •  

AI 写作对博主影响

2023年4月8日 00:00

当今数字时代,AI 写作已经成为越来越受欢迎的一种方式。AI 写作技术已非常成熟,许多人选择使用 AI 写作工具来帮助他们快速创建高质量内容。但是,这种技术对于博主来说究竟有什么影响呢?

提高写作效率

使用 AI 写作工具可以帮助博主在更短的时间内创作出更多的内容。这种工具可以帮助博主快速生成文章的结构和主题,也可以提供一些提示和建议来帮助博主更好地组织、表达想法。

这样,博主就可以更快地完成写作任务,有更多的时间来处理其它重要的事情。

带来新的创意

AI 写作工具通常会提供一些新颖的想法和主题,这些想法可能会激发博主的灵感,帮助他们创作出更有价值的内容。

此外,AI 写作工具也可识别出一些已有的文章中的主题和想法,并在此基础提出一些新的见解和建议。

提高内容质量

对于大多数的博主来说,质量是非常重要的。AI 写作工具可以帮助博主优化他们的文章,使它们更加的清晰、流畅、易读。

这些工具可以提供一些语法和拼写方面的帮助,还可以识别出文章中重复或冗余内容。

降低写作成本

使用 AI 写作工具可帮助博主降低写作成本。这种工具可以帮助博主快速创建大量内容,减少了雇佣写手或编辑需求。

此外,使用 AI 写作工具还可以减轻博主的工作量,使之能够专注于其它的任务。

结论

总之,AI 写作工具对博主来说可以带来很多好处。

它们可以提高写作效率、带来新的创意、提高内容质量,还能降低写作成本。

然而,博主也需注意,AI 写作工具只是一种辅助的工具,它们不能代替博主自己思考和创造力。

因此,博主应该在使用 AI 写作工具同时,保持自己独特性和思考方式。

写在最后

小伙伴们都知道杜老师经营起了知乎,为了快速提升积分,杜老师使用了 ChatGPT 回答问题。

其中也学习到很多知识及写作的技巧,可以说是在回复中提升。

进而也思考了 AI 写作对于博主的影响。

此文是在 AI 写作工具辅助下完成,不得不说有了 AI 的帮助,思路更加清晰,描述更加准确。

但需注意的是,不能过于依赖 AI 来进行创作,还是要表达出博主独特性和思考方式,做一个有态度的博客才会有受众。

最后为 FlowUs 做个广告,已集成 AI 辅助工具,可以实现写作、总结、摘要、解释功能!

  •  

使用 Memos 搭建时光机教程

2023年3月3日 00:00

首先感谢下林木木童鞋,参考他的代码才有此篇教程。时光机的效果可以参考本博说说广场,不过时光机只会展示个人的说说,如需 Memos 的搭建教程,或是广场搭建教程,可以静等之后教程!

写在前面

此篇教程兼容各类博客框架,不管用的是 Hexo/Hugo/Typecho/WordPress 都可直接使用。

若无服务器可以不用搭建 Memos,借助现有平台「如杜老师的 https://s.dusays.com」注册账户即可。

条数统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<div class="container">
<p>共发表了 <span id="memosCount">0</span> 条 Memos 说说!</p>
</div>
<script>
function getTotal() {
var totalUrl = "https://s.dusays.com/api/v1/memo/stats?creatorId=1";
fetch(totalUrl).then(res => res.json()).then(resdata => {
if (resdata) {
var memosCount = document.getElementById('total');
memosCount.innerHTML = resdata.length;
}
}).catch(err => {
});
};
window.onload = getTotal();
</script>

注意:上面代码的 https://s.dusays.com/api/v1/memo/stats?creatorId=1 一句,s.dusays.com 替换成自己 Memos 的域名,结尾的 1 改为用户的 ID。

前端展示

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id="bber"></div>
<script>
var bbMemos = {
memos : 'https://s.dusays.com/',
limit : '10',
creatorId:'1' ,
domId: '#bber',
}
</script>
<script src="https://npm.onmicrosoft.cn/penndu@4.0.9/memos.js"></script>
<script src="https://npm.onmicrosoft.cn/marked/marked.min.js"></script>
<script src="https://jsd.onmicrosoft.cn/gh/Tokinx/ViewImage/view-image.min.js"></script>
<script src="https://jsd.onmicrosoft.cn/gh/Tokinx/Lately/lately.min.js"></script>

注意:上面代码的 bber 可自定义,不要与整站 div 重名;s.dusays.com 替换成自己 Memos 的域名;limit 为展示数量限制,creatorId 对应用户 ID,domId 需与 div id 相同。

补充说明

如果不知道自己的 ID 是多少,可以直接留言问杜老师。或者发表一条说说,然后点击 这里,点击您的用户名称,所进入页面的网址末尾处的数字,就是 ID 了:

  •  

小推一波说说广场

2023年2月28日 00:00

细心的小伙伴应该发现,杜老师调整了说说页面,更换了说说的托管平台,由 Artitalk 调整为 Memos,相比 Artitalk 部署时会泄露 Token,Memos 更加安全且高效,欢迎注册体验!

页面展示

点击导航栏的 说说 即可进入广场。杜老师的前端能力有限,内容展示比较简陋,欢迎小伙伴提供建议及代码:

也可直接访问 说说平台 浏览整合后的内容页面:

注册使用

点击进入 页面 可以注册用户,也可登录账号:

登录后即可管理配置并发布说说:

使用规则

  1. 严禁发布不良内容;

  2. 不得发布带有超链接及有广告嫌疑的内容;

  3. 杜老师有权在不通知的情况下删除任何触犯以上条例的内容;

  4. 最终解释权归杜老师说所有。

扩展应用

如使用 Chrome 内核的浏览器,可以通过安装 扩展 实现快速发布:

如使用安卓系统的手机,可以通过安装 软件 实现快速发布:

  •  

讨论如何通过移动设备更新博客

2023年1月23日 00:00

今天农历正月初二,刚由一个城市,转到了另一个城市,趁着手边恰好有电脑的机会,更新此文,并希望看到的小伙伴可一同讨论!

写在前面

细心的小伙伴可能发现,平时杜老师发布的博文,都会在更新日零点 52 分刷新,那是因为博文已在前一日准备好,GitHub Actions 的计划任务零点 52 分触发自动部署更新博客内容。

今天已经快结束了,博文仍未更新,是因为之前的几天,杜老师身边一直没电脑,所以只好通过移动设备回复评论,但没条件更新博文,故写此文,讨论一下如何通过移动设备更新博客。

智能手机

现在一提手机,没人能想到不智能款式,不过杜老师写下此文时,奶奶刚好在旁边通过老年机听收音机「部分老年机具备FM功能」为了严谨,此段落强调是智能手机。

之前做过一些统计,发现杜老师接触 Hexo 博主,大多都是学生。除了休息日回家用电脑更新,绝大多数时间都是通过手机更新博客。

杜老师使用的工具是 Termux,这是一个终端的模拟器,可使用 Shell 命令,并能通过安装软件添加功能,如 Git。

杜老师会拉取文章仓库到手机中,然后在手机上更新站点内容,再提交至仓库完成更新。一般使用该种方法,都是少量更新需求,如友链等。

平板电脑

为了方便数据跨设备及平台传输,杜老师使用的安卓平板,使用博客维护工具为 AidLux,AidLux 是一个构建在 ARM 硬件上,基于创新性跨 Android+Linux 融合系统环境的智能物联网应用开发和部署平台。

借助 AidLux 不仅可以实现更好的终端操作体验,且通过内置的插件中心,还可安装 Visual Studio Code 等程序,更新博客更加方便!一般使用该种方法,是需要博文更新时,但手边无可用电脑设备。

写在最后

以上是杜老师如何通过移动设备更新博客,因为平时使用移送设备较少「虽然杜老师是一枚狂热的数码爱好者,但手机确实占用了杜老师不少精力和时间,所以在繁忙的工作和学习时,几乎不使用移动设备接收和处理信息」所以了解到的工具较少,希望经常使用移动设备更新博客的小伙伴可以多提建议、参与讨论!

另外杜老师说全年无休,每三天会更新内容,并会满足一些小伙伴的需求,提供宣传及图文教程类博文,欢迎关注!

  •  

WordPress 文件及权限

2023年1月11日 00:00

曾答应了小熊童鞋发布一篇关于 WP 目录权限的教程,本篇就已 Linux 系统加某塔面板为例,讲解 WordPress 各文件作用,及对应权限和设置方法!

文件列表

基于官方最新 6.1.1 版本安装包,内含文件如下:

名称作用
wp-admin存放后台面板相关文件,因文件比较多,这里不做详细介绍
wp-content存放用户上传文件,如模板插件及媒体文件
wp-includes存放 WP 相关库文件,为模板插件提供运行库
index.php核心索引文件 ,也是博客输出文件,里面的代码很简单,定义一个垂直变量,引用同目录下的 wp-blog-header.php 文件
license.txtGPL许可证文件
readme.html安装导言
wp-activate.php用户激活文件,用户注册之后就会发一封邮件给用户,激活账户
wp-blog-header.php加载环境和模板的
wp-comments-post.php添加评论把它添加到数据库的文件「个别主题提供评论提交入口,可删除该文件减少垃圾评论」
wp-config-sample.php官方给出的链接数据库示例文件,如果 wp-config.php 文件丢失了,通过这个文件进行修改也可以的
wp-cron.php执行定时任务文件,允许判断任务是不是到时间完成
wp-links-opml.php生成一个 opml 格式的链接列表
wp-load.php加载 wp-config.php 文件且设置公共变量,及加载 WP 的程序和类库
wp-login.php注册用户登录页面
wp-mail.php邮件操作页面
wp-settings.php运行前的例行程序,包括代码安装是否正确,使用辅助函数,应用用户插件,执行初始化计时器等等
wp-signup.php定义新用户的账号
wp-trackback.php处理 trackback 的请求「别人在博客外引用博文,如果对方开启这个功能,这个文件就会通知我们,他的博客引用了我们的文章」
xmlrpc.php远程发布功能,这个功能允许用别的工具通过远程来发布文章

权限设置

  1. 最简单的:将目录及文件的权限都设置为 755,所有者 www,应用到子目录。即所有者拥有读写执行权限,所有组即其它用户可以读取执行。

  2. 最安全的:将目录及文件的所有者设置为 www,文件权限设置为 600「即所有者仅拥有读权限」目录权限设置为 700,该种方法可一定意义上防止其它程序篡改网站源码。

  •  

一个面向 WordPress 博客的优化建议

2023年1月5日 00:00

随着新春将至,很多博主由日常的繁忙转向清闲,开始折腾起了博客。发现不少的小伙伴换了博客程序,一些小伙伴开始为博客调优,今天分享一些关于 WordPress 博客的优化建议!

写在前面

了解杜老师说的小伙伴比较清楚,杜老师说一直使用 Hexo 这款轻量级博客框架,且一直在用 Volantis 主题。

但杜老师对 WordPress 还算是比较了解的,因为杜老师说的前身是菜鸟博客,用的就是 WordPress 搭建的。

菜鸟博客文章量近 1600 篇,文章评论 12W 多。且安装了论坛插件「即 bbPress」注册用户量 13000,发帖及回复量约 22W。

在此数据量级,为了保证运营成本,最好的方式就是做优化!所以说杜老师的优化经验还是比较丰富的~

程序评价

每十个博客就有一个使用 WordPress,这是 WordPress 的宣传文案,但不是乱说的,有实际的数据统计。

毕竟 WordPress 的安装简单,使用方便,庞大的主题库和插件库可满足任何人对网站的任何需求。

但不管 WordPress 如何升级,都无法避免一个大问题:臃肿!

不支持源码上臃肿,运行时也有很多臃肿的机制,且因为主题及插件调用问题,对数据库的优化不够好,很多小伙伴都反馈数据库缓存命中率较低。

所以 WordPress 的使用者会感到博客越来越慢,最终只能通过升级服务器的配置维持运营。

以上评价仅为杜老师的个人使用体验,如有不同见解欢迎评论交流!

优化方法

  1. 静态文件:大多博客都会借助图片或特效让页面变得好看,但这些文件会占用大量带宽,影响页面打开速度。所以可以将这类的文件通过引用站外链接「如 CDN」方式调用,减少带宽占用,进而加快页面打开速度;

  2. 程序源码:WordPress 使用 PHP 语言,在博客页面切换时,会产出大量且重复的 PHP 执行,可借助 OPcache 缓存执行结果,加速执行过程,进而加快页面打开速度;

  3. 数据查询:WordPress 在运行时会大量产生数据库的交互操作,且 WordPress 本身缓存机制较弱,导致数据无法及时返回拖慢页面打开速度。我们可以增加缓存「如 Memcached」并可使用插件生成静态页面,进而减少数据库的查询次数,加快页面打开速度;

  4. 博客插件:WordPress 在做站点展示前,会扫描所有的插件,并对开启状态的插件调用其数据库中的配置项,而扫描和调用过程则会拖慢页面打开速度。所以尽量减少插件使用,未启用的插件可备份后删除,轻量级的插件功能尽量通过修改程序源码实现「如邮件通知等」

写在最后

杜老师自认为理论丰富但动手能力弱,所以暂不提供远程优化相关技术支持,不过可以留言讨论,共同来寻找更好的优化方式!

如果您有自己的服务器,服务器中仅运行一个 WordPress 博客,且博客中并无优化插件,可以尝试使用杜老师主推 OpenLiteSpeed 和 LiteSpeed Cache 插件。

  •  

杜老师说的 2022 年度总结

2022年12月30日 00:00

最近看到很多小伙伴都在写年度总结,就连十年之约论坛也开启了文章收集,杜老师也趁着机会水篇文章,文笔有限,小伙伴们随便看看即可!

博客年度事件

2022 年 11 月 26 日

杜老师说站点接入林林小盆友提供 Umami 访问分析服务,如因此导致访问中出现问题,欢迎随时反馈。

2022 年 11 月 24 日

因 Volantis 版本升级的原因,本站下线 Pjax 无刷新页面加载效果;

2022 年 10 月 04 日

本博客全面本地化,欢迎小伙伴们来测试稳定性;

2022 年 10 月 02 日

经多方测试 Meilisearch 的标题检索异常,正式修复前先切换至 Algolia;

2022 年 09 月 04 日

为测试 GitHub Actions 配置,临时托管至 CloudBase;

2022 年 09 月 02 日

因 Algolia 最近节点位于香港,大陆访问速度较慢,且有 API 调用数限制,现换成 Meilisearch;

2022 年 08 月 30 日

因 content.json 过大,严重影响访客搜索体验,现换成 Algolia 服务;

2022 年 08 月 28 日

下架 8 月 28 日后穿越文,新增定时发布功能;

2022 年 08 月 08 日

调整友情链接位置,由右侧调整到页脚。

2022 年 08 月 02 日

后端换到了 Netlify,页面生成加部署时间缩短 34%;

2022 年 07 月 10 日

博客三周年了,纪念一下!

2022 年 07 月 08 日

后端换到了 Vercel,前端使用阿里云 CDN 缓存加速;

2022 年 06 月 20 日

在星辰童鞋帮助下,自建了不蒜子统计平台,已经部署在本博客,待测试稳定后,会提供公益性统计服务;

2022 年 06 月 18 日

为了减少流量成本,本站关闭了页面预加载功能,经测试影响不明显,不会降低访客体验;

2022 年 05 月 24 日

随着更新日志增多,大量时间线内容拉长了留言页面,为了给小伙伴们更好的浏览体验,现将部分内容折叠;

2022 年 05 月 20 日

在柚子童靴帮助下,杜老师说进一步提升了贴图上传速度,图片不经过服务器,直接通过 API 上传至图床;

2022 年 04 月 24 日

今日有小伙伴反馈贴图上传速度较慢,因为贴图数据要先传到服务器上,再通过 API 传到图床,而服务器的下行带宽只有 1M。目前已将后端托管在家中的 NAS 上,上下行百兆带宽可提升上传速率;

2022 年 04 月 20 日

在柚子童靴疯狂邀请下,杜老师说更换了 Artalk 评论系统。在此也感谢柚子童靴和评论系统作者 QWQAQ 的大力帮助,完成无损切换;

2022 年 04 月 16 日

新增右键菜单,为访客提供更加便捷的操作方式,如需恢复原有菜单,可以按住CTRL时右键;

2022 年 04 月 14 日

新增暗黑模式,为夜间浏览带来更好的体验,保护视力,从我做起;

2022 年 04 月 04 日

因图床托管平台被查封,目前图片数据存放于杜老师说所在服务器,为了做好数据隔离,杜老师说将于近期进行服务器的迁移,可能会出现短时间无法访问,请大家耐心等待片刻后刷新即可;

2022 年 03 月 28 日

杜老师上线朋友圈页面,方便第一时间送上沙发,同时期待大家回访;

2022 年 02 月 10 日

杜老师说取消苹果教程分类,其下所有文章转至智慧生活,添加视频分享分类;

2022 年 02 月 08 日

杜老师说监控服务器替换为更加精确的 Freshping,可提供以小时为单位的监控数据;

图床年度事件

2022 年 10 月 06 日

图床近期调整运营策略,下线除 5G 容量外其它的套餐,已购买的套餐仍然生效。

2022 年 10 月 02 日

部分托管图片遭受流量攻击,产生大量费用,为减少图床的运营成本,会对异常流量图片进行删除处理,删除前会邮件通知,并至少保留 24 小时;

2022 年 08 月 30 日

去不图床首页新增背景图片,采集自某应的每日壁纸,如影响加载速度请大家及时反馈;

2022 年 08 月 28 日

近期服务器频繁遭受到恶意攻击,为保障服务器安全,开启很多安全策略,如有影响大家使用,请理解并留言反馈;

2022 年 08 月 22 日

去不图床开通 QQ 第三方登录模块,允许用户使用 QQ 接入及登录;

2022 年 08 月 20 日

已将图床整站转移至国内服务器,更高配置更大带宽保障用户使用体验;

2022 年 08 月 18 日

已通过 ICP 备案,图床官网接入多吉云 CDN 国内节点加速;

2022 年 08 月 16 日

去不图床开通 GitHub 第三方登录模块,允许用户使用 GitHub 接入及登录;

2022 年 08 月 10 日

去不图床全站添加访问统计,显示页面展示次数,以及访问人数;

2022 年 08 月 08 日

计划 8 月 20 日凌晨 2 点切换存储策略,时间预计一个小时,期间无法上传图片;

2022 年 07 月 30 日

去不图床计划于 8 月 1 日正式启用新付费模式;

2022 年 07 月 24 日

去不图床已将程序升级至商业版本,同时调整付费模式,付费账号改为付费容量;

2022 年 07 月 12 日

部分小伙伴反馈图床打开的速度较慢,经排查出了网络问题外,可能是服务器内存不足导致,已做内存升级,并调整了网站环境配置;

2022 年 07 月 08 日

因 PHP 扩展故障,导致图片的缩略图生成出现问题「不会影响外链」近期修复故障并重新生成缩略图,预计生成时间持续一周;

2022 年 05 月 24 日

近期发现部分访客上传大量违禁图片,已收到存储节点服务商警告邮件,决定关闭访客上传功能,接入实时图片审核服务;

2022 年 05 月 12 日

为提升图片的上传效率,已将并发数改为 3;

2022 年 05 月 04 日

部分用户反馈批量上传时输出的图片外链地址顺序错乱,已将该问题提交给图床程序作者,临时将上传并发数改为 1 避免该问题再现;

2022 年 05 月 02 日

为了保证国外用户可以正常使用,已将国外的节点临时切换到腾讯云 CDN;

2022 年 04 月 26 日

已有用户反馈国外节点逐步恢复,杜老师联系了节点客服,目前还未收到明确答复;

2022 年 04 月 24 日

新版图床正式启用,支持多图上传、拖拽上传、粘贴上传、复制图片、复制链接、一键复制链接及强大的图片管理功能;

2022 年 04 月 06 日

为了满足更多小伙伴的使用需求,去不图床将于近期进行新版本的内测,点击 这里 查看内测详情;

2022 年 04 月 04 日

因图床托管平台被查封,已将图片数据迁移至杜老师说所在服务器,为了做好数据隔离,杜老师说将于近期进行服务器的迁移,可能会出现短时间无法访问,请大家耐心等待片刻后刷新即可;

2022 年 02 月 28 日

开通境外加速节点,境外走 Cloudflare 节点加速;

2022 年 02 月 02 日

图床提卡系统已完成第一次价格调整;

博客站点数据

截至 2022 年 12 月 29 日 20 点 45 分,杜老师说文章量为 538 篇,已运行时间为 1268 天,总字数约为 312.7 千字,访客数为 53499 人「2022 年 6 月 22 日至今」访问量为 202126 次「同上」。

博客留言量为 19383 条,访问量最多的文章《小米云摄像头无法对接群晖存储解决方法》访问量为 12919 次,评论数最多的页面「关于」评论数为 2928 条。

图床站点数据

除了杜老师说,旗下还有去不图床,2019 年 10 月 28 日创建至今,已稳定运行了 1158 天,已托管图片约为 174.5 千张,相册数量 241 个,用户数量约为 10.9 千人,存储占用量约为 65.85GB。

相比博客,图床运营成本较大,除存储空间外,最大的费用支出就是流量了,目前收入虽然抵不上运营的成本,但仍在杜老师可接受支出范围内,所以不用担心跑路问题!

聊聊杜老师吧

杜老师目前在一家公司担任技术讲师,主要研究方向为 Linux 国产操作系统,平时的工作内容大致为编写课件、课程交付。因为工作任务比较零散、随机,所以有较多的时间可以维护博客、解答小伙伴的问题,所以经常免费提供技术支持。

不过目前行业竞争激烈,杜老师也需要不断学习强化自身,所以未来可能回复时间较集中在晚上,着急的话也可选择付费技术支持。

关于未来展望

在关于里有介绍过,杜老师说主题为技术类分享博客,主要是运维类技术文章分享。

但细心的小伙伴应该发现了,2022 年发布的文章大多都偏了这个主题,原因是杜老师肚子中的墨水所剩无几。

所以会在 2023 年着重提升自身技术水平,以此遍写出更详细更实用的教程!

除此之外,杜老师还发现很多的小伙伴对于技术文章的态度较统一:不明觉厉。

更多关注点放在了生活日志,加上访问统计分析结果,所以 2023 年的主题为:日常生活、智能家居、建站技术。

随着已经逐渐稳定,政策已经放宽,杜老师决定没事多出去走走,分享一些杜老师眼中的世界。

杜老师还是数码爱好者,经常会买一些奇奇怪怪的小物件,也会分享给小伙伴,共同来体验科技的新奇。

还要感谢陪伴杜老师说成长的小伙伴,名字就不一一提了,谨献上杜老师由衷感谢!

如果有建议和意见可以随时留言,杜老师会参考小伙伴们意愿调整博客运营。

最后祝愿各位小伙伴在新的一年,心想事成、身体健康、阖家欢乐、财源滚滚!

  •  

杜老师建站史

2022年11月12日 00:00

小伙伴还记得第一次接触建站是什么时候的事情吗?还记得一共搭建过多少个网站吗?哪些网站依旧印象深刻?今天来聊一聊杜老师建站史!

接触网络

第一次接触计算机还是在小学时,具体的年龄忘记了,只记得那会还是 DOS 系统,相比那时候的红色警戒,杜老师更喜欢扫雷,接触第一款操作系统还是 Windows 95。

时隔几年,家里买了台兼容机,运行了 Windows 98,当时因为硬件原因,运行极不稳定,但不妨碍刷大菠萝,那会还没有修改器,凭能力一遍又一遍刷图还是很有趣的。

杜老师第一次接触互联网还是通过调制解调器,那会一小时三块钱,而且会占用电话的线路「上网期间电话无法接听」因为费用和线路的关系,都是在网络的海洋中蘸点水,然后断开网络干搓~

到了初中家里办了宽带,别看只有两兆,可是打开了杜老师的世界观。那会很少会玩游戏,而是在网上浏览各类的资源,偶尔再聊聊天~

第一个站

好像是初二的时候,在日常浏览网站时,看到了一条免费内容托管的广告,顺着链接进入,就来到了名为 AnyP 的平台。

AnyP 为免费用户提供了 100M 存储空间,赠送 anyp.cn 后缀的二级域名。付费可以获得更多空间,并且支持绑定顶级域名。

在零几年的时候网络安全意识比较弱,页面支持各类代码,可以借助模块实现各种效果。

那会最大的乐趣就是在页面中集成新功能,然后接受隔壁小伙伴的膜拜以及请教「目前该平台已停止运营」

腾讯空间

随着内容不断增加,免费的 100M 容量已经不够用了,又没条件付费「那会还没手机,不像现在支付那么便捷」就转战 QQ 空间。

与现今的 QQ 空间不一样,最开始的空间自定义功能非常墙,借助 JS 代码可以打造各类的效果,当时身边小伙伴的空间都是非主流的主题。

杜老师生活在辽宁,当地比较流行的主题风格叫残血。杜老师在官方属于技术运营主力之一,来空间的访客大多都是寻求帮助,也有不少定制模板的小伙伴~

当年空间访问量达到了 50 万,也有付费的小伙伴,当时付费就是 Q 币,再者就是各种会员「不知各位看几年前的日志时,有没有想要掐死自己的冲动,杜老师舍不得掐死自己,就申请了空间注销」

班级网站

因为 QQ 空间对代码没有限制,久而久之就爆出了严重安全问题,腾讯平台开始限制代码使用,功能需要通过内置模块实现,效果等则需要办理黄钻才可。

在升入高中后,因高中强制性住校,家人为了方便给杜老师办了张银行卡,借此杜老师买了第一个虚拟主机,仅支持 ASP 网页语言。

借助开源平台搭建了班级的主页,据说是整个学校史上第一个班级网站,因为噱头较大,再加上新鲜感,除本班同学外,隔壁班的也跑来贡献 IP。

值得骄傲的是,杜老师还凭此获得学校颁发的计算机类比赛一等奖「空间当时买一赠一,就是两年,两年到期后并没有续费,整站数据随之消失」

世外桃源

在班级站运营期间,杜老师逐渐熟悉 BBS 平台,也在众多站长的帮助下,找到很多免费资源,于是就有了综合型论坛「世外桃源」

当时论坛程序是 Discuz,运行在一个国内的免费空间「08 年前国内的空间无需备案」认识了很多行业的大牛,在他们加入后,论坛会员达到了 10W。

那会不懂如何盈利,只是单纯想着人多热闹,而且作为站长,十分有成就感。不过也有一些问题,杜老师的同学知道该论坛后,都想凭借关系获得版主一职,不过论坛规则所限,不能满足他们要求,因此被孤立了好一阵子。

08 年后国内开始要求备案后接入,免费空间没有任何警示直接跑路,论坛全部数据丢失,杜老师的心态直接崩了,弃网备战高考。

工作室站

进入大学后在学者的怂恿下,迷迷糊糊创立了工作室,主要为学校周边的经营场所提供网站搭建、网络维护服务,就搭建了一个演示站点。

在众多开源程序中,杜老师选择了 emlog。忘记是什么原因了,但确实因为 emlog 让杜老师对 PHP 充满兴趣,并为 emlog 贡献了不少代码。

那会还没用 Git,写完代码后发给创始人那多,然后坐等审核、整合、上线,可惜的是 emlog 从 5.2.1 版本后,那多记忆逐渐淡出论坛,也不参与后期开发,元老团队成员逐渐转向其它程序,emlog 落没了~

大学毕业,工作室交给了学弟学妹管理,站点也没带走「毕业后两年的一天,再次访问工作室网站发现无法打开了」

菜鸟博客

大学毕业后从事了培训行业,光荣变成一枚讲师。因自身的授课风格需要学院配合,对埋头记笔记的学员甚无奈,所以和大学时学长及众伙伴创建:菜鸟团队技术博客「后更名为菜鸟博客」

杜老师的能力不多说了,垃圾一枚。

开发频道:老魏,国家计算机研究中心的技术总监,擅长各类编程语言。

网络频道:悦悦,华为华中地区项目经理,精通思科、华三网络设备调试。

数据频道:婧婧,北京理工大学当届校花,擅长数据分析、数据处理,那一条腿比杜老师的生命线还长。

还有些伙伴就不介绍了。因博客使用 WP 程序搭建,用过的小伙伴应该知道它多臃肿,数据量访问量上来之后,一般服务器扛不住。为了平衡运营成本,杜老师提供了很多付费内容、服务,可惜后期因为「分赃不均」导致团队解散,菜鸟博客因此关站。

杜老师说

就你们面前的这个破站,还需要杜老师多介绍吗?

水到这可以了,要什么自行车。

  •  

Volantis 主题新版渲染图

2022年10月19日 00:00

Hexo 有非常多好看的主题模板,一些博客圈的小伙伴喜欢经常换主题,杜老师也非常喜欢折腾,但文章量一旦上来,更换主题的成本非常大,很多主题自带的短代码都要调整,下面聊聊杜老师说建博以来用的唯一一款主题。

简单聊聊

Volantis 是一个功能丰富、高度模块化的博客主题。得益于其强大的模块化特性,可轻松搭建一个极简风格的博客,也可以仿照官网搭建一个多人协作的、含文档模块的大体量综合型博客。

建博之初,杜老师就在三款主题中纠结,分别是 Next/Volantis/Butterfly,不过 Next 是单栏,Butterfly 太过于花俏「没有任何贬低含义,只是杜老师喜欢简洁风」

当时这款主题叫 Material X,主题自带的功能模块可以让博文更好呈现,且维护者更新频繁。这些因素都使得杜老师建博以来一直没有更换其它主题。

之前主题原作者离开过一段时间,后期都是由其他小伙伴负责更新,杜老师也贡献一些代码。如今原作者回归了,带来了一些新想法,下面是新版本的渲染图,大家可以提前欣赏一下,顺便提提意见!

新版渲染

  •  

关于友情链接的一些事

2022年9月20日 00:00

友情链接,也称网站交换链接、互惠链接、互换链接、联盟链接。是具有一定资源互补优势的网站之间简单合作形式,即分别在自己的网站上放置对方网站的 Logo 图片或文字的网站名称,并设置对方网站的链接,使用户可以从合作网站中发现自己的网站,达到互相推广目的,因此常作为一种网站推广的基本手段。

关于友链

导语引自某度百科。在杜老师看来,友链并非推广手段,而是博主间维系互动的纽带。

通过友情链接,我们可以很方便的找到小伙伴的博客,在感兴趣的文章内留下我们脚印,博主间的互访,也是我们更新与维护博客的动力!

杜老师从未主动申请过友情链接,但收到的友情链接邀请从未拒绝。

即便如此,杜老师也希望各位小伙伴在申请友链时,遵循如下规则。

友善友链

  1. 请不要忘记友链是友情链接。相比友链更希望我们能拥有友情,所以希望不要一上来就丢个链接。经常会遇到这样的情况,有时杜老师好奇这些都是谁,各群问了一圈都不认识,拜访时才知道对方不知从何处寻到了杜老师的博客地址。建议多在对方站内评论留言,熟悉之后自然会加友链,且评论的链接地址还会带动反链,有助于增加搜索引擎的收录;

  2. 请不要设置站标防盗用。自从 jsD 被封后,有些小伙伴将图片数据托管在个人空间中,因怕数据盗用,设置了防盗链。身为云计算安全运维工程师,杜老师很理解这种操作,但给站标也设置防盗链,是不希望他人的平台显示你的友链吗?如果心疼流量,可以贴图到评论区,去不图床愿意托管小伙伴的站标;

  3. 关站或故障请及时通知。友链页面除申请留言外,更多的是「杜老师我的友链怎么没有了」在此郑重声明,杜老师说绝对不会恶意下链。平台后端会监控友链网站的状态,当故障时间超过六小时,则提醒杜老师下链。而下链前,杜老师会通过 QQ 群、邮箱等一切手段与博主联系,希望能协助其尽快修复。如遇此种情况,留言提醒下杜老师即可;

  4. 本博客仅做同级别链接。顾名思义,您把杜老师说放在首页,这边就会做全站链;您把杜老师说放在内页,这边就会做内页链。目前 handsome 主题的首页链接、及部分主题的随机首页链接,同样会放在本站的全站链中,待数量过多时,杜老师会考虑放入内页,届时会有留言告知;

  5. 本博客支持付费单向链。杜老师深知免费才是成本最高的选择,故目前运行的平台均为大厂付费产品。为了维持博客运营,支持付费单向全站链接,目前的价格是 18 元每月「按每月份 31 天计算」支持支付宝及微信支付,需要的话留言即可。另如需要调整付费链接展示顺序,可选竞价服务,相同竞价者按时间顺序排列;

  6. 下链或换站请及时通知。遇到过一些骗链的「互链没两天就偷偷下链」还有一些想从头开始的,新站并未同步原来友链数据。还有一些不知道因什么原因,就直接下链了。因遇到较多次,杜老师都想弄个黑名单,然后在 GitHub 公开,防止小伙伴们中招,目前想法依在,想出现在榜首的可以联系杜老师!

友链福利

  1. 献上 IP 及评论。杜老师说通过友链文章采集,可以获得友链博客更新数据,当发现有新文章发布后,杜老师都会在每天固定时间送上 IP 及评论。因采集平台的限制,部分博客的 RSS 无法直接识别「也有部分博客没有提供 RSS 或禁用该项服务」杜老师也会定期去拜访;

  2. 提供技术支持。杜老师是通过技术支持养活这个博客以及旗下站点,不过友链博客的一些小问题,都可免费协助处理。且杜老师认识了很多热心的大佬,互帮互助解决很多问题,有问题别害羞,随时留言,会有大佬协助解决。

写在最后

聊一些与此文无关的事。杜老师说主题相对单一,都是围绕技术类的内容。

之前有小伙伴提到「这里好热闹啊,但是就看不懂」还因为杜老师拜访部分小伙伴时,其文章的专业性也使杜老师不知如何留言,只能弱弱的说「过来学习一下」

简单说下近况。徘徊在居家隔离与出差之间,昨天出差、今天上课、明天回京。所以一直未能腾出时间更新内容,导致博文写了一半定时任务就发布了出去,被误认为水文~

就写这么多吧,文笔不好,高考作文都是造句拼的,小伙伴们凑合看吧!

  •  

使用 MeiliSearch 实现 Volantis 主题博客搜索「保姆教程」

2022年9月14日 00:00

感谢柚子童鞋在杜老师的疯狂怂恿下为 Volantis 主题整合了 MeiliSearch 搜索引擎,并花费大量心思编写了相关教程,反正杜老师照着柚子童鞋的教程没做出来,不过在柚子童鞋的耐心帮助下最后还是成功实现了,这里记录下部署过程中可能遇到的坑。

写在前面

习惯水文的杜老师花了很长时间才下决心写下此文,教程太长没耐心看,看了又不愿意自行搭建,搭建了又遇到了更多的问题……

正文开始前先卖下队友,点击 这里 访问柚子童鞋写的教程。

历史背景

杜老师的博客再水,也将近 300 万字,检索文件 content.json 大小 1.42MB「还是调整后的,原有的超过 4M」

当有小伙伴使用搜索功能时,需完整加载 content.json 文件才可显示搜索结果,不仅影响体验还会产生较大流量。

之后换成了 Algolia 服务,但其最近节点位于香港,大陆访问速度较慢,且有 API 调用数限制。

在百度上疯狂谷歌之后,发现一款可自建的开源搜索引擎,就是 MeiliSearch 了。

杜老师第一时间推给了柚子童鞋,对方回复能搞!

再次感谢柚子童鞋,很快写好了教程并推送调用代码至 Volantis 主题库中。

服务搭建

杜老师是忠实的容器党,能用 Docker 的绝不考虑其它部署方法,以下是官方的部署命令,其中 MASTER_KEY 自定义,版本号 v0.28 可换成 latest

1
2
3
4
5
6
docker run -it --rm \
-p 7700:7700 \
-e MEILI_MASTER_KEY='MASTER_KEY' \
-v $(pwd)/meili_data:/meili_data \
getmeili/meilisearch \
meilisearch --env="development"

如果想用某塔 Docker 管理器部署,配置如图。但墙裂建议使用命令行部署,杜老师尝试用 Docker 管理器部署几次失败,最后定位问题属于玄学:

获取密钥

部署完成后通过 IP:7700,如能看到下图页面说明部署成功:

这页面好看吧,然而没啥卵用!官方建议使用 Postman 调试 MeiliSearch,并提供了调试文件,点击 这里 跳转至 Postman 页面,复制官方调试文件链接 https://docs.meilisearch.com/postman/meilisearch-collection.json 到 Link 标签项,导入即可:

将上文的 MASTER_KEY 填入 Token 框中:

切换至 Variables,将 url 处替换为 MeiliSearch 的域名,indexUID 建议使用 hexo,记得点击右上方 Save:

展开 MeiliSearch 进入 Key Management-Get keys,点击右侧 Send 即可获取 searchKey:

如若长期使用,建议使用生产模式部署,停用上面的实例后,使用下面命令重新部署:

1
2
3
4
5
6
docker run -d --restart=always \
-p 7700:7700 \
-e MEILI_MASTER_KEY='MASTER_KEY' \
-v $(pwd)/meili_data:/meili_data \
getmeili/meilisearch \
meilisearch --env="production" --no-analytics

调试使用

为保证每篇文章拥有一个唯一值,推荐用 hexo-uuid 插件,进入到博客目录后使用如下命令按照:

1
npm install hexo-uuid

安装完后,需要 blog/_config.yml 配置文件为如下内容:

1
2
3
4
5
6
7
8
jsonContent: 
meta: false
pages: false
posts:
title: true
path: true
text: true
uuid: true

使用如下命令完成检索文件推送:

1
2
3
4
curl -X POST 'https://yoursdomain.com/indexes/hexo/documents/?primaryKey=uuid' \
-H "Authorization: Bearer MASTER_KEY" \
-H "Content-Type: application/json" \
--data-binary '@public/content.json'

参考下面代码修改主题配置文件即可:

1
2
3
4
5
6
7
8
search:
enable: true
service: meilisearch # hexo, algolia, meilisearch
meilisearch:
placeholder: 'Search...'
searchKey: 'searchKey'
indexName: 'hexo'
hostUrl: 'https://m.dusays.com'

注意事项

杜老师在推送检索文件时遇到了全量推送问题,表现为搜索时出现大量重复结果,杜老师选择了最简单粗暴的解决方法,上传前调用删除接口清空数据库:

1
curl -X DELETE 'https://m.dusays.com/indexes/hexo' -H "Authorization: Bearer MASTER_KEY"

最后分享下杜老师的 GitHub Actions 配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
name: CI
on:
push:
branches: [ "main" ]
workflow_dispatch:
schedule:
- cron: '30 16 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '16.17'
- name: npm
run: |
npm i -g hexo-cli
npm i
- name: hexo
run: |
hexo g --silent
gulp
curl -X DELETE 'https://m.dusays.com/indexes/hexo' -H "Authorization: Bearer ${{secrets.MEILISEARCH_KEY}}"
curl -X POST 'https://m.dusays.com/indexes/hexo/documents/?primaryKey=uuid' -H "Authorization: Bearer ${{secrets.MEILISEARCH_KEY}}" -H "Content-Type: application/json" --data-binary '@public/content.json'
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: penndu/my-website
publish_branch: master
publish_dir: ./public
  •  

通过 GitHub Actions 实现 Hexo 定时发布

2022年9月11日 00:00

经常会有小伙伴说杜老师总发穿越文,确实这种发布方式会让新伙伴一脸懵,且对搜索引擎不大友好。本文讲解如何通过 GitHub Actions 变相实现 Hexo 定时发布功能!

隐藏功能

其实 Hexo 根配置文件有个隐藏功能,通过调整 future 值可以实现是否显示当前时间点之后的文章。

为什么说隐藏功能,因为杜老师曾问了一圈,没一个知道的!

默认 future: true 时发布所有文章,改为 future: false 则隐藏当前时间点之后的文章。

需要注意的是,这里的隐藏指不生成该文章页面,而不是主页不显示。且到了文章的时间点后还需手动生成页面文件才可显示。

定时发布

这里借助 GitHub Actions 的计划任务功能实现,workflow 配置文件中加入如下代码即可:

1
2
schedule:
- cron: '30 16 * * *'

提示一下,GitHub Actions 和国内有时间差,杜老师设置每天 16 点 30 分部署后,实际部署时间为第二天 0 点 52 分,完整参考代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
name: CI
on:
push:
branches: [ "main" ]
workflow_dispatch:
schedule:
- cron: '30 16 * * *'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '16.17'
- name: npm
run: |
npm i -g hexo-cli
npm i
- name: hexo
run: |
hexo g --silent
gulp
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
deploy_key: ${{ secrets.ACTIONS_DEPLOY_KEY }}
external_repository: penndu/my-website
publish_branch: master
publish_dir: ./public
  •  

通过 GitHub Actions 将 Hexo 部署至良心云 CloudBase

2022年9月8日 00:00

部分主题如 Volantis 对 node 有版本要求,而 Web 应用托管无法指定 node 的版本,且直接推送 public 文件部署还会因为网络问题导致无法及时触发,本文讲解如何通过 GitHub Actions 解决该问题。

准备工作

首先登录良心云 CloudBase,获取 Web 应用托管对应环境 ID,记录一下等会要用:

进入访问管理——访问密钥,进入到 API 密钥管理,获取 SecretId 以及 SecretKey:

登录 GitHub 并进入博客的源码库,切换到 Settings-Secrets-Actions,分别添加红框变量,如 ENVID/SECRETID/SECRETKEY:

最后切换到 Actions-New workflow-set up a workflow yourself:

数据走向

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
name: CI
on:
push:
branches: [ "main" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: '16.17'
- name: npm
run: |
npm i -g hexo-cli
npm i
- name: hexo
run: hexo g --silent
- name: Deploy to Tencent CloudBase
uses: TencentCloudBase/cloudbase-action@v2.0.1
with:
secretId: ${{secrets.secretId}}
secretKey: ${{secrets.secretKey}}
envId: ${{secrets.envId}}

注意:以上为杜老师所用代码,替换原有内容,或根据现有内容做修改即可。

文件限制

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
"envId": "{{secrets.envId}}",
"version": "2.0",
"framework": {
"name": "gh-actions-test",
"plugins": {
"func": {
"use": "@cloudbase/framework-plugin-website",
"inputs": {
"outputPath": "public",
"ignore": [
".git",
".github",
"cloudbaserc.json"
]
}
}
}
}
}

注意:TencentCloudBase/cloudbase-action@v1 传输的文件不能超过一千,所以这里选择了 TencentCloudBase/cloudbase-action@v2.0.1,该版本执行需要在博客源码根目录中创建文件 cloudbaserc.json 并加入上面代码。

写在最后

  1. 以上方法适用于将博客所有源码托管至 GitHub 上,如只托管 public 目录内文件则需修改配置;

  2. 如 public 目录内的文件不超过 1000,可选择使用 TencentCloudBase/cloudbase-action@v1,该版本不需要在博客源码根目录中创建文件 cloudbaserc.json

  3. 默认强制全量推送策略,会删除 CloudBase 中原有的文件,使用该教程前请先做好数据备份;

  4. 偶尔会出现推送失败的提示,但实际测试已完成推送,无视即可。

  •  

Lsky Pro 企业版手动升级、优化教程

2022年9月2日 00:00

部分 Lsky Pro 企业版用户自行修改源码,如使用在线版本升级会覆盖已修改的文件。本文介绍如何使用手动升级,及图床程序的优化操作。

升级

使用管理账号登录图床后台,点击进入系统——系统设置——系统升级,下载新版本补丁包文件。合并补丁包文件至 Lsky Pro 程序源码后,在服务器终端执行如下命令应用更新:

1
composer update

上述命令执行完后,进入到数据库管理,执行如下语句升级版本,需要注意的是,其中的 V 1.1.1 根据升级版本修改:

1
UPDATE `configs` SET `value` = 'V 1.1.1' WHERE `configs`.`name` = 'app_version';

由于版本升级可能加入一些新的功能,需要修改数据库表,使用如下命令进行数据填充:

1
php artisan migrate --seed

版本升级后因文件改变可能导致网站报 500 错误,执行下面命令清理优化缓存即可:

1
php artisan optimize:clear

优化

项目部署到生产环境时,请确保您正在优化 Composer 的类自动加载器映射,以便 Composer 可以快速找到为给定类加载的正确文件:

1
composer install --optimize-autoloader --no-dev

下面命令会将 Laravel 的所有配置文件合并到一个缓存文件中,这大大减少了框架在加载配置值时必须访问文件系统的次数:

1
php artisan config:cache

下面命令将所有路由注册减少到缓存文件的单个方法调用中,从而在注册数百条路由时提高路由注册的性能:

1
php artisan route:cache

下面命令预编译所有 Blade 视图,因此它们不会按需编译,从而提高返回视图的每个请求的性能:

1
php artisan view:cache
  •  

有没有兴趣来抢个沙发

2022年8月3日 00:00

杜老师说建站至今,已经运营 1194 天,水文 514 篇。很多小伙伴把评论区当成聊天区,杜老师也会一一的回复并且回访,不过还有 62 篇文章还没有小伙伴临幸,已经整理出来,欢迎来抢沙发!

写在前面

这一天杜老师还在公司摸鱼,突然灵光一闪想清一波零评论的文章,好不容易有水文的机会必然不能错过!

杜老师使用 Artalk 评论系统,后端托管在 MySQL,导出 comments 表数据,筛选 page_key 项,这样即可将零评论文章整理出来「说的非常简单,做的时候还是蛮麻烦的」

文章列表

本想做成文章标题,但想想还是弄成盲盒比较好。友情提示,部分文章内有美女,欢迎前往留下您的脚印:

编号地址
1https://dusays.com/177/
2https://dusays.com/188/
3https://dusays.com/206/
4https://dusays.com/207/
5https://dusays.com/210/
6https://dusays.com/211/
7https://dusays.com/212/
8https://dusays.com/215/
9https://dusays.com/219/
10https://dusays.com/222/
11https://dusays.com/224/
12https://dusays.com/232/
13https://dusays.com/237/
14https://dusays.com/240/
15https://dusays.com/244/
16https://dusays.com/245/
17https://dusays.com/247/
18https://dusays.com/248/
19https://dusays.com/249/
20https://dusays.com/251/
21https://dusays.com/252/
22https://dusays.com/253/
23https://dusays.com/254/
24https://dusays.com/255/
25https://dusays.com/256/
26https://dusays.com/257/
27https://dusays.com/259/
28https://dusays.com/265/
29https://dusays.com/269/
30https://dusays.com/271/
31https://dusays.com/274/
32https://dusays.com/277/
33https://dusays.com/284/
34https://dusays.com/286/
35https://dusays.com/287/
36https://dusays.com/288/
37https://dusays.com/297/
38https://dusays.com/298/
39https://dusays.com/300/
40https://dusays.com/305/
41https://dusays.com/306/
42https://dusays.com/307/
43https://dusays.com/308/
44https://dusays.com/309/
45https://dusays.com/320/
46https://dusays.com/324/
47https://dusays.com/326/
48https://dusays.com/327/
49https://dusays.com/335/
50https://dusays.com/337/
51https://dusays.com/338/
52https://dusays.com/341/
53https://dusays.com/345/
54https://dusays.com/347/
55https://dusays.com/348/
56https://dusays.com/349/
57https://dusays.com/355/
58https://dusays.com/359/
59https://dusays.com/360/
60https://dusays.com/363/
61https://dusays.com/364/
62https://dusays.com/366/
  •  

杜老师说网站更新图解

2022年6月25日 00:00

想知道杜老师每次发布新文章时,网站的更新流程吗?耗时半天设计的流程图,展现杜老师卓越的艺术细菌!点进来看看吧~

更新图解

看懂的小伙伴记得评论:

流程详情

  1. 首先判断更新的是主题还是文章,如果是文章则直接上传至 GitLab;

  2. 如果是主题则通过 Webhook 触发服务器生成本地时间点标识文件并上传至 GitLab;

  3. GitLab 文件更新会触发 gitlab-runner 开始自动化构建;

  4. 进入指定目录「文章或是主题」开始同步最新代码;

  5. 如果是主题则执行清理数据缓存;

  6. 生成网站页面代码;

  7. 压缩网站页面代码;

  8. 网站源码上传至 GitHub;

  9. 触发 Vercel 获取源码后生成站点;

  10. 通过套路云 CDN 加速展示。

参与设备

自动构建所用到的设备是套路云的 ECS,配置为 1H2G。构建速度还算可以,但部署比较慢,最大瓶颈是 1M 的小水管!

代码托管在自家 NAS。配置不多说了,毕竟 GitLab 存储代码和触发事件都不需要太多资源。

写在最后

估计很多小伙伴看完杜老师的图解后,都会忍不住说一句:其实不用这么麻烦!

确实这道工序有些复杂。

有些小伙伴曾好奇杜老师是做什么的。杜老师是一枚不称职的云计算运维工程师,为什么说不称职呢?因为目前在 CEC 做云计算运维讲师,而且一做就是七年。

习惯大型集群架构的杜老师喜欢套用多种服务实现一个功能,让每一层独立处理自己的事。虽然效率不高,但和做人是一样的,最重要就是开心嘛!

  •  

坚持更新博客的动力是什么

2022年6月16日 00:00

博客圈子不断有新人的加入,也不断有老人退出。几乎每个月杜老师都会检查一下友情链接,看看哪些网站测掉了杜老师说的链接。而在这过程中,总会发现一些网站长久没有更新,还有一些网站,已然无法访问~

强迫症者

经常有小伙伴说文章的时间错了,为什么杜老师一直在更新穿越文「提前发布」

其实杜老师就是个强迫症加拖延症的患者,曾在《留言》中声称每三天更新一篇,不做到会浑身难受。

但有时候真的不知道该写什么好,有的时候又研究出有意思的技术,加上一些小伙伴的需求,总会突然更新多篇,而 Hexo 并没有定时发布的功能,所以杜老师就按照排期,一并发了出来,这就是各位小伙伴看到的穿越文!

不知道有多少的小伙伴和杜老师一样,通过强迫症迫使自己去更新博客,如果恰巧和杜老师一样,欢迎留言让杜老师知道,不是一个人在战斗!

习惯记录

朋友圈里不少的小伙伴,喜欢研究一些新奇的小玩意,有时候还会找到我交流。

在研究的过程中难免会遇到一些问题,每次解决之后,都会留下一篇笔记文章。

还有的小伙伴,会经常记录自己的生活。杜老师站在读者的角度,更加了解这些小伙伴的生活!

杜老师就非常喜欢记录,但自己的文笔不好,所以不会经常记录生活,加上本博主题就是技术分享,所以在本博中很少可以看到杜老师的生活分享,以后也许会有,敬请期待!

希望盈利

杜老师的友链圈中,还有一类博友,他们喜欢收集一些资源,然后付费分享。

或者提供一些收费服务,亦或站中加入大量广告。

首先杜老师要说明一点,本人不反感任何盈利性行为,毕竟建站本身就需要成本的。有些人可能不赞同,毕竟现在免费资源遍地都是。但大家都需要知道,维护时的精力和时间也算是成本,所以只要合理合法,大家应该都会支持。

杜老师目前的收费项目只有图床,实在是没办法,运营成本太大!而目前的付费收入远远不够支出,不过好在没有人再传违禁图片了,图片审核的成本降低了,而且每天不用提心吊胆担心链接被封,也知足了!

喜欢互动

常来杜老师博客的小伙伴都知道,在本博的每条评论,杜老师都会用心去回复,并且都会回访、留言。

杜老师很喜欢十年之约的一句话:一个人的寂寞,一群人的狂欢。

在社交平台如此繁多的时代,只有互访才能让博客不寂寞。

也喜欢杜老师说的博文,可以给小伙伴带来更多话题,让更多小伙伴加入互动,实现一群人的狂欢。

  •  

向 CODING 推送代码出现 Permission denied 的解决方法

2022年6月4日 00:00

杜老师说博客托管在腾讯云的 Webify,最近因 GitHub 的 Webhook 推送问题导致无法触发部署,故转移到了 CODING。在推送代码时出现 Permission denied 的问题,本文记录解决方法。

部署公钥

在推送代码前,我们需要将服务器的公钥部署到 CODING 上:

还可以添加到个人账户设置中 SSH 公钥一项。两者的区别是,前者只对指定项目有效,后者针对该用户的所有项目有效:

解决方法

部署公钥后使用 ssh -T git@e.coding.net 命令测试,会提示 Permission denied (publickey)。

如果是 Linux 系统,使用命令 vim /etc/ssh/ssh_config 在文件末尾加入以下代码:

1
2
3
Host *.coding.net
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa

如果是 Windows 系统,需先找到 Git 的安装目录,如 C:\Program Files\Git,则编辑配置文件 C:\Program Files\Git\etc\ssh\ssh_config 加入以下代码:

1
2
3
Host *.coding.net
HostkeyAlgorithms +ssh-rsa
PubkeyAcceptedAlgorithms +ssh-rsa

编辑完成后再试下 ssh -T git@e.coding.net,就不会提示 Permission denied (publickey),可正常推送代码了。

  •  
❌