-
Notifications
You must be signed in to change notification settings - Fork 0
/
wechat-webhook.cpp
215 lines (186 loc) · 7.02 KB
/
wechat-webhook.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#include <fmt/core.h>
#include <sstream>
#include <vector>
#include "cmdline.h"
#include "common.h"
#include "restclient-cpp/restclient.h"
// g++ -o wechat-webhook wechat-webhook.cpp -std=c++11 -lfmt -lspdlog
// -lpthread
// maybe -lrestclient-cpp
WeChatRobot::WeChatRobot(int port) : _port{port}, _url{kWechatRobotWebhookUrl} {
auto max_size = 1024 * 1024 * 5;
auto max_files = 3;
_logger = spdlog::daily_logger_mt("wechat-webhook", "logs/wechat-webhook.log",
2, 30);
// spdlog::set_default_logger(_logger);
spdlog::flush_on(spdlog::level::info);
}
void WeChatRobot::Run() {
_svr.Post("/webhook/gitlab", [&](const Request &req, Response &res) {
GitLabWebhookHandler(req, res);
});
_svr.Post("/webhook/grafana", [&](const Request &req, Response &res) {
GrafanaWebhookHandler(req, res);
});
_logger->info("wechat-webhook service run at port: {}", _port);
_svr.listen("0.0.0.0", _port);
}
void WeChatRobot::GitLabWebhookHandler(const httplib::Request &req,
httplib::Response &res) {
_logger->info("Recv gitlab request >>>>>>>>>> {}", req.body);
std::string id;
char buf[1024];
for (auto it = req.params.begin(); it != req.params.end(); ++it) {
const auto &x = *it;
if (!x.first.compare("id")) {
id = x.second;
}
}
if (!id.empty()) {
json body = json::parse(req.body);
if (body["object_kind"] == "push") {
BuildPushEventAndSendWechat("push", id, body);
} else if (body["object_kind"] == "tag_push") {
BuildPushEventAndSendWechat("tag", id, body);
} else if (body["object_kind"] == "merge_request") {
BuildMergeEventAndSendWechat(id, body);
}
}
res.set_content("Ok", "text/plain");
}
void WeChatRobot::GrafanaWebhookHandler(const httplib::Request &req,
httplib::Response &res) {
_logger->info("Rcev grafana request >>>>>>>>>> {}", req.body);
std::string id;
char buf[1024];
for (auto it = req.params.begin(); it != req.params.end(); ++it) {
const auto &x = *it;
if (!x.first.compare("id")) {
id = x.second;
}
}
if (!id.empty()) {
json body = json::parse(req.body);
json msg, markdown;
markdown["content"] = body["message"];
msg["msgtype"] = "markdown";
msg["markdown"] = markdown;
RestClient::Response r = RestClient::post(
kWechatRobotWebhookUrl + "/cgi-bin/webhook/send?key=" + id,
"application/json", msg.dump());
_logger->info("Wechat robot resp code: {} body: {}", r.code, r.body);
}
res.set_content("Ok", "text/plain");
}
std::vector<std::string> WeChatRobot::_split(const std::string &s, char delim) {
std::stringstream ss(s);
std::string item;
std::vector<std::string> elems;
while (std::getline(ss, item, delim)) {
elems.push_back(item);
// elems.push_back(std::move(item)); // if C++11 (based on comment from
// @mchiasson)
}
return elems;
}
void WeChatRobot::BuildPushEventAndSendWechat(std::string type, std::string id,
json body) {
std::vector<std::string> ref = _split(body["ref"].get<std::string>(), '/');
std::string branch;
if (ref.size() > 2) {
ref.erase(ref.begin(), ref.begin() + 2);
for (std::vector<std::string>::iterator it = ref.begin(); it != ref.end();
++it) {
branch = branch + "/" + *it;
}
}
std::string auther = body["user_name"];
// std::string branch = ref[2];
std::string repository = body["repository"]["name"];
std::string url = body["repository"]["homepage"];
std::vector<std::string> commits;
json msg, markdown;
std::string content;
if (!type.compare("tag")) {
std::string action = "remove";
if (body["ref"].dump().compare(
"0000000000000000000000000000000000000000")) {
action = "add";
}
std::string title = fmt::format(
"{} {} tag <font color=\"warning\">{}</font> at <font "
"color=\"comment\">[{}]({})</font>\n",
auther, action, branch, repository, url);
commits.push_back(title);
} else if (!type.compare("push")) {
std::string title = fmt::format(
"{} pushed to branch <font color=\"warning\">{}</font> at <font "
"color=\"comment\">[{}]({})</font>\n",
auther, branch, repository, url);
commits.push_back(title);
for (unsigned i = 0; i < body["commits"].size(); i++) {
std::string commit = fmt::format(
">[{}]({}): {}",
body["commits"].at(i)["id"].get<std::string>().substr(0, 6),
body["commits"].at(i)["url"].get<std::string>(),
body["commits"].at(i)["message"].get<std::string>());
_logger->info("commit >>> {}", commit);
commits.push_back(commit);
}
}
for (unsigned i = 0; i < commits.size(); i++) {
content = content + commits.at(i);
}
markdown["content"] = content;
msg["msgtype"] = "markdown";
msg["markdown"] = markdown;
RestClient::Response r = RestClient::post(
kWechatRobotWebhookUrl + "/cgi-bin/webhook/send?key=" + id,
"application/json", msg.dump());
_logger->info("Wechat robot resp code: {} body: {}", r.code, r.body);
}
void WeChatRobot::BuildMergeEventAndSendWechat(std::string id, json body) {
_logger->info(">>>>>>>>>>>>>>>>>>>>>BuildMergeEventAndSendWechat{}",
body.dump());
std::string auther = body["user"]["name"];
std::string source_branch = body["object_attributes"]["source_branch"];
std::string target_branch = body["object_attributes"]["target_branch"];
std::string title = body["object_attributes"]["title"];
std::string description = body["object_attributes"]["description"];
int merge_request_id = body["object_attributes"]["iid"];
std::string repository = body["object_attributes"]["target"]["name"];
std::string http_url = body["object_attributes"]["target"]["http_url"];
std::string url = body["object_attributes"]["url"];
std::string action = body["object_attributes"]["action"];
json msg, markdown;
std::string content = fmt::format(
"{} push new merge request from <font color=\"warning\">{}</font>"
" to <font color=\"warning\">{}</font>"
" at <font color=\"comment\">[{}]({})</font>\n"
"### [MergeRequest#{}]({}): {}\n"
">{}\n"
">Action: <font color=\"info\">{}</font>\n",
auther, source_branch, target_branch, repository, http_url,
merge_request_id, url, title, description, action);
markdown["content"] = content;
msg["msgtype"] = "markdown";
msg["markdown"] = markdown;
_logger->info(">>>>>>>>>>>", content);
RestClient::Response r = RestClient::post(
kWechatRobotWebhookUrl + "/cgi-bin/webhook/send?key=" + id,
"application/json", msg.dump());
_logger->info("Wechat robot resp code: {} body: {}", r.code, r.body);
}
int main(int argc, char *argv[]) {
cmdline::parser flags;
int port = 9527;
flags.add<int>("port", 'p', "port number", false, 9527,
cmdline::range(1, 65535));
flags.parse_check(argc, argv);
if (flags.exist("port")) {
port = flags.get<int>("port");
}
WeChatRobot robot(port);
robot.Run();
return 0;
}