172 lines
6.1 KiB
Ruby
172 lines
6.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Notifications
|
|
class ConsolidationPlanner
|
|
def consolidate_or_save!(notification)
|
|
plan = plan_for(notification)
|
|
return :no_plan if plan.nil?
|
|
|
|
plan.consolidate_or_save!(notification)
|
|
end
|
|
|
|
private
|
|
|
|
def plan_for(notification)
|
|
consolidation_plans = [
|
|
liked_by_two_users,
|
|
liked,
|
|
linked,
|
|
group_message_summary,
|
|
group_membership,
|
|
new_features_notification,
|
|
]
|
|
consolidation_plans.concat(DiscoursePluginRegistry.notification_consolidation_plans)
|
|
|
|
consolidation_plans.detect { |plan| plan.can_consolidate_data?(notification) }
|
|
end
|
|
|
|
def liked
|
|
ConsolidateNotifications
|
|
.new(
|
|
from: Notification.types[:liked],
|
|
to: Notification.types[:liked_consolidated],
|
|
threshold: -> { SiteSetting.notification_consolidation_threshold },
|
|
consolidation_window: SiteSetting.likes_notification_consolidation_window_mins.minutes,
|
|
unconsolidated_query_blk:
|
|
Proc.new do |notifications, data|
|
|
key = "display_username"
|
|
value = data[key.to_sym]
|
|
filtered = notifications.where("data::json ->> 'username2' IS NULL")
|
|
|
|
filtered = filtered.where("data::json ->> '#{key}' = ?", value) if value
|
|
|
|
filtered
|
|
end,
|
|
consolidated_query_blk: filtered_by_data_attribute("display_username"),
|
|
)
|
|
.set_mutations(
|
|
set_data_blk:
|
|
Proc.new do |notification|
|
|
data = notification.data_hash
|
|
data.merge(username: data[:display_username])
|
|
end,
|
|
)
|
|
.set_precondition(precondition_blk: Proc.new { |data| data[:username2].blank? })
|
|
end
|
|
|
|
def liked_by_two_users
|
|
DeletePreviousNotifications
|
|
.new(
|
|
type: Notification.types[:liked],
|
|
previous_query_blk:
|
|
Proc.new do |notifications, data|
|
|
notifications.where(id: data[:previous_notification_id])
|
|
end,
|
|
)
|
|
.set_mutations(
|
|
set_data_blk:
|
|
Proc.new do |notification|
|
|
existing_notification_of_same_type =
|
|
Notification
|
|
.where(user: notification.user)
|
|
.order("notifications.id DESC")
|
|
.where(topic_id: notification.topic_id, post_number: notification.post_number)
|
|
.where(notification_type: notification.notification_type)
|
|
.where("created_at > ?", 1.day.ago)
|
|
.first
|
|
|
|
data = notification.data_hash
|
|
if existing_notification_of_same_type
|
|
same_type_data = existing_notification_of_same_type.data_hash
|
|
data.merge(
|
|
previous_notification_id: existing_notification_of_same_type.id,
|
|
username2: same_type_data[:display_username],
|
|
count: (same_type_data[:count] || 1).to_i + 1,
|
|
)
|
|
else
|
|
data
|
|
end
|
|
end,
|
|
)
|
|
.set_precondition(
|
|
precondition_blk:
|
|
Proc.new do |data, notification|
|
|
always_freq = UserOption.like_notification_frequency_type[:always]
|
|
|
|
notification.user&.user_option&.like_notification_frequency == always_freq &&
|
|
data[:previous_notification_id].present?
|
|
end,
|
|
)
|
|
end
|
|
|
|
def linked
|
|
ConsolidateNotifications
|
|
.new(
|
|
from: Notification.types[:linked],
|
|
to: Notification.types[:linked_consolidated],
|
|
threshold: -> { SiteSetting.notification_consolidation_threshold },
|
|
consolidation_window: SiteSetting.linked_notification_consolidation_window_mins.minutes,
|
|
unconsolidated_query_blk: filtered_by_data_attribute("display_username"),
|
|
consolidated_query_blk: filtered_by_data_attribute("display_username"),
|
|
)
|
|
.set_mutations(
|
|
set_data_blk:
|
|
Proc.new do |notification|
|
|
data = notification.data_hash
|
|
data.merge(username: data[:display_username])
|
|
end,
|
|
)
|
|
.set_precondition(precondition_blk: Proc.new { |data| data[:username2].blank? })
|
|
end
|
|
|
|
def group_membership
|
|
ConsolidateNotifications
|
|
.new(
|
|
from: Notification.types[:private_message],
|
|
to: Notification.types[:membership_request_consolidated],
|
|
threshold: -> { SiteSetting.notification_consolidation_threshold },
|
|
consolidation_window: Notification::MEMBERSHIP_REQUEST_CONSOLIDATION_WINDOW_HOURS.hours,
|
|
unconsolidated_query_blk: filtered_by_data_attribute("topic_title"),
|
|
consolidated_query_blk: filtered_by_data_attribute("group_name"),
|
|
)
|
|
.set_precondition(precondition_blk: Proc.new { |data| data[:group_name].present? })
|
|
.set_mutations(
|
|
set_data_blk:
|
|
Proc.new do |notification|
|
|
data = notification.data_hash
|
|
post_id = data[:original_post_id]
|
|
custom_field =
|
|
PostCustomField.select(:value).find_by(post_id: post_id, name: "requested_group_id")
|
|
group_id = custom_field&.value
|
|
group_name =
|
|
group_id.present? ? Group.select(:name).find_by(id: group_id.to_i)&.name : nil
|
|
|
|
data[:group_name] = group_name
|
|
data
|
|
end,
|
|
)
|
|
end
|
|
|
|
def group_message_summary
|
|
DeletePreviousNotifications.new(
|
|
type: Notification.types[:group_message_summary],
|
|
previous_query_blk: filtered_by_data_attribute("group_id"),
|
|
).set_precondition(precondition_blk: Proc.new { |data| data[:group_id].present? })
|
|
end
|
|
|
|
def filtered_by_data_attribute(attribute_name)
|
|
Proc.new do |notifications, data|
|
|
if (value = data[attribute_name.to_sym])
|
|
notifications.where("data::json ->> '#{attribute_name}' = ?", value.to_s)
|
|
else
|
|
notifications
|
|
end
|
|
end
|
|
end
|
|
|
|
def new_features_notification
|
|
DeletePreviousNotifications.new(type: Notification.types[:new_features])
|
|
end
|
|
end
|
|
end
|