Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support content map #79

Merged
merged 6 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/apub/src/actors/db_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ impl Object for ApubUser {
private_key: None,
hatsu: None,
feed: None,
language: None,
last_refreshed_at: hatsu_utils::date::now(),
};

Expand Down
4 changes: 2 additions & 2 deletions crates/apub/src/actors/db_user_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl ApubUser {
private_key: Some(keypair.private_key),
hatsu: user_feed_top_level.hatsu.map(UserFeedHatsu::into_db),
feed: Some(user_feed.into_db()),
language: user_feed_top_level.language,
last_refreshed_at: hatsu_utils::date::now(),
};

Expand All @@ -65,8 +66,7 @@ impl ApubUser {
title: self.name.clone(),
description: self.summary.clone(),
icon: self.icon.clone().and_then(|url| Url::parse(&url).ok()),
// TODO: use language
language: Option::default(),
language: self.language.clone(),
kwaa marked this conversation as resolved.
Show resolved Hide resolved
feed_url: Url::parse("https://hatsu.local").unwrap(),
next_url: Option::default(),
items: Vec::default(),
Expand Down
18 changes: 16 additions & 2 deletions crates/apub/src/objects/note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use activitypub_federation::{
traits::{Actor, Object},
};
use hatsu_db_schema::prelude::Post;
use hatsu_feed::UserFeedItem;
use hatsu_feed::{UserFeedItem, UserFeedTopLevel};
use hatsu_utils::{markdown::markdown_to_html, AppData, AppError};
use sea_orm::EntityTrait;
use serde::{Deserialize, Serialize};
Expand All @@ -21,6 +21,7 @@ use crate::{
actors::ApubUser,
links::{Hashtag, Tag},
objects::ApubPost,
utils::generate_map,
};

/// <https://www.w3.org/ns/activitystreams#Note>
Expand All @@ -45,6 +46,7 @@ pub struct Note {
#[serde(deserialize_with = "deserialize_one_or_many")]
pub cc: Vec<Url>,
pub content: String,
pub content_map: Option<Value>,
/// TODO: customization via item._hatsu.source
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<Value>,
Expand Down Expand Up @@ -79,6 +81,7 @@ impl Note {
pub fn new(
actor: &ApubUser,
json: UserFeedItem,
top_level: &UserFeedTopLevel,
published: Option<String>,
updated: Option<String>,
data: &Data<AppData>,
Expand Down Expand Up @@ -135,6 +138,7 @@ impl Note {
to: vec![public()],
// Leaving a CC here to retain compatibility, figured I should CC followers instead of public twice
cc: vec![Url::parse(&format!("{}/followers", actor.id()))?],
content_map: generate_map(&content, json.language.or(top_level.language.clone())),
content,
source: Some(serde_json::to_value(NoteSource::new(source))?),
tag: json.tags.map_or_else(Vec::new, |tags| {
Expand Down Expand Up @@ -180,20 +184,30 @@ impl Note {
pub fn create(
actor: &ApubUser,
json: UserFeedItem,
top_level: &UserFeedTopLevel,
data: &Data<AppData>,
) -> Result<Self, AppError> {
Self::new(actor, json, Some(hatsu_utils::date::now()), None, data)
Self::new(
actor,
json,
top_level,
Some(hatsu_utils::date::now()),
None,
data,
)
}

pub fn update(
actor: &ApubUser,
json: UserFeedItem,
top_level: &UserFeedTopLevel,
published: String,
data: &Data<AppData>,
) -> Result<Self, AppError> {
Self::new(
actor,
json,
top_level,
Some(published),
Some(hatsu_utils::date::now()),
data,
Expand Down
11 changes: 11 additions & 0 deletions crates/apub/src/utils/generate_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
use serde_json::{json, Value};

pub fn generate_map(content: &str, language: Option<String>) -> Option<Value> {
match language {
Some(language) if language[.. 2].chars().all(|char| char.is_ascii_lowercase()) =>
Some(json!({
language[..2]: content
})),
_ => None,
}
}
2 changes: 2 additions & 0 deletions crates/apub/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod generate_map;
mod verify_blocked;

pub use generate_map::generate_map;
pub use verify_blocked::verify_blocked;
15 changes: 9 additions & 6 deletions crates/cron/src/tasks/check_feed_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,46 @@ use hatsu_db_schema::{
prelude::*,
user_feed_item::Model as DbUserFeedItem,
};
use hatsu_feed::{UserFeedItem as JsonUserFeedItem, WrappedUserFeedItem};
use hatsu_feed::{UserFeedItem as JsonUserFeedItem, UserFeedTopLevel, WrappedUserFeedItem};
use hatsu_utils::{AppData, AppError};
use sea_orm::{ActiveModelTrait, ActiveValue::Set, EntityTrait, IntoActiveModel};

pub async fn check_feed_item(
data: &Data<AppData>,
user: &ApubUser,
item: DbUserFeedItem,
top_level: &UserFeedTopLevel,
) -> Result<(), AppError> {
match UserFeedItem::find_by_id(&item.id).one(&data.conn).await? {
Some(prev_item) => {
// item.date_modified 不为空且不等于 prev_item.date_modified
if let Some(date_modified) = item.date_modified.clone() {
match prev_item.date_modified {
Some(prev_date_modified) if prev_date_modified != date_modified =>
update_feed_item(item, user, data).await?,
None => update_feed_item(item, user, data).await?,
update_feed_item(item, user, data, top_level).await?,
None => update_feed_item(item, user, data, top_level).await?,
_ => (),
};
}

Ok(())
},
None => Ok(create_feed_item(item, user, data).await?),
None => Ok(create_feed_item(item, user, data, top_level).await?),
}
}

async fn create_feed_item(
item: DbUserFeedItem,
user: &ApubUser,
data: &Data<AppData>,
top_level: &UserFeedTopLevel,
) -> Result<(), AppError> {
// 将 Item 保存到数据库
let item = item.into_active_model().insert(&data.conn).await?;
let item: WrappedUserFeedItem = item.into();

// 创建 Note
let note = Note::create(user, item.into_json()?, data)?;
let note = Note::create(user, item.into_json()?, top_level, data)?;

// 创建 Post 并保存到数据库
let _post = DbPost {
Expand Down Expand Up @@ -71,6 +73,7 @@ async fn update_feed_item(
item: DbUserFeedItem,
user: &ApubUser,
data: &Data<AppData>,
top_level: &UserFeedTopLevel,
) -> Result<(), AppError> {
// 更新 Item
let item = item
Expand All @@ -86,7 +89,7 @@ async fn update_feed_item(
.one(&data.conn)
.await?
{
let note = Note::update(user, item, post.published.clone(), data)?;
let note = Note::update(user, item, top_level, post.published.clone(), data)?;

post::ActiveModel {
object: Set(serde_json::to_string(&note)?),
Expand Down
20 changes: 12 additions & 8 deletions crates/cron/src/tasks/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@ pub async fn partial_update_per_user(
let feed = UserFeedTopLevel::get(db_user.clone()).await?;
let user: ApubUser = db_user.into();

for item in feed.items {
for item in feed.items.clone() {
check_feed_item(
data,
&user,
WrappedUserFeedItem::from_json(item, &user, data)?
.deref()
.clone(),
&feed,
kwaa marked this conversation as resolved.
Show resolved Hide resolved
)
.await?;
}
Expand Down Expand Up @@ -93,19 +94,21 @@ pub async fn full_update_per_user(data: &Data<AppData>, db_user: DbUser) -> Resu
if !Into::<ApubUser>::into(db_user.clone())
.to_user_feed_top_level()
.eq(&UserFeedTopLevel {
// TODO: use language
language: Option::default(),
feed_url: Url::parse("https://hatsu.local").unwrap(),
next_url: Option::default(),
items: Vec::default(),
..user_feed_top_level.clone()
})
{
db_user = hatsu_db_schema::user::ActiveModel {
hatsu: Set(user_feed_top_level.hatsu.map(UserFeedHatsu::into_db)),
name: Set(user_feed_top_level.title),
summary: Set(user_feed_top_level.description),
icon: Set(user_feed_top_level.icon.map(|url| url.to_string())),
hatsu: Set(user_feed_top_level
.hatsu
.clone()
.map(UserFeedHatsu::into_db)),
name: Set(user_feed_top_level.title.clone()),
summary: Set(user_feed_top_level.description.clone()),
icon: Set(user_feed_top_level.icon.clone().map(|url| url.to_string())),
kwaa marked this conversation as resolved.
Show resolved Hide resolved
language: Set(user_feed_top_level.language.clone()),
..db_user.clone().into_active_model()
}
.update(&data.conn)
Expand All @@ -114,13 +117,14 @@ pub async fn full_update_per_user(data: &Data<AppData>, db_user: DbUser) -> Resu

let user: ApubUser = db_user.into();

for item in user_feed_top_level.items {
for item in user_feed_top_level.items.clone() {
check_feed_item(
data,
&user,
WrappedUserFeedItem::from_json(item, &user, data)?
.deref()
.clone(),
&user_feed_top_level,
kwaa marked this conversation as resolved.
Show resolved Hide resolved
)
.await?;
}
Expand Down
2 changes: 2 additions & 0 deletions crates/db_migration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod m20240501_000002_received_announce;
mod m20240515_000001_user_feed_hatsu_extension;
mod m20240515_000002_user_feed;
mod m20240926_000001_blocked_url;
mod m20241028_000001_user_language;

pub struct Migrator;

Expand All @@ -27,6 +28,7 @@ impl MigratorTrait for Migrator {
Box::new(m20240515_000001_user_feed_hatsu_extension::Migration),
Box::new(m20240515_000002_user_feed::Migration),
Box::new(m20240926_000001_blocked_url::Migration),
Box::new(m20241028_000001_user_language::Migration),
]
}
}
2 changes: 2 additions & 0 deletions crates/db_migration/src/m20240131_000001_user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ pub enum User {
Hatsu,
/// User Feed
Feed,
/// language (`m20241028_000001`)
Language,
kwaa marked this conversation as resolved.
Show resolved Hide resolved
/// will be remove in v1.0.0
// #[deprecated(since = "0.2.0-beta.5", note = "replaced by feed")]
FeedJson,
Expand Down
35 changes: 35 additions & 0 deletions crates/db_migration/src/m20241028_000001_user_language.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use sea_orm_migration::{prelude::*, schema::*};

use crate::m20240131_000001_user::User;

#[derive(DeriveMigrationName)]
pub struct Migration;

#[async_trait::async_trait]
impl MigrationTrait for Migration {
async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(User::Table)
.add_column(string_null(User::Language))
.to_owned(),
)
.await?;

Ok(())
}
kwaa marked this conversation as resolved.
Show resolved Hide resolved

async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> {
manager
.alter_table(
Table::alter()
.table(User::Table)
.drop_column(User::Language)
.to_owned(),
)
.await?;

Ok(())
}
kwaa marked this conversation as resolved.
Show resolved Hide resolved
}
1 change: 1 addition & 0 deletions crates/db_schema/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct Model {
pub last_refreshed_at: String,
pub hatsu: Option<UserHatsu>,
pub feed: Option<UserFeed>,
pub language: Option<String>,
kwaa marked this conversation as resolved.
Show resolved Hide resolved
}

#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, FromJsonQueryResult)]
Expand Down