Skip to content
This repository has been archived by the owner on Dec 4, 2023. It is now read-only.

Commit

Permalink
support dingtalk robot
Browse files Browse the repository at this point in the history
  • Loading branch information
GCS-ZHN committed Mar 29, 2022
1 parent 3eaea74 commit 44d675d
Show file tree
Hide file tree
Showing 11 changed files with 207 additions and 28 deletions.
74 changes: 53 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</div>

## 项目概述
本项目为解决浙江大学每日重复的健康打卡而开发,在完成首次手动打卡后,可以自动进行定时打卡。并通过邮件形式提醒通知打卡结果。本项目使用spring-boot、quartz和httpclient开发,使用maven进行项目管理,编译版本为jdk-14.0.2。支持多账户配置,支持利用github action。如果没有服务器资源,请跳至[基于github-action的使用](#基于github-action的使用)
本项目为解决浙江大学每日重复的健康打卡而开发,在完成首次手动打卡后,可以自动进行定时打卡。并通过邮件形式提醒通知打卡结果。本项目使用spring-boot、quartz和httpclient开发,使用maven进行项目管理,编译版本为jdk-14.0.2。支持多账户配置,支持利用github action。支持钉钉消息推送。如果没有服务器资源,请跳至[基于github-action的使用](#基于github-action的使用)

## 基于自建平台的使用
**STEP 1 用来跑程序的设备**
Expand Down Expand Up @@ -43,32 +43,61 @@

用任意文本编辑器打开config目录下的application.json,配置下列信息。
```json
{
"mail":{ //配置发送邮件通知的邮箱
"username":"***", //用来发送邮件的账号
"nickname":"AutoCard", //发件名
"password":"***", //发件邮箱密码
"smtp":"smtp.zju.edu.cn", //SMTP邮件服务运营商服务器域名,默认浙大邮箱
"port":994 //SMTP邮件服务端口
{
//配置发送邮件通知的邮箱
"mail":{
//用来发送邮件的账号
"username":"***",
//发件名
"nickname":"AutoCard",
//发件邮箱密码
"password":"***",
//SMTP邮件服务运营商服务器域名,默认浙大邮箱
"smtp":"smtp.zju.edu.cn",
//SMTP邮件服务端口
"port":994
},
"jobs":[ //配置多个打卡账号
//配置多个打卡账号
"jobs":[
{
"username":"***", //打卡的通行证账号1,即学工号
"password":"***", //对应登录密码
"mail":"***", //发送打卡结果的收件邮箱
"cron":"0 0 0 * * ? *", //cron表达式定时,示例为每天00:00:00
"delay":true //任务开启随机延时0-1800秒
},
{
"username":"***", //打卡的通行证账号2
"password":"***", //对应登录密码
"mail":"***", //发送打卡结果的收件邮箱
"cron":"0 0 2 * * ? *" //cron表达式定时,示例为每天02:00:00
//打卡的通行证账号1,即学工号
"username":"***",
//对应登录密码
"password":"***",
//发送打卡结果的收件邮箱,如果不需要可以不配置
"mail":"***",
//cron表达式定时,示例为每天00:00:00,对github action无效
"cron":"0 0 0 * * ? *",
// 钉钉机器人webhook URL
"dingtalkurl": "https://oapi.dingtalk.com/robot/send?access_token=****",
// 钉钉机器人webhook 签名,如果没有可以不配置
"dingtalksecret": "SEC****",
//任务开启随机延时0-1800秒
"delay":true
},
{
//打卡的通行证账号2
"username":"***",
//对应登录密码
"password":"***",
//发送打卡结果的收件邮箱
"mail":"***",
//cron表达式定时,示例为每天02:00:00
"cron":"0 0 2 * * ? *"
}
]
}
```
邮箱用于打卡的通知,默认使用浙大邮箱,否则需要`mail.smtp``mail.port`参数配置为指定第三方邮箱如QQ邮箱的配置。若不配置邮箱信息,将不会邮件提醒。
邮箱用于打卡的通知,默认使用浙大邮箱,否则需要`mail.smtp``mail.port`参数配置为指定第三方邮箱如QQ邮箱的配置。若不配置邮箱信息,将不会邮件提醒。可以配置钉钉机器人消息推送,方式如下:

- 进入钉钉,选择一个用于接收消息的群,例如新手体验群
- 进入群设置,添加**群智能助手**
- 选择添加机器人
- 选择自定义
- 然后添加机器人,选择加签
- 复制url和加签的密钥,保存在配置文件中

![dingtalk](templete/dingtalk_robot.png)

cron表达式是用于定时任务的经典表达式,该参数允许用户自定义打卡定时方式。网上有很多现成的表达式模板以及表达式在线生成工具。**默认定时设定是每天早上9点自动打卡**。网上有很多介绍或[在线生成器](https://cron.qqe2.com/)。cron表达式从左到右(空格分开)指的是“秒 分 时 每月第几天 月份 每周第几天 年份”,特殊符号表示通配。**对于多个打卡用户配置,建议定时错开,并发登录容易被浙大后台拒绝**
```txt
Expand Down Expand Up @@ -159,6 +188,9 @@ fork本项目,修改**action/config/application.json**文件的用户配置,
若打卡题目被更新或者你的任何信息情况有变化(如返校),请先手动打卡一次。本项目仅供学习参考。使用时请确保信息的正确性。滥用造成的后果请自行承担。

## 更新记录
### v1.4.1
支持了钉钉消息推送,可以自定义钉钉机器人接收消息。

### v1.4.0
支持了即时打卡,加入了github action支持,用户可以利用github action功能来使用github服务器进行打卡。但暂时无法收到邮件通知。

Expand Down
2 changes: 2 additions & 0 deletions config/application.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
"password":"***",
"mail":"***",
"cron":"0 0 0 * * ? *",
"dingtalkurl": "https://oapi.dingtalk.com/robot/send?access_token=****",
"dingtalksecret": "SEC****",
"delay":true
},
{
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>org.gcszhn</groupId>
<artifactId>autocard</artifactId>
<version>1.4.0</version>
<version>1.4.1</version>
<packaging>jar</packaging>

<name>Auto Heathy Report for Zhejiang University</name>
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/org/gcszhn/autocard/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

import org.gcszhn.autocard.service.AutoClockinJob;
import org.gcszhn.autocard.service.ClockinService;
import org.gcszhn.autocard.service.DingTalkHookService;
import org.gcszhn.autocard.service.JobService;
import org.gcszhn.autocard.service.MailService;
import org.gcszhn.autocard.utils.LogUtils;
Expand Down Expand Up @@ -59,7 +60,7 @@ public class App {
* @param cardService
*/
@Autowired
public void start(JobService jobService, MailService mailService, ClockinService cardService) {
public void start(JobService jobService, MailService mailService, ClockinService cardService, DingTalkHookService dingTalkHookService) {
try {
JSONArray jsonArray = appConfig.getUserJobs();
jsonArray.forEach((Object obj)->{
Expand All @@ -68,7 +69,7 @@ public void start(JobService jobService, MailService mailService, ClockinService
JobDataMap jobDataMap = new JobDataMap(jsonObject);
if (immediate) {
try {
AutoClockinJob.execute(jobDataMap, mailService, cardService);
AutoClockinJob.execute(jobDataMap, mailService, cardService, dingTalkHookService);
} catch (Exception e) {
LogUtils.printMessage(null, e, LogUtils.Level.ERROR);
}
Expand Down
18 changes: 16 additions & 2 deletions src/main/java/org/gcszhn/autocard/service/AutoClockinJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,20 @@ public class AutoClockinJob implements Job {
public void execute(JobExecutionContext context) throws JobExecutionException {
ClockinService cardService = SpringUtils.getBean(ClockinService.class);
MailService mailService = SpringUtils.getBean(MailService.class);
execute(context.getMergedJobDataMap(), mailService, cardService);
DingTalkHookService dingTalkHookService = SpringUtils.getBean(DingTalkHookService.class);
execute(context.getMergedJobDataMap(), mailService, cardService, dingTalkHookService);
}
public static void execute(JobDataMap dataMap, MailService mailService, ClockinService cardService) throws JobExecutionException {
public static void execute(
JobDataMap dataMap,
MailService mailService,
ClockinService cardService,
DingTalkHookService dingTalkHookService) throws JobExecutionException {
boolean isDelay = dataMap.getBooleanValue("delay");
String username = dataMap.getString("username");
String password = dataMap.getString("password");
String mail = dataMap.getString("mail");
String dingtalkURL = dataMap.getString("dingtalkurl");
String dingtalkSecret = dataMap.getString("dingtalksecret");
//开启随机延迟,这样可以避免每次打卡时间过于固定
try {
if (isDelay) {
Expand Down Expand Up @@ -78,6 +85,13 @@ public static void execute(JobDataMap dataMap, MailService mailService, ClockinS
statusCode.getMessage(),
"text/html;charset=utf-8");
}

if (dingtalkURL!=null) {
if (dingtalkSecret!=null) {
dingtalkURL = dingTalkHookService.getSignature(dingtalkSecret, dingtalkURL);
}
LogUtils.printMessage(dingTalkHookService.sendText(dingtalkURL, "【健康打卡通知】" + statusCode.getMessage()));;
}
} catch (Exception e) {
LogUtils.printMessage(e.getMessage(), LogUtils.Level.ERROR);
}
Expand Down
58 changes: 58 additions & 0 deletions src/main/java/org/gcszhn/autocard/service/DingTalkHookService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* Copyright © 2021 <a href="mailto:[email protected]">Zhang.H.N</a>.
*
* Licensed under the Apache License, Version 2.0 (thie "License");
* You may not use this file except in compliance with the license.
* You may obtain a copy of the License at
*
* http://wwww.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language govering permissions and
* limitations under the License.
*/
package org.gcszhn.autocard.service;

import java.net.URLEncoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.alibaba.fastjson.JSONObject;

import org.apache.commons.codec.binary.Base64;
import org.gcszhn.autocard.utils.HttpClientUtils;
import org.gcszhn.autocard.utils.LogUtils;
import org.gcszhn.autocard.utils.LogUtils.Level;
import org.springframework.stereotype.Service;

@Service
public class DingTalkHookService implements WebHookService {
private HttpClientUtils utils = new HttpClientUtils();
@Override
public String sendText(String payLoadURL, String info) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("msgtype", "text");
JSONObject textObject = new JSONObject();
textObject.put("content", info);
jsonObject.put("text", textObject);
return utils.entityToString(utils.getResponseContent(utils.doPost(payLoadURL, jsonObject.toJSONString(), "application/json")));
}

public String getSignature(String secret, String payLoadURL) {
try {
Long timestamp = System.currentTimeMillis();
String stringToSign = timestamp + "\n" + secret;
Mac mac = Mac.getInstance("HmacSHA256");
mac.init(new SecretKeySpec(secret.getBytes("UTF-8"), "HmacSHA256"));
byte[] signData = mac.doFinal(stringToSign.getBytes("UTF-8"));
return payLoadURL +"&timestamp="+timestamp+ "&sign=" + URLEncoder.encode(new String(Base64.encodeBase64(signData)),"UTF-8");
} catch (Exception e) {
LogUtils.printMessage(e.getMessage(), Level.ERROR);
}
return payLoadURL;
}

}
20 changes: 20 additions & 0 deletions src/main/java/org/gcszhn/autocard/service/WebHookService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright © 2021 <a href="mailto:[email protected]">Zhang.H.N</a>.
*
* Licensed under the Apache License, Version 2.0 (thie "License");
* You may not use this file except in compliance with the license.
* You may obtain a copy of the License at
*
* http://wwww.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language govering permissions and
* limitations under the License.
*/
package org.gcszhn.autocard.service;

public interface WebHookService {
public String sendText(String payLoadURL, String info);
}
17 changes: 17 additions & 0 deletions src/main/java/org/gcszhn/autocard/utils/HttpClientUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
Expand Down Expand Up @@ -245,6 +246,22 @@ public CloseableHttpResponse doPost(String url, List<NameValuePair> parameters,
UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(parameters, AppConfig.APP_CHARSET);
request.setEntity(formEntity);
}

return getResponse(request, headers);
} catch (Exception e) {
LogUtils.printMessage(null, e, LogUtils.Level.ERROR);
}
return null;
}
public CloseableHttpResponse doPost(String url, String content, String contentType, Header... headers) {
LogUtils.printMessage("Try to post " + url, LogUtils.Level.DEBUG);
try {
HttpPost request = new HttpPost(url);
if (content != null) {
StringEntity entity = new StringEntity(content, AppConfig.APP_CHARSET);
entity.setContentType(contentType);
request.setEntity(entity);
}
return getResponse(request, headers);
} catch (Exception e) {
LogUtils.printMessage(null, e, LogUtils.Level.ERROR);
Expand Down
4 changes: 2 additions & 2 deletions src/test/java/org/gcszhn/autocard/AppTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@
@RunWith(SpringRunner.class)
@SpringBootTest
public abstract class AppTest {
protected static final String trueZjuPassPortUser = "220****";
protected static final String trueZjuPassPortPass = "202****";
protected static final String trueZjuPassPortUser = "***";
protected static final String trueZjuPassPortPass = "***";
}
35 changes: 35 additions & 0 deletions src/test/java/org/gcszhn/autocard/DingTalkHookTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright © 2021 <a href="mailto:[email protected]">Zhang.H.N</a>.
*
* Licensed under the Apache License, Version 2.0 (thie "License");
* You may not use this file except in compliance with the license.
* You may obtain a copy of the License at
*
* http://wwww.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language govering permissions and
* limitations under the License.
*/
package org.gcszhn.autocard;

import org.gcszhn.autocard.service.DingTalkHookService;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

public class DingTalkHookTest extends AppTest {
@Autowired
DingTalkHookService service;

@Test
public void sendTextTest() {
String baseUrl = "https://oapi.dingtalk.com/robot/send?access_token=***";
String secret = "SEC****";
String payLoadUrl = service.getSignature(secret, baseUrl);
System.out.println(payLoadUrl);
System.out.println( service.sendText(payLoadUrl, "打卡信息获取失败"));
}

}
Binary file added templete/dingtalk_robot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 44d675d

Please sign in to comment.