Podcastindex-org / podcast-namespace

A wholistic rss namespace for podcasting
Creative Commons Zero v1.0 Universal
380 stars 114 forks source link

Proposal - ⚡️ Lightning Comments #347

Closed MerryOscar closed 1 year ago

MerryOscar commented 2 years ago

I would like to propose an alternative for cross-app comments that integrates the feature we all love - BOOSTS!⚡️

Issues with podcast:social

Whilst the current <podcast:social> tag is workable, in my view there are some fundamental issues:

⚡️ Lightning Comments

A cross-app <lightningcomments> specification that could be added to the Podcasting 2.0 namespace.

By tying comments to Lightning payments, any app can post a comment or reply without needing the user to create an account. Optional user info can be parsed from the TLV record just as we do things for the podcast:value tag.

Comments can come from any app - but the host still has full control.

There are 2 components to this proposed spec:

1. Comments Tag <lightningcomments>

Tells the app where to load the comments JSON. The JSON will contain the comments data along with instructions on how to post a comment.

<lightningcomments url="https://api.fountain.fm/v1/comments?feed=920666&episode=6788136469" />

Importantly:

2. Comments JSON (returned from url in tag)

Defines the JSON format that any lightningcomments host should conform to:

{
  // how to post a comment
  "_post": {
    "type": "lightning",
    "method": "keysend",
    "minimum": 1,
    "address": "03bc290b26637eb8f25de69fca83c85c014796aa03d90bf0d4c03c18947e12127d",
    "tlv": {
      // required comment tlv record
      333333: {
        // the host field allows each comments host to provide their own data which is passed along through the tlv, apps should not modify.
        "host": {
          "_show_id": "",
          "_feed_id": "",
          "_episode_id": "",
          "_episode_title": ""
        },
        // the comment field should be consistent between hosts, apps should set.
        "comment": {
          "payment": 1, // payment value (required)
          "message": "", // comment message (required)
          "parent": "", // id of parent comment (optional if reply)
          "sender": {
            "app": "", // name of app sending comment (optional)
            "id": "", // unique id of user sending comment (optional)
            "name": "" // name of user sending comment (optional)
          },
        }
      }
      // ...optional tlv records
    }
  },

  // the existing comments data
  "data": {
    "comments": [
      // a route comment
      {
        "id": "75X5adm5VCsnolxzPJFN",
        "message": "",
        "sender": {
          "app": "",
          "id": "",
          "name": "",
        },
        "depth": 0,
        "payment": 1,
        "created": "2022-01-20T18:18:00.000-0100",
        "parent": null,
        "children": [
          "CGGDl8Hy3DNmCSAqAUSQ"
        ]
      },
      // a reply to the route comment (75X5adm5VCsnolxzPJFN)
      {
        "id": "CGGDl8Hy3DNmCSAqAUSQ",
        "message": "",
        "sender": {
          "app": "",
          "id": "",
          "name": "",
        },
        "depth": 1,
        "payment": 1,
        "created": "2022-01-20T18:18:00.000-0100",
        "parent": "75X5adm5VCsnolxzPJFN",
        "children": [
          "u5u27ntCCYP2AulIClmB"
        ]
      },
      // a reply to the reply (CGGDl8Hy3DNmCSAqAUSQ)
      {
        "id": "u5u27ntCCYP2AulIClmB",
        "message": "",
        "sender": {
          "app": "",
          "id": "",
          "name": ""
        },
        "depth": 2,
        "payment": 1,
        "created": "2022-01-20T18:18:00.000-0100",
        "parent": "CGGDl8Hy3DNmCSAqAUSQ",
        "children": [] 
      }
    ]
}

Although the existing comments data is a list, the parent and children properties will allow apps to render nested comments.

Working Demo

You can see that:

Questions

Should users have to pay for comments?

A payment is required to comment, but because the payment value can be very small (1 satoshi), apps can very easily cover the cost for users if they choose. The payment requirement brings an incredible benefit of spam protection and also incentivises better quality comments.

Will the Lightning TLV record have enough space for comments?

The TLV record is limited in size but will still be enough for multi-paragraph comments. No essays but limiting response length in this way is not nessessarily a bad thing.

What about the existing 7629169 TLV record?

We could definitely combine the TLV records - but I think in the short term it's easier to define a new record and let apps / hosting providers decide whether to include boosts from the 7629169 record in the comments JSON. This separates concerns until we have fully aggreed on the spec. It also leaves open the ability for apps to send private boosts.

The comments are stored on a central server - is this decentralised?

The comments are hosted on a central server yes, but the specification is still decentralised because you can switch comments hosts whenever you want - just like you can switch podcast hosts. As the JSON format is the same you can bring your comments with you to a new host or self-host them. The posting of comments is still decentralised because anyone can post a comment from any platform by sending a Lightning payment.

Next Steps

Please give a thumbs up on the issue if you think like the idea - otherwise I would love to open a discussion!

yoshimo commented 2 years ago

What about user privacy in this context? When comments are done on the podcasters wordpress page with captcha and so on i can post one comment as "max" the next as "john" and they can not be linked if i used a different ip they also can't tell if john on one podcast is the same john that posted a comment on another podcasts page. Can we keep this non linkability up with your new system?

MerryOscar commented 2 years ago

What about user privacy in this context? When comments are done on the podcasters wordpress page with captcha and so on i can post one comment as "max" the next as "john" and they can not be linked if i used a different ip they also can't tell if john on one podcast is the same john that posted a comment on another podcasts page. Can we keep this non linkability up with your new system?

It would up up to apps to set privacy policy - same as with the <podcast:value> tag. Some apps send an id / name / username - some apps are anonymous.

johnspurlock commented 2 years ago

This is a cool idea! A common structure for how to locate and surface comments generated via lightning is needed.

One note about the idea specifically: the podcaster will not want to put a url to fountain (an app) in their podcast feed. They'd want to point to the system that can can surface the transactions received, ie it should come from something like helipad for those with umbrel wallets. Or maybe in your example you meant fountain owns/manages a podcaster's wallet? It is a question for how you would do this for a wallet without custom software like helipad though.

One suggestion about the idea from a high level - you may want to consider implementing "lightningcomments" as a new protocol on the existing socialInteract tag, since you are effectively creating another protocol here. i.e.

<podcast:socialInteract platform="helipad" protocol="lightningcomments">
  https://helipad.example.com/v1/comments?feed=920666&amp;episode=6788136469
</podcast:socialInteract>

This way:

Oh and:

As a podcast app user I really don't want to have to login to different social accounts just to comment.

With ActivityPub at least, a good app will provide a transparent id on their domain, so no log in at all from the user's pov.

Hope that helps!

MerryOscar commented 2 years ago

@johnspurlock thanks so much for the detailed feedback!


the podcaster will not want to put a url to fountain (an app) in their podcast feed.

Yes definitely agree. The Fountain url is just an example and I envision each podcast having a different comments url based on their choice. So you could have a Fountain url, another app url, a hosting platform url, a helipad url (if that's possible).


you may want to consider implementing "lightningcomments" as a new protocol on the existing socialInteract tag

Yes agree this could be a great way to do it. I thought about proposing it this way but wanted to leave the option of having it separate. But all your points make a lot of sense. I especially love the idea of a url per-platform per episode and gradually (but optionally) introducing users to Lightning.

jamescridland commented 2 years ago

Since Oscar built the API, and since I support this idea in principle, I have implemented this specification within Podnews pages.

If you go and listen to the Podnews episode called "Google's new dubbing tool" and send a boostagram, the text of that boostagram will appear in the comments section towards the bottom of: https://podnews.net/update/google-dub

Screen Shot 2022-03-12 at 8 01 19 pm

The comments are updated every ten minutes; that's not a technical issue with this specification, but just how long the JSON will cache for at the CDN, to save Oscar's systems being hit every page load. The work I've had to do for this is minimal; I wrote a proxy for the comments API on Fountain (five lines of PHP, plus caching and CORS); a piece of JavaScript to asynchronously call this API and lay out the results (fourteen lines); and added an additional column in the database schema to store the Podcast Index episode ID. It'll take ten minutes more to add a tool to pull the episode ID out of Podcast Index.

I should note: I am very happy to give someone a value share in order for them to run an API for comments like this. There is a business model in operating comments like this and an API on the other end. (Indeed, some API operators might wish to add moderation tools.)

A suggestion to make it easier for developers and avoid a central point of failure

The current comments JSON lives at a URL like: https://api.fountain.fm/v1/comments?feed=227573&episode=7130637071

Both the feedID and the episodeID are both proprietary pieces of data from Podcast Index, requiring API calls and relying on a central database. I believe that where alternatives exist we shouldn't back ourselves into a proprietary corner, no matter how nice Dave and Adam are.

I'd therefore suggest

https://api.fountain.fm/v1/comments?feedUrl=https%3A%2F%2Fpodnews.net%2Frss&guid=https%3A%2F%2Fpodnews.net%2Fupdate%2Fgoogle-dub

I do, though, recognise that boosts all currently rely on PodcastIndex IDs currently, so perhaps right now this isn't a concern; but just a suggestion.

johnspurlock commented 2 years ago

Nice James - one step closer to making this hidden lightning comment data available for display in 3rd-party apps!

Just added two PRs to formally add fountain as a platform, and lightningcomments as a protocol to podcast:socialInteract, so we can get this into phase 5.

Can you add the following tag to the podnews rss feed, under the item with guid https://podnews.net/update/google-dub:

<podcast:socialInteract priority="1" platform="fountain" protocol="lightningcomments" accountId="033868c219bdb51a33560d854d500fe7d3898a1ad9e05dd89d0007e11313588500" pubDate="2021-04-14T10:25:42Z">https://api.fountain.fm/v1/comments?feed=227573&amp;episode=7130637071</podcast:socialInteract>

or for extra credit:

<podcast:socialInteract priority="1" platform="fountain" protocol="lightningcomments" accountId="033868c219bdb51a33560d854d500fe7d3898a1ad9e05dd89d0007e11313588500">https://api.fountain.fm/v1/comments?feed=227573&amp;episode=7130637071</podcast:socialInteract>
<podcast:socialInteract priority="2" platform="twitter" protocol="twitter" accountId="@Podnews">https://twitter.com/Podnews/status/1502242577122304005</podcast:socialInteract>

To provide the complete structured data for that episode, including your corresponding tweet. Didn't you used to provide this?

I could probably even add adapters to threadcap for Twitter and this new lightningcomments json format, so existing callers could just point it at any of the three: ActivityPub, Twitter, lightningcomments and get a normalized format for easy rendering.

jamescridland commented 2 years ago

Thanks, @johnspurlock - this is now in the RSS.

<podcast:socialInteract
 priority="1"
 platform="fountain"
 protocol="lightningcomments" 
 accountId="033868c219bdb51a33560d854d500fe7d3898a1ad9e05dd89d0007e11313588500"
>
https://api.fountain.fm/v1/comments?feed=227573&amp;episode=7130637071
</podcast:socialInteract>

I'm going to not publish a pubDate - it's programmatically difficult to get as far as I can see, and it appears optional in the spec.

Both @MerryOscar and @johnspurlock - It's sub-optimal to have to publish the RSS feed once in order to submit it to PodcastIndex, then to get the proprietary PodcastIndex episode ID from PodcastIndex once it's updated, and then publish the RSS feed again once I've found it. I need to fiddle with a lot of caching and double the notifications in order to achieve this. I would much rather use the episode GUID, which is set at publish time. Please can we consider how this is done?

The Twitter socialInteract - I need to see if I can programmatically get the ID of the tweet that's sent. At least, though, I can send the tweet as part of the publication process and get an instant response, which I can't rely on from PodcastIndex.

johnspurlock commented 2 years ago

100% behind using the (trimmed) item guid content value to identify episodes across our various systems, instead of PI episode ids.

Best (what you have above): https://api.fountain.fm/v1/comments?feedUrl=https%3A%2F%2Fpodnews.net%2Frss&guid=https%3A%2F%2Fpodnews.net%2Fupdate%2Fgoogle-dub

Supported alternative (podcastId known ahead of time): https://api.fountain.fm/v1/comments?podcastId=227573&guid=https%3A%2F%2Fpodnews.net%2Fupdate%2Fgoogle-dub

Maybe we should pester @daveajones to provide a brand new episodes-by-feed-id-and-item-guid endpoint (or maybe an optional new param to the existing episodes-by-feed-id endpoint?). Right now you can kind of do this by enumerating all episodes for the feed-id, but his DB would do a more efficient job of it given an item guid

jamescridland commented 2 years ago

(As an aside: you'll see a return of the SocialInteract for Twitter as of today; I've rewritten the tweet service to capture the tweetID. I've also added it to the /google-dub episode.)

MerryOscar commented 2 years ago

It's sub-optimal to have to publish the RSS feed once in order to submit it to PodcastIndex, then to get the proprietary PodcastIndex episode ID from PodcastIndex once it's updated, and then publish the RSS feed again once I've found it. I need to fiddle with a lot of caching and double the notifications in order to achieve this. I would much rather use the episode GUID, which is set at publish time. Please can we consider how this is done?

@jamescridland yes I agree this is sub-optimal.

I think it's important to note that because it is only a url that is specified in the spec, any Lightning Comments host can return the url in whatever form they want. Some hosts could use a combination of the feedUrl and the GUID, some hosts could use their own internal IDs.

For this Fountain demo we're using our internal showID + the PodcastIndex episode itemID. The reason for this is PodcastIndex have the GET /episodes/byid endpoint which makes things very easy.

@jamescridland - I'll update our comments load endpoint so that it accepts a Fountain showID and episode guid so you don't have the extra step of waiting for the PodcastIndex itemID - will let you know when this is done.

Agree with @johnspurlock if @daveajones could create a GET /episodes/byguid that would be amazing!

johnspurlock commented 2 years ago

Proposed the lookup by guid change in #352

johnspurlock commented 2 years ago

Added experimental support for this new lightningcomments protocol (and also twitter!) to the latest threadcap library

https://podcastindex.social/web/@js/107967439891619300

theDanielJLewis commented 2 years ago

I'm not seeing how this is different from publishing "public" Boostagrams anyway.

I see Boostagrams as a "response" that can be highlighted in a "comment" stream, similar to "superchats" on Twitch and YouTube Live.

However, I don't see Boostagrams as something intended to spark conversation with other listeners like comments often are.

I think, if anything, there should be a simple toggle in a feed that gives the app permission to surface the "public" Boostagrams. If it's allowed, then only those Boostagrams where the sender opts-in to having their response published will be visible. And if the tag is set to not allow, then no boostagrams will be displayed. Maybe there could be an in-between option that can let a podcaster show off the amount(s) and number of boosters, but not the individual boostagrams or their senders.

My position is that podcaster control and audience privacy should come before anything else.