#include "CorporationContext.h" #include "../ServiceManager.h" #include "BoostLog.h" #include "NetworkUtility.h" #include #include #include #include #include #include CorporationContext::CorporationContext(boost::asio::io_context &ioContext) : m_ioContext(ioContext), m_timer(ioContext) { auto manager = Amass::Singleton::instance(); if (manager) manager->registerTopic(NotifyServerChan, [this](const std::string &text) { sendMessage(MessageType::Text, text); }); } void CorporationContext::sendMessage(MessageType type, const std::string &message) { boost::format target("/cgi-bin/message/send?access_token=%1%"); target % m_accessToken; boost::json::object msg; msg["content"] = message; boost::json::object request; request["touser"] = "@all"; request["agentid"] = agentid; if (type == MessageType::Markdown) { request["msgtype"] = "markdown"; request["markdown"] = std::move(msg); } else { request["msgtype"] = "text"; request["text"] = std::move(msg); } auto body = boost::json::serialize(request); boost::beast::error_code error; auto response = Https::post(m_ioContext, host, port, target.str(), body, error); if (error) { LOG(error) << error.message(); return; } LOG(info) << response; } void CorporationContext::start() { boost::asio::defer(m_ioContext, [ptr{weak_from_this()}]() { if (ptr.expired()) { LOG(error) << "CorporationContext instance was expired"; return; } auto self = ptr.lock(); self->updateAccessToken(); }); } void CorporationContext::notify(const RequestType &request) { boost::system::error_code error; auto json = boost::json::parse(request.body(), error); if (error) { LOG(error) << "parse: [" << request.body() << "] failed, reason: " << error.message(); return; } // LOG(debug) << "parse: [" << request.body() << "] succeed."; auto &req = json.as_object(); MessageType type = MessageType::Text; if (req.contains("type")) { if (req.at("type").as_string() == "markdown") { type = MessageType::Markdown; } } if (req.contains("msg")) { std::string msg(req.at("msg").as_string()); sendMessage(type, std::move(msg)); } } void CorporationContext::updateAccessToken() { boost::beast::error_code error; boost::format target("/cgi-bin/gettoken?corpid=%1%&corpsecret=%2%"); target % corpid % corpsecret; auto response = Https::get(m_ioContext, host, port, target.str(), error); if (error) { LOG(error) << error.message(); return; } if (response.empty()) { LOG(warning) << "response is empty."; return; } auto json = boost::json::parse(response); auto &accessTokenObject = json.as_object(); int errcode = accessTokenObject.count("errcode") > 0 ? accessTokenObject.at("errcode").as_int64() : -1; if (errcode != 0) { LOG(error) << "get access_token failed,code: " << errcode << ", message: " << accessTokenObject.at("errmsg").as_string(); return; } m_accessToken = accessTokenObject.at("access_token").as_string(); auto expires_in = accessTokenObject.at("expires_in").as_int64(); // LOG(info) << "access_token: " << m_accessToken; LOG(info) << "re-access_token after " << expires_in << " s."; m_timer.expires_after(std::chrono::seconds(expires_in)); m_timer.async_wait([this](const boost::system::error_code &error) { if (error) { LOG(error) << error.message(); return; } updateAccessToken(); }); static bool started = true; if (started) { sendMessage(MessageType::Text, "您好,艾玛已上线......"); started = false; } }