activitystreams icon indicating copy to clipboard operation
activitystreams copied to clipboard

Feature similar to ostatus:conversation

Open evanp opened this issue 6 years ago • 11 comments

We should be able to associate a big thread for conversation

evanp avatar May 09 '18 15:05 evanp

So, this is used in OStatus for big hierarchical conversations. So when you have Notes like this:

  • Note1
    • Note2
      • Note4
      • Note5
        • Note6
    • Note3
      • Note7
      • Note8
        • Note9
          • Note10

Here, Note6 is inReplyTo Note5, and Note10 is inReplyTo Note9. But it's not clear that they are part of a larger conversation, unless you walk up the tree.

A conversation property links them all together. I think that most OStatus implementations use the ID of the root object (which is inReplyTo nothing else) as the conversation identifier, but I don't think they are required to.

evanp avatar May 09 '18 17:05 evanp

So, related features we already have in AS2:

  • context

    Identifies the context within which the object exists or an activity was performed.
    
     The notion of "context" used is intentionally vague. The intended function is to serve
     as a means of grouping objects and activities that share a common originating context
     or purpose. An example could be all activities relating to a common project or event.
    
  • tag This is often used for hashtags, where the "conversation" might not be direct replies to other objects in the conversation.

evanp avatar May 09 '18 17:05 evanp

One thing we could do is define a Conversation type, and use it like this:

{
  "type": "Note",
  "id": "https://an.example/note/6",
  "inReplyTo": "https://an.example/note/5",
  "context": {
    "type": "Conversation",
    "id": "https://an.example/conversation/1"
  }
}

Another is to specify a root or op item:

{
  "type": "Note",
  "id": "https://an.example/note/6",
  "inReplyTo": "https://an.example/note/5",
  "root": {
    "type": "Note",
    "id": "https://an.example/note/1"
  }
}

Or we could use a conversation property:

{
  "type": "Note",
  "id": "https://an.example/note/6",
  "inReplyTo": "https://an.example/note/5",
  "conversation": {
    "type": "Conversation",
    "id": "https://an.example/conversation/1"
  }
}
{
  "type": "Note",
  "id": "https://an.example/note/6",
  "inReplyTo": "https://an.example/note/5",
  "conversation": {
    "type": "Note",
    "id": "https://an.example/note/1"
  }
}

evanp avatar May 09 '18 17:05 evanp

It's also worth noting that many systems use a flat commenting/replying hierarchy, so everything would be inReplyTo Note1.

evanp avatar May 09 '18 17:05 evanp

for the record, even though mastodon uses a flat commenting UX, posts still technically form a nested heiarchy. (and even in more flat system, it's more intuitive sometimes to have notes as in reply to the last note in the thread, not the root note)

On Wed, May 9, 2018, 1:44 PM Evan Prodromou [email protected] wrote:

It's also worth noting that many systems use a flat commenting/replying hierarchy, so everything would be inReplyTo Note1.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/w3c/activitystreams/issues/476#issuecomment-387819135, or mute the thread https://github.com/notifications/unsubscribe-auth/AAORV--5CXtuWUG2SVnOSgUURbzrmswNks5twyr9gaJpZM4T4icd .

nightpool avatar May 09 '18 18:05 nightpool

inReplyTo is not marked as a functional property (there can be more than one), so is it expected that single objects could be part of many conversations?

I am a fan of the extra properties!

However, what is the compelling reason to having a separate Conversation type, too? I could maybe see an argument for it being a (Ordered?) Collection of a list of IRIs to every object in the conversation, but I don't see the utility that extra abstraction layer brings and two major costs: putting an arbitrary logical grouping in the graph, and forcing everyone to adhere to it. Instead, it seems more straightforward for any new properties to point directly to the head object and let applications crawl as far down as they please with whatever caching/grouping they want to do.

cjslep avatar May 09 '18 21:05 cjslep

@cjslep so say you have a conversation tree like in https://github.com/w3c/activitystreams/issues/476#issuecomment-387813503. In your UI you want to know if, say, note 6 and note 10 are associated with each other (which they are because they're both replies to replies to note 1). Normally you would be required to walk the entire tree to find that information, but with this extension you could determine that information in constant time.

Also remember that nobody's forced to use it - extensions are optional :P

strugee avatar May 10 '18 04:05 strugee

@strugee Yes, I agree, that can be accomplished with just the new properties referencing the IRI of the root node and comparing them. I like that. I just don't see a compelling need for a whole new Conversation type to embody this concept.

Also, in practice I am sure it is constant time with most people replying to 1 thread at a time. But theoretically, it is linear time with respect to the number of conversations the replies are in (since inReplyTo is not marked as functional).

cjslep avatar May 10 '18 08:05 cjslep

Don't think "Conversation" type is necessary. a Property whose range is Link would be sufficient for

{ "conversation": "https://conversation-url.com" }

I worked at a "conversation not comments" company for a long time. It's quite the overloaded term. I think inReplyToRoot would be a bit more clear and specific to what we're talking about here ('inReplyTo' relation-following as opposed to something else, root of tree data structure)

gobengo avatar Sep 12 '18 16:09 gobengo

So, 5 years later, we have a number of solutions to this issue. Mastodon uses the ostatus:conversation property directly. Here's an example "toot" from Mastodon:

{
   "@context" : [
      "https://www.w3.org/ns/activitystreams",
      {
         "atomUri" : "ostatus:atomUri",
         "conversation" : "ostatus:conversation",
         "inReplyToAtomUri" : "ostatus:inReplyToAtomUri",
         "ostatus" : "http://ostatus.org#",
         "sensitive" : "as:sensitive",
         "toot" : "http://joinmastodon.org/ns#",
         "votersCount" : "toot:votersCount"
      }
   ],
   "atomUri" : "https://cosocial.ca/users/evan/statuses/110257163940796886",
   "attachment" : [],
   "attributedTo" : "https://cosocial.ca/users/evan",
   "cc" : [
      "https://cosocial.ca/users/evan/followers"
   ],
   "content" : "<p>Why: temp rise under 1.5C</p><p>What: zero emissions by 2050; capture CO2</p><p>How to get to zero: vote and donate to climate+ pols, electric or no car, trains not planes, clean electricity or home solar, low or no meat, buy climate+</p><p>How to capture: plant 500 billion trees</p>",
   "contentMap" : {
      "en" : "<p>Why: temp rise under 1.5C</p><p>What: zero emissions by 2050; capture CO2</p><p>How to get to zero: vote and donate to climate+ pols, electric or no car, trains not planes, clean electricity or home solar, low or no meat, buy climate+</p><p>How to capture: plant 500 billion trees</p>"
   },
   "conversation" : "tag:cosocial.ca,2023-04-25:objectId=483056:objectType=Conversation",
   "id" : "https://cosocial.ca/users/evan/statuses/110257163940796886",
   "inReplyTo" : null,
   "inReplyToAtomUri" : null,
   "published" : "2023-04-25T02:46:47Z",
   "replies" : {
      "first" : {
         "items" : [],
         "next" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies?only_other_accounts=true&page=true",
         "partOf" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies",
         "type" : "CollectionPage"
      },
      "id" : "https://cosocial.ca/users/evan/statuses/110257163940796886/replies",
      "type" : "Collection"
   },
   "sensitive" : false,
   "summary" : null,
   "tag" : [],
   "to" : [
      "https://www.w3.org/ns/activitystreams#Public"
   ],
   "type" : "Note",
   "url" : "https://cosocial.ca/@evan/110257163940796886"
}

I believe other implementations use the context property for something similar. I think the best resolution here is to create a page at https://www.w3.org/wiki/Activity_Streams/Primer/Conversation and collect best practices.

Right now, I agree with @cjslep that the best way to do this is with a context property that links to the original post:

"context": {
    "type": "Note",
    "id": "https://an.example/note/1"
}

evanp avatar Nov 15 '23 17:11 evanp

Rather than linking to the original post, it would be better to have an explicit collection that can be managed by a mechanism similar to FEP-7888

trwnh avatar Nov 16 '23 00:11 trwnh