Skip to content
Snippets Groups Projects
Commit 68437558 authored by lain's avatar lain
Browse files

Make outgoing salmons work.

parent bed0b398
No related branches found
No related tags found
No related merge requests found
- Add cache for user fetching / representing. (mostly in TwitterAPI.activity_to_status)
Unliking:
- Add a proper undo activity, find out how to ignore those in twitter api.
WEBSUB:
- Add unsubscription
- Add periodical renewal
......@@ -121,7 +121,7 @@ defmodule Pleroma.User do
def get_cached_by_nickname(nickname) do
key = "nickname:#{nickname}"
Cachex.get!(:user_cache, key, fallback: fn(_) -> Repo.get_by(User, nickname: nickname) end)
Cachex.get!(:user_cache, key, fallback: fn(_) -> get_or_fetch_by_nickname(nickname) end)
end
def get_by_nickname(nickname) do
......@@ -137,7 +137,8 @@ defmodule Pleroma.User do
with %User{} = user <- get_by_nickname(nickname) do
user
else _e ->
with {:ok, user} <- OStatus.make_user(nickname) do
with [nick, domain] <- String.split(nickname, "@"),
{:ok, user} <- OStatus.make_user(nickname) do
user
else _e -> nil
end
......
......@@ -7,7 +7,11 @@ defmodule Pleroma.Web.Federator do
def handle(:publish, activity) do
Logger.debug("Running publish for #{activity.data["id"]}")
with actor when not is_nil(actor) <- User.get_cached_by_ap_id(activity.data["actor"]) do
Logger.debug("Sending #{activity.data["id"]} out via websub")
Pleroma.Web.Websub.publish(Pleroma.Web.OStatus.feed_path(actor), actor, activity)
Logger.debug("Sending #{activity.data["id"]} out via salmon")
Pleroma.Web.Salmon.publish(actor, activity)
end
end
......
defmodule Pleroma.Web.OStatus.ActivityRepresenter do
alias Pleroma.Activity
alias Pleroma.Web.OStatus.UserRepresenter
require Logger
defp get_in_reply_to(%{"object" => %{ "inReplyTo" => in_reply_to}}) do
......@@ -8,7 +9,17 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
defp get_in_reply_to(_), do: []
def to_simple_form(%{data: %{"object" => %{"type" => "Note"}}} = activity, user) do
defp get_mentions(to) do
Enum.map(to, fn
("https://www.w3.org/ns/activitystreams#Public") ->
{:link, [rel: "mentioned", "ostatus:object-type": "http://activitystrea.ms/schema/1.0/collection", href: "http://activityschema.org/collection/public"], []}
(id) ->
{:link, [rel: "mentioned", "ostatus:object-type": "http://activitystrea.ms/schema/1.0/person", href: id], []}
end)
end
def to_simple_form(activity, user, with_author \\ false)
def to_simple_form(%{data: %{"object" => %{"type" => "Note"}}} = activity, user, with_author) do
h = fn(str) -> [to_charlist(str)] end
updated_at = activity.updated_at
......@@ -22,6 +33,8 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
end)
in_reply_to = get_in_reply_to(activity.data)
author = if with_author, do: [{:author, UserRepresenter.to_simple_form(user)}], else: []
mentions = activity.data["to"] |> get_mentions
[
{:"activity:object-type", ['http://activitystrea.ms/schema/1.0/note']},
......@@ -33,8 +46,20 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do
{:updated, h.(updated_at)},
{:"ostatus:conversation", [], h.(activity.data["context"])},
{:link, [href: h.(activity.data["context"]), rel: 'ostatus:conversation'], []}
] ++ attachments ++ in_reply_to
] ++ attachments ++ in_reply_to ++ author ++ mentions
end
def wrap_with_entry(simple_form) do
[{
:entry, [
xmlns: 'http://www.w3.org/2005/Atom',
"xmlns:thr": 'http://purl.org/syndication/thread/1.0',
"xmlns:activity": 'http://activitystrea.ms/spec/1.0/',
"xmlns:poco": 'http://portablecontacts.net/spec/1.0',
"xmlns:ostatus": 'http://ostatus.org/schema/1.0'
], simple_form
}]
end
def to_simple_form(_,_), do: nil
def to_simple_form(_,_,_), do: nil
end
defmodule Pleroma.Web.Salmon do
use Bitwise
alias Pleroma.Web.XML
alias Pleroma.Web.OStatus.ActivityRepresenter
alias Pleroma.User
require Logger
def decode(salmon) do
doc = XML.parse_document(salmon)
......@@ -118,4 +121,37 @@ defmodule Pleroma.Web.Salmon do
{:ok, salmon}
end
def remote_users(%{data: %{"to" => to}}) do
to
|> Enum.map(fn(id) -> User.get_cached_by_ap_id(id) end)
|> Enum.filter(fn(user) -> user && !user.local end)
end
defp send_to_user(%{info: %{"salmon" => salmon}}, feed, poster) do
poster.(salmon, feed, [{"Content-Type", "application/magic-envelope+xml"}])
end
defp send_to_user(_,_,_), do: nil
def publish(user, activity, poster \\ &HTTPoison.post/3)
def publish(%{info: %{"keys" => keys}} = user, activity, poster) do
feed = ActivityRepresenter.to_simple_form(activity, user, true)
|> ActivityRepresenter.wrap_with_entry
|> :xmerl.export_simple(:xmerl_xml)
|> to_string
if feed do
{:ok, private, _} = keys_from_pem(keys)
{:ok, feed} = encode(private, feed)
remote_users(activity)
|> Enum.each(fn(remote_user) ->
Logger.debug("sending salmon to #{remote_user.ap_id}")
send_to_user(remote_user, feed, poster)
end)
end
end
def publish(%{id: id}, _, _), do: Logger.debug("Keys missing for user #{id}")
end
......@@ -95,6 +95,7 @@ defmodule Pleroma.UserTest do
assert user == fetched_user
end
# TODO: Make the test local.
test "fetches an external user via ostatus if no user exists" do
fetched_user = User.get_or_fetch_by_nickname("shp@social.heldscal.la")
assert fetched_user.nickname == "shp@social.heldscal.la"
......@@ -104,6 +105,11 @@ defmodule Pleroma.UserTest do
fetched_user = User.get_or_fetch_by_nickname("nonexistant@social.heldscal.la")
assert fetched_user == nil
end
test "returns nil for nonexistant local user" do
fetched_user = User.get_or_fetch_by_nickname("nonexistant")
assert fetched_user == nil
end
end
end
......@@ -25,6 +25,7 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenterTest do
<updated>#{updated_at}</updated>
<ostatus:conversation>#{note_activity.data["context"]}</ostatus:conversation>
<link href="#{note_activity.data["context"]}" rel="ostatus:conversation" />
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
"""
tuple = ActivityRepresenter.to_simple_form(note_activity, user)
......@@ -61,6 +62,7 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenterTest do
<ostatus:conversation>#{answer.data["context"]}</ostatus:conversation>
<link href="#{answer.data["context"]}" rel="ostatus:conversation" />
<thr:in-reply-to ref="#{note.data["object"]["id"]}" />
<link rel="mentioned" ostatus:object-type="http://activitystrea.ms/schema/1.0/collection" href="http://activityschema.org/collection/public"/>
"""
tuple = ActivityRepresenter.to_simple_form(answer, user)
......
defmodule Pleroma.Web.Salmon.SalmonTest do
use Pleroma.DataCase
alias Pleroma.Web.Salmon
alias Pleroma.{Repo, Activity, User}
import Pleroma.Factory
@magickey "RSA.pu0s-halox4tu7wmES1FVSx6u-4wc0YrUFXcqWXZG4-27UmbCOpMQftRCldNRfyA-qLbz-eqiwQhh-1EwUvjsD4cYbAHNGHwTvDOyx5AKthQUP44ykPv7kjKGh3DWKySJvcs9tlUG87hlo7AvnMo9pwRS_Zz2CacQ-MKaXyDepk=.AQAB"
......@@ -57,4 +59,34 @@ defmodule Pleroma.Web.Salmon.SalmonTest do
assert key == "RSA.uzg6r1peZU0vXGADWxGJ0PE34WvmhjUmydbX5YYdOiXfODVLwCMi1umGoqUDm-mRu4vNEdFBVJU1CpFA7dKzWgIsqsa501i2XqElmEveXRLvNRWFB6nG03Q5OUY2as8eE54BJm0p20GkMfIJGwP6TSFb-ICp3QjzbatuSPJ6xCE=.AQAB"
end
test "it pushes an activity to remote accounts it's addressed to" do
user_data = %{
info: %{
"salmon" => "http://example.org/salmon"
},
local: false
}
mentioned_user = insert(:user, user_data)
note = insert(:note)
activity_data = %{
"id" => Pleroma.Web.ActivityPub.ActivityPub.generate_activity_id,
"type" => "Create",
"actor" => note.data["actor"],
"to" => note.data["to"] ++ [mentioned_user.ap_id],
"object" => note.data,
"published_at" => DateTime.utc_now() |> DateTime.to_iso8601,
"context" => note.data["context"]
}
{:ok, activity} = Repo.insert(%Activity{data: activity_data})
user = Repo.get_by(User, ap_id: activity.data["actor"])
{:ok, user} = Pleroma.Web.WebFinger.ensure_keys_present(user)
poster = fn (url, data, headers) ->
assert url == "http://example.org/salmon"
end
Salmon.publish(user, activity, poster)
end
end
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment