Configuration
先搞一个测试号,并且让收消息的人关注,获取 USER_ID
:
有自己个人号更好,我的没管它自动注销了
加个消息模版,获取 TEMPLATE_ID
,加上测试号本身的 APP_ID
APP_SECRET
,配置就齐了:
在项目 Setting -> Secrets -> Actions 里新建几个我们要用的配置:
这里查天气的城市
CITY
是地级市汉字
生日
BIRTHDAY
是m-d
格式
纪念日
START_DATE
是Y-m-d
格式
Workflow
使用 GitHub 的 Actions 建立工作流:
支持定时
schedule
与手动workflow_dispatch
执行脚本 main.py,并且把设置中写的配置读出来
name: morning
on:
schedule:
- cron: '1 23 * * *'
workflow_dispatch:
jobs:
send_message:
runs-on: ubuntu-latest
name: send good morning
steps:
- name: checkout
uses: actions/checkout@v3
with:
ref: master
- name: sender
uses: actions/setup-python@v2
with:
python-version: '3.x'
architecture: 'x64'
- run: pip install -r ./requirements.txt && python ./main.py
env:
APP_ID: ${{ secrets.APP_ID }}
APP_SECRET: ${{ secrets.APP_SECRET }}
TEMPLATE_ID: ${{ secrets.TEMPLATE_ID }}
USER_ID: ${{ secrets.USER_ID }}
START_DATE: ${{ secrets.START_DATE }}
BIRTHDAY: ${{ secrets.BIRTHDAY }}
CITY: ${{ secrets.CITY }}
这里 Cron 格式是标准的分时日月年,更多内容查看文档:
UTC 时间,北京时间要减 8
Python
先把配置拿出来:
today = datetime.utcnow() + timedelta(hours=8)
today = datetime.strptime(str(today.date()), "%Y-%m-%d")
start_date = os.getenv('START_DATE')
city = os.getenv('CITY')
birthday = os.getenv('BIRTHDAY')
app_id = os.getenv('APP_ID')
app_secret = os.getenv('APP_SECRET')
user_ids = os.getenv('USER_ID', '').split("\n")
template_id = os.getenv('TEMPLATE_ID')
获取城市天气:
def get_weather():
if city is None:
print('check your CITY config')
return None
url = "http://autodev.openspeech.cn/csp/api/v2.1/weather?openId=aiuicus&clientType=android&sign=android&city=" + city
res = requests.get(url).json()
if res is None:
return None
weather = res['data']['list'][0]
return weather
计算纪念日:
def get_memorial_days_count():
if start_date is None:
print('check your START_DATE config')
return 0
delta = today - datetime.strptime(start_date, "%Y-%m-%d")
return delta.days
计算生日:
def get_birthday_left():
if birthday is None:
print('check your BIRTHDAY config')
return 0
next = datetime.strptime(str(date.today().year) + "-" + birthday, "%Y-%m-%d")
if next < datetime.now():
next = next.replace(year=next.year + 1)
return (next - today).days
获取一句情话:
失败重新调用
def get_words():
words = requests.get("https://api.shadiao.pro/chp")
if words.status_code != 200:
return get_words()
return words.json()['data']['text']
请求微信接口:
配置模版消息时
{{words.DATA}}
对应data.words
字段,依此类推
try:
client = WeChatClient(app_id, app_secret)
except WeChatClientException as e:
print('get access token fail')
exit(502)
wm = WeChatMessage(client)
weather = get_weather()
if weather is None:
print('get weather fail')
exit(422)
data = {
"city": {
"value": city,
"color": get_random_color()
},
"date": {
"value": today.strftime('%Y年%m月%d日'),
"color": get_random_color()
},
"weather": {
"value": weather['weather'],
"color": get_random_color()
},
"temperature": {
"value": math.floor(weather['temp']),
"color": get_random_color()
},
"highest": {
"value": math.floor(weather['high']),
"color": get_random_color()
},
"lowest": {
"value": math.floor(weather['low']),
"color": get_random_color()
},
"love_days": {
"value": get_memorial_days_count(),
"color": get_random_color()
},
"birthday_left": {
"value": get_birthday_left(),
"color": get_random_color()
},
"words": {
"value": get_words(),
"color": get_random_color()
},
}
if __name__ == '__main__':
count = 0
try:
for user_id in user_ids:
res = wm.send_template(user_id, template_id, data)
count+=1
except WeChatClientException as e:
print('wechat error:%s.code:%d' % (e.errmsg, e.errcode))
exit(502)
print("total" + str(count) + "messages")
随机颜色为了好看点,手机上生效:
def get_random_color():
return "#%06x" % random.randint(0, 0xFFFFFF)
引入依赖:
from datetime import date, datetime, timedelta
import math
from wechatpy import WeChatClient, WeChatClientException
from wechatpy.client.api import WeChatMessage
import requests
import os
import random
certifi==2022.6.15
cffi==1.15.1
charset-normalizer==2.1.0
cryptography==37.0.4
idna==3.3
optionaldict==0.1.2
pycparser==2.21
python-dateutil==2.8.2
requests==2.28.1
six==1.16.0
urllib3==1.26.11
wechatpy==1.8.18
xmltodict==0.13.0
最终效果如图: