Skill: chegangan/daily-englishnews-reader (version 1.0.0)

--- name: Daily-EnglishNews-Reader version: 1.0.0 description: 单次生成符合i+1学习法的英语阅读材料，自动适配CEFR难度，生成飞书云文档 author: lihua license: MIT required_extensions: - "@larksuite/openclaw-lark-tools" tags: - 英语学习 - RSS - 自动生成 - i+1学习法 metadata: { "openclaw": { "emoji": "📚", "requires": { "bins": ["python3", "pip3"] }, "install": [ { "id": "lark-plugin", "kind": "shell", "command": "npx -y @larksuite/openclaw-lark-tools install", "label": "Install official Lark/Feishu plugin", }, { "id": "pip-deps", "kind": "shell", "command": "pip3 install requests feedparser", "label": "Install Python dependencies (requests + feedparser)", }, ], }, } --- # English Daily Reader Skill for OpenClaw ## 功能说明 单次生成符合i+1学习法的英语阅读材料，解决两个核心痛点： 1. 自动搜索最新全球高质量文章，内容覆盖全球新闻、经济、科技、科学文化，学英语的同时了解行业资讯 2. 自动适配CEFR英语难度等级（A1/A2/B1/B2/C1），提供刚好匹配水平的学习语料 ### 核心特性 ✅ 每次调用从4个已经指定的分类RSS源各选1篇高质量文章（全球政治、经济、科技、科学文化） ✅ 改写为指定难度与字数的英文文章 ✅ 每篇文章提取指定数量的+1难度生词，附带英文释义和语境例句 ✅ 生成新的飞书云文档，直接返回文档链接 ✅ 自动去重，不会重复推荐已经生成过的文章 ## 使用方法 ### 前置检查 使用前请需要确保已安装飞书官方OpenClaw插件： 1. 执行安装命令：`npx -y @larksuite/openclaw-lark-tools install`（安装出错可加`sudo`重试） 2. 安装过程中选择「新建机器人」扫码创建，或「关联已有机器人」 3. 创建完成后在飞书给机器人发任意消息激活，发送`/feishu auth`完成批量授权 4. 验证安装：发送`/feishu start`，返回版本号即安装成功 如果没有安装插件，当用户调用本Skill时你要引导用户完成上述安装步骤。 ### 首次使用 当用户第一次调用本Skill时，你需要询问用户以下配置信息，并修改配置文件完成配置： 1. **阅读难度**：显示默认 A2，CEFR等级（A1/A2/B1/B2/C1，难度递增） 2. **每篇文章字数**：显示默认 350 （可自定义） 3. **每篇在文章最后讲解的可能为i+1难度的生词数量**：显示默认 3 个/篇（可自定义） ### 配置文件 所有配置都在`config`目录下，每次运行前读取一次： - `config/config.json`：基础阅读配置，包含阅读难度、每篇文章字数、每篇讲解生词数量 - `config/rss_sources.json`：预设RSS源，你需要从这里查找用户设置的rss源 - `config/sent_articles.json`：已生成过的文章去重列表，读取过的文章你需要记录在这里，避免下次重复读取 ### 调用方式与运行步骤 当用户发送类似意思的指令：`生成英语阅读材料` 或 `调用Daily-EnglishNews-Reader`，你会自动完成以下步骤： 1. 读取`config/rss_sources.json`配置 2. 运行`scripts/random_source_picker.py`，这个脚本会随机从4个rss分类中各选一个RSS源 3. 从每个源挑选一篇完整的且未在`config/sent_articles.json`中记录的高质量文章 4. 按照用户配置的难度、字数改写文章,在不影响理解的前提下，要求用词地道，且尽量保留专业技术用语 5. 在改写后的文章中，根据用户配置的讲解生词数量，在生成的短文中选取可能属于+1难度的生词加粗,在短文末尾列出所有加粗生词的英文释义和在短文中出现的语境例句； 6. 生成全新的飞书云文档，写入4篇文章内容，并附上来源和文章原始URL 7. 返回文档链接给用户 8. 将本次生成的文章的来源、标题、URL记录到`config/sent_articles.json`中，避免后续重复推荐 `config/config.json`默认配置： ```json { "reading": { "difficulty": "A2", "words_per_article": 350, "words_per_article_to_explain": 3 } } ``` ## 依赖工具 - `python3` 用于RSS源随机选择 - 飞书官方OpenClaw插件：`@larksuite/openclaw-lark-tools`

path: README.md
content: <div align="center">

# 📚 Daily-EnglishNews-Reader

**基于 OpenClaw 的英语新闻检索 Skill**  
*用 i+1 学习法轻松学英语 + 了解全球资讯*

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
![OpenClaw Skill](https://img.shields.io/badge/OpenClaw-Skill-brightgreen)
![Python 3](https://img.shields.io/badge/Python-3-yellow)

[功能特性](#-核心特性) • [安装指南](#%EF%B8%8F-安装与准备) • [使用方法](#-使用指南) • [配置说明](#-目录结构与配置说明)

</div>

---

## 📖 项目简介

**Daily-EnglishNews-Reader** 基于 OpenClaw 的英语新闻检索 Skill，旨在帮助用户用 i+1 学习法轻松学英语 + 了解全球资讯

> **Skill 运行效果**：OpenClaw 会自动返回一个 **飞书云文档链接**，包含：
> * 📄 **4 篇精选文章**：基于高质量新闻源，重写为符合你阅读难度的文章。
> * 📝 **生词讲解**：每篇文章末尾用简单的英文解析 自定义 个数量的 i+1 难度的生词，并附带例子
> * 🔗 **来源追溯**：附带文章的原始出处链接。

![](./static/1.png)

### 进阶玩法
可以让openclaw每日定时调用这个skills，生成每日阅读资料，快速了解近期国际新闻，顺便学习英语

### 💡"i+1 学习法"介绍

- **i+1 理论**：公认最高效的英语学习方法。"i" 代表你当前的水平，"+1" 代表稍高一点的挑战。
- **自然习得**：不靠死记硬背，而是通过大量阅读，在上下文中自然吸收那 10% 的新内容。
- **完美学习体验**：比背单词有意思，容易坚持

### 🎯 解决两大痛点

1. **😫 语料收集麻烦**：自动搜索最新全球高质量文章，内容覆盖全球新闻、经济、科技、科学文化，学英语的同时了解行业资讯
2. **😵 难度难以匹配**：自动重写文章以匹配你的 **CEFR 英语水平等级（A1-C1）**，每天都能通读大量英文语料。

## 🛠️ 安装与准备

本 Skill 基于openclaw开发，首先需要下载安装openclaw
依赖 Python 环境及飞书官方 OpenClaw 插件。

### 📦 快速部署

1. 将本项目文件夹拖拽到 `.openclaw/workspace/skills` 目录下。
2. 重启 OpenClaw。
3. 再次与 OpenClaw 交互时，系统会引导你完成依赖安装。

### ⚙️ 依赖说明

系统会自动通过 metadata 安装以下依赖：
* **Python 3 库**：`requests`, `feedparser`
* **OpenClaw 飞书插件**：`@larksuite/openclaw-lark-tools`

### 🔑 飞书授权（必读）

> **说明**：本 Skill 使用功能更强大的飞书官方插件 `@larksuite/openclaw-lark-tools`。安装后会自动禁用 OpenClaw 自带的飞书插件。
飞书官方插件安装文档在这：https://bytedance.larkoffice.com/docx/MFK7dDFLFoVlOGxWCv5cTXKmnMh

若openclaw引导安装飞书插件失败，请手动按以下步骤操作：

1. **安装插件**：执行命令：
   ```bash
   npx -y @larksuite/openclaw-lark-tools install
   # 如遇权限问题请加 sudo
   ```
2. **创建/关联机器人**：按终端提示选择「新建机器人」并扫码，或「关联已有机器人」。
3. **激活机器人**：在飞书客户端给该机器人发送任意消息。
4. **验证安装**：发送 `/feishu start`，返回版本号即成功。
5. **给机器人授权**：在使用skills的时候，机器人会询问你修改云文档的授权，同意即可。

> ⚠️ **注意**：必须完成飞书授权，否则无法生成云文档。

---

## 🚀 使用指南

### 1️⃣ 首次初始化

首次调用时，系统会引导你配置个性化参数（自动更新 `config/config.json`）：

- **📊 阅读难度 (CEFR)**：`A1` / `A2` / `B1` / `B2` / `C1`（默认：`A2`）
- **📝 文章字数**：每篇改写后的目标字数（默认：`350`）
- **🧠 讲解生词数**：每篇提取的生词数量（默认：`3`）

### 2️⃣ 唤醒与运行

发送自然语言指令即可调用：

> 🗣️ *"生成今天的英语阅读材料"*
>
> 🗣️ *"调用 Daily-EnglishNews-Reader"*

---
## ✨ 核心特性

| 特性 | 说明 |
| :--- | :--- |
| **🌍 多源聚合** | 自动从 4 个分类 RSS 源中各抽取 1 篇最新高质量文章。 |
| **🎚️ 智能适配** | 利用大模型将文章改写为指定的 **CEFR 难度** 和目标字数，行文地道。 |
| **📖 自动生词** | 智能提取 `+1` 难度生词，加粗显示并提供英文释义及例句。 |
| **☁️ 飞书直达** | 自动生成排版精美的 **飞书云文档**，直接返回阅读链接。 |
| **🛡️ 智能去重** | 内置本地记录机制，确保每天推荐的文章不重复。 |

---



## 📁 目录结构与配置说明

所有自定义配置均存放在 `config` 目录下：

| 文件名 | 说明 |
| :--- | :--- |
| **`config.json`** | **基础阅读偏好配置**<br>包含难度、字数、生词数等设置。 |
| **`rss_sources.json`** | **RSS 订阅源**<br>支持用户自行添加或修改订阅链接。 |
| **`sent_articles.json`** | **已读记录**<br>系统自动维护，用于去重。 |

**`config.json` 示例：**
```json
{
  "reading": {
    "difficulty": "A2",
    "words_per_article": 350,
    "words_per_article_to_explain": 3
  }
}
```

### 🔄 工作流解析

1. 📥 **读取配置**：加载 `config/rss_sources.json` 订阅源。
2. 🎲 **随机筛选**：从 4 个领域中随机挑选 RSS 源。
3. 🕵️ **抓取过滤**：抓取文章并根据 `config/sent_articles.json` 历史记录去重。
4. 🤖 **AI 重写**：大模型按指定难度和字数重写文章。
5. 📚 **生词提取**：加粗生词，附上释义和例句。
6. ☁️ **生成文档**：调用飞书 API 生成排版精美的云文档。
7. 🔗 **返回链接**：发送文档链接给用户。
8. 📝 **记录去重**：更新 `sent_articles.json`，防止重复推荐。

---

## 📄 License

This project is licensed under the **MIT License**.

## ⚖️ Disclaimer & Fair Use

**This project (English Daily Reader) is an educational tool designed exclusively for language learning purposes.**

- **Transformative Use**: The articles processed by this tool are heavily modified, summarized, and rewritten to match specific CEFR language levels (e.g., A1-C1). Under copyright law, this constitutes "transformative use" and falls under Fair Use principles.
- **Attribution**: All generated content retains clear attribution to the original publishers and provides direct links to the original source articles.
- **No Affiliation**: This project is strictly independent. It is not affiliated with, sponsored by, or endorsed by any of the news outlets or RSS feed providers used in the default configuration.
- **Non-Commercial**: This codebase and its outputs are intended for personal, non-commercial use. Users who deploy this tool to generate and distribute content for commercial gain do so entirely at their own legal risk.

> *Notice to Copyright Holders: If you believe that this project's use of your public RSS feeds exceeds fair use, please open an issue, and your domain will be promptly removed from the default source list.*

path: scripts/random_source_picker.py
content: #!/usr/bin/env python3
import random
import json
import sys
import requests
from typing import List, Dict

def pick_random_sources(rss_config: Dict) -> List[Dict]:
    """
    Pick one random source from each group in the RSS config
    Args:
        rss_config: loaded content from rss_sources.json
    Returns:
        list of selected sources, one per group
    """
    selected = []
    groups = rss_config["groups"]
    
    for group_name, sources in groups.items():
        # Pick a random index from 0 to len(sources)-1
        random_index = random.randint(0, len(sources) - 1)
        picked_source = sources[random_index]
        # Add group name to the picked source info
        picked_source["group"] = group_name
        selected.append(picked_source)
        print(f"Picked source from {group_name}: {picked_source['name']}")
    
    return selected

def test_sources(rss_config: Dict) -> bool:
    """Test if all RSS sources are reachable"""
    all_ok = True
    groups = rss_config["groups"]
    
    for group_name, sources in groups.items():
        print(f"\nTesting {group_name} sources:")
        for source in sources:
            try:
                response = requests.get(source["url"], timeout=10)
                response.raise_for_status()
                print(f"✅ {source['name']}: OK")
            except Exception as e:
                print(f"❌ {source['name']}: Failed - {str(e)}")
                all_ok = False
    return all_ok

if __name__ == "__main__":
    # Load RSS sources config
    import os
    script_dir = os.path.dirname(os.path.abspath(__file__))
    rss_config_path = os.path.join(script_dir, "../config/rss_sources.json")
    with open(rss_config_path, "r", encoding="utf-8") as f:
        config = json.load(f)
    
    # Check for test flag
    if len(sys.argv) > 1 and sys.argv[1] == "--test":
        success = test_sources(config)
        sys.exit(0 if success else 1)
    
    # Pick random sources
    picked = pick_random_sources(config)
    print("\nAll selected sources for today:")
    for s in picked:
        print(f"- {s['name']} ({s['group']}): {s['url']}")


path: config/rss_sources.json
content: {
  "groups": {
    "group1_global_geopolitics": [
      {
        "name": "Al Jazeera English",
        "url": "https://morss.it/:format=json/https://www.aljazeera.com/xml/rss/all.xml",
        "description": "覆盖全球的高质量国际新闻，语言简洁易懂，适合英语学习"
      }
    ],
    "group2_politics_economy": [
      {
        "name": "Vox Business",
        "url": "https://morss.it/:format=json/https://www.vox.com/rss/business-and-finance/index.xml",
        "description": "用通俗语言解释复杂经济和商业问题，解释性强，生词少"
      }
    ],
    "group3_tech_ai_cloud": [
      {
        "name": "Cloudflare Blog",
        "url": "https://morss.it/:format=json/https://blog.cloudflare.com/rss/",
        "description": "Deep technical posts about cloud and network security"
      }
    ],
    "group4_culture_science": [
      {
        "name": "The Conversation",
        "url": "https://morss.it/:format=json/https://theconversation.com/us/articles.atom",
        "description": "大学教授和研究员撰写的科学文化类文章，内容准确权威，语言严谨易懂"
      }
    ]
  }
}

path: config/sent_articles.json

path: config/config.json
content: {
  "reading": {
    "difficulty": "A2",
    "words_per_article": 350,
    "words_per_article_to_explain": 3
  }
}

Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)