add extra info for analysis.
All checks were successful
Deploy / PullDocker (push) Successful in 12s
Deploy / Build (push) Successful in 53s

This commit is contained in:
amass 2024-07-31 22:28:05 +08:00
parent fee13aebe7
commit 2b45dad26e
5 changed files with 69 additions and 52 deletions

View File

@ -9,8 +9,14 @@
| id | INTEGER | NOT NULL | | | id | INTEGER | NOT NULL | |
| url | TEXT | NOT NULL | | | url | TEXT | NOT NULL | |
| visitor_uuid | TEXT | NOT NULL | | | visitor_uuid | TEXT | NOT NULL | |
| last_user_agent | TEXT | NOT NULL | |
| last_view_time | INTEGER | NOT NULL | |
| page_view_count | INTEGER | NOT NULL | | | page_view_count | INTEGER | NOT NULL | |
插入 urlvisitor_uuidlast_user_agent last_view_time至表中如果表中已存在urlvisitor_uuid的item则更新last_user_agent last_view_time并将page_view_count加1否则创建新的item并将page_view_count赋值为1
### 任务清单 ### 任务清单

View File

@ -119,7 +119,7 @@ Application::Application(const std::string &path)
session.reply( session.reply(
ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html")); ServiceLogic::make_200<boost::beast::http::string_body>(request, "notify successed.\n", "text/html"));
}); });
// clang-format on
m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request, m_router->insert("/api/v1/visit_analysis", [this](HttpSession &session, const Request &request,
const boost::urls::matches &matches) { const boost::urls::matches &matches) {
using namespace boost::beast; using namespace boost::beast;
@ -127,15 +127,21 @@ Application::Application(const std::string &path)
auto &root = rootJson.as_object(); auto &root = rootJson.as_object();
std::string url; std::string url;
std::string visitorUuid; std::string visitorUuid;
std::string userAgent;
if (root.contains("url")) { if (root.contains("url")) {
url = root["url"].as_string(); url = root["url"].as_string();
} }
if (root.contains("visitor_uuid")) { if (root.contains("visitor_uuid")) {
visitorUuid = root["visitor_uuid"].as_string(); visitorUuid = root["visitor_uuid"].as_string();
} }
if (root.contains("user_agent")) {
userAgent = root["user_agent"].as_string();
}
auto database = Amass::Singleton<Database>::instance(); auto database = Amass::Singleton<Database>::instance();
database->updateVisitCount(url, visitorUuid); auto now = std::chrono::system_clock::now();
std::time_t now_time = std::chrono::system_clock::to_time_t(now);
database->updateVisitCount(url, visitorUuid, userAgent, now_time);
auto data = database->visitAnalysisData(std::string(url)); auto data = database->visitAnalysisData(std::string(url));
auto total = database->siteVisitAnalysisData(); auto total = database->siteVisitAnalysisData();
@ -153,7 +159,6 @@ Application::Application(const std::string &path)
s.prepare_payload(); s.prepare_payload();
session.reply(std::move(s)); session.reply(std::move(s));
}); });
// clang-format on
m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads()); m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads());
m_timer = std::make_shared<boost::asio::system_timer>(*m_ioContext->ioContext()); m_timer = std::make_shared<boost::asio::system_timer>(*m_ioContext->ioContext());

View File

@ -106,48 +106,51 @@ void Database::setTaskFinished(int id, bool finished, uint64_t finishedTime) {
} }
} }
void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid) { void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
sqlite3_stmt *stmt = nullptr; int64_t time) {
const char *sql_select = "SELECT page_view_count FROM visit_analysis WHERE url = ? AND visitor_uuid = ?"; sqlite3_stmt *stmt;
if (sqlite3_prepare_v2(m_sqlite3, sql_select, -1, &stmt, 0) != SQLITE_OK) { const char *query = "SELECT id, page_view_count FROM visit_analysis WHERE url = ? AND visitor_uuid = ?";
if (sqlite3_prepare_v2(m_sqlite3, query, -1, &stmt, 0) != SQLITE_OK) {
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3); LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
return;
} }
sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
int rc = sqlite3_step(stmt); int id = -1;
if (rc == SQLITE_ROW) { // 记录存在执行UPDATE语句 int page_view_count = 0;
sqlite3_finalize(stmt); // 释放SELECT语句的资源 if (sqlite3_step(stmt) == SQLITE_ROW) {
const char *sql_update = id = sqlite3_column_int(stmt, 0);
"UPDATE visit_analysis SET page_view_count = page_view_count + 1 WHERE url = ? AND visitor_uuid = ?"; page_view_count = sqlite3_column_int(stmt, 1);
if (sqlite3_prepare_v2(m_sqlite3, sql_update, -1, &stmt, 0) != SQLITE_OK) {
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3);
return;
} }
sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC); sqlite3_finalize(stmt);
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC); if (id != -1) { // 更新记录
const char *updateQuery =
"UPDATE visit_analysis SET last_user_agent = ?, last_view_time = ?, page_view_count = ? WHERE id = ?";
if (sqlite3_prepare_v2(m_sqlite3, updateQuery, -1, &stmt, 0) != SQLITE_OK) {
LOG(error) << "Failed to prepare update statement: " << sqlite3_errmsg(m_sqlite3);
}
sqlite3_bind_text(stmt, 1, userAgent.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int64(stmt, 2, time);
sqlite3_bind_int(stmt, 3, page_view_count + 1);
sqlite3_bind_int(stmt, 4, id);
if (sqlite3_step(stmt) != SQLITE_DONE) { if (sqlite3_step(stmt) != SQLITE_DONE) {
LOG(error) << "Failed to execute statement: " << sqlite3_errmsg(m_sqlite3); LOG(error) << "Failed to update record: " << sqlite3_errmsg(m_sqlite3);
sqlite3_finalize(stmt);
return;
} }
} else { // 记录不存在执行INSERT语句 sqlite3_finalize(stmt);
sqlite3_finalize(stmt); // 释放SELECT语句的资源 } else { // 插入新记录
const char *sql_insert = "INSERT INTO visit_analysis (url, visitor_uuid, page_view_count) VALUES (?, ?, 1)"; const char *insertQuery = "INSERT INTO visit_analysis (url, visitor_uuid, last_user_agent, last_view_time, "
if (sqlite3_prepare_v2(m_sqlite3, sql_insert, -1, &stmt, 0) != SQLITE_OK) { "page_view_count) VALUES (?, ?, ?, ?, 1)";
LOG(error) << "Failed to prepare statement: " << sqlite3_errmsg(m_sqlite3); if (sqlite3_prepare_v2(m_sqlite3, insertQuery, -1, &stmt, 0) != SQLITE_OK) {
return; LOG(error) << "Failed to prepare insert statement: " << sqlite3_errmsg(m_sqlite3);
} }
sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC); sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE) { // 执行INSERT语句 sqlite3_bind_text(stmt, 3, userAgent.c_str(), -1, SQLITE_STATIC);
LOG(error) << "Failed to execute statement: " << sqlite3_errmsg(m_sqlite3); sqlite3_bind_int64(stmt, 4, time);
sqlite3_finalize(stmt); if (sqlite3_step(stmt) != SQLITE_DONE) {
return; LOG(error) << "Failed to insert record: " << sqlite3_errmsg(m_sqlite3) << std::endl;
} }
}
// 释放语句资源
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
}
} }
void Database::clearVisitRecord() { void Database::clearVisitRecord() {
@ -261,16 +264,17 @@ void Database::initialize() {
} }
char *message = nullptr; char *message = nullptr;
const char *sql_create_visit_analysis = R"( sql = R"(
CREATE TABLE IF NOT EXISTS visit_analysis ( CREATE TABLE IF NOT EXISTS visit_analysis (
id INTEGER NOT NULL, id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT NOT NULL, url TEXT NOT NULL,
visitor_uuid TEXT NOT NULL, visitor_uuid TEXT NOT NULL,
page_view_count INTEGER NOT NULL, last_user_agent TEXT NOT NULL,
PRIMARY KEY (id) last_view_time INTEGER NOT NULL,
page_view_count INTEGER NOT NULL
); );
)"; )";
result = sqlite3_exec(m_sqlite3, sql_create_visit_analysis, 0, 0, &message); result = sqlite3_exec(m_sqlite3, sql, 0, 0, &message);
if (result != SQLITE_OK) { if (result != SQLITE_OK) {
LOG(error) << "Failed to create table: " << message << std::endl; LOG(error) << "Failed to create table: " << message << std::endl;
sqlite3_free(message); sqlite3_free(message);

View File

@ -27,7 +27,8 @@ public:
bool removeTask(int id); bool removeTask(int id);
void setTaskFinished(int id, bool finished, uint64_t finishedTime); void setTaskFinished(int id, bool finished, uint64_t finishedTime);
void updateVisitCount(const std::string &url, const std::string &visitorUuid); void updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
int64_t time);
void clearVisitRecord(); void clearVisitRecord();
VisitAnalysis visitAnalysisData(const std::string &url); VisitAnalysis visitAnalysisData(const std::string &url);
VisitAnalysis siteVisitAnalysisData(); VisitAnalysis siteVisitAnalysisData();

View File

@ -21,11 +21,12 @@ BOOST_AUTO_TEST_CASE(DatabaseTest) {
auto items = database.homeBoxItems(); auto items = database.homeBoxItems();
BOOST_CHECK_EQUAL(items.size(), 1); BOOST_CHECK_EQUAL(items.size(), 1);
auto now = duration_cast<seconds>(std::chrono::system_clock::now().time_since_epoch()).count(); auto now = std::chrono::system_clock::now();
database.setTaskFinished(1, true, now); std::time_t now_time = std::chrono::system_clock::to_time_t(now);
database.setTaskFinished(1, true, now_time);
database.updateVisitCount("/note", "uuid_123"); database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
database.updateVisitCount("/note/1", "uuid_1232"); database.updateVisitCount("/note/1", "uuid_1232", "chrome", now_time);
database.updateVisitCount("/note", "uuid_123"); database.updateVisitCount("/note", "uuid_123", "chrome", now_time);
database.updateVisitCount("/note", "uuid_1234"); database.updateVisitCount("/note", "uuid_1234", "chrome", now_time);
} }