├── .DS_Store
├── .github
└── workflows
│ └── rssbot.yml
├── .gitignore
├── README.md
├── robot
├── models.py
├── requirements.txt
├── rss.db
└── rss.py
└── screens
└── 效果图.png
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LeetaoGoooo/dingding-rssbot/8f841851f76832ee2879e01d8d7626dff4d7c3fc/.DS_Store
--------------------------------------------------------------------------------
/.github/workflows/rssbot.yml:
--------------------------------------------------------------------------------
1 | # 钉钉 rss 推送机器人
2 | name: DingDingRssBot
3 |
4 | on:
5 | schedule:
6 | - cron: '0 0/1 * * *'
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: 'Checkout codes'
13 | uses: actions/checkout@v2
14 | - name: Set up Python Version
15 | uses: actions/setup-python@v2
16 | with:
17 | python-version: '3.10'
18 | - name: Install dependencies
19 | run: |
20 | cd robot
21 | pip install -r requirements.txt
22 | - name: send rss
23 | env:
24 | DD_WEBHOOK: ${{ secrets.webhook }}
25 | DD_SECRET: ${{ secrets.secret }}
26 | run: |
27 | cd robot
28 | python rss.py
29 | - name: Commit
30 | run: |
31 | git config --global user.email leetao94cn@gmail.com
32 | git config --global user.name lt94
33 | git add .
34 | git commit -m "update" -a
35 | - name: Push changes
36 | uses: ad-m/github-push-action@master
37 | with:
38 | branch: main
39 | github_token: ${{ secrets.TOKEN }}
40 |
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | venv
3 | .venv
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # DingDing Rss Robot
2 | 钉钉 rss 订阅机器人
3 |
4 | # 功能
5 |
6 | - rss 订阅
7 | - rss 定时推送
8 |
9 | # 使用说明
10 |
11 | fork 本项目后,需要进行配置后才能正常使用
12 |
13 | ## rss 源配置
14 |
15 | 使用数据库管理源打开 rss.db 文件,修改 rss.db 表中的 Rss 表
16 |
17 | ```python
18 | class Rss(BaseModel):
19 | feed = CharField(unique=True) # 订阅地址
20 | cover = CharField(max_length=255, null=True) # 封面(图片地址)
21 | title = CharField(max_length=20) # 订阅名称
22 | url = CharField(max_length=255) # 网站地址
23 | ```
24 |
25 |
26 | ## 定时配置
27 |
28 | 修改 `.github/workflows/rssbot.yml` 文件第 8 行 cronb 的表达式
29 |
30 | ⚠️ **频率不要太频繁,避免被误判滥用**
31 |
32 | 其中 31 和 32 行配置可以设置为自己的邮箱和名称
33 |
34 | ```yaml
35 | git config --global user.email lineporte@gmail.com
36 | git config --global user.name linep47
37 | ```
38 |
39 | ## 配置环境变量
40 |
41 | 钉钉机器人需要使用 `WEBHOOK` 和 `SECRET`(对应**加签**) 这两个参考钉钉机器人文档自行申请。
42 |
43 | 还需要申请一个 `TOKEN`, 点击 [Personal access tokens (classic)](https://github.com/settings/tokens) 申请
44 |
45 | 然后在项目的 Settings 中依次添加 `WEBHOOK`,`SECRET`,`TOKEN` 三个参数
46 |
47 |
48 |
49 |
50 |
51 | # 效果
52 |
53 |
54 |
--------------------------------------------------------------------------------
/robot/models.py:
--------------------------------------------------------------------------------
1 | from peewee import *
2 | import datetime
3 |
4 | db = SqliteDatabase('rss.db')
5 |
6 |
7 | class BaseModel(Model):
8 | class Meta:
9 | database = db
10 |
11 |
12 | class Rss(BaseModel):
13 | feed = CharField(unique=True) # 订阅地址
14 | cover = CharField(max_length=255, null=True) # 封面(图片地址)
15 | title = CharField(max_length=20) # 订阅名称
16 | url = CharField(max_length=255) # 网站地址
17 |
18 |
19 | class History(BaseModel):
20 | url = CharField(max_length=255)
21 | publish_at = DateField(default=datetime.datetime.now)
22 |
23 |
24 | def create_tables():
25 | with db:
26 | db.create_tables([Rss, History])
27 |
--------------------------------------------------------------------------------
/robot/requirements.txt:
--------------------------------------------------------------------------------
1 | dateparser==0.7.6
2 | DingtalkChatbot==1.5.1
3 | feedparser==6.0.1
4 | peewee==3.13.3
--------------------------------------------------------------------------------
/robot/rss.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LeetaoGoooo/dingding-rssbot/8f841851f76832ee2879e01d8d7626dff4d7c3fc/robot/rss.db
--------------------------------------------------------------------------------
/robot/rss.py:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | """
4 | rss.py
5 |
6 | 钉钉 Rss 机器人
7 | 推送 Rss 信息到钉钉机器人Api
8 |
9 | """
10 | from datetime import datetime, timedelta
11 | from itertools import takewhile
12 | import feedparser
13 | from dingtalkchatbot.chatbot import DingtalkChatbot, CardItem
14 | import dateparser
15 | from models import db, Rss, History
16 | import os
17 |
18 |
19 | class RssRobot:
20 | def __init__(self):
21 | # 说明文档的效果图中的 post_cover
22 | self.post_cover = "https://leetao.zhubai.love/api/wechat/miniprogram_qrcode?page=pages%2Fpublication%2Fpublication&publication_id=2170089804120211456&scene=token%3Dleetao&width=200"
23 | self.robot = DingtalkChatbot(
24 | os.environ.get("DD_WEBHOOK"),
25 | pc_slide=True, secret=os.environ.get("DD_SECRET"))
26 | self.remove_old_history()
27 |
28 | @property
29 | def sended_urls(self):
30 | return [rss_history.url for rss_history in History.select()]
31 |
32 | @property
33 | def subscriptions(self):
34 | return Rss.select()
35 |
36 | def get_post_cards(self):
37 | feeds = []
38 | for subscription in self.subscriptions:
39 | feed = feedparser.parse(subscription.feed)
40 | pic_url = subscription.cover if subscription.cover else self.post_cover
41 | feed_header = CardItem(
42 | title=subscription.title, url=subscription.url, pic_url=pic_url)
43 | posts = self.get_posts(feed.entries)
44 | if posts:
45 | feeds.append([feed_header, *posts])
46 | return feeds
47 |
48 | def get_posts(self, entries):
49 | post_cards = []
50 | post_urls = []
51 | for entry in takewhile(self.is_not_sended, entries):
52 | post_cards.append(CardItem(title=entry.title,
53 | url=entry.link, pic_url=self.post_cover))
54 | post_urls.append(History(url=entry.link))
55 | with db.atomic():
56 | History.bulk_create(post_urls, batch_size=100)
57 | return post_cards
58 |
59 | def is_not_sended(self, url):
60 | return url not in self.sended_urls
61 |
62 | def is_today(self, entry):
63 | return dateparser.parse(entry['updated']).date() == datetime.today().date()
64 |
65 | def send_rss(self):
66 | post_cards = self.get_post_cards()
67 | for post_card in post_cards:
68 | self.robot.send_feed_card(post_card)
69 |
70 | def remove_old_history(self):
71 | # 只保留最近一周的记录
72 | week_date_range = datetime.now() + timedelta(days=-7)
73 | History.delete().where(History.publish_at <
74 | week_date_range.strftime("%Y-%m-%d")).execute()
75 |
76 |
77 | def send_rss():
78 | rss_bot = RssRobot()
79 | rss_bot.send_rss()
80 |
81 |
82 | if __name__ == '__main__':
83 | send_rss()
84 |
--------------------------------------------------------------------------------
/screens/效果图.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/LeetaoGoooo/dingding-rssbot/8f841851f76832ee2879e01d8d7626dff4d7c3fc/screens/效果图.png
--------------------------------------------------------------------------------