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 pleroma-f3a71f2986fc0787c03bec786e772353e99ae9f9.zip | |
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) | 
