Add mastodonAPI endpoints for hashtag following

This commit is contained in:
FloatingGhost 2022-12-04 04:07:47 +00:00
parent b5f8232e0f
commit 341aa3b169
6 changed files with 147 additions and 1 deletions

View file

@ -31,6 +31,10 @@ def get_by_id(id) do
Repo.get(Hashtag, id) Repo.get(Hashtag, id)
end end
def get_by_name(name) do
Repo.get_by(Hashtag, name: normalize_name(name))
end
def get_or_create_by_name(name) do def get_or_create_by_name(name) do
changeset = changeset(%Hashtag{}, %{name: name}) changeset = changeset(%Hashtag{}, %{name: name})

View file

@ -0,0 +1,65 @@
defmodule Pleroma.Web.ApiSpec.TagOperation do
alias OpenApiSpex.Operation
alias OpenApiSpex.Schema
alias Pleroma.Web.ApiSpec.Schemas.ApiError
alias Pleroma.Web.ApiSpec.Schemas.Tag
def open_api_operation(action) do
operation = String.to_existing_atom("#{action}_operation")
apply(__MODULE__, operation, [])
end
def show_operation do
%Operation{
tags: ["Tags"],
summary: "Hashtag",
description: "View a hashtag",
security: [%{"oAuth" => ["read"]}],
parameters: [id_param()],
operationId: "TagController.show",
responses: %{
200 => Operation.response("Hashtag", "application/json", Tag),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def follow_operation do
%Operation{
tags: ["Tags"],
summary: "Follow a hashtag",
description: "Follow a hashtag",
security: [%{"oAuth" => ["write:follow"]}],
parameters: [id_param()],
operationId: "TagController.follow",
responses: %{
200 => Operation.response("Hashtag", "application/json", Tag),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
def unfollow_operation do
%Operation{
tags: ["Tags"],
summary: "Unfollow a hashtag",
description: "Unfollow a hashtag",
security: [%{"oAuth" => ["write:follow"]}],
parameters: [id_param()],
operationId: "TagController.unfollow",
responses: %{
200 => Operation.response("Hashtag", "application/json", Tag),
404 => Operation.response("Not Found", "application/json", ApiError)
}
}
end
defp id_param do
Operation.parameter(
:id,
:path,
%Schema{type: :string},
"Name of the hashtag"
)
end
end

View file

@ -17,11 +17,16 @@ defmodule Pleroma.Web.ApiSpec.Schemas.Tag do
type: :string, type: :string,
format: :uri, format: :uri,
description: "A link to the hashtag on the instance" description: "A link to the hashtag on the instance"
},
following: %Schema{
type: :boolean,
description: "Whether the authenticated user is following the hashtag"
} }
}, },
example: %{ example: %{
name: "cofe", name: "cofe",
url: "https://lain.com/tag/cofe" url: "https://lain.com/tag/cofe",
following: false
} }
}) })
end end

View file

@ -0,0 +1,47 @@
defmodule Pleroma.Web.MastodonAPI.TagController do
@moduledoc "Hashtag routes for mastodon API"
use Pleroma.Web, :controller
alias Pleroma.User
alias Pleroma.Hashtag
plug(Pleroma.Web.ApiSpec.CastAndValidate)
plug(Pleroma.Web.Plugs.OAuthScopesPlug, %{scopes: ["read"]} when action in [:show])
plug(
Pleroma.Web.Plugs.OAuthScopesPlug,
%{scopes: ["write:follows"]} when action in [:follow, :unfollow]
)
defdelegate open_api_operation(action), to: Pleroma.Web.ApiSpec.TagOperation
def show(conn, %{id: id} = params) do
with %Hashtag{} = hashtag <- Hashtag.get_by_name(id) do
render(conn, "show.json", tag: hashtag, for_user: conn.assigns.user)
else
_ -> conn |> render_error(:not_found, "Hashtag not found")
end
end
def follow(conn, %{id: id} = params) do
with %Hashtag{} = hashtag <- Hashtag.get_by_name(id),
%User{} = user <- conn.assigns.user,
{:ok, _} <-
User.follow_hashtag(user, hashtag) do
render(conn, "show.json", tag: params["tag"], for_user: user)
else
_ -> render_error(conn, :not_found, "Hashtag not found")
end
end
def unfollow(conn, %{id: id} = params) do
with %Hashtag{} = hashtag <- Hashtag.get_by_name(id),
%User{} = user <- conn.assigns.user,
{:ok, _} <-
User.unfollow_hashtag(user, hashtag) do
render(conn, "show.json", tag: params["tag"], for_user: user)
else
_ -> render_error(conn, :not_found, "Hashtag not found")
end
end
end

View file

@ -0,0 +1,21 @@
defmodule Pleroma.Web.MastodonAPI.TagView do
use Pleroma.Web, :view
alias Pleroma.User
alias Pleroma.Web.Router.Helpers
def render("show.json", %{tag: tag, for_user: user}) do
following =
with %User{} <- user do
User.following_hashtag?(user, tag)
else
_ -> false
end
%{
name: tag.name,
url: Helpers.tag_url(Pleroma.Web.Endpoint, :show, tag),
history: [],
following: following
}
end
end

View file

@ -598,6 +598,10 @@ defmodule Pleroma.Web.Router do
get("/announcements", AnnouncementController, :index) get("/announcements", AnnouncementController, :index)
post("/announcements/:id/dismiss", AnnouncementController, :mark_read) post("/announcements/:id/dismiss", AnnouncementController, :mark_read)
get("/tags/:id", TagController, :show)
post("/tags/:id/follow", TagController, :follow)
post("/tags/:id/unfollow", TagController, :unfollow)
end end
scope "/api/web", Pleroma.Web do scope "/api/web", Pleroma.Web do