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 | |
| url | 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 | |
插入 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(
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,
const boost::urls::matches &matches) {
using namespace boost::beast;
@ -127,15 +127,21 @@ Application::Application(const std::string &path)
auto &root = rootJson.as_object();
std::string url;
std::string visitorUuid;
std::string userAgent;
if (root.contains("url")) {
url = root["url"].as_string();
}
if (root.contains("visitor_uuid")) {
visitorUuid = root["visitor_uuid"].as_string();
}
if (root.contains("user_agent")) {
userAgent = root["user_agent"].as_string();
}
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 total = database->siteVisitAnalysisData();
@ -153,8 +159,7 @@ Application::Application(const std::string &path)
s.prepare_payload();
session.reply(std::move(s));
});
// clang-format on
m_ioContext = Amass::Singleton<IoContext>::instance<Amass::Construct>(getThreads());
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) {
sqlite3_stmt *stmt = nullptr;
const char *sql_select = "SELECT page_view_count FROM visit_analysis WHERE url = ? AND visitor_uuid = ?";
if (sqlite3_prepare_v2(m_sqlite3, sql_select, -1, &stmt, 0) != SQLITE_OK) {
void Database::updateVisitCount(const std::string &url, const std::string &visitorUuid, const std::string &userAgent,
int64_t time) {
sqlite3_stmt *stmt;
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);
return;
}
sqlite3_bind_text(stmt, 1, url.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
int rc = sqlite3_step(stmt);
if (rc == SQLITE_ROW) { // 记录存在执行UPDATE语句
sqlite3_finalize(stmt); // 释放SELECT语句的资源
const char *sql_update =
"UPDATE visit_analysis SET page_view_count = page_view_count + 1 WHERE url = ? AND visitor_uuid = ?";
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_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE) {
LOG(error) << "Failed to execute statement: " << sqlite3_errmsg(m_sqlite3);
sqlite3_finalize(stmt);
return;
}
} else { // 记录不存在执行INSERT语句
sqlite3_finalize(stmt); // 释放SELECT语句的资源
const char *sql_insert = "INSERT INTO visit_analysis (url, visitor_uuid, page_view_count) VALUES (?, ?, 1)";
if (sqlite3_prepare_v2(m_sqlite3, sql_insert, -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_bind_text(stmt, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
if (sqlite3_step(stmt) != SQLITE_DONE) { // 执行INSERT语句
LOG(error) << "Failed to execute statement: " << sqlite3_errmsg(m_sqlite3);
sqlite3_finalize(stmt);
return;
}
int id = -1;
int page_view_count = 0;
if (sqlite3_step(stmt) == SQLITE_ROW) {
id = sqlite3_column_int(stmt, 0);
page_view_count = sqlite3_column_int(stmt, 1);
}
// 释放语句资源
sqlite3_finalize(stmt);
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) {
LOG(error) << "Failed to update record: " << sqlite3_errmsg(m_sqlite3);
}
sqlite3_finalize(stmt);
} else { // 插入新记录
const char *insertQuery = "INSERT INTO visit_analysis (url, visitor_uuid, last_user_agent, last_view_time, "
"page_view_count) VALUES (?, ?, ?, ?, 1)";
if (sqlite3_prepare_v2(m_sqlite3, insertQuery, -1, &stmt, 0) != SQLITE_OK) {
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, 2, visitorUuid.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_text(stmt, 3, userAgent.c_str(), -1, SQLITE_STATIC);
sqlite3_bind_int64(stmt, 4, time);
if (sqlite3_step(stmt) != SQLITE_DONE) {
LOG(error) << "Failed to insert record: " << sqlite3_errmsg(m_sqlite3) << std::endl;
}
sqlite3_finalize(stmt);
}
}
void Database::clearVisitRecord() {
@ -261,16 +264,17 @@ void Database::initialize() {
}
char *message = nullptr;
const char *sql_create_visit_analysis = R"(
sql = R"(
CREATE TABLE IF NOT EXISTS visit_analysis (
id INTEGER NOT NULL,
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT NOT NULL,
visitor_uuid TEXT NOT NULL,
page_view_count INTEGER NOT NULL,
PRIMARY KEY (id)
last_user_agent TEXT NOT NULL,
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) {
LOG(error) << "Failed to create table: " << message << std::endl;
sqlite3_free(message);

View File

@ -27,7 +27,8 @@ public:
bool removeTask(int id);
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();
VisitAnalysis visitAnalysisData(const std::string &url);
VisitAnalysis siteVisitAnalysisData();

View File

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