Introduce the group activity section

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2021-02-24 19:06:48 +01:00
parent d0567f783d
commit 3fe64a4389
70 changed files with 3224 additions and 70 deletions

View File

@@ -0,0 +1,7 @@
defmodule Mobilizon.Service.Activity do
@moduledoc """
Behavior for Activity creators
"""
@callback insert_activity(entity :: struct(), options :: map()) :: {:ok, Oban.Job.t()}
end

View File

@@ -0,0 +1,51 @@
defmodule Mobilizon.Service.Activity.Discussion do
@moduledoc """
Insert a discussion activity
"""
alias Mobilizon.Actors
alias Mobilizon.Discussions.Discussion
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(discussion, options \\ [])
def insert_activity(
%Discussion{creator_id: creator_id, actor_id: actor_id} = discussion,
options
)
when not is_nil(creator_id) do
creator = Actors.get_actor(creator_id)
group = Actors.get_actor(actor_id)
subject = Keyword.fetch!(options, :subject)
author = Keyword.get(options, :moderator, creator)
author_id = Keyword.get(options, :actor_id, author.id)
old_discussion = Keyword.get(options, :old_discussion)
ActivityBuilder.enqueue(:build_activity, %{
"type" => "discussion",
"subject" => subject,
"subject_params" => subject_params(discussion, subject, old_discussion),
"group_id" => group.id,
"author_id" => author_id,
"object_type" => "discussion",
"object_id" => if(subject != "discussion_deleted", do: to_string(discussion.id), else: nil),
"inserted_at" => DateTime.utc_now()
})
end
def insert_activity(_, _), do: {:ok, nil}
@spec subject_params(Discussion.t(), String.t() | nil, Discussion.t() | nil) :: map()
defp subject_params(%Discussion{} = discussion, "discussion_renamed", old_discussion) do
discussion
|> subject_params(nil, nil)
|> Map.put(:old_discussion_title, old_discussion.title)
end
defp subject_params(%Discussion{} = discussion, _, _) do
%{discussion_slug: discussion.slug, discussion_title: discussion.title}
end
end

View File

@@ -0,0 +1,39 @@
defmodule Mobilizon.Service.Activity.Event do
@moduledoc """
Insert an event activity
"""
alias Mobilizon.Actors
alias Mobilizon.Events.Event
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(event, options \\ [])
def insert_activity(
%Event{attributed_to_id: attributed_to_id, organizer_actor_id: organizer_actor_id} =
event,
options
)
when not is_nil(attributed_to_id) do
actor = Actors.get_actor(organizer_actor_id)
group = Actors.get_actor(attributed_to_id)
subject = Keyword.fetch!(options, :subject)
ActivityBuilder.enqueue(:build_activity, %{
"type" => "event",
"subject" => subject,
"subject_params" => %{event_uuid: event.uuid, event_title: event.title},
"group_id" => group.id,
"author_id" => actor.id,
"object_type" => "event",
"object_id" => if(subject != "event_deleted", do: to_string(event.id), else: nil),
"inserted_at" => DateTime.utc_now()
})
end
@impl Activity
def insert_activity(_, _), do: {:ok, nil}
end

View File

@@ -0,0 +1,150 @@
defmodule Mobilizon.Service.Activity.Group do
@moduledoc """
Insert a group setting activity
"""
alias Mobilizon.Actors
alias Mobilizon.Actors.Actor
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(group, options \\ [])
def insert_activity(
%Actor{type: :Group, id: group_id},
options
) do
with %Actor{type: :Group} = group <- Actors.get_actor(group_id),
subject when not is_nil(subject) <- Keyword.get(options, :subject),
actor_id <- Keyword.get(options, :actor_id),
default_updater_actor <- Actors.get_actor(actor_id),
%Actor{id: actor_id} <-
Keyword.get(options, :updater_actor, default_updater_actor),
old_group <- Keyword.get(options, :old_group) do
ActivityBuilder.enqueue(:build_activity, %{
"type" => "group",
"subject" => subject,
"subject_params" => subject_params(group, subject, old_group),
"group_id" => group.id,
"author_id" => actor_id,
"object_type" => "group",
"object_id" => to_string(group.id),
"inserted_at" => DateTime.utc_now()
})
else
_ -> {:ok, nil}
end
end
def insert_activity(_, _), do: {:ok, nil}
@spec subject_params(Actor.t(), String.t() | nil, Actor.t() | nil) :: map()
defp subject_params(%Actor{} = group, "group_updated", %Actor{} = old_group) do
group
|> subject_params(nil, nil)
|> maybe_put_old_name_if_updated(old_group.name, group.name)
|> maybe_put_summary_change_if_updated(old_group.summary, group.summary)
|> maybe_put_old_visibility_if_updated(old_group.visibility, group.visibility)
|> maybe_put_old_openness_if_updated(old_group.openness, group.openness)
|> maybe_put_address_change_if_updated(
old_group.physical_address_id,
group.physical_address_id
)
|> maybe_put_avatar_change_if_updated(
old_group.avatar,
group.avatar
)
|> maybe_put_banner_change_if_updated(
old_group.banner,
group.banner
)
|> maybe_put_manually_approves_followers_change_if_updated(
old_group.manually_approves_followers,
group.manually_approves_followers
)
end
defp subject_params(
%Actor{preferred_username: preferred_username, domain: domain, name: name},
_,
_
) do
%{
group_preferred_username: preferred_username,
group_name: name,
group_domain: domain,
group_changes: []
}
end
@spec maybe_put_old_name_if_updated(map(), String.t(), String.t()) :: map()
defp maybe_put_old_name_if_updated(params, old_group_name, new_group_name)
when old_group_name != new_group_name do
params
|> Map.update(:group_changes, [], fn changes -> changes ++ [:name] end)
|> Map.put(:old_group_name, old_group_name)
end
defp maybe_put_old_name_if_updated(params, _, _), do: params
defp maybe_put_summary_change_if_updated(params, old_summary, new_summary)
when old_summary != new_summary do
Map.update(params, :group_changes, [], fn changes -> changes ++ [:summary] end)
end
defp maybe_put_summary_change_if_updated(params, _, _), do: params
defp maybe_put_old_visibility_if_updated(params, old_group_visibility, new_group_visibility)
when old_group_visibility != new_group_visibility do
params
|> Map.update(:group_changes, [], fn changes -> changes ++ [:visibility] end)
|> Map.put(:old_group_visibility, old_group_visibility)
end
defp maybe_put_old_visibility_if_updated(params, _, _), do: params
defp maybe_put_old_openness_if_updated(params, old_group_openness, new_group_openness)
when old_group_openness != new_group_openness do
params
|> Map.update(:group_changes, [], fn changes -> changes ++ [:openness] end)
|> Map.put(:old_group_openness, old_group_openness)
end
defp maybe_put_old_openness_if_updated(params, _, _), do: params
defp maybe_put_address_change_if_updated(params, old_address_id, new_address_id)
when old_address_id != new_address_id do
Map.update(params, :group_changes, [], fn changes -> changes ++ [:address] end)
end
defp maybe_put_address_change_if_updated(params, _, _), do: params
defp maybe_put_avatar_change_if_updated(params, old_avatar, new_avatar)
when old_avatar != new_avatar do
Map.update(params, :group_changes, [], fn changes -> changes ++ [:avatar] end)
end
defp maybe_put_avatar_change_if_updated(params, _, _), do: params
defp maybe_put_banner_change_if_updated(params, old_banner, new_banner)
when old_banner != new_banner do
Map.update(params, :group_changes, [], fn changes -> changes ++ [:banner] end)
end
defp maybe_put_banner_change_if_updated(params, _, _), do: params
defp maybe_put_manually_approves_followers_change_if_updated(
params,
old_group_manually_approves_followers,
new_group_manually_approves_followers
)
when old_group_manually_approves_followers != new_group_manually_approves_followers do
params
|> Map.update(:group_changes, [], fn changes -> changes ++ [:manually_approves_followers] end)
|> Map.put(:old_group_manually_approves_followers, old_group_manually_approves_followers)
end
defp maybe_put_manually_approves_followers_change_if_updated(params, _, _), do: params
end

View File

@@ -0,0 +1,97 @@
defmodule Mobilizon.Service.Activity.Member do
@moduledoc """
Insert a member activity
"""
alias Mobilizon.Actors
alias Mobilizon.Actors.{Actor, Member}
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(member, options \\ [])
def insert_activity(
%Member{parent_id: parent_id, id: member_id} = new_member,
options
) do
subject = Keyword.get(options, :subject)
with author_id <- get_author(new_member, options),
object_id <- if(subject == "member_removed", do: nil, else: to_string(member_id)) do
ActivityBuilder.enqueue(:build_activity, %{
"type" => "member",
"subject" => subject,
"subject_params" => get_subject_params(new_member, options),
"group_id" => parent_id,
"author_id" => author_id,
"object_type" => "member",
"object_id" => object_id,
"inserted_at" => DateTime.utc_now()
})
end
end
def insert_activity(_, _), do: {:ok, nil}
@spec get_author(Member.t(), Member.t() | nil) :: String.t() | integer()
defp get_author(%Member{actor_id: actor_id}, options) do
moderator = Keyword.get(options, :moderator)
if is_nil(moderator) do
actor_id
else
moderator.id
end
end
@spec get_subject_params(Member.t(), Keyword.t()) :: map()
defp get_subject_params(%Member{actor: actor, role: role, id: member_id}, options) do
# We may need to preload the member to make sure the actor exists
actor =
case actor do
%Actor{} = actor ->
actor
_ ->
case Actors.get_member(member_id) do
%Member{actor: actor} -> actor
_ -> nil
end
end
moderator = Keyword.get(options, :moderator)
old_member = Keyword.get(options, :old_member)
subject_params = %{
member_role: String.upcase(to_string(role))
}
subject_params =
if(is_nil(actor),
do: subject_params,
else:
Map.put(
subject_params,
:member_preferred_username,
Actor.preferred_username_and_domain(actor)
)
)
subject_params =
if(is_nil(old_member),
do: subject_params,
else: Map.put(subject_params, :old_role, String.upcase(to_string(old_member.role)))
)
if is_nil(moderator),
do: subject_params,
else:
Map.put(
subject_params,
:moderator_preferred_username,
Actor.preferred_username_and_domain(moderator)
)
end
end

View File

@@ -0,0 +1,37 @@
defmodule Mobilizon.Service.Activity.Post do
@moduledoc """
Insert an post activity
"""
alias Mobilizon.Actors
alias Mobilizon.Posts.Post
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(post, options \\ [])
def insert_activity(
%Post{attributed_to_id: attributed_to_id, author_id: author_id} = post,
options
)
when not is_nil(attributed_to_id) do
author = Actors.get_actor(author_id)
group = Actors.get_actor(attributed_to_id)
subject = Keyword.fetch!(options, :subject)
ActivityBuilder.enqueue(:build_activity, %{
"type" => "post",
"subject" => subject,
"subject_params" => %{post_slug: post.slug, post_title: post.title},
"group_id" => group.id,
"author_id" => author.id,
"object_type" => "post",
"object_id" => if(subject != "post_deleted", do: to_string(post.id), else: nil),
"inserted_at" => DateTime.utc_now()
})
end
def insert_activity(_, _), do: {:ok, nil}
end

View File

@@ -0,0 +1,50 @@
defmodule Mobilizon.Service.Activity.Resource do
@moduledoc """
Insert an resource activity
"""
alias Mobilizon.Actors
alias Mobilizon.Resources.Resource
alias Mobilizon.Service.Activity
alias Mobilizon.Service.Workers.ActivityBuilder
@behaviour Activity
@impl Activity
def insert_activity(resource, options \\ [])
def insert_activity(
%Resource{actor_id: actor_id, creator_id: creator_id} = resource,
options
)
when not is_nil(actor_id) do
actor = Actors.get_actor(creator_id)
group = Actors.get_actor(actor_id)
subject = Keyword.fetch!(options, :subject)
old_resource = Keyword.get(options, :old_resource)
ActivityBuilder.enqueue(:build_activity, %{
"type" => "resource",
"subject" => subject,
"subject_params" => subject_params(resource, subject, old_resource),
"group_id" => group.id,
"author_id" => actor.id,
"object_type" => "resource",
"object_id" => if(subject != "resource_deleted", do: to_string(resource.id), else: nil),
"inserted_at" => DateTime.utc_now()
})
end
@impl Activity
def insert_activity(_, _), do: {:ok, nil}
@spec subject_params(Resource.t(), String.t() | nil, Resource.t() | nil) :: map()
defp subject_params(%Resource{} = resource, "resource_renamed", old_resource) do
resource
|> subject_params(nil, nil)
|> Map.put(:old_resource_title, old_resource.title)
end
defp subject_params(%Resource{path: path, title: title}, _, _) do
%{resource_path: path, resource_title: title}
end
end

View File

@@ -0,0 +1,22 @@
defmodule Mobilizon.Service.Workers.ActivityBuilder do
@moduledoc """
Worker to insert activity items in users feeds
"""
alias Mobilizon.Activities
alias Mobilizon.Activities.Activity
use Mobilizon.Service.Workers.Helper, queue: "activity"
@impl Oban.Worker
def perform(%Job{args: args}) do
with {"build_activity", args} <- Map.pop(args, "op") do
build_activity(args)
end
end
@spec build_activity(map()) :: {:ok, Activity.t()}
def build_activity(args) do
Activities.create_activity(args)
end
end