Add webfinger and basic feed support.
This commit is contained in:
parent
36e883cd4b
commit
d23f3e3cf3
|
@ -0,0 +1,26 @@
|
||||||
|
defmodule Pleroma.Web.OStatus.FeedRepresenter do
|
||||||
|
alias Pleroma.Web.OStatus
|
||||||
|
alias Pleroma.Web.OStatus.UserRepresenter
|
||||||
|
|
||||||
|
def to_simple_form(user, activities, users) do
|
||||||
|
most_recent_update = List.first(activities).updated_at
|
||||||
|
|> NaiveDateTime.to_iso8601
|
||||||
|
|
||||||
|
h = fn(str) -> [to_charlist(str)] end
|
||||||
|
|
||||||
|
entries = []
|
||||||
|
[{
|
||||||
|
:feed, [
|
||||||
|
xmlns: 'http://www.w3.org/2005/Atom',
|
||||||
|
"xmlns:activity": 'http://activitystrea.ms/spec/1.0/'
|
||||||
|
], [
|
||||||
|
{:id, h.(OStatus.feed_path(user))},
|
||||||
|
{:title, ['#{user.nickname}\'s timeline']},
|
||||||
|
{:updated, h.(most_recent_update)},
|
||||||
|
{:entries, []},
|
||||||
|
{:link, [rel: 'hub', href: h.(OStatus.pubsub_path)], []},
|
||||||
|
{:author, UserRepresenter.to_simple_form(user)}
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,14 @@
|
||||||
|
defmodule Pleroma.Web.OStatus do
|
||||||
|
alias Pleroma.Web
|
||||||
|
|
||||||
|
def feed_path(user) do
|
||||||
|
"#{user.ap_id}/feed.atom"
|
||||||
|
end
|
||||||
|
|
||||||
|
def pubsub_path() do
|
||||||
|
"#{Web.base_url}/push/hub"
|
||||||
|
end
|
||||||
|
|
||||||
|
def user_path(user) do
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,26 @@
|
||||||
|
defmodule Pleroma.Web.OStatus.OStatusController do
|
||||||
|
use Pleroma.Web, :controller
|
||||||
|
|
||||||
|
alias Pleroma.{User, Activity}
|
||||||
|
alias Pleroma.Web.OStatus.FeedRepresenter
|
||||||
|
alias Pleroma.Repo
|
||||||
|
import Ecto.Query
|
||||||
|
|
||||||
|
def feed(conn, %{"nickname" => nickname}) do
|
||||||
|
user = User.get_cached_by_nickname(nickname)
|
||||||
|
query = from activity in Activity,
|
||||||
|
where: fragment("? @> ?", activity.data, ^%{actor: user.ap_id}),
|
||||||
|
limit: 20,
|
||||||
|
order_by: [desc: :inserted_at]
|
||||||
|
|
||||||
|
activities = query
|
||||||
|
|> Repo.all
|
||||||
|
|
||||||
|
response = FeedRepresenter.to_simple_form(user, activities, [user])
|
||||||
|
|> :xmerl.export_simple(:xmerl_xml)
|
||||||
|
|
||||||
|
conn
|
||||||
|
|> put_resp_content_type("application/atom+xml")
|
||||||
|
|> send_resp(200, response)
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,14 +1,15 @@
|
||||||
defmodule Pleroma.Web.OStatus.UserRepresenter do
|
defmodule Pleroma.Web.OStatus.UserRepresenter do
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
def to_tuple(user, wrapper \\ :author) do
|
def to_simple_form(user) do
|
||||||
{
|
ap_id = to_charlist(user.ap_id)
|
||||||
wrapper, [
|
nickname = to_charlist(user.nickname)
|
||||||
{ :id, user.ap_id },
|
avatar_url = to_charlist(User.avatar_url(user))
|
||||||
{ :"activity:object", "http://activitystrea.ms/schema/1.0/person" },
|
[
|
||||||
{ :uri, user.ap_id },
|
{ :id, [ap_id] },
|
||||||
{ :name, user.nickname },
|
{ :"activity:object", ['http://activitystrea.ms/schema/1.0/person'] },
|
||||||
{ :link, %{rel: "avatar", href: User.avatar_url(user)}}
|
{ :uri, [ap_id] },
|
||||||
]
|
{ :name, [nickname] },
|
||||||
}
|
{ :link, [rel: 'avatar', href: avatar_url], []}
|
||||||
|
]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -54,6 +54,16 @@ def user_fetcher(username) do
|
||||||
post "/qvitter/update_avatar", TwitterAPI.Controller, :update_avatar
|
post "/qvitter/update_avatar", TwitterAPI.Controller, :update_avatar
|
||||||
end
|
end
|
||||||
|
|
||||||
|
pipeline :ostatus do
|
||||||
|
plug :accepts, ["xml", "atom"]
|
||||||
|
end
|
||||||
|
|
||||||
|
scope "/users", Pleroma.Web do
|
||||||
|
pipe_through :ostatus
|
||||||
|
|
||||||
|
get "/:nickname/feed", OStatus.OStatusController, :feed
|
||||||
|
end
|
||||||
|
|
||||||
scope "/.well-known", Pleroma.Web do
|
scope "/.well-known", Pleroma.Web do
|
||||||
pipe_through :well_known
|
pipe_through :well_known
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
defmodule Pleroma.Web.WebFinger do
|
defmodule Pleroma.Web.WebFinger do
|
||||||
alias Pleroma.XmlBuilder
|
alias Pleroma.XmlBuilder
|
||||||
alias Pleroma.User
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.OStatus
|
||||||
|
|
||||||
def host_meta() do
|
def host_meta() do
|
||||||
base_url = Pleroma.Web.base_url
|
base_url = Pleroma.Web.base_url
|
||||||
|
@ -30,7 +31,7 @@ def represent_user(user) do
|
||||||
[
|
[
|
||||||
{:Subject, "acct:#{user.nickname}@#{Pleroma.Web.host}"},
|
{:Subject, "acct:#{user.nickname}@#{Pleroma.Web.host}"},
|
||||||
{:Alias, user.ap_id},
|
{:Alias, user.ap_id},
|
||||||
{:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: "#{user.ap_id}.atom"}}
|
{:Link, %{rel: "http://schemas.google.com/g/2010#updates-from", type: "application/atom+xml", href: OStatus.feed_path(user)}}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|> XmlBuilder.to_doc
|
|> XmlBuilder.to_doc
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
defmodule Pleroma.Web.OStatus.FeedRepresenterTest do
|
||||||
|
use Pleroma.DataCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
alias Pleroma.User
|
||||||
|
alias Pleroma.Web.OStatus.{FeedRepresenter, UserRepresenter}
|
||||||
|
alias Pleroma.Web.OStatus
|
||||||
|
|
||||||
|
test "returns a feed of the last 20 items of the user" do
|
||||||
|
note_activity = insert(:note_activity)
|
||||||
|
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||||
|
|
||||||
|
tuple = FeedRepresenter.to_simple_form(user, [note_activity], [user])
|
||||||
|
|
||||||
|
most_recent_update = note_activity.updated_at
|
||||||
|
|> NaiveDateTime.to_iso8601
|
||||||
|
|
||||||
|
res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary
|
||||||
|
user_xml = UserRepresenter.to_simple_form(user)
|
||||||
|
|> :xmerl.export_simple_content(:xmerl_xml)
|
||||||
|
|
||||||
|
expected = """
|
||||||
|
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:activity="http://activitystrea.ms/spec/1.0/">
|
||||||
|
<id>#{OStatus.feed_path(user)}</id>
|
||||||
|
<title>#{user.nickname}'s timeline</title>
|
||||||
|
<updated>#{most_recent_update}</updated>
|
||||||
|
<entries />
|
||||||
|
<link rel="hub" href="#{OStatus.pubsub_path}" />
|
||||||
|
<author>
|
||||||
|
#{user_xml}
|
||||||
|
</author>
|
||||||
|
</feed>
|
||||||
|
"""
|
||||||
|
assert clean(res) == clean(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp clean(string) do
|
||||||
|
String.replace(string, ~r/\s/, "")
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
defmodule Pleroma.Web.OStatus.OStatusControllerTest do
|
||||||
|
use Pleroma.Web.ConnCase
|
||||||
|
import Pleroma.Factory
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
|
test "gets a feed", %{conn: conn} do
|
||||||
|
note_activity = insert(:note_activity)
|
||||||
|
user = User.get_cached_by_ap_id(note_activity.data["actor"])
|
||||||
|
|
||||||
|
conn = conn
|
||||||
|
|> get("/users/#{user.nickname}/feed.atom")
|
||||||
|
|
||||||
|
assert response(conn, 200)
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,15 +3,26 @@ defmodule Pleroma.Web.OStatus.UserRepresenterTest do
|
||||||
alias Pleroma.Web.OStatus.UserRepresenter
|
alias Pleroma.Web.OStatus.UserRepresenter
|
||||||
|
|
||||||
import Pleroma.Factory
|
import Pleroma.Factory
|
||||||
|
alias Pleroma.User
|
||||||
|
|
||||||
test "returns a user with id, uri, name and link" do
|
test "returns a user with id, uri, name and link" do
|
||||||
user = build(:user)
|
user = build(:user)
|
||||||
tuple = UserRepresenter.to_tuple(user)
|
tuple = UserRepresenter.to_simple_form(user)
|
||||||
{:author, author} = tuple
|
|
||||||
|
|
||||||
[:id, :uri, :name, :link]
|
res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary
|
||||||
|> Enum.each(fn (tag) ->
|
|
||||||
assert Enum.find(author, fn(e) -> tag == elem(e, 0) end)
|
expected = """
|
||||||
end)
|
<id>#{user.ap_id}</id>
|
||||||
|
<activity:object>http://activitystrea.ms/schema/1.0/person</activity:object>
|
||||||
|
<uri>#{user.ap_id}</uri>
|
||||||
|
<name>#{user.nickname}</name>
|
||||||
|
<link rel="avatar" href="#{User.avatar_url(user)}" />
|
||||||
|
"""
|
||||||
|
|
||||||
|
assert clean(res) == clean(expected)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp clean(string) do
|
||||||
|
String.replace(string, ~r/\s/, "")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue