Skip to content

Commit d99b538

Browse files
committed
feat:update views and post views
1 parent f03ea91 commit d99b538

File tree

3 files changed

+70
-23
lines changed

3 files changed

+70
-23
lines changed

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ default-run = "miguer_api-cli"
1313
loco-rs = { version = "0.15" }
1414

1515
[dependencies]
16-
loco-rs = { workspace = true }
16+
loco-rs = { workspace = true }
1717
serde = { version = "1", features = ["derive"] }
1818
serde_json = { version = "1" }
1919
tokio = { version = "1.33.0", default-features = false, features = [
20-
"rt-multi-thread",
20+
"rt-multi-thread",
2121
] }
2222
async-trait = { version = "0.1.74" }
2323
axum = { version = "0.8.1" }
@@ -26,17 +26,17 @@ tracing-subscriber = { version = "0.3.17", features = ["env-filter", "json"] }
2626
regex = { version = "1.11.1" }
2727
migration = { path = "migration" }
2828
sea-orm = { version = "1.1.0", features = [
29-
"sqlx-sqlite",
30-
"sqlx-postgres",
31-
"runtime-tokio-rustls",
32-
"macros",
29+
"sqlx-sqlite",
30+
"sqlx-postgres",
31+
"runtime-tokio-rustls",
32+
"macros",
3333
] }
3434
chrono = { version = "0.4" }
3535
validator = { version = "0.20" }
3636
uuid = { version = "1.6.0", features = ["v4"] }
3737
include_dir = { version = "0.7" }
3838
dotenvy = "0.15.7"
39-
axum-client-ip = "1.0.0"
39+
axum-client-ip = "0.7.0"
4040

4141
[[bin]]
4242
name = "miguer_api-cli"

src/app.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use async_trait::async_trait;
2+
use axum_client_ip::SecureClientIpSource;
23
use loco_rs::{
34
app::{AppContext, Hooks, Initializer},
45
bgworker::{BackgroundWorker, Queue},
@@ -50,6 +51,11 @@ impl Hooks for App {
5051
.add_route(controllers::posts::routes())
5152
.add_route(controllers::auth::routes())
5253
}
54+
55+
async fn after_routes(router: axum::Router, _ctx: &AppContext) -> Result<axum::Router> {
56+
let router = router.layer(SecureClientIpSource::ConnectInfo.into_extension());
57+
Ok(router)
58+
}
5359
async fn connect_workers(ctx: &AppContext, queue: &Queue) -> Result<()> {
5460
queue.register(DownloadWorker::build(ctx)).await?;
5561
Ok(())

src/controllers/posts.rs

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ use crate::models::{
77
};
88
use axum::{
99
debug_handler,
10-
extract::{Query, Request},
11-
http::{header, HeaderMap, StatusCode},
10+
extract::Query,
11+
http::{HeaderMap, StatusCode},
1212
};
13+
use axum_client_ip::{InsecureClientIp, SecureClientIp};
1314
use chrono::{Duration, Utc};
1415
use loco_rs::prelude::*;
1516
use serde::Deserialize;
@@ -122,23 +123,63 @@ pub async fn create(
122123
pub async fn increase_views(
123124
State(_ctx): State<AppContext>,
124125
Path(id): Path<i32>,
125-
req: Request,
126+
insecure_ip: InsecureClientIp,
127+
headers: HeaderMap,
126128
) -> Result<Response> {
127-
let post_model = posts::Model::by_id(id)
128-
.await
129+
let ip_str = insecure_ip.0.to_string();
130+
let now = Utc::now();
131+
let cutoff = now - Duration::hours(6);
132+
133+
let mut post = posts::Entity::find_by_id(id)
129134
.one(&_ctx.db)
130135
.await?
131-
.ok_or_else(|| Error::NotFound)?;
132-
let cutoff = Utc::now() - Duration::hours(6);
133-
println!("{:?}", req.headers());
134-
// let ip = headers
135-
// .get()
136-
// .and_then(|value| value.to_str().ok())
137-
// .and_then(|x_forwarded| x_forwarded.split(',').next())
138-
// .unwrap_or_else(|| String::from("default-ip"));
139-
// let already_viewed = post_model
140-
// .find_related(post_views::Entity)
141-
// .filter(post_views::Column::IpAddress.eq(ip));
136+
.ok_or(Error::NotFound)?;
137+
138+
let recent_view = post_views::Entity::find()
139+
.filter(post_views::Column::PostId.eq(post.id))
140+
.filter(post_views::Column::IpAddress.eq(ip_str.clone()))
141+
.filter(post_views::Column::CreatedAt.gt(cutoff))
142+
.one(&_ctx.db)
143+
.await?;
144+
145+
if recent_view.is_none() {
146+
let user_agent = headers
147+
.get("user-agent")
148+
.and_then(|v| v.to_str().ok())
149+
.map(|s| s.to_string());
150+
151+
let referer = headers
152+
.get("referer")
153+
.and_then(|v| v.to_str().ok())
154+
.map(|s| s.to_string());
155+
156+
let device_type = user_agent
157+
.as_ref()
158+
.map(|ua| {
159+
if ua.contains("Mobile") {
160+
Some("mobile")
161+
} else if ua.contains("Tablet") {
162+
Some("tablet")
163+
} else {
164+
Some("desktop")
165+
}
166+
})
167+
.flatten()
168+
.map(String::from);
169+
170+
let view = post_views::ActiveModel {
171+
post_id: Set(post.id),
172+
ip_address: Set(ip_str),
173+
user_agent: Set(user_agent),
174+
referer: Set(referer),
175+
device_type: Set(device_type),
176+
..Default::default()
177+
};
178+
view.insert(&_ctx.db).await?;
179+
let mut active_post = post.clone().into_active_model().clone();
180+
active_post.views = Set(post.views + 1);
181+
active_post.update(&_ctx.db).await?;
182+
}
142183

143184
format::text("Views Increased")
144185
}

0 commit comments

Comments
 (0)