Add following and followers

This commit is contained in:
Mirai Kumiko 2025-06-11 15:03:21 +02:00
parent f8bedff913
commit 0b88881934
Signed by: miraikumiko
GPG key ID: 3F178B1B5E0CB278
8 changed files with 261 additions and 4 deletions

View file

@ -139,4 +139,90 @@ defmodule Nulla.ActivityPub do
to: activity.to
)
end
@spec following(String.t(), Nulla.Models.User.t(), Integer.t()) :: Jason.OrderedObject.t()
def following(domain, user, total) do
Jason.OrderedObject.new(
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://#{domain}/@#{user.username}/following",
type: "OrderedCollection",
totalItems: total,
first: "https://#{domain}/@#{user.username}/following?page=1"
)
end
@spec following(String.t(), Nulla.Models.User.t(), Integer.t(), List.t(), Integer.t(), Integer.t()) :: Jason.OrderedObject.t()
def following(domain, user, total, following_list, page, offset) when is_integer(page) and page > 0 do
data = [
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://#{domain}/@#{user.username}/following?page=#{page}",
type: "OrderedCollectionPage",
totalItems: total,
next: "https://#{domain}/@#{user.username}/following?page=#{page + 1}",
prev: "https://#{domain}/@#{user.username}/following?page=#{page - 1}",
partOf: "https://#{domain}/@#{user.username}/following",
orderedItems: following_list
]
data =
if page <= 1 do
Keyword.delete(data, :prev)
else
data
end
data =
if page * offset > total do
data
|> Keyword.delete(:next)
|> Keyword.delete(:prev)
else
data
end
Jason.OrderedObject.new(data)
end
@spec followers(String.t(), Nulla.Models.User.t(), Integer.t()) :: Jason.OrderedObject.t()
def followers(domain, user, total) do
Jason.OrderedObject.new(
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://#{domain}/@#{user.username}/followers",
type: "OrderedCollection",
totalItems: total,
first: "https://#{domain}/@#{user.username}/followers?page=1"
)
end
@spec followers(String.t(), Nulla.Models.User.t(), Integer.t(), List.t(), Integer.t(), Integer.t()) :: Jason.OrderedObject.t()
def followers(domain, user, total, followers_list, page, offset) when is_integer(page) and page > 0 do
data = [
"@context": "https://www.w3.org/ns/activitystreams",
id: "https://#{domain}/@#{user.username}/followers?page=#{page}",
type: "OrderedCollectionPage",
totalItems: total,
next: "https://#{domain}/@#{user.username}/followers?page=#{page + 1}",
prev: "https://#{domain}/@#{user.username}/followers?page=#{page - 1}",
partOf: "https://#{domain}/@#{user.username}/followers",
orderedItems: followers_list
]
data =
if page <= 1 do
Keyword.delete(data, :prev)
else
data
end
data =
if page * offset > total do
data
|> Keyword.delete(:next)
|> Keyword.delete(:prev)
else
data
end
Jason.OrderedObject.new(data)
end
end

View file

@ -11,6 +11,7 @@ defmodule Nulla.Models.InstanceSettings do
field :registration, :boolean, default: false
field :max_characters, :integer, default: 5000
field :max_upload_size, :integer, default: 50
field :offset, :integer, default: 100
field :public_key, :string
field :private_key, :string
end
@ -25,6 +26,7 @@ defmodule Nulla.Models.InstanceSettings do
:registration,
:max_characters,
:max_upload_size,
:offset,
:public_key,
:private_key
])
@ -35,6 +37,7 @@ defmodule Nulla.Models.InstanceSettings do
:registration,
:max_characters,
:max_upload_size,
:offset,
:public_key,
:private_key
])

87
lib/nulla/utils.ex Normal file
View file

@ -0,0 +1,87 @@
defmodule Nulla.Utils do
import Ecto.Query
alias Nulla.Repo
alias Nulla.Models.User
alias Nulla.Models.Follow
alias Nulla.Models.InstanceSettings
def count_following_by_username!(username) do
case Repo.get_by(User, username: username) do
nil ->
{:error, :user_not_found}
%User{id: user_id} ->
count =
Follow
|> where([f], f.user_id == ^user_id)
|> select([f], count(f.id))
|> Repo.one()
count
end
end
def get_following_users_by_username!(username, page) when is_integer(page) and page > 0 do
case Repo.get_by(User, username: username) do
nil ->
{:error, :user_not_found}
%User{id: user_id} ->
instance_settings = InstanceSettings.get_instance_settings!()
per_page = instance_settings.offset
offset = (page - 1) * per_page
query =
from [f, u] in
from(f in Follow,
join: u in User, on: u.id == f.target_id,
where: f.user_id == ^user_id,
order_by: [asc: u.inserted_at],
offset: ^offset,
limit: ^per_page,
select: u
)
users = Repo.all(query)
users
end
end
def count_followers_by_username!(username) do
case Repo.get_by(User, username: username) do
nil ->
0
%User{id: user_id} ->
from(f in Follow, where: f.target_id == ^user_id)
|> select([f], count(f.id))
|> Repo.one()
end
end
def get_followers_by_username!(username, page) when is_integer(page) and page > 0 do
case Repo.get_by(User, username: username) do
nil ->
{:error, :user_not_found}
%User{id: user_id} ->
instance_settings = InstanceSettings.get_instance_settings!()
per_page = instance_settings.offset
offset = (page - 1) * per_page
query =
from f in Follow,
where: f.target_id == ^user_id,
join: u in User, on: u.id == f.user_id,
order_by: [asc: u.inserted_at],
offset: ^offset,
limit: ^per_page,
select: u
users = Repo.all(query)
users
end
end
end