Federate tags

This commit is contained in:
Bat 2018-09-06 09:21:08 +01:00
parent 5b3eca63e0
commit a54d2e9d71
4 changed files with 46 additions and 3 deletions

View file

@ -158,3 +158,20 @@ pub struct PublicKey {
#[activitystreams(concrete(String), functional)] #[activitystreams(concrete(String), functional)]
pub public_key_pem: Option<serde_json::Value> pub public_key_pem: Option<serde_json::Value>
} }
#[derive(Clone, Debug, Default, UnitString)]
#[activitystreams(Hashtag)]
pub struct HashtagType;
#[derive(Clone, Debug, Default, Deserialize, Serialize, Properties)]
#[serde(rename_all = "camelCase")]
pub struct Hashtag {
#[serde(rename = "type")]
kind: HashtagType,
#[activitystreams(concrete(String), functional)]
pub href: Option<serde_json::Value>,
#[activitystreams(concrete(String), functional)]
pub name: Option<serde_json::Value>,
}

View file

@ -19,6 +19,7 @@ extern crate openssl;
extern crate pulldown_cmark; extern crate pulldown_cmark;
extern crate reqwest; extern crate reqwest;
extern crate rocket; extern crate rocket;
extern crate serde;
#[macro_use] #[macro_use]
extern crate serde_derive; extern crate serde_derive;
#[macro_use] #[macro_use]

View file

@ -9,6 +9,7 @@ use heck::KebabCase;
use serde_json; use serde_json;
use plume_common::activity_pub::{ use plume_common::activity_pub::{
Hashtag,
PUBLIC_VISIBILTY, Id, IntoId, PUBLIC_VISIBILTY, Id, IntoId,
inbox::{Deletable, FromActivity} inbox::{Deletable, FromActivity}
}; };
@ -206,7 +207,8 @@ impl Post {
let mut to = self.get_receivers_urls(conn); let mut to = self.get_receivers_urls(conn);
to.push(PUBLIC_VISIBILTY.to_string()); to.push(PUBLIC_VISIBILTY.to_string());
let mentions = Mention::list_for_post(conn, self.id).into_iter().map(|m| m.to_activity(conn)).collect::<Vec<link::Mention>>(); let mut mentions_json = Mention::list_for_post(conn, self.id).into_iter().map(|m| json!(m.to_activity(conn))).collect::<Vec<serde_json::Value>>();
let mut tags_json = Tag::for_post(conn, self.id).into_iter().map(|t| json!(t.into_activity(conn))).collect::<Vec<serde_json::Value>>();
let mut article = Article::default(); let mut article = Article::default();
article.object_props.set_name_string(self.title.clone()).expect("Article::into_activity: name error"); article.object_props.set_name_string(self.title.clone()).expect("Article::into_activity: name error");
@ -218,7 +220,7 @@ impl Post {
article.object_props.set_content_string(self.content.get().clone()).expect("Article::into_activity: content error"); article.object_props.set_content_string(self.content.get().clone()).expect("Article::into_activity: content error");
article.object_props.set_published_utctime(Utc.from_utc_datetime(&self.creation_date)).expect("Article::into_activity: published error"); article.object_props.set_published_utctime(Utc.from_utc_datetime(&self.creation_date)).expect("Article::into_activity: published error");
article.object_props.set_summary_string(self.subtitle.clone()).expect("Article::into_activity: summary error"); article.object_props.set_summary_string(self.subtitle.clone()).expect("Article::into_activity: summary error");
article.object_props.set_tag_link_vec(mentions).expect("Article::into_activity: tag error"); article.object_props.tag = json!(mentions_json.append(&mut tags_json));
article.object_props.set_url_string(self.ap_url.clone()).expect("Article::into_activity: url error"); article.object_props.set_url_string(self.ap_url.clone()).expect("Article::into_activity: url error");
article.object_props.set_to_link_vec::<Id>(to.into_iter().map(Id::new).collect()).expect("Article::into_activity: to error"); article.object_props.set_to_link_vec::<Id>(to.into_iter().map(Id::new).collect()).expect("Article::into_activity: to error");
article.object_props.set_cc_link_vec::<Id>(vec![]).expect("Article::into_activity: cc error"); article.object_props.set_cc_link_vec::<Id>(vec![]).expect("Article::into_activity: cc error");
@ -295,12 +297,16 @@ impl FromActivity<Article, PgConnection> for Post {
}); });
} }
// save mentions // save mentions and tags
if let Some(serde_json::Value::Array(tags)) = article.object_props.tag.clone() { if let Some(serde_json::Value::Array(tags)) = article.object_props.tag.clone() {
for tag in tags.into_iter() { for tag in tags.into_iter() {
serde_json::from_value::<link::Mention>(tag) serde_json::from_value::<link::Mention>(tag)
.map(|m| Mention::from_activity(conn, m, post.id, true)) .map(|m| Mention::from_activity(conn, m, post.id, true))
.ok(); .ok();
serde_json::from_value::<Hashtag>(tag)
.map(|t| Tag::from_activity(conn, t, post.id))
.ok();
} }
} }
post post

View file

@ -1,4 +1,8 @@
use diesel::{self, PgConnection, ExpressionMethods, RunQueryDsl, QueryDsl}; use diesel::{self, PgConnection, ExpressionMethods, RunQueryDsl, QueryDsl};
use plume_common::activity_pub::Hashtag;
use ap_url;
use instance::Instance;
use schema::tags; use schema::tags;
#[derive(Serialize, Queryable)] #[derive(Serialize, Queryable)]
@ -21,4 +25,19 @@ impl Tag {
insert!(tags, NewTag); insert!(tags, NewTag);
get!(tags); get!(tags);
list_by!(tags, for_post, post_id as i32); list_by!(tags, for_post, post_id as i32);
pub fn into_activity(&self, conn: &PgConnection) -> Hashtag {
let ht = Hashtag::default();
ht.set_href_string(ap_url(format!("{}/tag/{}", Instance::get_local(conn).unwrap().public_domain, self.tag))).expect("Tag::into_activity: href error");
ht.set_name_string(self.tag).expect("Tag::into_activity: name error");
ht
}
pub fn from_activity(conn: &PgConnection, tag: Hashtag, post: i32) -> Tag {
Tag::insert(conn, NewTag {
tag: tag.name_string().expect("Tag::from_activity: name error"),
is_hastag: false,
post_id: post
})
}
} }