11 Commits

Author SHA1 Message Date
glidea
57ea6e681e correction for commit 170703ce80: v0.1.1. OMG I need to sleep!! 2025-04-23 19:55:56 +08:00
glidea
170703ce80 correction for commit 9026a08298: v0.1.0 2025-04-23 19:48:57 +08:00
glidea
396ee45e8c fix docker image label 2025-04-23 19:47:41 +08:00
glidea
9026a08298 v0.1.0 2025-04-23 19:15:31 +08:00
glidea
57112b916b adapting to RSSHub's incompatible changes 2025-04-23 11:43:36 +08:00
glidea
2896dfa108 lock rsshub version 2025-04-23 11:42:44 +08:00
glidea
b76fc32c9a add issue-translator 2025-04-23 10:34:49 +08:00
glidea
668f6da981 update README 2025-04-22 15:24:55 +08:00
glidea
b45fd547ab optimize deploy 2025-04-22 14:59:41 +08:00
glidea
afc15b1ed6 fix install cmd for Linux 2025-04-21 22:35:09 +08:00
glidea
0f3b282c12 remove used render.sh 2025-04-20 12:08:58 +08:00
11 changed files with 162 additions and 235 deletions

14
.github/workflows/issue-translator.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: 'issue-translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: usthe/issues-translate-action@v2.7
with:
IS_MODIFY_TITLE: true

View File

@@ -10,10 +10,14 @@ RUN GOOS=linux go build -ldflags="-s -w -X main.version=${VERSION}" -o /app/zenf
FROM alpine:latest
ARG VERSION=dev
LABEL org.opencontainers.image.version=${VERSION}
RUN apk add --no-cache ca-certificates tzdata && \
mkdir -p /app/data
COPY --from=builder /app/zenfeed /app/
WORKDIR /app
ENTRYPOINT ["/app/zenfeed"]
CMD ["--config", "/app/config/config.yaml"]

View File

@@ -59,83 +59,43 @@ zenfeed 是你的智能信息助手。它自动收集、筛选并总结关注的
### 1. 安装
替换下方 APIKey 等参数,并完整复制到终端一键执行。注意:
默认使用硅基流动的 Qwen/Qwen2.5-7B-Instruct(免费) 和 Pro/BAAI/bge-m3。如果你还没有硅基账号使用 [邀请链接](https://cloud.siliconflow.cn/i/U2VS0Q5A) 得 14 元额度
1. `provider` 除了硅基还支持 openai, openrouter, deepseek, gemini, volc火山(keng)引擎)。也可自定义,参考 [配置文档](docs/config-zh.md)。需要自定义其它参数的大佬也可参考
2. `llms[0].model` 默认会用来总结内容,相对耗费 Token一般 Qwen/Qwen2.5-7B-Instruct免费足够当然米够的话越强越好。如果你还没有硅基账号使用 [邀请链接](https://cloud.siliconflow.cn/i/U2VS0Q5A) 得 14 元额度
支持使用其他厂商或模型,按下方提示操作即可
#### Mac/Linux
```bash
docker run --rm \
-v "$(PWD):/app" \
-w /app \
--entrypoint sh \
mikefarah/yq -c '
set -e
mkdir -p zenfeed/config && cd zenfeed
TEMPLATE_URL="https://raw.githubusercontent.com/glidea/zenfeed/main/install/config-template.yaml"
COMPOSE_URL="https://raw.githubusercontent.com/glidea/zenfeed/main/install/docker-compose.yml"
CONFIG_OUTPUT="config/config.yaml"
COMPOSE_OUTPUT="docker-compose.yml"
curl -L -O https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml
wget -qO- "$TEMPLATE_URL" | yq \
".timezone = \"Asia/Shanghai\" |
.llms[0].provider = \"siliconflow\" |
.llms[0].model = \"Qwen/Qwen2.5-7B-Instruct\" |
.llms[0].api_key = \"your_api_key\" | # <<<--- 替换 API Key! 其它参数按需选择
.llms[1].provider = \"siliconflow\" |
.llms[1].embedding_model = \"Pro/BAAI/bge-m3\" |
.llms[1].api_key = \"your_api_key\" | # <<<--- 替换 API Key!
.storage.feed.rewrites[0].transform.to_text.prompt = \"{{.summary_html_snippet}}使用中文回复\"" \
> "$CONFIG_OUTPUT"
wget -qO "$COMPOSE_OUTPUT" "$COMPOSE_URL"
' && cd zenfeed && docker compose up -d --wait
# 如果你需要自定义更多配置参数,请直接编辑(执行下方命令前) docker-compose.yml#configs.zenfeed_config.content
# 配置文档 https://github.com/glidea/zenfeed/blob/main/docs/config-zh.md
API_KEY=your_apikey docker-compose -p zenfeed up -d
```
#### Windows
> 使用 PowerShell 执行
```powershell
docker run --rm `
-v "${PWD}:/app" `
-w /app `
--entrypoint sh `
mikefarah/yq -c '
set -e
mkdir -p zenfeed/config && cd zenfeed
TEMPLATE_URL="https://raw.githubusercontent.com/glidea/zenfeed/main/install/config-template.yaml"
COMPOSE_URL="https://raw.githubusercontent.com/glidea/zenfeed/main/install/docker-compose.yml"
CONFIG_OUTPUT="config/config.yaml"
COMPOSE_OUTPUT="docker-compose.yml"
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml" -OutFile ([System.IO.Path]::GetFileName("https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml"))
wget -qO- "$TEMPLATE_URL" | yq \
".timezone = \"Asia/Shanghai\" |
.llms[0].provider = \"siliconflow\" |
.llms[0].model = \"Qwen/Qwen2.5-7B-Instruct\" |
.llms[0].api_key = \"your_api_key\" | # <<<--- 替换 API Key! 其它参数按需选择
.llms[1].provider = \"siliconflow\" |
.llms[1].embedding_model = \"Pro/BAAI/bge-m3\" |
.llms[1].api_key = \"your_api_key\" | # <<<--- 替换 API Key!
.storage.feed.rewrites[0].transform.to_text.prompt = \"{{.summary_html_snippet}}使用中文回复\"" \
> "$CONFIG_OUTPUT"
wget -qO "$COMPOSE_OUTPUT" "$COMPOSE_URL"
' ; cd zenfeed; docker compose up -d --wait
# 如果你需要自定义更多配置参数,请直接编辑(执行下方命令前) docker-compose.yml#configs.zenfeed_config.content
# 配置文档 https://github.com/glidea/zenfeed/blob/main/docs/config-zh.md
$env:API_KEY = "your_apikey"; docker-compose -p zenfeed up -d
```
### 2. 使用 Web 端
访问 https://zenfeed-web.pages.dev
> 会默认连接本地的 zenfeed
> 如果部署在 VPS 等环境请访问 https://vps_public_ip:1400记得开放安全组端口不要使用上方的公共前端
> ⚠️ zenfeed 尚无认证手段,暴露到公网可能会泄露 APIKey请小心设置安全组。如果你有这方面的安全需求请提 Issue
#### 添加 RSS 订阅源
<img src="docs/images/web-add-source.png" alt="" width="400">
> 从 Follow 迁移过来,参考 [migrate-from-follow.md](docs/migrate-from-follow.md)
> 需要访问对应的源站,请保证网络畅通
> 添加后稍等几分钟,特别模型有严格速率限制的情况下
#### 配置每日简报,监控等
@@ -173,6 +133,12 @@ docker run --rm `
* 商用请联系报备,可提供合理范围内的支持。注意是合法商用哦,不欢迎搞灰色
* 数据不会永久保存,默认只存储 8 天
## 鸣谢
* 感谢 [eryajf](https://github.com/eryajf) 提供的 [Compose Inline Config](https://github.com/glidea/zenfeed/issues/1) 让部署更易理解
## 👏🏻 欢迎贡献
* 目前还没有规范,只要求一点,“代码一致性”,很重要
## 免责声明 (Disclaimer)
**在使用 `zenfeed` 软件(以下简称“本软件”)前,请仔细阅读并理解本免责声明。您的下载、安装、使用本软件或任何相关服务的行为,即表示您已阅读、理解并同意接受本声明的所有条款。如果您不同意本声明的任何内容,请立即停止使用本软件。**

76
docker-compose.yml Normal file
View File

@@ -0,0 +1,76 @@
services:
zenfeed-web:
image: glidea/zenfeed-web:latest
ports:
- "1400:1400"
environment:
- PUBLIC_DEFAULT_API_URL=http://zenfeed:1300
depends_on:
- zenfeed
zenfeed:
image: glidea/zenfeed:latest
entrypoint: >
sh -c "
if [ ! -f /app/config/config.yaml ]; then
echo 'Config file not found in volume, initializing from base config...'
cp /app/config.base.yaml /app/config/config.yaml;
else
echo 'Existing config file found in volume.'
fi &&
echo 'Starting Zenfeed...' &&
exec /app/zenfeed --config /app/config/config.yaml
"
configs:
- source: zenfeed_config_base
target: /app/config.base.yaml
volumes:
- data:/app/data
- config:/app/config
ports:
- "1300:1300"
- "1301:1301"
depends_on:
- rsshub
rsshub:
image: diygod/rsshub:2024-12-14
ports:
- "1200:1200"
environment:
- NODE_ENV=production
volumes:
data: {}
config: {}
configs:
zenfeed_config_base:
content: |
timezone: ${TZ:-Asia/Shanghai}
llms:
- name: general
default: true
provider: siliconflow
model: Qwen/Qwen2.5-7B-Instruct
api_key: ${API_KEY:-your-api-key}
- name: embed
provider: siliconflow
embedding_model: Pro/BAAI/bge-m3
api_key: ${API_KEY:-your-api-key}
scrape:
rsshub_endpoint: http://rsshub:1200
storage:
feed:
rewrites:
- transform:
to_text:
prompt: |
{{ .summary_html_snippet }} Respond in ${LANG:-Chinese}
label: summary_html_snippet
embedding_llm: embed
notify:
channels:
email:
feed_html_snippet_template: |
{{ .summary_html_snippet }}

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@@ -0,0 +1,28 @@
## 0. Check your current version
```bash
# Mac/Linux
docker inspect glidea/zenfeed:latest | grep version
# Windows PowerShell
docker inspect glidea/zenfeed:latest | Select-String -Pattern 'version'
```
If you **don't see any results**, it means you're using version v0.1.0. This is because the first version didn't include version information. Therefore, **this document applies to you.**
## 1. Move your data to the correct volume path
```bash
docker-compose -p zenfeed exec zenfeed cp -a /data/. /app/data/
```
## 2. Backup your config
Access: http://localhost:1400
![](images/upgrade-from-v0.1.0-backup.png)
## 3. Upgrade
See [upgrade](./upgrade.md)
## 4. Resave your config
Access: http://localhost:1400
Resave your config.
These tedious steps are due to the oversight in the deployment form of the first version, and I apologize for that. Subsequent versions will not require these extra steps.

19
docs/upgrade.md Normal file
View File

@@ -0,0 +1,19 @@
**NOTE:** If you are upgrading from v0.1.0, which is the first version, please refer to [upgrade-from-v0.1.0.md](./upgrade-from-v0.1.0.md)
```bash
# Ensure compose yml up to date.
## Mac/Linux
curl -L -O https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml
## Windows PowerShell
Invoke-WebRequest -Uri "https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml" -OutFile ([System.IO.Path]::GetFileName("https://raw.githubusercontent.com/glidea/zenfeed/main/docker-compose.yml"))
# Ensure images up to date.
docker-compose -p zenfeed pull
# Upgrading without reconfiguring, etc APIKey.
docker-compose -p zenfeed up -d
```
Then all the feed data and configurations should be intact.

View File

@@ -1,25 +0,0 @@
timezone: Asia/Shanghai
llms:
- name: general
default: true
provider: siliconflow
model: Qwen/Qwen2.5-7B-Instruct
- name: embed
provider: siliconflow
embedding_model: Pro/BAAI/bge-m3
scrape:
rsshub_endpoint: http://rsshub:1200
storage:
feed:
rewrites:
- transform:
to_text:
prompt: |
{{ .summary_html_snippet }}
label: summary_html_snippet
embedding_llm: embed
notify:
channels:
email:
feed_html_snippet_template: |
{{ .summary_html_snippet }}

View File

@@ -1,24 +0,0 @@
version: "3.8"
services:
zenfeed:
image: glidea/zenfeed:latest
volumes:
- data:/app/data
- type: bind
source: ./config
target: /app/config
ports:
- "1300:1300"
- "1301:1301"
depends_on:
- rsshub
rsshub:
image: diygod/rsshub:latest
ports:
- "1200:1200"
environment:
- NODE_ENV=production
volumes:
data: {}

View File

@@ -1,131 +0,0 @@
#!/bin/bash
YQ_IMAGE="mikefarah/yq:latest"
template_source=""
values_args=()
# --- Parse command line arguments ---
while [[ $# -gt 0 ]]; do
key="$1"
case $key in
--template)
template_source="$2"
shift # past argument
shift # past value
;;
--values)
# Collect all arguments after --values until next -- argument or end
shift # past --values
while [[ $# -gt 0 ]] && [[ ! "$1" =~ ^-- ]]; do
values_args+=("$1")
shift # past value argument
done
;;
*) # Unknown option
echo "Error: Unknown option $1" >&2
exit 1
;;
esac
done
# --- Get template content ---
current_yaml=""
if [[ -z "$template_source" ]]; then
# If no template provided, start with empty YAML
current_yaml="{}"
elif [[ "$template_source" =~ ^https?:// ]]; then
# Download from URL
# Use curl, exit if fails
if ! command -v curl &> /dev/null; then
echo "Error: curl command required to download URL template." >&2
exit 1
fi
template_content=$(curl -sfL "$template_source")
if [[ $? -ne 0 ]]; then
echo "Error: Failed to download template from URL: $template_source" >&2
exit 1
fi
# Check if downloaded content is empty
if [[ -z "$template_content" ]]; then
current_yaml="{}"
else
current_yaml="$template_content"
fi
elif [[ -f "$template_source" ]]; then
# Read from local file
current_yaml=$(cat "$template_source")
# Check if file content is empty
if [[ -z "$current_yaml" ]]; then
current_yaml="{}"
fi
else
# Invalid template source
echo "Error: Invalid template source '$template_source'. Please provide valid file path or HTTP/HTTPS URL." >&2
exit 1
fi
# --- Check if Docker is available ---
if ! command -v docker &> /dev/null; then
echo "Error: docker command required to run yq." >&2
exit 1
fi
# Try pulling or verifying yq image (helps catch issues early)
docker pull $YQ_IMAGE > /dev/null
# --- Apply values ---
if [[ ${#values_args[@]} -gt 0 ]]; then
for val_arg in "${values_args[@]}"; do
# Parse key=value
if [[ ! "$val_arg" =~ ^([^=]+)=(.*)$ ]]; then
continue
fi
# BASH_REMATCH is result array from =~ operator
yaml_path="${BASH_REMATCH[1]}"
raw_value="${BASH_REMATCH[2]}"
# Prepare yq value (try handling basic types, otherwise treat as string)
yq_value=""
if [[ "$raw_value" == "true" || "$raw_value" == "false" || "$raw_value" == "null" ]]; then
yq_value="$raw_value"
# Check if integer or float (simple regex)
elif [[ "$raw_value" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
# If value starts with 0 but isn't 0 itself and has no decimal point, force string to prevent octal interpretation
if [[ "$raw_value" =~ ^0[0-9]+$ ]]; then
# Need to escape internal double quotes
escaped_value=$(echo "$raw_value" | sed 's/"/\\"/g')
yq_value="\"$escaped_value\""
else
yq_value="$raw_value"
fi
else
# Treat as string, need to escape internal double quotes
escaped_value=$(echo "$raw_value" | sed 's/"/\\"/g')
yq_value="\"$escaped_value\""
fi
# Build yq expression
yq_expression=".$yaml_path = $yq_value"
# Apply update via docker run yq
# Pass current YAML via stdin to yq, get stdout as new YAML
# Use <<< for here-string input to avoid temp files
new_yaml=$(docker run --rm -i "$YQ_IMAGE" "$yq_expression" <<< "$current_yaml")
yq_exit_code=$?
if [[ $yq_exit_code -ne 0 ]]; then
echo "Error: yq execution failed (exit code: $yq_exit_code). Expression: '$yq_expression'" >&2
# Could output yq error message, but requires more complex docker run call to capture stderr
exit 1
fi
current_yaml="$new_yaml"
done
fi
# --- Output final result ---
printf "%s\n" "$current_yaml"
exit 0

View File

@@ -138,7 +138,7 @@ type QueryRSSHubRoutesResponse struct {
type RSSHubRoute struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Path string `json:"path,omitempty"`
Path any `json:"path,omitempty"`
Example string `json:"example,omitempty"`
Parameters map[string]any `json:"parameters,omitempty"`
Features map[string]any `json:"features,omitempty"`