This commit is contained in:
Mirai Kumiko 2025-06-19 16:16:27 +02:00
parent 8f63a831c4
commit f963620cf0
Signed by: miraikumiko
GPG key ID: 3F178B1B5E0CB278
11 changed files with 135 additions and 20 deletions

View file

@ -87,12 +87,12 @@ defmodule Nulla.ActivityPub do
"https://www.w3.org/ns/activitystreams",
Jason.OrderedObject.new(sensitive: "as:sensitive")
],
id: "#{note.actor.ap_id}/statuses/#{note.id}",
id: "#{note.actor.ap_id}/notes/#{note.id}",
type: "Note",
summary: nil,
inReplyTo: nil,
inReplyTo: note.inReplyTo,
published: note.inserted_at,
url: "#{note.actor.ap_id}/#{note.id}",
url: note.url,
attributedTo: note.actor.ap_id,
to: [
"https://www.w3.org/ns/activitystreams#Public"
@ -100,7 +100,7 @@ defmodule Nulla.ActivityPub do
cc: [
"#{note.actor.ap_id}/followers"
],
sensetive: false,
sensitive: note.sensitive,
content: note.content,
contentMap: Jason.OrderedObject.new("#{note.language}": note.content),
attachment: attachment
@ -329,7 +329,7 @@ defmodule Nulla.ActivityPub do
@spec activity_note(Note.t()) :: Jason.OrderedObject.t()
def activity_note(note) do
Jason.OrderedObject.new(
id: "#{note.actor.ap_id}/statuses/#{note.id}/activity",
id: "#{note.actor.ap_id}/notes/#{note.id}/activity",
type: "Create",
actor: note.actor.ap_id,
published: note.inserted_at |> DateTime.to_iso8601(),
@ -338,7 +338,7 @@ defmodule Nulla.ActivityPub do
],
object:
Jason.OrderedObject.new(
id: "#{note.actor.ap_id}/statuses/#{note.id}",
id: "#{note.actor.ap_id}/notes/#{note.id}",
type: "Note",
content: note.content,
published: note.inserted_at |> DateTime.to_iso8601(),

View file

@ -24,7 +24,7 @@ defmodule Nulla.Models.Activity do
end
def create_activity(attrs) do
id = Snowflake.next_id()
id = Map.get(attrs, :id, Snowflake.next_id())
%__MODULE__{}
|> __MODULE__.changeset(attrs)

View file

@ -93,7 +93,7 @@ defmodule Nulla.Models.Actor do
end
def create_actor(attrs) when is_map(attrs) do
id = Snowflake.next_id()
id = Map.get(attrs, :id, Snowflake.next_id())
%__MODULE__{}
|> changeset(attrs)

View file

@ -3,20 +3,22 @@ defmodule Nulla.Models.Note do
import Ecto.Changeset
import Ecto.Query
alias Nulla.Repo
alias Nulla.Snowflake
alias Nulla.Models.Actor
alias Nulla.Models.MediaAttachment
@primary_key {:id, :integer, autogenerate: false}
schema "notes" do
field :content, :string
field :inReplyTo, :string
field :url, :string
field :visibility, Ecto.Enum,
values: [:public, :unlisted, :followers, :private],
default: :public
field :sensitive, :boolean, default: false
field :content, :string
field :language, :string
field :in_reply_to, :string
belongs_to :actor, Actor
has_many :media_attachments, MediaAttachment
@ -27,11 +29,20 @@ defmodule Nulla.Models.Note do
@doc false
def changeset(note, attrs) do
note
|> cast(attrs, [:content, :visibility, :sensitive, :language, :in_reply_to, :actor_id])
|> validate_required([:content, :visibility, :sensitive, :language, :in_reply_to, :actor_id])
|> cast(attrs, [:content, :visibility, :sensitive, :language, :inReplyTo, :actor_id])
|> validate_required([:content, :visibility, :sensitive, :language, :actor_id])
end
def get_note!(id), do: Repo.get!(__MODULE__, id)
def create_note(attrs) when is_map(attrs) do
id = Map.get(attrs, :id, Snowflake.next_id())
%__MODULE__{}
|> changeset(attrs)
|> put_change(:id, id)
|> Repo.insert()
end
def get_note(id), do: Repo.get(__MODULE__, id)
def get_latest_notes(actor_id, limit \\ 20) do
from(n in __MODULE__,

View file

@ -53,7 +53,7 @@ defmodule Nulla.Models.Relation do
end
def create_relation(attrs) do
id = Snowflake.next_id()
id = Map.get(attrs, :id, Snowflake.next_id())
%__MODULE__{}
|> __MODULE__.changeset(attrs)

View file

@ -95,3 +95,9 @@ defmodule NullaWeb.ActorHTML do
end
end
end
defmodule NullaWeb.NoteHTML do
use NullaWeb, :html
embed_templates "templates/note/*"
end

View file

@ -0,0 +1,22 @@
<main class="grid grid-cols-[25%_50%_25%]">
<div class="flex flex-col items-center mt-5 gap-5">
<input
placeholder="Search"
class="border border-gray-300 px-4 py-3 rounded-xl outline-none w-[90%]"
/>
<div class="text-sm rounded-xl border border-gray-300 p-2 w-[90%]">
<textarea
placeholder="What's on your mind?"
class="h-[150px] w-full resize-none border-none focus:ring-0"
></textarea>
<div>
<button class="text-white bg-black px-3 py-1 rounded-xl">Post</button>
</div>
</div>
</div>
<div class="relative border border-gray-300 shadow-md mt-5 rounded-t-xl overflow-hidden">
</div>
<div class="flex flex-col items-center mt-5 gap-5">
<div class="text-sm rounded-xl border border-gray-300 p-4 w-[90%] h-[300px]"></div>
</div>
</main>

View file

@ -6,12 +6,12 @@ defmodule NullaWeb.NoteController do
def show(conn, %{"username" => username, "id" => id}) do
accept = List.first(get_req_header(conn, "accept"))
note = Note.get_note!(id) |> Repo.preload([:user, :media_attachments])
note = Note.get_note(id) |> Repo.preload([:actor, :media_attachments])
if username != note.user.username do
if username != note.actor.preferredUsername do
conn
|> put_status(:not_found)
|> json(%{error: "Note not found"})
|> json(%{error: "Not Found"})
|> halt()
end

View file

@ -35,7 +35,7 @@ defmodule NullaWeb.Router do
get "/followers", FollowController, :followers
post "/inbox", InboxController, :inbox
get "/outbox", OutboxController, :outbox
get "/statuses/:id", NoteController, :show
get "/notes/:id", NoteController, :show
end
scope "/@:username" do