-
-
Notifications
You must be signed in to change notification settings - Fork 7.1k
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
Add groups support #19059
base: main
Are you sure you want to change the base?
Add groups support #19059
Conversation
9ad4ba2
to
d4b88c4
Compare
I guess users should be able to boosts within the group, according to the visibility of the post. Outside public posts could be boosted in public groups only, so the replies would be public too.
When a user leave a private group, they should not access posts inside the group, including their own. And that sounds not okay to me I guess, not seeing my own posts... |
d4b88c4
to
8bfa3ed
Compare
It has been decided that, at least initially, we will not support any kind of boosts within or across groups: otherwise publicly-viewable group posts will only be seen within the context of the group and won't be boostable within or outside of the group. Public non-group posts won't be boostable in the group either.
The most likely approach we are going to take is have you be able to review your posts from groups you have left or have been kicked out of, and be able to delete them. It's not completely decided yet, though, and it's not completely sure how the UI for that would look like. |
After lengthy discussions, I think we will be making the following decisions for the initial implementation:
|
8bfa3ed
to
2e25b15
Compare
5a2bde8
to
7fe590e
Compare
|
Fixed |
867b084
to
7730865
Compare
ac41b9c
to
ebf7df2
Compare
85eefb8
to
2c31ed4
Compare
end | ||
|
||
# Kick existing members that we are banning | ||
memberships.each(&:destroy) # TODO: federate |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note for later
In Friendica people use groups for different reasons. One is the classical discussion group. The other is to extend your audience, which means that you then post to your followers and additionally to one or more groups. This is separated via |
Just a note that we have also been discussing the reconciliation of FEP-400e (e.g. Smithereen) and FEP-1b12 (e.g. Lemmy) in the context of Discourse, NodeBB, Flarum and other "threaded" implementations here. |
FEP-400e would also work for forum-style experiences. If you imagine a forum in its simplest 00s form, e.g. phpBB/IPB/vBulletin, I'd map it to ActivityPub like this:
|
@grishka That's not how we've implemented things so far, but it's good to think through the alternatives. Your insight would be most welcome in our working group! |
One thing with Lemmy's approach I really appreciate, is the usage of the |
@ClearlyClaire Could we get an statement on the status of this PR? Groups is the single most important thing I'm looking forward to. |
I've since had more thoughts about my implementation and I'm going to change it a bit. The problem I realized I have is how comments/replies work. If done naively, like it's done now in Smithereen, the
So I'm going to soon experiment with a different approach: |
@grishka have you considered having that "single flat collection" be |
Just FYI, a lot of people have been asking via FediTips if there is any feature like this on Mastodon. They basically want to come off Meta and are willing to do so if there is a Facebook Groups style feature, which this seems to be. Any progress at all on this? |
Well i think Friendica is a better alternative for Meta users. |
The Friendica approach is still bad because your group posts also appear on your profile. It's a crutch on top of there being no groups. It's a quick-and-dirty workaround that leaks straight into the UX. Mastodon also has these pseudo-groups in the form of bots that boost everything that mentions them, the only difference being that there's no dedicated syntax for that, it's just regular mentions.
I did, but iirc that property is already used by some other implementations for some other purposes, so I had to invent something brand new to rule out any ambiguity that may arise otherwise. |
I don't understand what you mean. |
If I remember correctly, you post in Friendica groups by posting to your profile but starting with |
It shows for the followers in that group yes as it should but not in your profile. |
@Leatherface75 @grishka to be exact: A post created with @grishka of course these posts will also be visible in the user's outbox, as it is a post created by that user, just as any comments will also be part of the outbox. |
Logging into my very old Github account to find out if GROUPS are coming to Mastodon. Leaving Meta with all my friends and family but this is the sole reason we are still hanging around there. Is this actually happening and if so when? |
In the last couple of weeks have had even more people getting in touch via FediTips asking if there is a Facebook Groups equivalent they can move to. People are desperate to move off Facebook and are looking at the Fedi right now (especially Mastodon), in the words of one message today: "there is momentum". Is there any word at all on when/if Mastodon groups will actually happen, and if so will it provide private groups in a similar manner to FB Groups?
Friendica isn't really suitable for non-technical people in its current form, it doesn't have an abuse reporting feature for example. I love Friendica but it isn't ready for non-techies yet. And it doesn't have an FB groups equivalent, which is the topic of this pull request. |
Yes Friendica supports Gruops and that's what this PR is supporting so i don't understand what you mean. |
(No, this PR implements the Smithereen protocol) |
I'm not interested in a new protocol that is not compatible with other ActivityPub solutions. |
I've already written here why I made Smithereen groups the way they are. There were no other solutions to avoid leaking the protocol into the UX. (though I am going to change that a bit soon — I'll make the comments on wall posts go into a separate collection, like I've done for photo albums, instead of |
@FediVideos What do you mean with "abuse reporting feature"? Friendica has got a report functionality. Back to the topic: If this PR changes anything on how to handle accounts with the type |
at present this PR doesn't use the type
furthermore, this PR at present doesn't use to address potential responses ahead-of-time:
|
@trwnh Currently |
This PR is not intended to be merged outside of purely development environments until it's finished. While it has reached a pretty stable state, groups are a complicated topic, and the database model, API and protocol design may change before the PR gets merged, with no clear migration path between versions of this PR.
Basic expectations around groups
Nothing is set in stone yet, but what we are going for is something along those lines:
Interface
Video overview
demo.mp4
Viewing and posting
Pending and rejected posts
While a priori moderation isn't planned on Mastodon's side on the short term, interacting with remote groups means you can't synchronously know whether your posts are accepted. They may have a priori moderation, or there might be federation hiccups. For these reasons, your posts may be pending or eventually rejected
Group administration dropdown
Group members list (with group administration dropdown)
Server administration interface
REST API
New OAuth scopes
read:groups
write:groups
admin:read:groups
admin:write:groups
New entities
Group
:id
: string, local identifier for the groupdisplay_name
: string, name of the groupcreated_at
: string (ISO 8601 Datetime), date at which the group was creatednote
: string, description of the groupuri
: string, global (ActivityPub) identifier for the groupurl
: string, user-friendly URL for the groupavatar
: string, URL to a possibly animated image to be used as icon for the groupavatar_static
: string, URL to an image to be used as icon for the groupheader
: string, URL to a possibly animated image to be used as a cover/header image for the groupheader_static
: string, URL to an image to be used as a cover/header image for the groupdomain
: string, domain hosting the group.null
if the group is hosted locallylocked
: boolean,false
if the group is expected to automatically accept membership requestsstatuses_visibility
: boolean,'public'
is the only value so far and means all posts are expected to be publicmembership_required
: boolean, onlytrue
so far, meaning that it is expected that only members can postGroupMembership
:id
: string, internal identifier for the membershipaccount
:Account
entity, which user this membership is aboutrole
: string, role of the user within the group. Valid values areadmin
,moderator
andusers
Existing entities with new or changed attributes
Status
:group
attribute:Group
in which the status exists. When this attribute is set,visibility
must be"group"
visibility
attribute:"group"
. Whenvisibility
is"group"
, theStatus
has agroup
attributeapproval_status
attribute with the following possible values:"pending"
,"approved"
,"rejected"
,"revoked"
. Its absence is equivalent to"approved"
and does not require any special handling. It is currently only used for group posts but may be used in other cases in the future (e.g. reply control policies)."pending"
means it has not been approved yet, while"rejected"
means it has been rejected in a priori moderation / automatic filtering / access rules, and"revoked"
means it has been denied after being first being approved for a timeNew endpoints
POST /api/v1/groups
(requireswrite
orwrite:groups
and also requires proper user permissions): create a group with the given attributes (display_name
,note
,avatar
andheader
). Sets the user who made the request as group administratorGET /api/v1/groups
(requiresread
orread:groups
): returns an array ofGroup
entities the current user is a member ofGET /api/v1/groups/:id
(requiresread
orread:groups
): returns theGroup
entity describing a given groupPOST /api/v1/groups/:id/join
(requireswrite
orwrite:groups
): joins (or request to join) a given groupPOST /api/v1/groups/:id/leave
(requireswrite
orwrite:groups
): leaves a given groupGET /api/v1/groups/:id/memberships
(requiresread
orread:groups
). Has an optionalrole
attribute that can be used to filter by role (valid roles are"admin"
,"moderator"
,"user"
).Group administration
All of these require the current account to be an admin of the group:
PUT /api/v1/groups/:group_id
(requireswrite
orwrite:groups
): update group attributes (display_name
,note
,avatar
andheader
)DELETE /api/v1/groups/:group_id
(requireswrite
orwrite:groups
): irreversibly deletes the groupGroup moderation
All of these require the current account to be an admin/moderator of the group:
GET /api/v1/groups/:group_id/membership_requests
(requiresread
orread:groups
): returns an array ofAccount
entities representing pending requests to join a groupPOST /api/v1/groups/:group_id/membership_requests/:account_id/authorize
(requireswrite
orwrite:groups
): accept a pending request to become a group memberPOST /api/v1/groups/:group_id/membership_requests/:account_id/reject
(requireswrite
orwrite:groups
): reject a pending request to become a group memberDELETE /api/v1/groups/:group_id/statuses/:id
(requireswrite
orwrite:groups
): delete a group post (actually marks it asrevoked
if it is a local post)POST /api/v1/groups/:group_id/kick?account_ids[]=…
(requireswrite
orwrite:groups
): kick one or more group membersGET /api/v1/groups/:group_id/blocks
(requiresread
orread:groups
): list accounts blocked from interacting with the groupPOST /api/v1/groups/:group_id/blocks?account_ids[]=…
(requireswrite
orwrite:groups
): block one or more users. If they were in the group, they are also kicked of itDELETE /api/v1/groups/:group_id/blocks?account_ids[]=…
(requireswrite
orwrite:groups
): lift one or more blocksPOST /api/v1/groups/:group_id/promote?role=new_role&account_ids[]=…
(requirewrite
orwrite:groups
): promote one or more accounts to rolenew_role
. An error is returned if any of those accounts has a higher role thannew_role
already, or if the role is higher than the issuing user's. Valid roles areadmin
, andmoderator
anduser
.POST /api/v1/groups/:group_id/demote?role=new_role&account_ids[]=…
(requirewrite
orwrite:groups
): demote one or more accounts to rolenew_role
. Returns an error unless every of the target account has a strictly lower role than the user (you cannot demote someone with the same role as you), or if any target account already has a role lower thannew_role
. Valid roles areadmin
,moderator
anduser
.Instance moderation
GET /api/v1/admin/groups
(requiresadmin:read:groups
and permissions to manage users): list groups known to the instance. Mimics the interface of/api/v1/admin/accounts
Optional query parameters:
origin
(string):"remote"
to list only remote groups, or"local"
to list only local groupsstatus
(string):"active"
to list only groups that have not been suspended, or"suspended"
to list only suspended groupsby_domain
(string): search for groups originating from a specific domaindisplay_name
(string): filter groups on display nameorder
(string):"active"
to sort by date of most recent post,"recent"
to sort by group creation dateby_member
(string): search groups in which a specific account (given by account id) is a memberGET /api/v1/admin/groups/:group_id
: return basic group informationPOST /api/v1/admin/groups/:group_id/suspend
(requiresadmin:write:groups
and permissions to manage users): suspends a groupPOST /api/v1/admin/groups/:group_id/unsuspend
(requiresadmin:write:groups
and permissions to manage users): lift a suspensionDELETE /api/v1/admin/groups/:group_id
(requiresadmin:write:groups
and permissions to delete user data): deletes an already-suspended groupChanges to existing endpoints
POST /api/v1/statuses
: accepts the new value"group"
for thevisibility
parameter, and accepts a newgroup_id
parameter. Whenvisibility
is set to"group"
, a validgroup_id
must be provided, and when agroup_id
is provided,visibility
must be set to"group"
. A reply cannot have a differentgroup_id
than the post it is in reply to.ActivityPub (federation)
Context and survey of existing work
Other fediverse projects have or are working on similar functionality, though there is no definite standard yet, and there are still many open questions. From what I have gathered, the main implementations seem to be:
sm:wall
collectionFollow
andAnnounce
flowAt the same time, other projects such as Mobilizon and Peertube use
Group
actors for different purposes.Implementation in this PR
Remote users interacting with local groups and local users interacting with remote groups are supported. For the time being, local groups can only have local moderators, and local users can only moderate local groups.
At this time, Mastodon does not perform JSON-LD compaction and expects implementations to use the shorthand for the described attributes, but produces a valid context properly qualifying them.
PublicGroup
, and are expected to provide the following attributes:wall
: an identified publicOrderedCollection
of all approved group postsmembers
: aCollection
orOrderedCollection
of group membersname
: a human-readable name for the grouppublicKey
: public key used for signing requestsattributedTo
(optional): array of non-group actors with group moderation powerssummary
(optional): a description of the groupicon
(optional): icon for the group, akin to profile avatarsimage
(optional): header illustration for the group, akin to profile headersmanuallyApprovesMembers
(optional): true if the group is expected to not automatically approve new members (similar tomanuallyApprovesFollowers
)suspended
(optional): indicates that the group has been temporarily suspended and should not be interacted withJoin
activity and expecting anAccept
in returnLeave
activityto
attributeCreate
activity exclusively to the group's inbox, with the embedded object targeting the group'swall
collection. Such an activity can be denied in /a priori/ moderation or access control via aReject
activityAdd
activity from the group actor, adding the post to itswall
collection. The post is fetched and MUST include thewall
collection as itstarget
. If the added post is a local post, it will be marked as approved.Delete
their group posts, and the group actor distributes aRemove
activity to reflect it. In addition, if theDelete
activity is signed, the group actor may forward itRemove
activityUpdate
itself orDelete
itself likePerson
actorsExamples
Group actor:
Join activity:
Create activity:
Add activity:
TODO
This is a rough outline of the planned development, but as stated above, “finished” steps will likely be revisited as UX or protocol considerations emerge when working on other steps.
This project was funded through the NGI0 Discovery Fund, a fund established by NLnet with financial support from the European Commission's Next Generation Internet programme, under the aegis of DG Communications Networks, Content and Technology under grant agreement No 825322.