diff --git a/.github/workflows/send_love.yml b/.github/workflows/send_love.yml index 09648dd..125b14a 100644 --- a/.github/workflows/send_love.yml +++ b/.github/workflows/send_love.yml @@ -1,22 +1,48 @@ name: CI on: schedule: - - cron: "5 0 * * *" + # 每天早上7:40运行 + - cron: "40 7 * * *" + # 每天下午5:00运行 + - cron: "0 17 * * *" push: branches: [ "main" ] jobs: - build: + send-morning-message: runs-on: ubuntu-latest - steps: + steps: + - name: Checkout repository - uses: actions/checkout@v3 + - name: Set up Python 3.9 uses: actions/setup-python@v2 with: python-version: 3.9 + - name: Install dependencies run: | python -m pip install --upgrade pip pip install -r requirements.txt - - name: send msg + + - name: Run morning message script run: | - python send_love_msg.py + python send_morning_message.py + send-evening-message: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.9 + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install -r requirements.txt + + - name: Run evening message script + run: | + python send_evening_message.py diff --git a/config.dev.yaml b/config.dev.yaml deleted file mode 100644 index fcf15cf..0000000 --- a/config.dev.yaml +++ /dev/null @@ -1,17 +0,0 @@ -wxPusher: - appToken: "xxxxxxxxxxxxxxxxxxxxxx" # wxPusher的appToken - topicIds: - - xxxx # wxPusher的topicIds,支持多个ID - -wechatWork: - webhookKey: "xxxxxx" # 企业微信的webhook key - -weather: - apiKey: "xxxxxxxxxxxxx" # 高德天气接口的key - city: 420100 # https://a.amap.com/lbs/static/code_resource/AMap_adcode_citycode.zip - -lover: - expressLoveTimestamp: 1136185445 - monthOfBirthday: 1 - dayOfBirthday: 1 - meetingTimestamp: 1136185445 diff --git a/config.yaml b/config.yaml new file mode 100644 index 0000000..9b37656 --- /dev/null +++ b/config.yaml @@ -0,0 +1,17 @@ +wxPusher: + appToken: "AT_penx9gyzxwP6g7dwd4lb6LoWHskuGPiE" # wxPusher的appToken + topicIds: + - 34432 # wxPusher的topicIds,支持多个ID + +wechatWork: + webhookKey: "xxxxxx" # 企业微信的webhook key + +weather: + apiKey: "fd14b9ca913160e65eb47b1edba5d48c" # 高德天气接口的key + city: 610118 # https://a.amap.com/lbs/static/code_resource/AMap_adcode_citycode.zip + +lover: + expressLoveTimestamp: 1594378800 + monthOfBirthday: 8 + dayOfBirthday: 19 + meetingTimestamp: 1504233600 diff --git a/send_evening_message.py b/send_evening_message.py new file mode 100644 index 0000000..2fb1257 --- /dev/null +++ b/send_evening_message.py @@ -0,0 +1,71 @@ +import json +from datetime import datetime, timedelta +import pytz +import requests +from config import loadConfig + +# Load configuration +config = loadConfig("config.yaml") +qywxWebhookKey = config.weChatWork.webhookKey +wxpushAppToken = config.wxPusher.appToken +wxpushTopicIds = config.wxPusher.topicIds + +def getDaysUntil(date_str): + target_date = datetime.strptime(date_str, "%Y-%m-%d") + tz = pytz.timezone("Asia/Shanghai") + now = datetime.now(tz) + return (target_date - now).days + +def sendAlarmMsg(mdTex): + wechatwork(mdTex) + +def wechatwork(tex): + webhook = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={qywxWebhookKey}" + header = {"Content-Type": "application/json", "Charset": "UTF-8"} + message = {"msgtype": "markdown", "markdown": {"content": tex}} + message_json = json.dumps(message) + try: + requests.post(url=webhook, data=message_json, headers=header) + except requests.exceptions.RequestException as e: + print("unable to connect to wechat server, err:", e) + except Exception as e2: + print("send message to wechat server, err:", e2) + sendAlarmMsg(str(e2)) + +def wxPusher(tex): + url = "http://wxpusher.zjiecode.com/api/send/message" + header = {"Content-Type": "application/json", "Charset": "UTF-8"} + message = { + "appToken": wxpushAppToken, + "content": tex, + "summary": "按时吃药提醒", + "contentType": 2, + "topicIds": wxpushTopicIds, + "url": "http://wxpusher.zjiecode.com", + } + message_json = json.dumps(message) + try: + info = requests.post(url=url, data=message_json, headers=header) + print(info.text) + except requests.exceptions.RequestException as e: + print("unable to connect to wx, err:", e) + sendAlarmMsg(str(e)) + except Exception as e: + print("send message to wx, err:", e) + sendAlarmMsg(str(e)) + +if __name__ == "__main__": + days_until_end = getDaysUntil("2024-10-27") + + # 新增的提醒内容 + medication_reminder = ( + '宝宝快要下班了呢,记得按时吃药哦:' + '饭前半小时:雷贝拉唑 * 1,枸酸秘钾 * 2;' + '饭后半小时:阿莫西林 * 4,克拉霉素 * 2。' + ) + + # 发送提醒内容到企业微信 + wechatwork(medication_reminder) + + # 发送提醒内容到WxPusher + wxPusher(medication_reminder) diff --git a/send_morning_message.py b/send_morning_message.py new file mode 100644 index 0000000..9cf7355 --- /dev/null +++ b/send_morning_message.py @@ -0,0 +1,332 @@ +import json +from datetime import datetime + +import pytz +import requests + +from config import loadConfig + +# Load configuration +config = loadConfig("config.yaml") +qywxWebhookKey = config.weChatWork.webhookKey +wxpushAppToken = config.wxPusher.appToken +wxpushTopicIds = config.wxPusher.topicIds +city = config.weather.city +monthOfBirthday = config.lover.monthOfBirthday +dayOfBirthday = config.lover.dayOfBirthday +expressLoveTimestamp = config.lover.expressLoveTimestamp +meetingTimestamp = config.lover.meetingTimestamp +weatherApiKey = config.weather.apiKey + + +def getMsgHeader(): + tz = pytz.timezone("Asia/Shanghai") + dt = datetime.now(tz) + h = '今天是 {}'.format(dt.strftime("%Y-%m-%d %A")) + return h + + +def getMsgHeaderToWechat(): + tz = pytz.timezone("Asia/Shanghai") + dt = datetime.now(tz) + h = '今天是 {}'.format(dt.strftime("%Y-%m-%d %A")) + return h + + +class Weather: + def __init__(self): + self.city = "" + self.adcode = "" + self.province = "" + self.reporttime = "" + self.date = "" + self.week = "" + self.dayweather = "" + self.nightweather = "" + self.daytemp = "" + self.nighttemp = "" + self.daywind = "" + self.nightwind = "" + self.daypower = "" + self.nightpower = "" + + def isValide(self) -> bool: + return self.city != "" + + def jsonDecode(self, jsonTex): + self.city = jsonTex["city"] + self.adcode = jsonTex["adcode"] + self.province = jsonTex["province"] + self.reporttime = jsonTex["reporttime"] + casts = jsonTex["casts"][0] + self.date = casts["date"] + self.week = casts["week"] + self.dayweather = casts["dayweather"] + self.nightweather = casts["nightweather"] + self.daytemp = casts["daytemp"] + self.nighttemp = casts["nighttemp"] + self.daywind = casts["daywind"] + self.nightwind = casts["nightwind"] + self.daypower = casts["daypower"] + self.nightpower = casts["nightpower"] + + def getWeatherTextToWechatWork(self): + tex = '西安天气\n > {}, 白天温度: {} ~ 晚上温度: {}\n白天风力:{}-{},晚上风力:{}-{}。'.format( + self.dayweather, + self.daytemp, + self.nighttemp, + self.daypower, + self.daywind, + self.nightpower, + self.nightwind, + ) + return tex + + def getWeatherTextToWechat(self): + tex = '
西安天气
{}, 白天温度: {} ~ 晚上温度: {}, 白天风力:{}-{},晚上风力:{}-{}。'.format( + self.dayweather, + self.daytemp, + self.nighttemp, + self.daypower, + self.daywind, + self.nightpower, + self.nightwind, + ) + return tex + + +def getWeather() -> Weather: + url = "https://restapi.amap.com/v3/weather/weatherInfo" + params = { + "city": city, + "extensions": "all", + "key": weatherApiKey, + } + + try: + response = requests.get(url, params=params) + response.raise_for_status() # 检查请求是否成功 + data = response.json() + + if data.get("status") != "1": + raise ValueError(f"API Error: {data.get('info')}") + + forecasts_data = data.get("forecasts", []) + if not forecasts_data: + raise ValueError("No forecasts data available.") + + forecast = forecasts_data[0] + weather = Weather() + weather.jsonDecode(forecast) + + return weather + + except requests.RequestException as e: + print(f"Request error: {e}") + except ValueError as e: + print(f"Value error: {e}") + except Exception as e: + print(f"Unexpected error: {e}") + + return Weather() # 返回一个无效的 Weather 对象 + + +def getMeetingDay(): + tz = pytz.timezone("Asia/Shanghai") + now = datetime.now(tz) + day = int((now.timestamp() - meetingTimestamp) / (24 * 60 * 60)) + print(day) + print("相遇的:", day) + return day + + +def getBirthDayOfLover(): + tz = pytz.timezone("Asia/Shanghai") + yearNow = datetime.now(tz) + dt = datetime(yearNow.year, yearNow.month, yearNow.day) + # 判断今年的生日是否已经过去 + birthday = datetime(yearNow.year, monthOfBirthday, dayOfBirthday) + if birthday.timestamp() < yearNow.timestamp(): + # 下一年的生日 + birthday = datetime(birthday.year + 1, monthOfBirthday, dayOfBirthday) + day = int((birthday.timestamp() - dt.timestamp()) / (24 * 60 * 60)) + print("生日:", day) + return day + + +def getExpressLoveDay(): + # unixTimeStamp = 1599148800 + tz = pytz.timezone("Asia/Shanghai") + now = datetime.now(tz) + day = int((now.timestamp() - expressLoveTimestamp) / (24 * 60 * 60)) + print(day) + print("相爱的天:", day) + return day + + +class DailyWord: + def __init__(self): + self.sid = "" + self.note = "" + self.content = "" + self.pic = "" + + def isValide(self) -> bool: + return self.sid != "" + + def getDailyWordHtml(self) -> str: + return '
每日一句
{}
{}
'.format( + self.content, self.note, self.pic + ) + + +def getDailyWord() -> DailyWord: + url = "http://open.iciba.com/dsapi" + r = requests.get(url) + r.encoding = "utf-8" + result = r.json() + dw = DailyWord() + if result.get("sid"): + dw.sid = result["sid"] + dw.note = result["note"] + dw.content = result["content"] + dw.pic = result["fenxiang_img"] + return dw + + +def sendDailyWordToWechatWork(dw: DailyWord): + if dw.isValide(): + webhook = ( + f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={qywxWebhookKey}" + ) + header = {"Content-Type": "application/json", "Charset": "UTF-8"} + message = { + "msgtype": "news", + "news": { + "articles": [ + { + "title": "每日一句", + "description": dw.content, + "url": dw.pic, + "picurl": dw.pic, + } + ] + }, + } + message_json = json.dumps(message) + requests.post(url=webhook, data=message_json, headers=header) + return + + +def sendAlarmMsg(mdTex): + wechatwork(mdTex) + + +def wechatwork(tex): + webhook = f"https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key={qywxWebhookKey}" + header = {"Content-Type": "application/json", "Charset": "UTF-8"} + message = {"msgtype": "markdown", "markdown": {"content": tex}} + print(f"wechat send msg, key:{qywxWebhookKey}") + print(message) + message_json = json.dumps(message) + try: + requests.post(url=webhook, data=message_json, headers=header) + except requests.exceptions.RequestException as e: + print("unable to connect to wechat server, err:", e) + except Exception as e2: + print("send message to wechat server, err:", e2) + sendAlarmMsg(str(e2)) + + +def wxPusher(tex): + url = "http://wxpusher.zjiecode.com/api/send/message" + header = {"Content-Type": "application/json", "Charset": "UTF-8"} + message = { + "appToken": wxpushAppToken, + "content": tex, + "summary": "相爱一生", + "contentType": 2, + "topicIds": wxpushTopicIds, + "url": "http://wxpusher.zjiecode.com", + } + message_json = json.dumps(message) + try: + info = requests.post(url=url, data=message_json, headers=header) + print(info.text) + except requests.exceptions.RequestException as e: + print("unable to connect to wx, err:", e) + sendAlarmMsg(str(e)) + except Exception as e: + print("send message to wx, err:", e) + sendAlarmMsg(str(e)) + + +if __name__ == "__main__": + h = getMsgHeader() + w = getWeather() + bd = getBirthDayOfLover() + md = getMeetingDay() + ed = getExpressLoveDay() + dw = getDailyWord() + days_until_end = getDaysUntil("2024-10-27") + + # 新增的提醒内容 + medication_reminder = ( + '宝宝记得按时吃药哦,再坚持 {} 天就好拉:' + '早晨空腹:雷贝拉唑 * 1,枸酸秘钾 * 2;' + '饭后半小时:阿莫西林 * 4,克拉霉素 * 2。' + ).format(days_until_end) + + # 企业微信 + w1 = w.getWeatherTextToWechatWork() + # tex1 = '{}\n> 今天是我们相爱的 {} 天\n我们已经相遇 {} + # 天({})\n距离你的生日还有 {} 天\n\n{}'.format( + # h, ed, md,datetime.utcfromtimestamp(meetingTimestamp).strftime('%Y-%m-%d %H:%M:%S') , bd, w1 + # ) + + # 一行代码完成转换和格式化,并插入到原始字符串中 + + tex1 = ( + '{}\n> 今天是我们相爱的 {} 天({})\n' + '我们已经相遇 {} 天({})\n' + '距离你的生日还有 {} 天' + ).format( + h, + ed, + datetime.fromtimestamp(expressLoveTimestamp, tz=pytz.utc) + .astimezone(pytz.timezone("Asia/Shanghai")) + .strftime("%Y-%m-%d"), + md, + datetime.fromtimestamp(meetingTimestamp, tz=pytz.utc) + .astimezone(pytz.timezone("Asia/Shanghai")) + .strftime("%Y-%m-%d"), + bd, + ) + + wechatwork(tex1) + sendDailyWordToWechatWork(dw) + + # wxpusher + h2 = getMsgHeaderToWechat() + w2 = w.getWeatherTextToWechat() + dw2 = dw.getDailyWordHtml() + tex2 = ( + '{}
今天是我们相爱的 {} 天({})
' + '我们已经相遇{}天({})
' + '距离你的生日还有 {}

{}
{}' + ).format( + h2, + ed, + datetime.fromtimestamp(expressLoveTimestamp, tz=pytz.utc) + .astimezone(pytz.timezone("Asia/Shanghai")) + .strftime("%Y-%m-%d"), + md, + datetime.fromtimestamp(meetingTimestamp, tz=pytz.utc) + .astimezone(pytz.timezone("Asia/Shanghai")) + .strftime("%Y-%m-%d"), + bd, + w2, + dw2, + medication_reminder + ) + wxPusher(tex2)