Remove credo and use mix format, and lint everything

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2018-07-27 10:45:35 +02:00
parent df3f08c528
commit 979aad5acb
104 changed files with 2278 additions and 1487 deletions

View File

@@ -27,12 +27,13 @@ defmodule Eventos.Service.ActivityPub do
with map <- lazy_put_activity_defaults(map),
:ok <- insert_full_object(map) do
map = Map.put(map, "id", Ecto.UUID.generate())
activity = %Activity{
data: map,
local: local,
actor: map["actor"],
recipients: get_recipients(map)
}
data: map,
local: local,
actor: map["actor"],
recipients: get_recipients(map)
}
# Notification.create_notifications(activity)
# stream_out(activity)
@@ -71,7 +72,7 @@ defmodule Eventos.Service.ActivityPub do
{:ok, Events.get_event_by_url!(activity.data["object"]["id"])}
else
object = %Event{} -> {:ok, object}
e -> e
e -> e
end
end
end
@@ -89,12 +90,12 @@ defmodule Eventos.Service.ActivityPub do
),
{:ok, activity} <- insert(create_data, local),
:ok <- maybe_federate(activity) do
# {:ok, actor} <- Actors.increase_event_count(actor) do
# {:ok, actor} <- Actors.increase_event_count(actor) do
{:ok, activity}
else
err ->
Logger.debug("Something went wrong")
Logger.debug(inspect err)
Logger.debug(inspect(err))
end
end
@@ -114,12 +115,12 @@ defmodule Eventos.Service.ActivityPub do
local = !(params[:local] == false)
with data <- %{
"to" => to,
"cc" => cc,
"type" => "Update",
"actor" => actor,
"object" => object
},
"to" => to,
"cc" => cc,
"type" => "Update",
"actor" => actor,
"object" => object
},
{:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity) do
{:ok, activity}
@@ -135,7 +136,6 @@ defmodule Eventos.Service.ActivityPub do
end
def delete(%Event{url: url, organizer_actor: actor} = event, local \\ true) do
data = %{
"type" => "Delete",
"actor" => actor.url,
@@ -145,14 +145,12 @@ defmodule Eventos.Service.ActivityPub do
with Events.delete_event(event),
{:ok, activity} <- insert(data, local),
:ok <- maybe_federate(activity)
do
:ok <- maybe_federate(activity) do
{:ok, activity}
end
end
def create_public_activities(%Actor{} = actor) do
end
def make_actor_from_url(url) do
@@ -161,12 +159,12 @@ defmodule Eventos.Service.ActivityPub do
else
e ->
Logger.error("Failed to make actor from url")
Logger.error(inspect e)
Logger.error(inspect(e))
{:error, e}
end
end
@spec find_or_make_actor_from_nickname(String.t) :: tuple()
@spec find_or_make_actor_from_nickname(String.t()) :: tuple()
def find_or_make_actor_from_nickname(nickname) do
with %Actor{} = actor <- Actors.get_actor_by_name(nickname) do
{:ok, actor}
@@ -185,6 +183,7 @@ defmodule Eventos.Service.ActivityPub do
def publish(actor, activity) do
Logger.debug("Publishing an activity")
followers =
if actor.followers_url in activity.recipients do
{:ok, followers} = Actor.get_followers(actor)
@@ -217,22 +216,26 @@ defmodule Eventos.Service.ActivityPub do
signature =
Eventos.Service.HTTPSignatures.sign(actor, %{host: host, "content-length": byte_size(json)})
Logger.debug("signature")
Logger.debug(inspect signature)
{:ok, response} = HTTPoison.post(
inbox,
json,
[{"Content-Type", "application/activity+json"}, {"signature", signature}],
hackney: [pool: :default]
)
Logger.debug(inspect response)
Logger.debug("signature")
Logger.debug(inspect(signature))
{:ok, response} =
HTTPoison.post(
inbox,
json,
[{"Content-Type", "application/activity+json"}, {"signature", signature}],
hackney: [pool: :default]
)
Logger.debug(inspect(response))
end
def fetch_and_prepare_user_from_url(url) do
Logger.debug("Fetching and preparing user from url")
with {:ok, %{status_code: 200, body: body}} <-
HTTPoison.get(url, [Accept: "application/activity+json"], [follow_redirect: true]),
HTTPoison.get(url, [Accept: "application/activity+json"], follow_redirect: true),
{:ok, data} <- Jason.decode(body) do
user_data_from_user_object(data)
else
@@ -241,17 +244,18 @@ defmodule Eventos.Service.ActivityPub do
end
def user_data_from_user_object(data) do
name = if String.trim(data["name"]) === "" do
data["preferredUsername"]
else
data["name"]
end
name =
if String.trim(data["name"]) === "" do
data["preferredUsername"]
else
data["name"]
end
user_data = %{
url: data["id"],
info: %{
"ap_enabled" => true,
"source_data" => data,
"source_data" => data
},
avatar_url: data["icon"]["url"],
banner_url: data["image"]["url"],
@@ -267,38 +271,50 @@ defmodule Eventos.Service.ActivityPub do
shared_inbox_url: data["endpoints"]["sharedInbox"],
domain: URI.parse(data["id"]).host,
manually_approves_followers: data["manuallyApprovesFollowers"],
type: data["type"],
type: data["type"]
}
Logger.debug("user_data_from_user_object")
Logger.debug(inspect user_data)
Logger.debug(inspect(user_data))
{:ok, user_data}
end
@spec fetch_public_activities_for_actor(Actor.t, integer(), integer()) :: list()
@spec fetch_public_activities_for_actor(Actor.t(), integer(), integer()) :: list()
def fetch_public_activities_for_actor(%Actor{} = actor, page \\ 1, limit \\ 10) do
case actor.type do
:Person ->
{:ok, events, total} = Events.get_events_for_actor(actor, page, limit)
activities = Enum.map(events, fn event ->
{:ok, activity} = event_to_activity(event)
activity
end)
activities =
Enum.map(events, fn event ->
{:ok, activity} = event_to_activity(event)
activity
end)
{activities, total}
:Service ->
bot = Actors.get_bot_by_actor(actor)
case bot.type do
"ics" ->
{:ok, %HTTPoison.Response{body: body} = _resp} = HTTPoison.get(bot.source)
ical_events = body |> ExIcal.parse() |> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
activities = ical_events
|> Enum.chunk_every(limit)
|> Enum.at(page - 1)
|> Enum.map(fn event ->
{:ok, activity} = ical_event_to_activity(event, actor, bot.source)
activity
end)
ical_events =
body
|> ExIcal.parse()
|> ExIcal.by_range(DateTime.utc_now(), DateTime.utc_now() |> Timex.shift(years: 1))
activities =
ical_events
|> Enum.chunk_every(limit)
|> Enum.at(page - 1)
|> Enum.map(fn event ->
{:ok, activity} = ical_event_to_activity(event, actor, bot.source)
activity
end)
{activities, length(ical_events)}
end
end
@@ -313,36 +329,42 @@ defmodule Eventos.Service.ActivityPub do
}
# Notification.create_notifications(activity)
#stream_out(activity)
# stream_out(activity)
{:ok, activity}
end
defp ical_event_to_activity(%ExIcal.Event{} = ical_event, %Actor{} = actor, source) do
# Logger.debug(inspect ical_event)
# TODO : refactor me !
category = if is_nil ical_event.categories do
nil
else
ical_category = ical_event.categories |> hd() |> String.downcase()
case ical_category |> Events.get_category_by_title() do
nil -> case Events.create_category(%{"title" => ical_category}) do
{:ok, %Category{} = category} -> category
_ -> nil
end
category -> category
end
end
category =
if is_nil(ical_event.categories) do
nil
else
ical_category = ical_event.categories |> hd() |> String.downcase()
{:ok, event} = Events.create_event(%{
begins_on: ical_event.start,
ends_on: ical_event.end,
inserted_at: ical_event.stamp,
updated_at: ical_event.stamp,
description: ical_event.description |> sanitize_ical_event_strings,
title: ical_event.summary |> sanitize_ical_event_strings,
organizer_actor: actor,
category: category,
})
case ical_category |> Events.get_category_by_title() do
nil ->
case Events.create_category(%{"title" => ical_category}) do
{:ok, %Category{} = category} -> category
_ -> nil
end
category ->
category
end
end
{:ok, event} =
Events.create_event(%{
begins_on: ical_event.start,
ends_on: ical_event.end,
inserted_at: ical_event.stamp,
updated_at: ical_event.stamp,
description: ical_event.description |> sanitize_ical_event_strings,
title: ical_event.summary |> sanitize_ical_event_strings,
organizer_actor: actor,
category: category
})
event_to_activity(event, false)
end

View File

@@ -19,28 +19,28 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
|> Map.put("actor", object["attributedTo"])
|> fix_attachments
|> fix_context
#|> fix_in_reply_to
# |> fix_in_reply_to
|> fix_tag
end
# def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
# when not is_nil(in_reply_to_id) do
# case ActivityPub.fetch_object_from_id(in_reply_to_id) do
# {:ok, replied_object} ->
# activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"])
#
# object
# |> Map.put("inReplyTo", replied_object.data["id"])
# |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
# |> Map.put("inReplyToStatusId", activity.id)
# |> Map.put("conversation", replied_object.data["context"] || object["conversation"])
# |> Map.put("context", replied_object.data["context"] || object["conversation"])
#
# e ->
# Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
# object
# end
# end
# def fix_in_reply_to(%{"inReplyTo" => in_reply_to_id} = object)
# when not is_nil(in_reply_to_id) do
# case ActivityPub.fetch_object_from_id(in_reply_to_id) do
# {:ok, replied_object} ->
# activity = Activity.get_create_activity_by_object_ap_id(replied_object.data["id"])
#
# object
# |> Map.put("inReplyTo", replied_object.data["id"])
# |> Map.put("inReplyToAtomUri", object["inReplyToAtomUri"] || in_reply_to_id)
# |> Map.put("inReplyToStatusId", activity.id)
# |> Map.put("conversation", replied_object.data["context"] || object["conversation"])
# |> Map.put("context", replied_object.data["context"] || object["conversation"])
#
# e ->
# Logger.error("Couldn't fetch #{object["inReplyTo"]} #{inspect(e)}")
# object
# end
# end
def fix_in_reply_to(object), do: object
@@ -78,6 +78,7 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
# - emoji
def handle_incoming(%{"type" => "Create", "object" => %{"type" => "Note"} = object} = data) do
Logger.debug("Handle incoming to create notes")
with %Actor{} = actor <- Actor.get_or_fetch_by_url(data["actor"]) do
Logger.debug("found actor")
object = fix_object(data["object"])
@@ -100,32 +101,35 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
end
end
def handle_incoming(%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data) do
def handle_incoming(
%{"type" => "Follow", "object" => followed, "actor" => follower, "id" => id} = data
) do
with %Actor{} = followed <- Actors.get_actor_by_url(followed),
%Actor{} = follower <- Actors.get_or_fetch_by_url(follower),
{:ok, activity} <- ActivityPub.follow(follower, followed, id, false) do
ActivityPub.accept(%{to: [follower.url], actor: followed.url, object: data, local: true})
#Actors.follow(follower, followed)
# Actors.follow(follower, followed)
{:ok, activity}
else
_e -> :error
end
end
#
# def handle_incoming(
# %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data
# ) do
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# {:ok, object} <-
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity, object} <- ActivityPub.like(actor, object, id, false) do
# {:ok, activity}
# else
# _e -> :error
# end
# end
#
#
# def handle_incoming(
# %{"type" => "Like", "object" => object_id, "actor" => actor, "id" => id} = data
# ) do
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# {:ok, object} <-
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity, object} <- ActivityPub.like(actor, object, id, false) do
# {:ok, activity}
# else
# _e -> :error
# end
# end
#
def handle_incoming(
%{"type" => "Announce", "object" => object_id, "actor" => actor, "id" => id} = data
) do
@@ -138,63 +142,64 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
_e -> :error
end
end
#
# def handle_incoming(
# %{"type" => "Update", "object" => %{"type" => "Person"} = object, "actor" => actor_id} =
# data
# ) do
# with %User{ap_id: ^actor_id} = actor <- User.get_by_ap_id(object["id"]) do
# {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
#
# banner = new_user_data[:info]["banner"]
#
# update_data =
# new_user_data
# |> Map.take([:name, :bio, :avatar])
# |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner}))
#
# actor
# |> User.upgrade_changeset(update_data)
# |> User.update_and_set_cache()
#
# ActivityPub.update(%{
# local: false,
# to: data["to"] || [],
# cc: data["cc"] || [],
# object: object,
# actor: actor_id
# })
# else
# e ->
# Logger.error(e)
# :error
# end
# end
#
# # TODO: Make secure.
# def handle_incoming(
# %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data
# ) do
# object_id =
# case object_id do
# %{"id" => id} -> id
# id -> id
# end
#
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# {:ok, object} <-
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity} <- ActivityPub.delete(object, false) do
# {:ok, activity}
# else
# e -> :error
# end
# end
#
# # TODO
# # Accept
# # Undo
#
#
# def handle_incoming(
# %{"type" => "Update", "object" => %{"type" => "Person"} = object, "actor" => actor_id} =
# data
# ) do
# with %User{ap_id: ^actor_id} = actor <- User.get_by_ap_id(object["id"]) do
# {:ok, new_user_data} = ActivityPub.user_data_from_user_object(object)
#
# banner = new_user_data[:info]["banner"]
#
# update_data =
# new_user_data
# |> Map.take([:name, :bio, :avatar])
# |> Map.put(:info, Map.merge(actor.info, %{"banner" => banner}))
#
# actor
# |> User.upgrade_changeset(update_data)
# |> User.update_and_set_cache()
#
# ActivityPub.update(%{
# local: false,
# to: data["to"] || [],
# cc: data["cc"] || [],
# object: object,
# actor: actor_id
# })
# else
# e ->
# Logger.error(e)
# :error
# end
# end
#
# # TODO: Make secure.
# def handle_incoming(
# %{"type" => "Delete", "object" => object_id, "actor" => actor, "id" => id} = data
# ) do
# object_id =
# case object_id do
# %{"id" => id} -> id
# id -> id
# end
#
# with %User{} = actor <- User.get_or_fetch_by_ap_id(actor),
# {:ok, object} <-
# get_obj_helper(object_id) || ActivityPub.fetch_object_from_id(object_id),
# {:ok, activity} <- ActivityPub.delete(object, false) do
# {:ok, activity}
# else
# e -> :error
# end
# end
#
# # TODO
# # Accept
# # Undo
#
def handle_incoming(_), do: :error
def get_obj_helper(id) do
@@ -211,16 +216,16 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
end
def set_reply_to_uri(obj), do: obj
#
# # Prepares the object of an outgoing create activity.
#
# # Prepares the object of an outgoing create activity.
def prepare_object(object) do
object
# |> set_sensitive
# |> add_hashtags
# |> add_mention_tags
# |> add_emoji_tags
# |> set_sensitive
# |> add_hashtags
# |> add_mention_tags
# |> add_emoji_tags
|> add_attributed_to
# |> prepare_attachments
# |> prepare_attachments
|> set_conversation
|> set_reply_to_uri
end
@@ -246,7 +251,7 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
def prepare_outgoing(%{"type" => type} = data) do
data =
data
#|> maybe_fix_object_url
# |> maybe_fix_object_url
|> Map.put("@context", "https://www.w3.org/ns/activitystreams")
{:ok, data}
@@ -255,177 +260,180 @@ defmodule Eventos.Service.ActivityPub.Transmogrifier do
def prepare_outgoing(%Event{} = event) do
event =
event
|> Map.from_struct
|> Map.drop([:"__meta__"])
|> Map.from_struct()
|> Map.drop([:__meta__])
|> Map.put(:"@context", "https://www.w3.org/ns/activitystreams")
|> prepare_object
{:ok, event}
end
#
# def maybe_fix_object_url(data) do
# if is_binary(data["object"]) and not String.starts_with?(data["object"], "http") do
# case ActivityPub.fetch_object_from_id(data["object"]) do
# {:ok, relative_object} ->
# if relative_object.data["external_url"] do
# data =
# data
# |> Map.put("object", relative_object.data["external_url"])
# else
# data
# end
#
# e ->
# Logger.error("Couldn't fetch #{data["object"]} #{inspect(e)}")
# data
# end
# else
# data
# end
# end
#
# def add_mention_tags(object) do
# recipients = object["to"] ++ (object["cc"] || [])
#
# mentions =
# recipients
# |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
# |> Enum.filter(& &1)
# |> Enum.map(fn user ->
# %{"type" => "Mention", "href" => user.ap_id, "name" => "@#{user.nickname}"}
# end)
#
# tags = object["tag"] || []
#
# object
# |> Map.put("tag", tags ++ mentions)
# end
#
# # TODO: we should probably send mtime instead of unix epoch time for updated
# def add_emoji_tags(object) do
# tags = object["tag"] || []
# emoji = object["emoji"] || []
#
# out =
# emoji
# |> Enum.map(fn {name, url} ->
# %{
# "icon" => %{"url" => url, "type" => "Image"},
# "name" => ":" <> name <> ":",
# "type" => "Emoji",
# "updated" => "1970-01-01T00:00:00Z",
# "id" => url
# }
# end)
#
# object
# |> Map.put("tag", tags ++ out)
# end
#
#
# def maybe_fix_object_url(data) do
# if is_binary(data["object"]) and not String.starts_with?(data["object"], "http") do
# case ActivityPub.fetch_object_from_id(data["object"]) do
# {:ok, relative_object} ->
# if relative_object.data["external_url"] do
# data =
# data
# |> Map.put("object", relative_object.data["external_url"])
# else
# data
# end
#
# e ->
# Logger.error("Couldn't fetch #{data["object"]} #{inspect(e)}")
# data
# end
# else
# data
# end
# end
#
# def add_mention_tags(object) do
# recipients = object["to"] ++ (object["cc"] || [])
#
# mentions =
# recipients
# |> Enum.map(fn ap_id -> User.get_cached_by_ap_id(ap_id) end)
# |> Enum.filter(& &1)
# |> Enum.map(fn user ->
# %{"type" => "Mention", "href" => user.ap_id, "name" => "@#{user.nickname}"}
# end)
#
# tags = object["tag"] || []
#
# object
# |> Map.put("tag", tags ++ mentions)
# end
#
# # TODO: we should probably send mtime instead of unix epoch time for updated
# def add_emoji_tags(object) do
# tags = object["tag"] || []
# emoji = object["emoji"] || []
#
# out =
# emoji
# |> Enum.map(fn {name, url} ->
# %{
# "icon" => %{"url" => url, "type" => "Image"},
# "name" => ":" <> name <> ":",
# "type" => "Emoji",
# "updated" => "1970-01-01T00:00:00Z",
# "id" => url
# }
# end)
#
# object
# |> Map.put("tag", tags ++ out)
# end
#
def set_conversation(object) do
Map.put(object, "conversation", object["context"])
end
#
# def set_sensitive(object) do
# tags = object["tag"] || []
# Map.put(object, "sensitive", "nsfw" in tags)
# end
#
#
# def set_sensitive(object) do
# tags = object["tag"] || []
# Map.put(object, "sensitive", "nsfw" in tags)
# end
#
def add_attributed_to(object) do
attributed_to = object["attributedTo"] || object["actor"]
object |> Map.put("attributedTo", attributed_to)
end
#
# def prepare_attachments(object) do
# attachments =
# (object["attachment"] || [])
# |> Enum.map(fn data ->
# [%{"mediaType" => media_type, "href" => href} | _] = data["url"]
# %{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"}
# end)
#
# object
# |> Map.put("attachment", attachments)
# end
#
# defp user_upgrade_task(user) do
# old_follower_address = User.ap_followers(user)
#
# q =
# from(
# u in User,
# where: ^old_follower_address in u.following,
# update: [
# set: [
# following:
# fragment(
# "array_replace(?,?,?)",
# u.following,
# ^old_follower_address,
# ^user.follower_address
# )
# ]
# ]
# )
#
# Repo.update_all(q, [])
#
# maybe_retire_websub(user.ap_id)
#
# # Only do this for recent activties, don't go through the whole db.
# # Only look at the last 1000 activities.
# since = (Repo.aggregate(Activity, :max, :id) || 0) - 1_000
#
# q =
# from(
# a in Activity,
# where: ^old_follower_address in a.recipients,
# where: a.id > ^since,
# update: [
# set: [
# recipients:
# fragment(
# "array_replace(?,?,?)",
# a.recipients,
# ^old_follower_address,
# ^user.follower_address
# )
# ]
# ]
# )
#
# Repo.update_all(q, [])
# end
#
# def upgrade_user_from_ap_id(ap_id, async \\ true) do
# with %User{local: false} = user <- User.get_by_ap_id(ap_id),
# {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do
# data =
# data
# |> Map.put(:info, Map.merge(user.info, data[:info]))
#
# already_ap = User.ap_enabled?(user)
#
# {:ok, user} =
# User.upgrade_changeset(user, data)
# |> Repo.update()
#
# if !already_ap do
# # This could potentially take a long time, do it in the background
# if async do
# Task.start(fn ->
# user_upgrade_task(user)
# end)
# else
# user_upgrade_task(user)
# end
# end
#
# {:ok, user}
# else
# e -> e
# end
# end
#
#
# def prepare_attachments(object) do
# attachments =
# (object["attachment"] || [])
# |> Enum.map(fn data ->
# [%{"mediaType" => media_type, "href" => href} | _] = data["url"]
# %{"url" => href, "mediaType" => media_type, "name" => data["name"], "type" => "Document"}
# end)
#
# object
# |> Map.put("attachment", attachments)
# end
#
# defp user_upgrade_task(user) do
# old_follower_address = User.ap_followers(user)
#
# q =
# from(
# u in User,
# where: ^old_follower_address in u.following,
# update: [
# set: [
# following:
# fragment(
# "array_replace(?,?,?)",
# u.following,
# ^old_follower_address,
# ^user.follower_address
# )
# ]
# ]
# )
#
# Repo.update_all(q, [])
#
# maybe_retire_websub(user.ap_id)
#
# # Only do this for recent activties, don't go through the whole db.
# # Only look at the last 1000 activities.
# since = (Repo.aggregate(Activity, :max, :id) || 0) - 1_000
#
# q =
# from(
# a in Activity,
# where: ^old_follower_address in a.recipients,
# where: a.id > ^since,
# update: [
# set: [
# recipients:
# fragment(
# "array_replace(?,?,?)",
# a.recipients,
# ^old_follower_address,
# ^user.follower_address
# )
# ]
# ]
# )
#
# Repo.update_all(q, [])
# end
#
# def upgrade_user_from_ap_id(ap_id, async \\ true) do
# with %User{local: false} = user <- User.get_by_ap_id(ap_id),
# {:ok, data} <- ActivityPub.fetch_and_prepare_user_from_ap_id(ap_id) do
# data =
# data
# |> Map.put(:info, Map.merge(user.info, data[:info]))
#
# already_ap = User.ap_enabled?(user)
#
# {:ok, user} =
# User.upgrade_changeset(user, data)
# |> Repo.update()
#
# if !already_ap do
# # This could potentially take a long time, do it in the background
# if async do
# Task.start(fn ->
# user_upgrade_task(user)
# end)
# else
# user_upgrade_task(user)
# end
# end
#
# {:ok, user}
# else
# e -> e
# end
# end
#
end

View File

@@ -44,28 +44,28 @@ defmodule Eventos.Service.ActivityPub.Utils do
generate_id("contexts")
end
# def generate_object_id do
# Helpers.o_status_url(Endpoint, :object, UUID.generate())
# end
# def generate_object_id do
# Helpers.o_status_url(Endpoint, :object, UUID.generate())
# end
def generate_id(type) do
"#{EventosWeb.Endpoint.url()}/#{type}/#{UUID.generate()}"
end
# def create_context(context) do
# context = context || generate_id("contexts")
# changeset = Object.context_mapping(context)
#
# case Repo.insert(changeset) do
# {:ok, object} ->
# object
#
# # This should be solved by an upsert, but it seems ecto
# # has problems accessing the constraint inside the jsonb.
# {:error, _} ->
# Events.get_cached_by_url(context)
# end
# end
# def create_context(context) do
# context = context || generate_id("contexts")
# changeset = Object.context_mapping(context)
#
# case Repo.insert(changeset) do
# {:ok, object} ->
# object
#
# # This should be solved by an upsert, but it seems ecto
# # has problems accessing the constraint inside the jsonb.
# {:error, _} ->
# Events.get_cached_by_url(context)
# end
# end
@doc """
Enqueues an activity for federation if it's local
@@ -89,14 +89,14 @@ defmodule Eventos.Service.ActivityPub.Utils do
also adds it to an included object
"""
def lazy_put_activity_defaults(map) do
# %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
#
# map =
# map
# |> Map.put_new_lazy("id", &generate_activity_id/0)
# |> Map.put_new_lazy("published", &make_date/0)
# |> Map.put_new("context", context)
# |> Map.put_new("context_id", context_id)
# %{data: %{"id" => context}, id: context_id} = create_context(map["context"])
#
# map =
# map
# |> Map.put_new_lazy("id", &generate_activity_id/0)
# |> Map.put_new_lazy("published", &make_date/0)
# |> Map.put_new("context", context)
# |> Map.put_new("context_id", context_id)
if is_map(map["object"]) do
object = lazy_put_object_defaults(map["object"], map)
@@ -111,7 +111,7 @@ defmodule Eventos.Service.ActivityPub.Utils do
"""
def lazy_put_object_defaults(map, activity \\ %{}) do
map
#|> Map.put_new_lazy("id", &generate_object_id/0)
# |> Map.put_new_lazy("id", &generate_object_id/0)
|> Map.put_new_lazy("published", &make_date/0)
|> Map.put_new("context", activity["context"])
|> Map.put_new("context_id", activity["context_id"])
@@ -134,9 +134,16 @@ defmodule Eventos.Service.ActivityPub.Utils do
when is_map(object_data) and type == "Note" do
import Logger
Logger.debug("insert full object")
Logger.debug(inspect object_data)
Logger.debug(inspect(object_data))
actor = Actors.get_actor_by_url(object_data["actor"])
data = %{"text" => object_data["content"], "url" => object_data["id"], "actor_id" => actor.id, "in_reply_to_comment_id" => object_data["inReplyTo"]}
data = %{
"text" => object_data["content"],
"url" => object_data["id"],
"actor_id" => actor.id,
"in_reply_to_comment_id" => object_data["inReplyTo"]
}
with {:ok, _} <- Events.create_comment(data) do
:ok
end
@@ -144,43 +151,43 @@ defmodule Eventos.Service.ActivityPub.Utils do
def insert_full_object(_), do: :ok
# def update_object_in_activities(%{data: %{"id" => id}} = object) do
# # TODO
# # Update activities that already had this. Could be done in a seperate process.
# # Alternatively, just don't do this and fetch the current object each time. Most
# # could probably be taken from cache.
# relevant_activities = Activity.all_by_object_url(id)
#
# Enum.map(relevant_activities, fn activity ->
# new_activity_data = activity.data |> Map.put("object", object.data)
# changeset = Changeset.change(activity, data: new_activity_data)
# Repo.update(changeset)
# end)
# end
# def update_object_in_activities(%{data: %{"id" => id}} = object) do
# # TODO
# # Update activities that already had this. Could be done in a seperate process.
# # Alternatively, just don't do this and fetch the current object each time. Most
# # could probably be taken from cache.
# relevant_activities = Activity.all_by_object_url(id)
#
# Enum.map(relevant_activities, fn activity ->
# new_activity_data = activity.data |> Map.put("object", object.data)
# changeset = Changeset.change(activity, data: new_activity_data)
# Repo.update(changeset)
# end)
# end
#### Like-related helpers
# @doc """
# Returns an existing like if a user already liked an object
# """
# def get_existing_like(actor, %{data: %{"id" => id}}) do
# query =
# from(
# activity in Activity,
# where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
# # this is to use the index
# where:
# fragment(
# "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
# activity.data,
# activity.data,
# ^id
# ),
# where: fragment("(?)->>'type' = 'Like'", activity.data)
# )
#
# Repo.one(query)
# end
# @doc """
# Returns an existing like if a user already liked an object
# """
# def get_existing_like(actor, %{data: %{"id" => id}}) do
# query =
# from(
# activity in Activity,
# where: fragment("(?)->>'actor' = ?", activity.data, ^actor),
# # this is to use the index
# where:
# fragment(
# "coalesce((?)->'object'->>'id', (?)->>'object') = ?",
# activity.data,
# activity.data,
# ^id
# ),
# where: fragment("(?)->>'type' = 'Like'", activity.data)
# )
#
# Repo.one(query)
# end
def make_like_data(%Actor{url: url} = actor, %{data: %{"id" => id}} = object, activity_id) do
data = %{
@@ -206,21 +213,21 @@ defmodule Eventos.Service.ActivityPub.Utils do
end
end
# def update_likes_in_object(likes, object) do
# update_element_in_object("like", likes, object)
# end
#
# def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
# update_likes_in_object(likes, object)
# end
# end
#
# def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- (object.data["likes"] || []) |> List.delete(actor) do
# update_likes_in_object(likes, object)
# end
# end
# def update_likes_in_object(likes, object) do
# update_element_in_object("like", likes, object)
# end
#
# def add_like_to_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- [actor | object.data["likes"] || []] |> Enum.uniq() do
# update_likes_in_object(likes, object)
# end
# end
#
# def remove_like_from_object(%Activity{data: %{"actor" => actor}}, object) do
# with likes <- (object.data["likes"] || []) |> List.delete(actor) do
# update_likes_in_object(likes, object)
# end
# end
#### Follow-related helpers
@@ -239,22 +246,22 @@ defmodule Eventos.Service.ActivityPub.Utils do
if activity_id, do: Map.put(data, "id", activity_id), else: data
end
# def fetch_latest_follow(%Actor{url: follower_id}, %Actor{url: followed_id}) do
# query =
# from(
# activity in Activity,
# where:
# fragment(
# "? @> ?",
# activity.data,
# ^%{type: "Follow", actor: follower_id, object: followed_id}
# ),
# order_by: [desc: :id],
# limit: 1
# )
#
# Repo.one(query)
# end
# def fetch_latest_follow(%Actor{url: follower_id}, %Actor{url: followed_id}) do
# query =
# from(
# activity in Activity,
# where:
# fragment(
# "? @> ?",
# activity.data,
# ^%{type: "Follow", actor: follower_id, object: followed_id}
# ),
# order_by: [desc: :id],
# limit: 1
# )
#
# Repo.one(query)
# end
#### Announce-related helpers

View File

@@ -17,7 +17,6 @@ defmodule Eventos.Service.Federator do
end
def start_link do
spawn(fn ->
# 1 minute
Process.sleep(1000 * 60)
@@ -34,11 +33,10 @@ defmodule Eventos.Service.Federator do
end
def handle(:publish, activity) do
Logger.debug(inspect activity)
Logger.debug(inspect(activity))
Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end)
with actor when not is_nil(actor) <- Actors.get_actor_by_url(activity.data["actor"]) do
Logger.info(fn -> "Sending #{activity.data["id"]} out via AP" end)
ActivityPub.publish(actor, activity)
end
@@ -46,7 +44,7 @@ defmodule Eventos.Service.Federator do
def handle(:incoming_ap_doc, params) do
Logger.info("Handling incoming AP activity")
Logger.debug(inspect params)
Logger.debug(inspect(params))
with {:ok, _activity} <- Transmogrifier.handle_incoming(params) do
else
@@ -71,6 +69,7 @@ defmodule Eventos.Service.Federator do
def enqueue(type, payload, priority \\ 1) do
Logger.debug("enqueue")
if Mix.env() == :test do
handle(type, payload)
else
@@ -105,9 +104,10 @@ defmodule Eventos.Service.Federator do
end
def handle_cast(m, state) do
Logger.error fn ->
Logger.error(fn ->
"Unknown: #{inspect(m)}, #{inspect(state)}"
end
end)
{:noreply, state}
end

View File

@@ -28,12 +28,15 @@ defmodule Eventos.Service.HTTPSignatures do
def validate(headers, signature, public_key) do
sigstring = build_signing_string(headers, signature["headers"])
Logger.debug fn ->
Logger.debug(fn ->
"Signature: #{signature["signature"]}"
end
Logger.debug fn ->
end)
Logger.debug(fn ->
"Sigstring: #{sigstring}"
end
end)
{:ok, sig} = Base.decode64(signature["signature"])
:public_key.verify(sigstring, :sha256, sig, public_key)
end
@@ -55,13 +58,13 @@ defmodule Eventos.Service.HTTPSignatures do
public_key_code <- Actor.get_public_key_for_url(actor_id),
[public_key] = :public_key.pem_decode(public_key_code),
public_key = :public_key.pem_entry_decode(public_key) do
validate_conn(conn, public_key)
validate_conn(conn, public_key)
end
end
else
e ->
Logger.debug("Could not found url for actor!")
Logger.debug(inspect e)
Logger.debug(inspect(e))
false
end
end

View File

@@ -58,9 +58,11 @@ defmodule Eventos.Service.Streamer do
sockets_for_topic = sockets[topic] || []
sockets_for_topic = Enum.uniq([socket | sockets_for_topic])
sockets = Map.put(sockets, topic, sockets_for_topic)
Logger.debug fn ->
Logger.debug(fn ->
"Got new conn for #{topic}"
end
end)
{:noreply, sockets}
end
@@ -69,9 +71,11 @@ defmodule Eventos.Service.Streamer do
sockets_for_topic = sockets[topic] || []
sockets_for_topic = List.delete(sockets_for_topic, socket)
sockets = Map.put(sockets, topic, sockets_for_topic)
Logger.debug fn ->
Logger.debug(fn ->
"Removed conn for #{topic}"
end
end)
{:noreply, sockets}
end

View File

@@ -52,7 +52,7 @@ defmodule Eventos.Service.WebFinger do
"subject" => "acct:#{user.preferred_username}@#{EventosWeb.Endpoint.host() <> ":4001"}",
"aliases" => [user.url],
"links" => [
%{"rel" => "self", "type" => "application/activity+json", "href" => user.url},
%{"rel" => "self", "type" => "application/activity+json", "href" => user.url}
]
}
end
@@ -63,10 +63,12 @@ defmodule Eventos.Service.WebFinger do
case {link["type"], link["rel"]} do
{"application/activity+json", "self"} ->
Map.put(data, "url", link["href"])
_ ->
Logger.debug fn ->
Logger.debug(fn ->
"Unhandled type: #{inspect(link["type"])}"
end
end)
data
end
end)
@@ -85,13 +87,19 @@ defmodule Eventos.Service.WebFinger do
URI.parse(actor).host
end
address = "http://#{domain}/.well-known/webfinger?resource=acct:#{actor}"
address = "http://#{domain}/.well-known/webfinger?resource=acct:#{actor}"
Logger.debug(inspect address)
with {:ok, %HTTPoison.Response{} = response} <- HTTPoison.get(address, [Accept: "application/json, application/activity+json, application/jrd+json"], follow_redirect: true),
Logger.debug(inspect(address))
with {:ok, %HTTPoison.Response{} = response} <-
HTTPoison.get(
address,
[Accept: "application/json, application/activity+json, application/jrd+json"],
follow_redirect: true
),
%{status_code: status_code, body: body} when status_code in 200..299 <- response do
{:ok, doc} = Jason.decode(body)
webfinger_from_json(doc)
{:ok, doc} = Jason.decode(body)
webfinger_from_json(doc)
else
e ->
Logger.debug(fn -> "Couldn't finger #{actor}" end)