use super::*;
+#[derive(Deserialize)]
+pub struct CommentQuery {
+ comment_id: String,
+}
+
+/// Return the post json over HTTP.
+pub async fn get_apub_comment(
+ info: Path<CommentQuery>,
+ db: DbPoolParam,
+) -> Result<HttpResponse<Body>, Error> {
+ let id = info.comment_id.parse::<i32>()?;
+ let comment = Comment::read(&&db.get()?, id)?;
+ if !comment.deleted {
+ Ok(create_apub_response(&comment.to_apub(&db.get().unwrap())?))
+ } else {
+ Ok(create_apub_tombstone_response(&comment.to_tombstone()?))
+ }
+}
+
impl ToApub for Comment {
type Response = Note;
Person(Box<PersonExt>),
Group(Box<GroupExt>),
Page(Box<PageExt>),
+ Comment(Box<Note>),
}
/// Attempt to parse the query as URL, and fetch an ActivityPub object from it.
/// Some working examples for use with the docker/federation/ setup:
/// http://lemmy_alpha:8540/c/main, or !main@lemmy_alpha:8540
/// http://lemmy_alpha:8540/u/lemmy_alpha, or @lemmy_alpha@lemmy_alpha:8540
-/// http://lemmy_alpha:8540/p/3
+/// http://lemmy_alpha:8540/post/3
+/// http://lemmy_alpha:8540/comment/2
pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchResponse, Error> {
// Parse the shorthand query url
let query_url = if query.contains('@') {
let p = upsert_post(&PostForm::from_apub(&p, conn)?, conn)?;
response.posts = vec![PostView::read(conn, p.id, None)?];
}
+ SearchAcceptedObjects::Comment(c) => {
+ let post_url = c
+ .object_props
+ .get_many_in_reply_to_xsd_any_uris()
+ .unwrap()
+ .next()
+ .unwrap()
+ .to_string();
+ // TODO: also fetch parent comments if any
+ let post = fetch_remote_object(&Url::parse(&post_url)?)?;
+ upsert_post(&PostForm::from_apub(&post, conn)?, conn)?;
+ let c = upsert_comment(&CommentForm::from_apub(&c, conn)?, conn)?;
+ response.comments = vec![CommentView::read(conn, c.id, None)?];
+ }
}
Ok(response)
}
}
}
+fn upsert_comment(comment_form: &CommentForm, conn: &PgConnection) -> Result<Comment, Error> {
+ let existing = Comment::read_from_apub_id(conn, &comment_form.ap_id);
+ match existing {
+ Err(NotFound {}) => Ok(Comment::create(conn, &comment_form)?),
+ Ok(p) => Ok(Comment::update(conn, p.id, &comment_form)?),
+ Err(e) => Err(Error::from(e)),
+ }
+}
+
// TODO It should not be fetching data from a community outbox.
// All posts, comments, comment likes, etc should be posts to our community_inbox
// The only data we should be periodically fetching (if it hasn't been fetched in the last day
use super::*;
+use crate::apub::comment::get_apub_comment;
use crate::apub::community::*;
use crate::apub::community_inbox::community_inbox;
use crate::apub::post::get_apub_post;
// web::get().to(get_apub_community_outbox),
// )
.route("/u/{user_name}", web::get().to(get_apub_user_http))
- .route("/post/{post_id}", web::get().to(get_apub_post)),
+ .route("/post/{post_id}", web::get().to(get_apub_post))
+ .route("/comment/{comment_id}", web::get().to(get_apub_comment)),
)
// Inboxes dont work with the header guard for some reason.
.route("/c/{community_name}/inbox", web::post().to(community_inbox))
lemmyBetaAuth = resB.jwt;
});
- describe('beta_fetch', () => {
+ describe('post_search', () => {
test('Create test post on alpha and fetch it on beta', async () => {
let name = 'A jest test post';
let postForm: PostForm = {
expect(getPrivateMessagesUnDeletedRes.messages[0].deleted).toBe(false);
});
});
+
+ describe('comment_search', () => {
+ test('Create comment on alpha and search it', async () => {
+ let content = 'A jest test federated comment for search';
+ let commentForm: CommentForm = {
+ content,
+ post_id: 1,
+ auth: lemmyAlphaAuth,
+ };
+
+ let createResponse: CommentResponse = await fetch(
+ `${lemmyAlphaApiUrl}/comment`,
+ {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: wrapper(commentForm),
+ }
+ ).then(d => d.json());
+
+ let searchUrl = `${lemmyBetaApiUrl}/search?q=${createResponse.comment.ap_id}&type_=All&sort=TopAll`;
+ let searchResponse: SearchResponse = await fetch(searchUrl, {
+ method: 'GET',
+ }).then(d => d.json());
+
+ // TODO: check more fields
+ expect(searchResponse.comments[0].content).toBe(content);
+ });
+ });
});
function wrapper(form: any): string {