diff --git a/lib/pleroma/web/ostatus/feed_representer.ex b/lib/pleroma/web/ostatus/feed_representer.ex
new file mode 100644
index 000000000..cb76022fe
--- /dev/null
+++ b/lib/pleroma/web/ostatus/feed_representer.ex
@@ -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
diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex
new file mode 100644
index 000000000..9fcbe6cb0
--- /dev/null
+++ b/lib/pleroma/web/ostatus/ostatus.ex
@@ -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
diff --git a/lib/pleroma/web/ostatus/ostatus_controller.ex b/lib/pleroma/web/ostatus/ostatus_controller.ex
new file mode 100644
index 000000000..ff6d7301a
--- /dev/null
+++ b/lib/pleroma/web/ostatus/ostatus_controller.ex
@@ -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
diff --git a/lib/pleroma/web/ostatus/user_representer.ex b/lib/pleroma/web/ostatus/user_representer.ex
index 66fc6e053..e7ee4cfeb 100644
--- a/lib/pleroma/web/ostatus/user_representer.ex
+++ b/lib/pleroma/web/ostatus/user_representer.ex
@@ -1,14 +1,15 @@
defmodule Pleroma.Web.OStatus.UserRepresenter do
alias Pleroma.User
- def to_tuple(user, wrapper \\ :author) do
- {
- wrapper, [
- { :id, user.ap_id },
- { :"activity:object", "http://activitystrea.ms/schema/1.0/person" },
- { :uri, user.ap_id },
- { :name, user.nickname },
- { :link, %{rel: "avatar", href: User.avatar_url(user)}}
- ]
- }
+ def to_simple_form(user) do
+ ap_id = to_charlist(user.ap_id)
+ nickname = to_charlist(user.nickname)
+ avatar_url = to_charlist(User.avatar_url(user))
+ [
+ { :id, [ap_id] },
+ { :"activity:object", ['http://activitystrea.ms/schema/1.0/person'] },
+ { :uri, [ap_id] },
+ { :name, [nickname] },
+ { :link, [rel: 'avatar', href: avatar_url], []}
+ ]
end
end
diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex
index 99d1f69c2..cc1f0e165 100644
--- a/lib/pleroma/web/router.ex
+++ b/lib/pleroma/web/router.ex
@@ -54,6 +54,16 @@ defmodule Pleroma.Web.Router do
post "/qvitter/update_avatar", TwitterAPI.Controller, :update_avatar
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
pipe_through :well_known
diff --git a/lib/pleroma/web/web_finger/web_finger.ex b/lib/pleroma/web/web_finger/web_finger.ex
index 258ff7671..eb540e92a 100644
--- a/lib/pleroma/web/web_finger/web_finger.ex
+++ b/lib/pleroma/web/web_finger/web_finger.ex
@@ -1,6 +1,7 @@
defmodule Pleroma.Web.WebFinger do
alias Pleroma.XmlBuilder
alias Pleroma.User
+ alias Pleroma.Web.OStatus
def host_meta() do
base_url = Pleroma.Web.base_url
@@ -30,7 +31,7 @@ defmodule Pleroma.Web.WebFinger do
[
{:Subject, "acct:#{user.nickname}@#{Pleroma.Web.host}"},
{: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
diff --git a/test/web/ostatus/feed_representer_test.exs b/test/web/ostatus/feed_representer_test.exs
new file mode 100644
index 000000000..e252eca9f
--- /dev/null
+++ b/test/web/ostatus/feed_representer_test.exs
@@ -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 = """
+
+ #{OStatus.feed_path(user)}
+ #{user.nickname}'s timeline
+ #{most_recent_update}
+
+
+
+ #{user_xml}
+
+
+ """
+ assert clean(res) == clean(expected)
+ end
+
+ defp clean(string) do
+ String.replace(string, ~r/\s/, "")
+ end
+end
diff --git a/test/web/ostatus/ostatus_controller_test.exs b/test/web/ostatus/ostatus_controller_test.exs
new file mode 100644
index 000000000..229cd9b1e
--- /dev/null
+++ b/test/web/ostatus/ostatus_controller_test.exs
@@ -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
diff --git a/test/web/ostatus/user_representer_test.exs b/test/web/ostatus/user_representer_test.exs
index 02a4b5b14..a401a56da 100644
--- a/test/web/ostatus/user_representer_test.exs
+++ b/test/web/ostatus/user_representer_test.exs
@@ -3,15 +3,26 @@ defmodule Pleroma.Web.OStatus.UserRepresenterTest do
alias Pleroma.Web.OStatus.UserRepresenter
import Pleroma.Factory
+ alias Pleroma.User
test "returns a user with id, uri, name and link" do
user = build(:user)
- tuple = UserRepresenter.to_tuple(user)
- {:author, author} = tuple
+ tuple = UserRepresenter.to_simple_form(user)
- [:id, :uri, :name, :link]
- |> Enum.each(fn (tag) ->
- assert Enum.find(author, fn(e) -> tag == elem(e, 0) end)
- end)
+ res = :xmerl.export_simple_content(tuple, :xmerl_xml) |> IO.iodata_to_binary
+
+ expected = """
+ #{user.ap_id}
+ http://activitystrea.ms/schema/1.0/person
+ #{user.ap_id}
+ #{user.nickname}
+
+ """
+
+ assert clean(res) == clean(expected)
+ end
+
+ defp clean(string) do
+ String.replace(string, ~r/\s/, "")
end
end