diff options
author | lambda <pleromagit@rogerbraun.net> | 2018-05-24 20:22:43 +0000 |
---|---|---|
committer | lambda <pleromagit@rogerbraun.net> | 2018-05-24 20:22:43 +0000 |
commit | f3a71f2986fc0787c03bec786e772353e99ae9f9 (patch) | |
tree | ee918da7bd09ba9c1082158ab8b8f1a0337553ba /lib | |
parent | c2dcd767cf4abaa88da946e12ca643840b65e184 (diff) | |
parent | 3dbd9809d44297c2edc8e08bde33f9ef7b998412 (diff) | |
download | pleroma-f3a71f2986fc0787c03bec786e772353e99ae9f9.tar.gz |
Merge branch 'feature/lists' into 'develop'
Mastodon List API
See merge request pleroma/pleroma!138
Diffstat (limited to 'lib')
-rw-r--r-- | lib/pleroma/list.ex | 87 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/mastodon_api_controller.ex | 98 | ||||
-rw-r--r-- | lib/pleroma/web/mastodon_api/views/list_view.ex | 15 | ||||
-rw-r--r-- | lib/pleroma/web/router.ex | 11 |
4 files changed, 209 insertions, 2 deletions
diff --git a/lib/pleroma/list.ex b/lib/pleroma/list.ex new file mode 100644 index 000000000..9d0b9285b --- /dev/null +++ b/lib/pleroma/list.ex @@ -0,0 +1,87 @@ +defmodule Pleroma.List do + use Ecto.Schema + import Ecto.{Changeset, Query} + alias Pleroma.{User, Repo} + + schema "lists" do + belongs_to(:user, Pleroma.User) + field(:title, :string) + field(:following, {:array, :string}, default: []) + + timestamps() + end + + def title_changeset(list, attrs \\ %{}) do + list + |> cast(attrs, [:title]) + |> validate_required([:title]) + end + + def follow_changeset(list, attrs \\ %{}) do + list + |> cast(attrs, [:following]) + |> validate_required([:following]) + end + + def for_user(user, opts) do + query = + from( + l in Pleroma.List, + where: l.user_id == ^user.id, + order_by: [desc: l.id], + limit: 50 + ) + + Repo.all(query) + end + + def get(id, %{id: user_id} = _user) do + query = + from( + l in Pleroma.List, + where: l.id == ^id, + where: l.user_id == ^user_id + ) + + Repo.one(query) + end + + def get_following(%Pleroma.List{following: following} = list) do + q = + from( + u in User, + where: u.follower_address in ^following + ) + + {:ok, Repo.all(q)} + end + + def rename(%Pleroma.List{} = list, title) do + list + |> title_changeset(%{title: title}) + |> Repo.update() + end + + def create(title, %User{} = creator) do + list = %Pleroma.List{user_id: creator.id, title: title} + Repo.insert(list) + end + + def follow(%Pleroma.List{following: following} = list, %User{} = followed) do + update_follows(list, %{following: Enum.uniq([followed.follower_address | following])}) + end + + def unfollow(%Pleroma.List{following: following} = list, %User{} = unfollowed) do + update_follows(list, %{following: List.delete(following, unfollowed.follower_address)}) + end + + def delete(%Pleroma.List{} = list) do + Repo.delete(list) + end + + def update_follows(%Pleroma.List{} = list, attrs) do + list + |> follow_changeset(attrs) + |> Repo.update() + end +end diff --git a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex index 2c0277124..460942f1a 100644 --- a/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex +++ b/lib/pleroma/web/mastodon_api/mastodon_api_controller.ex @@ -2,7 +2,7 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do use Pleroma.Web, :controller alias Pleroma.{Repo, Activity, User, Notification, Stats} alias Pleroma.Web - alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView} + alias Pleroma.Web.MastodonAPI.{StatusView, AccountView, MastodonView, ListView} alias Pleroma.Web.ActivityPub.ActivityPub alias Pleroma.Web.{CommonAPI, OStatus} alias Pleroma.Web.OAuth.{Authorization, Token, App} @@ -568,6 +568,102 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) end + def get_lists(%{assigns: %{user: user}} = conn, opts) do + lists = Pleroma.List.for_user(user, opts) + res = ListView.render("lists.json", lists: lists) + json(conn, res) + end + + def get_list(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with %Pleroma.List{} = list <- Pleroma.List.get(id, user) do + res = ListView.render("list.json", list: list) + json(conn, res) + else + _e -> json(conn, "error") + end + end + + def delete_list(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with %Pleroma.List{} = list <- Pleroma.List.get(id, user), + {:ok, _list} <- Pleroma.List.delete(list) do + json(conn, %{}) + else + _e -> + json(conn, "error") + end + end + + def create_list(%{assigns: %{user: user}} = conn, %{"title" => title}) do + with {:ok, %Pleroma.List{} = list} <- Pleroma.List.create(title, user) do + res = ListView.render("list.json", list: list) + json(conn, res) + end + end + + def add_to_list(%{assigns: %{user: user}} = conn, %{"id" => id, "account_ids" => accounts}) do + accounts + |> Enum.each(fn account_id -> + with %Pleroma.List{} = list <- Pleroma.List.get(id, user), + %User{} = followed <- Repo.get(User, account_id) do + Pleroma.List.follow(list, followed) + end + end) + + json(conn, %{}) + end + + def remove_from_list(%{assigns: %{user: user}} = conn, %{"id" => id, "account_ids" => accounts}) do + accounts + |> Enum.each(fn account_id -> + with %Pleroma.List{} = list <- Pleroma.List.get(id, user), + %User{} = followed <- Repo.get(Pleroma.User, account_id) do + Pleroma.List.unfollow(list, followed) + end + end) + + json(conn, %{}) + end + + def list_accounts(%{assigns: %{user: user}} = conn, %{"id" => id}) do + with %Pleroma.List{} = list <- Pleroma.List.get(id, user), + {:ok, users} = Pleroma.List.get_following(list) do + render(conn, AccountView, "accounts.json", %{users: users, as: :user}) + end + end + + def rename_list(%{assigns: %{user: user}} = conn, %{"id" => id, "title" => title}) do + with %Pleroma.List{} = list <- Pleroma.List.get(id, user), + {:ok, list} <- Pleroma.List.rename(list, title) do + res = ListView.render("list.json", list: list) + json(conn, res) + else + _e -> + json(conn, "error") + end + end + + def list_timeline(%{assigns: %{user: user}} = conn, %{"list_id" => id} = params) do + with %Pleroma.List{title: title, following: following} <- Pleroma.List.get(id, user) do + params = + params + |> Map.put("type", "Create") + |> Map.put("blocking_user", user) + + # adding title is a hack to not make empty lists function like a public timeline + activities = + ActivityPub.fetch_activities([title | following], params) + |> Enum.reverse() + + conn + |> render(StatusView, "index.json", %{activities: activities, for: user, as: :activity}) + else + _e -> + conn + |> put_status(403) + |> json(%{error: "Error."}) + end + end + def index(%{assigns: %{user: user}} = conn, _params) do token = conn diff --git a/lib/pleroma/web/mastodon_api/views/list_view.ex b/lib/pleroma/web/mastodon_api/views/list_view.ex new file mode 100644 index 000000000..1a1b7430b --- /dev/null +++ b/lib/pleroma/web/mastodon_api/views/list_view.ex @@ -0,0 +1,15 @@ +defmodule Pleroma.Web.MastodonAPI.ListView do + use Pleroma.Web, :view + alias Pleroma.Web.MastodonAPI.ListView + + def render("lists.json", %{lists: lists} = opts) do + render_many(lists, ListView, "list.json", opts) + end + + def render("list.json", %{list: list}) do + %{ + id: to_string(list.id), + title: list.title + } + end +end diff --git a/lib/pleroma/web/router.ex b/lib/pleroma/web/router.ex index 9389244b1..726275158 100644 --- a/lib/pleroma/web/router.ex +++ b/lib/pleroma/web/router.ex @@ -104,7 +104,6 @@ defmodule Pleroma.Web.Router do get("/domain_blocks", MastodonAPIController, :empty_array) get("/follow_requests", MastodonAPIController, :empty_array) get("/mutes", MastodonAPIController, :empty_array) - get("/lists", MastodonAPIController, :empty_array) get("/timelines/home", MastodonAPIController, :home_timeline) @@ -124,6 +123,15 @@ defmodule Pleroma.Web.Router do get("/notifications/:id", MastodonAPIController, :get_notification) post("/media", MastodonAPIController, :upload) + + get("/lists", MastodonAPIController, :get_lists) + get("/lists/:id", MastodonAPIController, :get_list) + delete("/lists/:id", MastodonAPIController, :delete_list) + post("/lists", MastodonAPIController, :create_list) + put("/lists/:id", MastodonAPIController, :rename_list) + get("/lists/:id/accounts", MastodonAPIController, :list_accounts) + post("/lists/:id/accounts", MastodonAPIController, :add_to_list) + delete("/lists/:id/accounts", MastodonAPIController, :remove_from_list) end scope "/api/web", Pleroma.Web.MastodonAPI do @@ -141,6 +149,7 @@ defmodule Pleroma.Web.Router do get("/timelines/public", MastodonAPIController, :public_timeline) get("/timelines/tag/:tag", MastodonAPIController, :hashtag_timeline) + get("/timelines/list/:list_id", MastodonAPIController, :list_timeline) get("/statuses/:id", MastodonAPIController, :get_status) get("/statuses/:id/context", MastodonAPIController, :get_context) |