Current section

Files

Jump to
urbit_ex lib json graph_store.ex
Raw

lib/json/graph_store.ex

defmodule UrbitEx.GraphStore do
alias UrbitEx.Utils
alias UrbitEx.{Resource, Post, Node}
# this works for both groups and channels, "leave" is different for some reason
def join_resource(resource) do
%{
join: %{
resource: resource,
ship: resource.ship
}
}
end
def leave_group(resource) do
%{
leave: %{
ship: resource.ship,
name: resource.name
}
}
end
def leave_channel(resource) do
%{
leave: %{
resource: resource
}
}
end
def create_group(name, title, description, "open", opts) do
banned_ranks = Keyword.get(opts, :banned_ranks) || []
banned_ships = Keyword.get(opts, :banned_ships) || []
banned_ranks = Enum.map(banned_ranks, &Utils.add_tilde/1)
banned_ships = Enum.map(banned_ships, &Utils.add_tilde/1)
%{
create: %{
name: name |> Utils.group_name(),
title: title,
description: description,
policy: %{
open: %{
banRanks: banned_ranks,
banned: banned_ships
}
}
}
}
end
def create_group(name, title, description, "invite", opts) do
invitees = Keyword.get(opts, :invitees) || []
invitees = Enum.map(invitees, &Utils.add_tilde/1)
%{
create: %{
name: name |> String.downcase() |> String.replace(" ", "-"),
title: title,
description: description,
policy: %{
invite: %{
pending: invitees
}
}
}
}
end
def delete_group(resource) do
%{
remove: %{
ship: resource.ship,
name: resource.name
}
}
end
def change_group_policy(resource, type) do
%{
changePolicy: %{
diff: %{
replace: policy_change(type)
},
resource: resource
}
}
end
defp policy_change(:to_public), do: %{open: %{banned: [], banRanks: []}}
defp policy_change(:to_private), do: %{invite: %{pending: []}}
def ban_from_group(resource, type, targets) do
%{
changePolicy: %{
resource: resource,
diff: %{
open: banned_target(type, targets)
}
}
}
end
defp banned_target(:ships, targets), do: %{banShips: targets}
defp banned_target(:ranks, targets), do: %{banRanks: targets}
def invite_to_group(resource, invitees, message) do
%{
invite: %{
ships: invitees,
description: message,
resource: resource
}
}
end
def kick_from_group(group, ships) do
%{
removeMembers: %{
resource: group,
ships: ships
}
}
end
def accept_invite() do
end
def leave_channel(resource) do
%{
leave: %{
resource: %{
ship: resource.ship,
name: resource.name
}
}
}
end
def create_channel(ship, group, title, name, description, type, association, invitees) do
channel_name = if String.starts_with?(name, "dm"), do: name, else: Utils.channel_name(name)
%{
create: %{
title: title,
description: description,
module: type,
mark: "graph-validator-#{type}",
resource:
Resource.new(
ship,
channel_name
),
associated: branch_channel(association, group, invitees)
}
}
end
defp branch_channel(:group, group, _), do: %{group: group}
defp branch_channel(:private, _, invitees), do: %{policy: %{invite: %{pending: invitees}}}
def delete_channel(resource), do: %{delete: %{resource: resource}}
def enable_group_feed(resource, permission) do
%{
"create-group-feed": %{
resource: resource,
vip: permission
}
}
end
def disable_group_feed(resource) do
%{
"disable-group-feed": %{
resource: resource
}
}
end
# feed posts use this too
def send_message(author, resource, message, custom) do
contents = if custom, do: custom, else: Utils.tokenize(message)
contents
|> build_post(author)
|> build_node()
|> wrap_node(resource)
end
def add_collection_link(author, resource, text, url) do
build_collection_link(text, url)
|> build_post(author)
|> build_node()
|> wrap_node(resource)
end
def add_notebook_post(author, resource, title, text, custom) do
contents = if custom, do: custom, else: build_notebook_post(title, text)
container = build_post([], author)
post_wrapper = build_post([], author) |> Map.put(:index, "#{container.index}/1")
comments_wrapper = build_post([], author) |> Map.put(:index, "#{container.index}/2")
post = build_post(contents, author) |> Map.put(:index, "#{container.index}/1/1")
post_node = build_child_node(post, 1)
post_wrapper_node = build_child_node(post_wrapper, 1, post_node)
comments_wrapper_node = build_child_node(comments_wrapper, 2)
container_node =
build_node(container, Map.merge(post_wrapper_node, comments_wrapper_node))
|> wrap_node(resource)
end
def edit_post(author, resource, new_index, title, text, custom) do
contents = if custom, do: custom, else: build_notebook_post(title, text)
post = build_post(contents, author) |> Map.put(:index, new_index)
post_node =
build_node(post)
|> wrap_node(resource)
end
# to delete graphs with wrappers you need to specify all indexes
def add_comment(author, resource, index, text, custom) do
contents = if custom, do: custom, else: Utils.tokenize(text)
comment_wrapper = build_post([], author)
comment_wrapper = Map.put(comment_wrapper, :index, "#{index}/2#{comment_wrapper.index}")
comment =
build_post(contents, author)
|> Map.put(:index, "#{comment_wrapper.index}/1")
comment_node = build_child_node(comment, 1)
build_node(comment_wrapper, comment_node)
|> wrap_node(resource)
end
def edit_comment(author, resource, new_index, text, custom) do
contents = if custom, do: custom, else: Utils.tokenize(text)
post = build_post(contents, author) |> Map.put(:index, new_index)
post_node =
build_node(post)
|> wrap_node(resource)
end
defp build_collection_link(text, url) do
[%{text: text}, %{url: url}]
end
defp build_notebook_post(title, body), do: [%{text: title} | Utils.tokenize(body)]
defp build_post(contents, author) do
timestamp = System.os_time(:millisecond)
index = "/#{Utils.calculate_index(timestamp)}"
# need some logic here to check if already there
author = "~#{author}"
%UrbitEx.Post{
author: author,
contents: contents,
"time-sent": timestamp,
index: index
}
end
defp build_node(post, children \\ nil) do
%{post.index => %{post: post, children: children}}
end
defp build_child_node(post, index, children \\ nil) do
%{index => %{post: post, children: children}}
end
defp wrap_node(node, resource) do
%{
"add-nodes": %{
resource: resource,
nodes: node
}
}
end
# comments remove two indices, main and main/1
def remove_node(resource, indices) do
%{
"remove-posts": %{
resource: %{
name: resource.name,
ship: resource.ship
},
indices: indices
}
}
end
end