Skip to content

Commit bea7bbd

Browse files
committed
add vrchat world filter based on content tags
1 parent 3ee09e7 commit bea7bbd

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,5 @@ vrhose-*.tar
2929
.Elixir*.zig
3030
priv/lib
3131
*.db*
32+
33+
.envrc

lib/vrhose/hydrator.ex

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,47 @@ defmodule VRHose.Hydrator do
3535
)
3636
end
3737

38-
defp process({did, post_data, subscribers} = event) do
38+
defp process({_did, post_data, _subscribers} = event) do
39+
if post_data.world_id == nil do
40+
process_post(event)
41+
else
42+
is_good? = is_good_world?(post_data.world_id)
43+
Logger.warning("is wrld #{post_data.world_id} good? #{inspect(is_good?)}")
44+
45+
if is_good? do
46+
process_post(event)
47+
end
48+
end
49+
end
50+
51+
@unwanted_tags [
52+
"content_sex",
53+
"content_adult"
54+
]
55+
56+
defp is_good_world?(wrld_id) do
57+
case VRHose.VRChatWorld.fetch(wrld_id) do
58+
{:ok, nil} ->
59+
true
60+
61+
{:ok, world} ->
62+
matches_unwanted_tags? =
63+
world.tags
64+
|> Jason.decode!()
65+
|> Enum.map(fn tag ->
66+
tag in @unwanted_tags
67+
end)
68+
|> Enum.any?()
69+
70+
# wanted when unwanted tags arent in the world
71+
not matches_unwanted_tags?
72+
73+
{:error, _} ->
74+
true
75+
end
76+
end
77+
78+
defp process_post({did, post_data, subscribers} = event) do
3979
identity = VRHose.Identity.one(did)
4080

4181
post_data =

lib/vrhose/vrchat_world.ex

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
defmodule VRHose.VRChatWorld do
2+
use Ecto.Schema
3+
import Ecto.Query
4+
import Ecto.Changeset
5+
alias VRHose.Repo
6+
7+
@type t :: %__MODULE__{}
8+
9+
schema "vrchat_worlds" do
10+
field(:wrld_id, :string)
11+
field(:name, :string)
12+
field(:author_id, :string)
13+
field(:tags, :string)
14+
field(:capacity, :integer)
15+
field(:description, :string)
16+
timestamps(autogenerate: {VRHose.Data, :generate_unix_timestamp, []})
17+
end
18+
19+
def one(wrld_id) do
20+
query = from(s in __MODULE__, where: s.wrld_id == ^wrld_id, select: s)
21+
Repo.replica(wrld_id).one(query, log: false)
22+
end
23+
24+
def changeset(%__MODULE__{} = world, params) do
25+
world
26+
|> cast(params, [:wrld_id, :name, :author_id, :tags, :capacity, :description])
27+
|> validate_required([:wrld_id, :name, :author_id, :tags, :capacity, :description])
28+
end
29+
30+
def insert(wrld_id, name, author_id, tags, capacity, description) do
31+
%__MODULE__{}
32+
|> changeset(%{
33+
wrld_id: wrld_id,
34+
name: name,
35+
author_id: author_id,
36+
tags: tags,
37+
capacity: capacity,
38+
description: description
39+
})
40+
|> Repo.insert()
41+
end
42+
43+
def fetch(wrld_id) do
44+
maybe_world = one(wrld_id)
45+
46+
if maybe_world == nil do
47+
{:ok, resp} = fetch_upstream(wrld_id)
48+
49+
tags =
50+
resp.body["tags"]
51+
|> Enum.filter(fn tag ->
52+
String.starts_with?(tag, "content_")
53+
end)
54+
|> Jason.encode!()
55+
56+
insert(
57+
resp.body["id"],
58+
resp.body["name"],
59+
resp.body["authorId"],
60+
tags,
61+
resp.body["capacity"],
62+
resp.body["description"]
63+
)
64+
else
65+
{:ok, maybe_world}
66+
end
67+
end
68+
69+
defp fetch_upstream(wrld_id) do
70+
operator_email = System.get_env("VRHOSE_OPERATOR_EMAIL")
71+
72+
if operator_email == nil do
73+
{:error, :no_operator_email}
74+
else
75+
Req.get("https://api.vrchat.cloud/api/1/worlds/#{wrld_id}",
76+
headers: [{"User-Agent", "BlueskyFirehoseVR/0.0.0 #{operator_email}"}]
77+
)
78+
end
79+
end
80+
end
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
defmodule VRHose.Repo.Migrations.AddWorldLabels do
2+
use Ecto.Migration
3+
4+
def change do
5+
create table(:vrchat_worlds) do
6+
add(:wrld_id, :text, null: false)
7+
add(:name, :text, null: false)
8+
add(:author_id, :text, null: false)
9+
add(:tags, :text, null: false)
10+
add(:capacity, :integer, null: false)
11+
add(:description, :text, null: false)
12+
timestamps()
13+
end
14+
15+
create(unique_index(:vrchat_worlds, [:wrld_id]))
16+
end
17+
end

0 commit comments

Comments
 (0)