Packages
ami
0.2.5
0.3.9
0.3.8
retired
0.3.7
retired
0.3.6
retired
0.3.5
retired
0.3.4
retired
0.3.3
retired
0.3.2
retired
0.3.1
retired
0.3.0
retired
0.2.9
retired
0.2.8
retired
0.2.7
retired
0.2.6
retired
0.2.5
retired
0.2.3
retired
0.2.2
retired
0.2.1
retired
0.2.0
retired
0.1.9
retired
0.1.8
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
Package containing all AMI Models shared between micro-services.
Retired package: Security issue - retiring
Current section
Files
Jump to
Current section
Files
lib/ami/notification.ex
defmodule Ami.Notification do
use Ecto.Schema
import Ecto.{
Query,
Changeset
}
alias Ami.{
User,
Repo,
Share,
Community,
CoursePeriod,
Enrollment,
Like,
Comment,
Post,
Lesson
}
schema "notifications" do
@timestamps_opts [type: :naive_datetime_usec]
field(:category, :string)
field(:title, :string)
field(:body, :string)
field(:icon, :string)
field(:unread, :boolean, default: true)
field(:broadcasted, :boolean)
field(:created_at, :utc_datetime_usec)
field(:updated_at, :utc_datetime_usec)
belongs_to(:user, User)
end
def unread do
__MODULE__ |> Ecto.Query.where(unread: true)
end
def unread(query) do
query |> Ecto.Query.where(unread: true)
end
def or_unread(query) do
query |> Ecto.Query.or_where(unread: true)
end
def read do
__MODULE__ |> Ecto.Query.where(unread: false)
end
def read(query) do
query |> Ecto.Query.where(unread: false)
end
def for_user(user_id) do
__MODULE__ |> Ecto.Query.where(user_id: ^user_id)
end
def for_user(query, user_id) do
query |> Ecto.Query.where(user_id: ^user_id)
end
def with_limit(limit) do
__MODULE__ |> Ecto.Query.limit(^limit)
end
def with_limit(query, limit) do
query |> Ecto.Query.limit(^limit)
end
def order_by_creation_date(query) do
query |> Ecto.Query.order_by(desc: :created_at)
end
def exclude_ids(query, ids) do
from(n in query, where: n.id not in ^ids)
end
def for_user_navbar(user_id, limit \\ 5) do
query = for_user(user_id) |> unread() |> with_limit(limit) |> order_by_creation_date()
Repo.all(query)
end
def unread_count_for_user(user_id) do
from(
n in __MODULE__,
where: n.unread == true and n.user_id == ^user_id,
select: count(n.id)
)
|> Repo.one()
end
def latest_activities_for(user) do
from(
n in __MODULE__,
where: n.user_id == ^user.id,
where: n.category in ["Post", "Comment", "Course", "Community"],
order_by: [desc: :created_at],
limit: 5
)
|> Repo.all()
end
def clear_old_notifications_for_user(user_id, time_in_month \\ 1) do
from(
n in __MODULE__,
where: n.user_id == ^user_id,
where: n.created_at <= ^Timex.shift(Timex.now(), months: -time_in_month)
)
|> Repo.delete_all()
end
def send(notification) do
AmiWeb.Endpoint.broadcast!("notification:#{notification.user_id}", "new_notification", %{
notification_id: notification.id
})
notification
end
def create(%{} = params) do
%__MODULE__{}
|> cast(params, [:user_id, :category, :title, :icon, :body])
|> cast(%{created_at: DateTime.utc_now(), updated_at: DateTime.utc_now()}, [
:created_at,
:updated_at
])
|> validate_required([:user_id, :body])
|> Repo.insert()
end
def notify_of_post_sharing(%{
post_id: post_id,
message: message,
recipient_id: "#all",
user_id: user_id,
community: community,
socket: socket
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
Community.community_members(community)
|> Enum.each(fn recipient ->
post_url = "/my_resources/#{recipient.id}/community/#{community.id}##{post_id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, socket)
notification =
%{
user_id: recipient.id,
category: "Post",
title: "Share",
icon: profile_pic_url,
body: """
#{User.user_name(author)} thinks you would like this Post in #{community.title}. <em>“#{
message
}“</em>. You can see and comment on the post <a href=#{post_url}>here</a>.
.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Post", post_id, user_id)
end)
share_count = share_count_for(post_id, "Post")
{:ok, share_count, post_id}
end
def notify_of_post_sharing(%{
post_id: post_id,
message: message,
recipient_id: recipient_id,
user_id: user_id,
community: community,
socket: socket
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
recipient = Repo.one(from(u in User, where: u.uuid == ^recipient_id))
post_url = "/my_resources/#{recipient.id}/community/#{community.id}##{post_id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, socket)
notification =
%{
user_id: recipient.id,
category: "Post",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Post in #{community.title}. <em>“#{
message
}“</em>. You can see and comment on the post <a href=#{post_url}>here</a>.
.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Post", post_id, user_id)
share_count = share_count_for(post_id, "Post")
{:ok, share_count, post_id}
end
def notify_of_post_sharing(%{
post_id: post_id,
message: message,
recipient_id: "#all",
user_id: user_id,
course_period_id: course_period_id,
lesson: lesson,
socket: socket
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
course_period = Repo.get(CoursePeriod, course_period_id) |> Repo.preload(:course)
recipients = CoursePeriod.students_for(course_period) |> Enum.map(fn enr -> enr.user end)
Enum.map(recipients, fn recipient ->
enrollment =
Repo.one(
from(
e in Enrollment,
where: e.user_id == ^recipient.id and e.course_period_id == ^course_period_id
)
)
post_url =
"/course/#{recipient.id}/#{course_period.course_id}/#{enrollment.id}/show?lesson_id=#{
lesson.id
}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, socket)
notification =
%{
user_id: recipient.id,
category: "Post",
title: "Share",
icon: profile_pic_url,
body: """
#{User.user_name(author)} thinks you would like this Post in #{
course_period.course.title
}, lesson: #{lesson.title}. <em>“#{message}“</em>. You can see and comment on the post <a href=#{
post_url
}>here</a>.
.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Post", post_id, user_id)
end)
share_count = share_count_for(post_id, "Post")
{:ok, share_count, post_id}
end
def notify_of_post_sharing(%{
post_id: post_id,
message: message,
recipient_id: recipient_id,
user_id: user_id,
course_period_id: course_period_id,
lesson: lesson,
socket: socket
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
course_period = Repo.get(CoursePeriod, course_period_id) |> Repo.preload(:course)
recipient = Ami.Repo.one(from(u in Ami.User, where: u.uuid == ^recipient_id))
enrollment =
Repo.one(
from(
e in Enrollment,
where: e.user_id == ^recipient.id and e.course_period_id == ^course_period_id
)
)
post_url =
"/course/#{recipient.id}/#{course_period.course_id}/#{enrollment.id}/show?lesson_id=#{
lesson.id
}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, socket)
notification =
%{
user_id: recipient.id,
category: "Post",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Post in #{
course_period.course.title
}, lesson: #{lesson.title}. <em>“#{message}“</em>. You can see and comment on the post <a href=#{
post_url
}>here</a>.
.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Post", post_id, user_id)
share_count = share_count_for(post_id, "Post")
{:ok, share_count, post_id}
end
def notify_of_liking(%Like{likeable_type: "Post"} = like, %{
recipient_id: recipient_id,
context: %Community{} = community,
socket: socket
}) do
post_url = "/my_resources/#{recipient_id}/community/#{community.id}##{like.likeable_id}"
profile_pic_url = AmiWeb.LayoutView.user_image(like.user.profile, socket)
%{
user_id: recipient_id,
category: "Post",
title: "Like",
icon: profile_pic_url,
body:
"#{User.user_name(like.user)} liked your <a href=#{post_url}>post</a> in #{
community.title
}"
}
|> create_and_send()
end
def notify_of_liking(%Like{likeable_type: "Post"} = like, %{
recipient_id: recipient_id,
context: %Lesson{} = lesson,
socket: socket
}) do
post = Repo.get(Post, like.likeable_id) |> Repo.preload(course_period: :course)
enrollment =
Repo.one(
from(
e in Enrollment,
where: e.user_id == ^recipient_id and e.course_period_id == ^post.course_period_id
)
)
post_url =
"/course/#{recipient_id}/#{post.course_period.course_id}/#{enrollment.id}/show?lesson_id=#{
lesson.id
}"
profile_pic_url = AmiWeb.LayoutView.user_image(like.user.profile, socket)
%{
user_id: recipient_id,
category: "Post",
title: "Like",
icon: profile_pic_url,
body:
"#{User.user_name(like.user)} liked your <a href=#{post_url}>post</a> in #{
post.course_period.course.title
} course - lesson: #{lesson.title}"
}
|> create_and_send()
end
def notify_of_liking(%Like{likeable_type: "Comment"} = like, %{
recipient_id: recipient_id,
context: %Community{} = community,
socket: socket
}) do
profile_pic_url = AmiWeb.LayoutView.user_image(like.user.profile, socket)
%{
user_id: recipient_id,
category: "Comment",
title: "Like",
icon: profile_pic_url,
body:
"#{User.user_name(like.user)} liked your comment in #{community.title} community wall."
}
|> create_and_send()
end
def notify_of_liking(%Like{likeable_type: "Comment"} = like, %{
recipient_id: recipient_id,
context: %Lesson{} = lesson,
socket: socket
}) do
profile_pic_url = AmiWeb.LayoutView.user_image(like.user.profile, socket)
%{
user_id: recipient_id,
category: "Comment",
title: "Like",
icon: profile_pic_url,
body: "#{User.user_name(like.user)} liked your comment in #{lesson.title} lesson."
}
|> create_and_send()
end
def notify_of_commenting(%Comment{commentable_type: "Post"} = comment, %{
recipient_id: recipient_id,
context: %Community{} = community,
socket: socket
}) do
profile_pic_url = AmiWeb.LayoutView.user_image(comment.user.profile, socket)
post_url = "/my_resources/#{recipient_id}/community/#{community.id}##{comment.commentable_id}"
%{
user_id: recipient_id,
category: "Post",
title: "Comment",
icon: profile_pic_url,
body:
"#{User.user_name(comment.user)} has commented on your post in #{community.title} community wall - <a href=#{
post_url
}>reply now!</a>"
}
|> create_and_send()
end
def notify_of_commenting(%Comment{commentable_type: "Post"} = comment, %{
recipient_id: recipient_id,
context: %Lesson{} = lesson,
socket: socket
}) do
profile_pic_url = AmiWeb.LayoutView.user_image(comment.user.profile, socket)
post = Repo.get(Post, comment.commentable_id) |> Repo.preload(course_period: :course)
%{
user_id: recipient_id,
category: "Post",
title: "Comment",
icon: profile_pic_url,
body:
"#{User.user_name(comment.user)} has commented on your post in #{
post.course_period.course.title
} course - lesson: #{lesson.title}"
}
|> create_and_send()
end
def notify_of_tool_sharing(%{
tool_id: tool_id,
message: message,
recipient_id: "#all",
user_id: user_id,
community: community,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
Community.community_members(community)
|> Enum.each(fn recipient ->
tool_url = "/my_resources/#{recipient.id}/tool/#{tool_id}?community_id=#{community.id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Tool",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Tool in #{community.title}. <em>“#{
message
}“</em>. You can see the tool <a href=#{tool_url}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Tool", tool_id, user_id)
end)
share_count = share_count_for(tool_id, "Tool")
{:ok, share_count, tool_id}
end
def notify_of_tool_sharing(%{
tool_id: tool_id,
message: message,
recipient_id: recipient_id,
user_id: user_id,
community: %Community{} = community,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
recipient = Repo.one(from(u in User, where: u.uuid == ^recipient_id))
tool_url = "/my_resources/#{recipient.id}/tool/#{tool_id}?community_id=#{community.id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Tool",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Tool in #{community.title}. <em>“#{
message
}“</em>. You can see the tool <a href=#{tool_url}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Tool", tool_id, user_id)
share_count = share_count_for(tool_id, "Tool")
{:ok, share_count, tool_id}
end
def notify_of_tool_sharing(%{
tool_id: tool_id,
message: message,
user_id: user_id,
recipient_id: recipient_id,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
recipient = Repo.one(from(u in User, where: u.uuid == ^recipient_id))
tool_url = "/my_resources/#{recipient.id}/tool/#{tool_id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Tool",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Tool. <em>“#{message}“</em>. You can see the tool <a href=#{
tool_url
}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("Tool", tool_id, user_id)
share_count = share_count_for(tool_id, "Tool")
{:ok, share_count, tool_id}
end
def notify_of_toolkit_sharing(%{
toolkit_id: toolkit_id,
message: message,
recipient_id: "#all",
user_id: user_id,
community: community,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
Community.community_members(community)
|> Enum.each(fn recipient ->
toolkit_url =
"/my_resources/#{recipient.id}/toolkit/#{toolkit_id}?community_id=#{community.id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Toolkit",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Toolkit in #{community.title}. <em>“#{
message
}“</em>. You can check it <a href=#{toolkit_url}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("ToolKit", toolkit_id, user_id)
end)
share_count = share_count_for(toolkit_id, "ToolKit")
{:ok, share_count, toolkit_id}
end
def notify_of_toolkit_sharing(%{
toolkit_id: toolkit_id,
message: message,
recipient_id: recipient_id,
user_id: user_id,
community: community,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
recipient = Repo.one(from(u in User, where: u.uuid == ^recipient_id))
toolkit_url =
"/my_resources/#{recipient.id}/toolkit/#{toolkit_id}?community_id=#{community.id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Toolkit",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Toolkit in #{community.title}. <em>“#{
message
}“</em>. You can check it <a href=#{toolkit_url}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("ToolKit", toolkit_id, user_id)
share_count = share_count_for(toolkit_id, "ToolKit")
{:ok, share_count, toolkit_id}
end
def notify_of_toolkit_sharing(%{
toolkit_id: toolkit_id,
message: message,
recipient_id: recipient_id,
user_id: user_id,
conn: conn
}) do
author = Repo.get(User, user_id) |> Repo.preload(:profile)
recipient = Repo.one(from(u in User, where: u.uuid == ^recipient_id))
toolkit_url = "/my_resources/#{recipient.id}/toolkit/#{toolkit_id}"
profile_pic_url = AmiWeb.LayoutView.user_image(author.profile, conn)
notification =
%{
user_id: recipient.id,
category: "Toolkit",
title: "Share",
icon: profile_pic_url,
body: """
#{Ami.User.user_name(author)} thinks you would like this Toolkit. <em>“#{message}“</em>. You can check it <a href=#{
toolkit_url
}>here</a>.
"""
}
|> create_and_send()
if %__MODULE__{} = notification, do: create_share("ToolKit", toolkit_id, user_id)
share_count = share_count_for(toolkit_id, "ToolKit")
{:ok, share_count, toolkit_id}
end
def create_and_send(notification_params) do
case __MODULE__.create(notification_params) do
{:ok, notification} ->
__MODULE__.send(notification)
{:error, changeset} ->
{:error, changeset}
end
end
def create_and_send?(notification_params) do
beginning_of_day = Timex.beginning_of_day(DateTime.utc_now())
end_of_day = Timex.end_of_day(DateTime.utc_now())
count =
Ami.Repo.one(
from(
n in __MODULE__,
where: n.user_id == ^notification_params[:user_id],
where: n.category == ^notification_params[:category],
where: n.title == ^notification_params[:title],
where: n.body == ^notification_params[:body],
where: n.created_at >= ^beginning_of_day and n.created_at <= ^end_of_day,
select: count(n.id)
)
)
if count == 0, do: create_and_send(notification_params)
end
defp share_count_for(id, type) do
Repo.one(
from(
s in Ami.Share,
where: s.shareable_type == ^type and s.shareable_id == ^id,
select: count(s.id)
)
)
end
defp create_share(type, resource_id, user_id) do
Share.create_share(%{
shareable_type: type,
shareable_id: resource_id,
user_id: user_id,
created_at: DateTime.utc_now(),
updated_at: DateTime.utc_now()
})
end
end