diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/activity.ex | 14 | ||||
-rw-r--r-- | lib/pleroma/formatter.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/upload.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/user.ex | 85 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/activity_pub.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/activity_pub/utils.ex | 4 | ||||
-rw-r--r-- | lib/pleroma/web/federator/federator.ex | 9 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/activity_representer.ex | 40 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/handlers/delete_handler.ex | 15 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/handlers/note_handler.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/web/ostatus/ostatus.ex | 94 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 3 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/twitter_api_controller.ex | 16 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/utils.ex | 2 | ||||
-rw-r--r-- | lib/pleroma/web/twitter_api/views/user_view.ex | 8 | ||||
-rw-r--r-- | lib/pleroma/web/web_finger/web_finger_controller.ex | 12 | ||||
-rw-r--r-- | lib/pleroma/web/websub/websub.ex | 6 | ||||
-rw-r--r-- | lib/pleroma/web/websub/websub_controller.ex | 2 |
19 files changed, 258 insertions, 76 deletions
diff --git a/lib/pleroma/activity.ex b/lib/pleroma/activity.ex index 40e14005b..f226c4c5f 100644 --- a/lib/pleroma/activity.ex +++ b/lib/pleroma/activity.ex @@ -15,9 +15,19 @@ defmodule Pleroma.Activity do where: fragment("(?)->>'id' = ?", activity.data, ^to_string(ap_id))) end + # Wrong name, only returns create activities + def all_by_object_ap_id_q(ap_id) do + from activity in Activity, + where: fragment("(?)->'object'->>'id' = ?", activity.data, ^to_string(ap_id)) + end + + def all_non_create_by_object_ap_id_q(ap_id) do + from activity in Activity, + where: fragment("(?)->>'object' = ?", activity.data, ^to_string(ap_id)) + end + def all_by_object_ap_id(ap_id) do - Repo.all(from activity in Activity, - where: fragment("(?)->'object'->>'id' = ?", activity.data, ^to_string(ap_id))) + Repo.all(all_by_object_ap_id_q(ap_id)) end def get_create_activity_by_object_ap_id(ap_id) do diff --git a/lib/pleroma/formatter.ex b/lib/pleroma/formatter.ex index a7e3f6ab8..e95a314b4 100644 --- a/lib/pleroma/formatter.ex +++ b/lib/pleroma/formatter.ex @@ -1,7 +1,7 @@ defmodule Pleroma.Formatter do alias Pleroma.User - @link_regex ~r/https?:\/\/[\w\.\/?=\-#%&]+[\w]/ + @link_regex ~r/https?:\/\/[\w\.\/?=\-#%&]+[\w]/u def linkify(text) do Regex.replace(@link_regex, text, "<a href='\\0'>\\0</a>") end @@ -14,7 +14,7 @@ defmodule Pleroma.Formatter do def parse_mentions(text) do # Modified from https://www.w3.org/TR/html5/forms.html#valid-e-mail-address - regex = ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/ + regex = ~r/@[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@?[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*/u Regex.scan(regex, text) |> List.flatten diff --git a/lib/pleroma/upload.ex b/lib/pleroma/upload.ex index 9275eff87..2717377a3 100644 --- a/lib/pleroma/upload.ex +++ b/lib/pleroma/upload.ex @@ -13,7 +13,7 @@ defmodule Pleroma.Upload do "url" => [%{ "type" => "Link", "mediaType" => file.content_type, - "href" => url_for(Path.join(uuid, file.filename)) + "href" => url_for(Path.join(uuid, :cow_uri.urlencode(file.filename))) }], "name" => file.filename, "uuid" => uuid @@ -38,7 +38,7 @@ defmodule Pleroma.Upload do "url" => [%{ "type" => "Link", "mediaType" => content_type, - "href" => url_for(Path.join(uuid, filename)) + "href" => url_for(Path.join(uuid, :cow_uri.urlencode(filename))) }], "name" => filename, "uuid" => uuid diff --git a/lib/pleroma/user.ex b/lib/pleroma/user.ex index a30c8daed..f28f0deb0 100644 --- a/lib/pleroma/user.ex +++ b/lib/pleroma/user.ex @@ -21,6 +21,7 @@ defmodule Pleroma.User do field :avatar, :map field :local, :boolean, default: true field :info, :map, default: %{} + field :follower_address, :string timestamps() end @@ -53,24 +54,16 @@ defmodule Pleroma.User do end def user_info(%User{} = user) do - note_count_query = from a in Object, - where: fragment("? @> ?", a.data, ^%{actor: user.ap_id, type: "Note"}), - select: count(a.id) - - follower_count_query = from u in User, - where: fragment("? @> ?", u.following, ^User.ap_followers(user)), - select: count(u.id) - %{ following_count: length(user.following), - note_count: Repo.one(note_count_query), - follower_count: Repo.one(follower_count_query) + note_count: user.info["note_count"] || 0, + follower_count: user.info["follower_count"] || 0 } end @email_regex ~r/^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/ def remote_user_creation(params) do - %User{} + changes = %User{} |> cast(params, [:bio, :name, :ap_id, :nickname, :info, :avatar]) |> validate_required([:name, :ap_id, :nickname]) |> unique_constraint(:nickname) @@ -78,6 +71,13 @@ defmodule Pleroma.User do |> validate_length(:bio, max: 5000) |> validate_length(:name, max: 100) |> put_change(:local, false) + if changes.valid? do + followers = User.ap_followers(%User{nickname: changes.changes[:nickname]}) + changes + |> put_change(:follower_address, followers) + else + changes + end end def register_changeset(struct, params \\ %{}) do @@ -100,13 +100,14 @@ defmodule Pleroma.User do |> put_change(:password_hash, hashed) |> put_change(:ap_id, ap_id) |> put_change(:following, [followers]) + |> put_change(:follower_address, followers) else changeset end end def follow(%User{} = follower, %User{} = followed) do - ap_followers = User.ap_followers(followed) + ap_followers = followed.follower_address if following?(follower, followed) do {:error, "Could not follow user: #{followed.nickname} is already on your list."} @@ -118,14 +119,18 @@ defmodule Pleroma.User do following = [ap_followers | follower.following] |> Enum.uniq - follower + follower = follower |> follow_changeset(%{following: following}) |> Repo.update + + {:ok, followed} = update_follower_count(followed) + + follower end end def unfollow(%User{} = follower, %User{} = followed) do - ap_followers = User.ap_followers(followed) + ap_followers = followed.follower_address if following?(follower, followed) do following = follower.following |> List.delete(ap_followers) @@ -133,14 +138,17 @@ defmodule Pleroma.User do { :ok, follower } = follower |> follow_changeset(%{following: following}) |> Repo.update - { :ok, follower, Utils.fetch_latest_follow(follower, followed)} + + {:ok, followed} = update_follower_count(followed) + + {:ok, follower, Utils.fetch_latest_follow(follower, followed)} else {:error, "Not subscribed!"} end end def following?(%User{} = follower, %User{} = followed) do - Enum.member?(follower.following, User.ap_followers(followed)) + Enum.member?(follower.following, followed.follower_address) end def get_by_ap_id(ap_id) do @@ -177,4 +185,49 @@ defmodule Pleroma.User do end end end + + # TODO: these queries could be more efficient if the type in postgresql wasn't map, but array. + def get_followers(%User{id: id, follower_address: follower_address}) do + q = from u in User, + where: fragment("? @> ?", u.following, ^follower_address ), + where: u.id != ^id + + {:ok, Repo.all(q)} + end + + def get_friends(%User{id: id, following: following}) do + q = from u in User, + where: u.follower_address in ^following, + where: u.id != ^id + + {:ok, Repo.all(q)} + end + + def update_note_count(%User{} = user) do + note_count_query = from a in Object, + where: fragment("? @> ?", a.data, ^%{actor: user.ap_id, type: "Note"}), + select: count(a.id) + + note_count = Repo.one(note_count_query) + + new_info = Map.put(user.info, "note_count", note_count) + + cs = info_changeset(user, %{info: new_info}) + + Repo.update(cs) + end + + def update_follower_count(%User{} = user) do + follower_count_query = from u in User, + where: fragment("? @> ?", u.following, ^user.follower_address), + select: count(u.id) + + follower_count = Repo.one(follower_count_query) + + new_info = Map.put(user.info, "follower_count", follower_count) + + cs = info_changeset(user, %{info: new_info}) + + Repo.update(cs) + end end diff --git a/lib/pleroma/web/activity_pub/activity_pub.ex b/lib/pleroma/web/activity_pub/activity_pub.ex index 69a2d8f4e..fbe259f50 100644 --- a/lib/pleroma/web/activity_pub/activity_pub.ex +++ b/lib/pleroma/web/activity_pub/activity_pub.ex @@ -119,7 +119,7 @@ defmodule Pleroma.Web.ActivityPub.ActivityPub do def fetch_activities(recipients, opts \\ %{}) do base_query = from activity in Activity, limit: 20, - order_by: [desc: :inserted_at] + order_by: [desc: :id] base_query |> restrict_recipients(recipients) diff --git a/lib/pleroma/web/activity_pub/utils.ex b/lib/pleroma/web/activity_pub/utils.ex index ed5ae021e..ef58b88d2 100644 --- a/lib/pleroma/web/activity_pub/utils.ex +++ b/lib/pleroma/web/activity_pub/utils.ex @@ -99,7 +99,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do "type" => "Like", "actor" => ap_id, "object" => id, - "to" => [User.ap_followers(actor), object.data["actor"]], + "to" => [actor.follower_address, object.data["actor"]], "context" => object.data["context"] } @@ -167,7 +167,7 @@ defmodule Pleroma.Web.ActivityPub.Utils do "type" => "Announce", "actor" => ap_id, "object" => id, - "to" => [User.ap_followers(user), object.data["actor"]], + "to" => [user.follower_address, object.data["actor"]], "context" => object.data["context"] } diff --git a/lib/pleroma/web/federator/federator.ex b/lib/pleroma/web/federator/federator.ex index 8d4f497b8..4d6ebff8e 100644 --- a/lib/pleroma/web/federator/federator.ex +++ b/lib/pleroma/web/federator/federator.ex @@ -26,6 +26,15 @@ defmodule Pleroma.Web.Federator do end) end + def handle(:request_subscription, websub) do + Logger.debug("Refreshing #{websub.topic}") + with {:ok, websub } <- Websub.request_subscription(websub) do + Logger.debug("Successfully refreshed #{websub.topic}") + else + _e -> Logger.debug("Couldn't refresh #{websub.topic}") + end + end + def handle(:publish, activity) do Logger.debug(fn -> "Running publish for #{activity.data["id"]}" end) with actor when not is_nil(actor) <- User.get_cached_by_ap_id(activity.data["actor"]) do diff --git a/lib/pleroma/web/ostatus/activity_representer.ex b/lib/pleroma/web/ostatus/activity_representer.ex index eaa3c65e9..842e44ee4 100644 --- a/lib/pleroma/web/ostatus/activity_representer.ex +++ b/lib/pleroma/web/ostatus/activity_representer.ex @@ -1,10 +1,18 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do - alias Pleroma.{Activity, User} + alias Pleroma.{Activity, User, Object} alias Pleroma.Web.OStatus.UserRepresenter require Logger + defp get_href(id) do + with %Object{data: %{ "external_url" => external_url } }<- Object.get_cached_by_ap_id(id) do + external_url + else + _e -> id + end + end + defp get_in_reply_to(%{"object" => %{"inReplyTo" => in_reply_to}}) do - [{:"thr:in-reply-to", [ref: to_charlist(in_reply_to)], []}] + [{:"thr:in-reply-to", [ref: to_charlist(in_reply_to), href: to_charlist(get_href(in_reply_to))], []}] end defp get_in_reply_to(_), do: [] @@ -24,6 +32,29 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do end) end + defp get_links(%{local: true, data: data}) do + h = fn(str) -> [to_charlist(str)] end + [ + {:link, [type: ['application/atom+xml'], href: h.(data["object"]["id"]), rel: 'self'], []}, + {:link, [type: ['text/html'], href: h.(data["object"]["id"]), rel: 'alternate'], []} + ] + end + + defp get_links(%{local: false, + data: %{ + "object" => %{ + "external_url" => external_url + } + }}) do + + h = fn(str) -> [to_charlist(str)] end + [ + {:link, [type: ['text/html'], href: h.(external_url), rel: 'alternate'], []} + ] + end + + defp get_links(_activity), do: [] + 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 @@ -48,13 +79,12 @@ defmodule Pleroma.Web.OStatus.ActivityRepresenter do {:"activity:verb", ['http://activitystrea.ms/schema/1.0/post']}, {:id, h.(activity.data["object"]["id"])}, # For notes, federate the object id. {:title, ['New note by #{user.nickname}']}, - {:content, [type: 'html'], h.(activity.data["object"]["content"])}, + {:content, [type: 'html'], h.(activity.data["object"]["content"] |> String.replace(~r/[\n\r]/, ""))}, {:published, h.(inserted_at)}, {:updated, h.(updated_at)}, {:"ostatus:conversation", [], h.(activity.data["context"])}, {:link, [ref: h.(activity.data["context"]), rel: 'ostatus:conversation'], []}, - {:link, [type: ['application/atom+xml'], href: h.(activity.data["object"]["id"]), rel: 'self'], []} - ] ++ categories ++ attachments ++ in_reply_to ++ author ++ mentions + ] ++ get_links(activity) ++ categories ++ attachments ++ in_reply_to ++ author ++ mentions end def to_simple_form(%{data: %{"type" => "Like"}} = activity, user, with_author) do diff --git a/lib/pleroma/web/ostatus/handlers/delete_handler.ex b/lib/pleroma/web/ostatus/handlers/delete_handler.ex new file mode 100644 index 000000000..f54a037a0 --- /dev/null +++ b/lib/pleroma/web/ostatus/handlers/delete_handler.ex @@ -0,0 +1,15 @@ +defmodule Pleroma.Web.OStatus.DeleteHandler do + require Logger + alias Pleroma.Web.{XML, OStatus} + alias Pleroma.{Activity, Object, Repo} + + def handle_delete(entry, doc \\ nil) do + with id <- XML.string_from_xpath("//id", entry), + object when not is_nil(object) <- Object.get_by_ap_id(id) do + Repo.delete(object) + Repo.delete_all(Activity.all_non_create_by_object_ap_id_q(id)) + Repo.delete_all(Activity.all_by_object_ap_id_q(id)) + nil + end + end +end diff --git a/lib/pleroma/web/ostatus/handlers/note_handler.ex b/lib/pleroma/web/ostatus/handlers/note_handler.ex index e0e4afef6..e67f67b37 100644 --- a/lib/pleroma/web/ostatus/handlers/note_handler.ex +++ b/lib/pleroma/web/ostatus/handlers/note_handler.ex @@ -10,7 +10,7 @@ defmodule Pleroma.Web.OStatus.NoteHandler do if inReplyTo && !Object.get_cached_by_ap_id(inReplyTo) do inReplyToHref = XML.string_from_xpath("//thr:in-reply-to[1]/@href", entry) if inReplyToHref do - OStatus.fetch_activity_from_html_url(inReplyToHref) + OStatus.fetch_activity_from_url(inReplyToHref) else Logger.debug("Couldn't find a href link to #{inReplyTo}") end @@ -61,7 +61,7 @@ defmodule Pleroma.Web.OStatus.NoteHandler do def make_to_list(actor, mentions) do [ - User.ap_followers(actor) + actor.follower_address ] ++ mentions end @@ -92,7 +92,9 @@ defmodule Pleroma.Web.OStatus.NoteHandler do # TODO: Handle this case in make_note_data note <- (if inReplyTo && !inReplyToActivity, do: note |> Map.put("inReplyTo", inReplyTo), else: note) do - ActivityPub.create(to, actor, context, note, %{}, date, false) + res = ActivityPub.create(to, actor, context, note, %{}, date, false) + User.update_note_count(actor) + res else %Activity{} = activity -> {:ok, activity} e -> {:error, e} diff --git a/lib/pleroma/web/ostatus/ostatus.ex b/lib/pleroma/web/ostatus/ostatus.ex index 4187afa9d..02a0996b0 100644 --- a/lib/pleroma/web/ostatus/ostatus.ex +++ b/lib/pleroma/web/ostatus/ostatus.ex @@ -9,7 +9,7 @@ defmodule Pleroma.Web.OStatus do alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.ActivityPub.Utils alias Pleroma.Web.{WebFinger, Websub} - alias Pleroma.Web.OStatus.{FollowHandler, NoteHandler} + alias Pleroma.Web.OStatus.{FollowHandler, NoteHandler, DeleteHandler} def feed_path(user) do "#{user.ap_id}/feed.atom" @@ -24,34 +24,48 @@ defmodule Pleroma.Web.OStatus do end def handle_incoming(xml_string) do - doc = parse_document(xml_string) - entries = :xmerl_xpath.string('//entry', doc) - - activities = Enum.map(entries, fn (entry) -> - {:xmlObj, :string, object_type} = :xmerl_xpath.string('string(/entry/activity:object-type[1])', entry) - {:xmlObj, :string, verb} = :xmerl_xpath.string('string(/entry/activity:verb[1])', entry) - Logger.debug("Handling #{verb}") - - case verb do - 'http://activitystrea.ms/schema/1.0/follow' -> - with {:ok, activity} <- FollowHandler.handle(entry, doc), do: activity - 'http://activitystrea.ms/schema/1.0/share' -> - with {:ok, activity, retweeted_activity} <- handle_share(entry, doc), do: [activity, retweeted_activity] - 'http://activitystrea.ms/schema/1.0/favorite' -> - with {:ok, activity, favorited_activity} <- handle_favorite(entry, doc), do: [activity, favorited_activity] - _ -> - case object_type do - 'http://activitystrea.ms/schema/1.0/note' -> - with {:ok, activity} <- NoteHandler.handle_note(entry, doc), do: activity - 'http://activitystrea.ms/schema/1.0/comment' -> - with {:ok, activity} <- NoteHandler.handle_note(entry, doc), do: activity + with doc when doc != :error <- parse_document(xml_string) do + entries = :xmerl_xpath.string('//entry', doc) + + activities = Enum.map(entries, fn (entry) -> + {:xmlObj, :string, object_type} = :xmerl_xpath.string('string(/entry/activity:object-type[1])', entry) + {:xmlObj, :string, verb} = :xmerl_xpath.string('string(/entry/activity:verb[1])', entry) + Logger.debug("Handling #{verb}") + + try do + case verb do + 'http://activitystrea.ms/schema/1.0/delete' -> + with {:ok, activity} <- DeleteHandler.handle_delete(entry, doc), do: activity + 'http://activitystrea.ms/schema/1.0/follow' -> + with {:ok, activity} <- FollowHandler.handle(entry, doc), do: activity + 'http://activitystrea.ms/schema/1.0/share' -> + with {:ok, activity, retweeted_activity} <- handle_share(entry, doc), do: [activity, retweeted_activity] + 'http://activitystrea.ms/schema/1.0/favorite' -> + with {:ok, activity, favorited_activity} <- handle_favorite(entry, doc), do: [activity, favorited_activity] _ -> - Logger.error("Couldn't parse incoming document") - nil + case object_type do + 'http://activitystrea.ms/schema/1.0/note' -> + with {:ok, activity} <- NoteHandler.handle_note(entry, doc), do: activity + 'http://activitystrea.ms/schema/1.0/comment' -> + with {:ok, activity} <- NoteHandler.handle_note(entry, doc), do: activity + _ -> + Logger.error("Couldn't parse incoming document") + nil + end end - end - end) - {:ok, activities} + rescue + e -> + Logger.error("Error occured while handling activity") + Logger.error(inspect(e)) + nil + end + end) + |> Enum.filter(&(&1)) + + {:ok, activities} + else + _e -> {:error, []} + end end def make_share(entry, doc, retweeted_activity) do @@ -100,7 +114,7 @@ defmodule Pleroma.Web.OStatus do else e -> Logger.debug("Couldn't get, will try to fetch") with href when not is_nil(href) <- string_from_xpath("//activity:object[1]/link[@type=\"text/html\"]/@href", entry), - {:ok, [favorited_activity]} <- fetch_activity_from_html_url(href) do + {:ok, [favorited_activity]} <- fetch_activity_from_url(href) do {:ok, favorited_activity} else e -> Logger.debug("Couldn't find href: #{inspect(e)}") end @@ -267,14 +281,30 @@ defmodule Pleroma.Web.OStatus do end end + def fetch_activity_from_atom_url(url) do + with {:ok, %{body: body, status_code: code}} when code in 200..299 <- @httpoison.get(url, [Accept: "application/atom+xml"], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do + Logger.debug("Got document from #{url}, handling...") + handle_incoming(body) + else e -> Logger.debug("Couldn't get #{url}: #{inspect(e)}") + end + end + def fetch_activity_from_html_url(url) do Logger.debug("Trying to fetch #{url}") with {:ok, %{body: body}} <- @httpoison.get(url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000), - {:ok, atom_url} <- get_atom_url(body), - {:ok, %{status_code: code, body: body}} when code in 200..299 <- @httpoison.get(atom_url, [], follow_redirect: true, timeout: 10000, recv_timeout: 20000) do - Logger.debug("Got document from #{url}, handling...") - handle_incoming(body) + {:ok, atom_url} <- get_atom_url(body) do + fetch_activity_from_atom_url(atom_url) else e -> Logger.debug("Couldn't get #{url}: #{inspect(e)}") end end + + def fetch_activity_from_url(url) do + with {:ok, activities} <- fetch_activity_from_atom_url(url) do + {:ok, activities} + else + _e -> with {:ok, activities} <- fetch_activity_from_html_url(url) do + {:ok, activities} + end + end + end end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index d92ee29ba..34207a62f 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -70,6 +70,9 @@ defmodule Pleroma.Web.Router do post "/favorites/destroy/:id", TwitterAPI.Controller, :unfavorite post "/qvitter/update_avatar", TwitterAPI.Controller, :update_avatar + + get "/statuses/followers", TwitterAPI.Controller, :followers + get "/statuses/friends", TwitterAPI.Controller, :friends end pipeline :ostatus do diff --git a/lib/pleroma/web/twitter_api/twitter_api.ex b/lib/pleroma/web/twitter_api/twitter_api.ex index b5b59eb4b..dc66e27ad 100644 --- a/lib/pleroma/web/twitter_api/twitter_api.ex +++ b/lib/pleroma/web/twitter_api/twitter_api.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do def to_for_user_and_mentions(user, mentions, inReplyTo) do default_to = [ - User.ap_followers(user), + user.follower_address, "https://www.w3.org/ns/activitystreams#Public" ] @@ -39,7 +39,9 @@ defmodule Pleroma.Web.TwitterAPI.TwitterAPI do context <- make_context(inReplyTo), tags <- Formatter.parse_tags(status), object <- make_note_data(user.ap_id, to, context, content_html, attachments, inReplyTo, tags) do - ActivityPub.create(to, user, context, object) + res = ActivityPub.create(to, user, context, object) + User.update_note_count(user) + res end end diff --git a/lib/pleroma/web/twitter_api/twitter_api_controller.ex b/lib/pleroma/web/twitter_api/twitter_api_controller.ex index 2b29b6ccf..9b1c74a3f 100644 --- a/lib/pleroma/web/twitter_api/twitter_api_controller.ex +++ b/lib/pleroma/web/twitter_api/twitter_api_controller.ex @@ -210,6 +210,22 @@ defmodule Pleroma.Web.TwitterAPI.Controller do end end + def followers(%{assigns: %{user: user}} = conn, _params) do + with {:ok, followers} <- User.get_followers(user) do + render(conn, UserView, "index.json", %{users: followers, for: user}) + else + _e -> bad_request_reply(conn, "Can't get followers") + end + end + + def friends(%{assigns: %{user: user}} = conn, _params) do + with {:ok, friends} <- User.get_friends(user) do + render(conn, UserView, "index.json", %{users: friends, for: user}) + else + _e -> bad_request_reply(conn, "Can't get friends") + end + end + defp bad_request_reply(conn, error_message) do json = error_json(conn, error_message) json_reply(conn, 400, json) diff --git a/lib/pleroma/web/twitter_api/utils.ex b/lib/pleroma/web/twitter_api/utils.ex index 2c3507dfb..cd7e04ca1 100644 --- a/lib/pleroma/web/twitter_api/utils.ex +++ b/lib/pleroma/web/twitter_api/utils.ex @@ -12,7 +12,7 @@ defmodule Pleroma.Web.TwitterAPI.Utils do def add_attachments(text, attachments) do attachment_text = Enum.map(attachments, fn (%{"url" => [%{"href" => href} | _]}) -> - "<a href=\"#{URI.encode(href)}\" class='attachment'>#{Path.basename(href)}</a>" + "<a href=\"#{href}\" class='attachment'>#{Path.basename(href)}</a>" _ -> "" end) Enum.join([text | attachment_text], "<br>\n") diff --git a/lib/pleroma/web/twitter_api/views/user_view.ex b/lib/pleroma/web/twitter_api/views/user_view.ex index fdab5be31..24d2981fa 100644 --- a/lib/pleroma/web/twitter_api/views/user_view.ex +++ b/lib/pleroma/web/twitter_api/views/user_view.ex @@ -4,6 +4,14 @@ defmodule Pleroma.Web.TwitterAPI.UserView do alias Pleroma.Web.TwitterAPI.Utils def render("show.json", %{user: user = %User{}} = assigns) do + render_one(user, Pleroma.Web.TwitterAPI.UserView, "user.json", assigns) + end + + def render("index.json", %{users: users, for: user}) do + render_many(users, Pleroma.Web.TwitterAPI.UserView, "user.json", for: user) + end + + def render("user.json", %{user: user = %User{}} = assigns) do image = User.avatar_url(user) following = if assigns[:for] do User.following?(assigns[:for], user) diff --git a/lib/pleroma/web/web_finger/web_finger_controller.ex b/lib/pleroma/web/web_finger/web_finger_controller.ex index d8959a96f..d4536fc46 100644 --- a/lib/pleroma/web/web_finger/web_finger_controller.ex +++ b/lib/pleroma/web/web_finger/web_finger_controller.ex @@ -12,10 +12,12 @@ defmodule Pleroma.Web.WebFinger.WebFingerController do end def webfinger(conn, %{"resource" => resource}) do - {:ok, response} = WebFinger.webfinger(resource) - - conn - |> put_resp_content_type("application/xrd+xml") - |> send_resp(200, response) + with {:ok, response} <- WebFinger.webfinger(resource) do + conn + |> put_resp_content_type("application/xrd+xml") + |> send_resp(200, response) + else + _e -> send_resp(conn, 404, "Couldn't find user") + end end end diff --git a/lib/pleroma/web/websub/websub.ex b/lib/pleroma/web/websub/websub.ex index 932bf1862..6bbf13130 100644 --- a/lib/pleroma/web/websub/websub.ex +++ b/lib/pleroma/web/websub/websub.ex @@ -212,12 +212,12 @@ defmodule Pleroma.Web.Websub do cut_off = NaiveDateTime.add(NaiveDateTime.utc_now, delta) query = from sub in WebsubClientSubscription, - where: sub.valid_until < ^cut_off and sub.state == "accepted" + where: sub.valid_until < ^cut_off subs = Repo.all(query) - Enum.map(subs, fn (sub) -> - request_subscription(sub) + Enum.each(subs, fn (sub) -> + Pleroma.Web.Federator.enqueue(:request_subscription, sub) end) end end diff --git a/lib/pleroma/web/websub/websub_controller.ex b/lib/pleroma/web/websub/websub_controller.ex index 188144a88..6c9164ec8 100644 --- a/lib/pleroma/web/websub/websub_controller.ex +++ b/lib/pleroma/web/websub/websub_controller.ex @@ -20,6 +20,8 @@ defmodule Pleroma.Web.Websub.WebsubController do # TODO: Extract this into the Websub module def websub_subscription_confirmation(conn, %{"id" => id, "hub.mode" => "subscribe", "hub.challenge" => challenge, "hub.topic" => topic} = params) do + Logger.debug("Got websub confirmation") + Logger.debug(inspect(params)) lease_seconds = if params["hub.lease_seconds"] do String.to_integer(params["hub.lease_seconds"]) else |