Skip to content

Commit

Permalink
Merge pull request #1478 from hippware/1474-active-bots-connection
Browse files Browse the repository at this point in the history
Active bots connection
  • Loading branch information
bernardd authored May 2, 2018
2 parents 62cfee2 + 191b4de commit 6912709
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 86 deletions.
15 changes: 15 additions & 0 deletions apps/wocky/lib/wocky/bot/bot.ex
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,21 @@ defmodule Wocky.Bot do
user
|> by_relationship_query(:subscribed)
|> where([..., s], s.visitor)
|> order_by([..., s], desc: s.visited_at)
end

@spec active_bots_query(User.t()) :: Ecto.Queryable.t()
def active_bots_query(user) do
user
|> by_relationship_query(:guest)
|> is_visible_query(user)
|> join(
:inner,
[b],
a in "bot_activity",
b.id == a.bot_id
)
|> order_by([..., a], desc: a.visited_at)
end

@spec subscribers_query(t, boolean()) :: [User.t()]
Expand Down
19 changes: 17 additions & 2 deletions apps/wocky/lib/wocky/bot/subscription.ex
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ defmodule Wocky.Bot.Subscription do
field :bot_id, :binary_id, primary_key: true
field :guest, :boolean, default: false
field :visitor, :boolean, default: false
field :visited_at, :utc_datetime
field :departed_at, :utc_datetime

timestamps()

Expand Down Expand Up @@ -58,9 +60,16 @@ defmodule Wocky.Bot.Subscription do
def depart(user, bot), do: visit(user, bot, false)

defp visit(user, bot, enter) do
timestamps =
if enter do
[visited_at: DateTime.utc_now(), departed_at: nil]
else
[departed_at: DateTime.utc_now()]
end

Subscription
|> where(user_id: ^user.id, bot_id: ^bot.id)
|> Repo.update_all(set: [visitor: enter])
|> Repo.update_all(set: [visitor: enter] ++ timestamps)

:ok
end
Expand All @@ -79,7 +88,13 @@ defmodule Wocky.Bot.Subscription do
end

defp maybe_set_visitor(changes, true), do: changes
defp maybe_set_visitor(changes, false), do: Map.put(changes, :visitor, false)

defp maybe_set_visitor(changes, false) do
changes
|> Map.put(:visitor, false)
|> Map.put(:visited_at, nil)
|> Map.put(:departed_at, nil)
end

defp make_changeset(changes), do: changeset(%Subscription{}, changes)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
defmodule Wocky.Repo.Migrations.AddVisitTimestamps do
use Wocky.Repo.Migration

def change do
alter table(:bot_subscriptions) do
add :visited_at, :timestamptz
add :departed_at, :timestamptz
end

flush()

execute """
CREATE VIEW bot_activity AS
SELECT bot_id, MAX(visited_at) AS visited_at
FROM bot_subscriptions AS subs
WHERE EXISTS (
SELECT 1
FROM bot_subscriptions
WHERE bot_id = subs.bot_id
AND visitor
)
GROUP BY bot_id;
"""
end
end
2 changes: 1 addition & 1 deletion apps/wocky_api/lib/wocky_api/channels/user_socket.ex
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ defmodule WockyAPI.UserSocket do
{:ok, socket}
end

defp host() do
defp host do
{:ok, host} = :inet.gethostname()
to_string(host)
end
Expand Down
2 changes: 1 addition & 1 deletion apps/wocky_api/lib/wocky_api/plugs/absinthe_conn_data.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ defmodule WockyAPI.Plugs.AbsintheConnData do
to_string(:inet.ntoa(addr)) <> ":" <> to_string(port)
end

defp host() do
defp host do
{:ok, host} = :inet.gethostname()
to_string(host)
end
Expand Down
6 changes: 6 additions & 0 deletions apps/wocky_api/lib/wocky_api/resolvers/bot.ex
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,12 @@ defmodule WockyAPI.Resolvers.Bot do
{:ok, Bot.lon(bot)}
end

def get_active_bots(_root, args, %{context: %{current_user: user}}) do
user
|> Bot.active_bots_query()
|> Utils.connection_from_query(user, args)
end

def create_bot(_root, args, %{context: %{current_user: user}}) do
args[:input][:values]
|> parse_lat_lon()
Expand Down
1 change: 1 addition & 0 deletions apps/wocky_api/lib/wocky_api/resolvers/utils.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ defmodule WockyAPI.Resolvers.Utils do
defp get_count(query) do
query
|> exclude(:preload)
|> exclude(:order_by)
|> select([x], count(1))
|> Repo.one()
|> Kernel.||(0)
Expand Down
3 changes: 3 additions & 0 deletions apps/wocky_api/lib/wocky_api/schema/bot_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ defmodule WockyAPI.Schema.BotTypes do
enum :subscription_type do
@desc "A user who is subscribed to the bot"
value :subscriber

@desc """
A user who is subscribed to the bot and is a guest
(entry/exit will be reported)
"""
value :guest

@desc """
A user who is subscribed to the bot and is a guest who is currently
visiting the bot
Expand Down Expand Up @@ -188,6 +190,7 @@ defmodule WockyAPI.Schema.BotTypes do
input do
@desc "ID of bot to which to subscribe"
field :id, non_null(:uuid)

@desc """
Whether to enable guest functionality for the user (default: false)
"""
Expand Down
54 changes: 32 additions & 22 deletions apps/wocky_api/lib/wocky_api/schema/user_types.ex
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ defmodule WockyAPI.Schema.UserTypes do
field :tagline, :string
@desc "A list of roles assigned to the user"
field :roles, non_null(list_of(non_null(:string)))
@desc "The user's ID for the external auth system (eg Firebase or Digits)"
field :external_id, :string
@desc "The user's phone number in E.123 international notation"
field :phone_number, :string
field :email, :string

@desc "Bots related to the user specified by either relationship or ID"
connection field :bots, node_type: :bots do
Expand All @@ -42,12 +37,6 @@ defmodule WockyAPI.Schema.UserTypes do
resolve &Bot.get_bots/3
end

@desc "The user's location history for a given device"
connection field :locations, node_type: :locations do
arg :device, non_null(:string)
resolve &User.get_locations/3
end

@desc """
The user's contacts (ie the XMPP roster) optionally filtered by relationship
"""
Expand All @@ -56,6 +45,36 @@ defmodule WockyAPI.Schema.UserTypes do
resolve &User.get_contacts/3
end

@desc "The user's owned bot collections"
connection field :collections, node_type: :collections do
resolve &Collection.get_collections/3
end

@desc "Bot collections to which the user is subscribed"
connection field :subscribed_collections, node_type: :collections do
resolve &Collection.get_subscribed_collections/3
end
end

object :current_user do
import_fields :user

@desc "The user's ID for the external auth system (eg Firebase or Digits)"
field :external_id, :string
@desc "The user's phone number in E.123 international notation"
field :phone_number, :string
field :email, :string

connection field :active_bots, node_type: :bots do
resolve &Bot.get_active_bots/3
end

@desc "The user's location history for a given device"
connection field :locations, node_type: :locations do
arg :device, non_null(:string)
resolve &User.get_locations/3
end

@desc "The user's home stream items"
connection field :home_stream, node_type: :home_stream do
resolve &User.get_home_stream/3
Expand All @@ -67,16 +86,6 @@ defmodule WockyAPI.Schema.UserTypes do
connection field :conversations, node_type: :conversations do
resolve &User.get_conversations/3
end

@desc "The user's owned bot collections"
connection field :collections, node_type: :collections do
resolve &Collection.get_collections/3
end

@desc "Bot collections to which the user is subscribed"
connection field :subscribed_collections, node_type: :collections do
resolve &Collection.get_subscribed_collections/3
end
end

enum :user_bot_relationship do
Expand Down Expand Up @@ -170,6 +179,7 @@ defmodule WockyAPI.Schema.UserTypes do
field :other_jid, non_null(:string)
@desc "The contents of the message"
field :message, non_null(:string)

@desc """
True if the message was sent from the user,
false if it was received by them.
Expand Down Expand Up @@ -224,7 +234,7 @@ defmodule WockyAPI.Schema.UserTypes do

object :user_queries do
@desc "Retrive the currently authenticated user"
field :current_user, :user do
field :current_user, :current_user do
resolve &User.get_current_user/3
end

Expand Down
73 changes: 73 additions & 0 deletions apps/wocky_api/test/wocky_api/graphql/bot_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,79 @@ defmodule WockyAPI.GraphQL.BotTest do
end
end

describe "active bots" do
setup %{user: user, bot: bot, user2: user2, bot2: bot2} do
Bot.subscribe(bot, user, true)
Bot.subscribe(bot2, user, true)
Bot.visit(bot, user, false)

Bot.subscribe(bot2, user2, true)
Bot.visit(bot2, user2, false)

for b <- Factory.insert_list(3, :bot, public: true) do
Bot.subscribe(b, user, true)
end

:ok
end

@query """
{
currentUser {
activeBots(first: 5) {
edges {
node {
id
subscribers(first: 5, type: VISITOR) {
edges {
node {
id
}
}
}
}
}
}
}
}
"""

test "get active bots", %{user: user, bot: bot, user2: user2, bot2: bot2} do
result = run_query(@query, user)

refute has_errors(result)

assert result.data == %{
"currentUser" => %{
"activeBots" => %{
"edges" => [
%{
"node" => %{
"id" => bot2.id,
"subscribers" => %{
"edges" => [
%{"node" => %{"id" => user2.id}}
]
}
}
},
%{
"node" => %{
"id" => bot.id,
"subscribers" => %{
"edges" => [
%{"node" => %{"id" => user.id}}
]
}
}
}
]
}
}
}
end
end

describe "bot mutations" do
test "create bot", %{user: user} do
fields = [:title, :server, :lat, :lon, :radius, :description, :shortname]
Expand Down
Loading

0 comments on commit 6912709

Please sign in to comment.