Skip to content

Commit

Permalink
Merge remote-tracking branch 'parent/main' into upstream-20240308
Browse files Browse the repository at this point in the history
  • Loading branch information
kmycode committed Mar 7, 2024
2 parents 1edf92b + e8605a6 commit fa96bf2
Show file tree
Hide file tree
Showing 106 changed files with 1,103 additions and 249 deletions.
13 changes: 7 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ GEM
jmespath (1.6.2)
json (2.7.1)
json-canonicalization (1.0.0)
json-jwt (1.15.3)
json-jwt (1.15.3.1)
activesupport (>= 4.2)
aes_key_wrap
bindata
Expand Down Expand Up @@ -465,11 +465,11 @@ GEM
statsd-ruby (~> 1.4, >= 1.4.0)
oj (3.16.3)
bigdecimal (>= 3.0)
omniauth (2.1.1)
omniauth (2.1.2)
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
omniauth-cas (3.0.0.beta.1)
omniauth-cas (3.0.0)
addressable (~> 2.8)
nokogiri (~> 1.12)
omniauth (~> 2.1)
Expand Down Expand Up @@ -505,7 +505,7 @@ GEM
parslet (2.0.0)
pastel (0.8.0)
tty-color (~> 0.5)
pg (1.5.5)
pg (1.5.6)
pghero (3.4.1)
activerecord (>= 6)
posix-spawn (0.3.15)
Expand Down Expand Up @@ -543,8 +543,9 @@ GEM
httpclient
json-jwt (>= 1.11.0)
rack (>= 2.1.0)
rack-protection (3.0.5)
rack
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-proxy (0.7.6)
rack
rack-session (1.0.2)
Expand Down
37 changes: 37 additions & 0 deletions app/controllers/api/v1/notifications/policies_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

class Api::V1::Notifications::PoliciesController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: :show
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, only: :update

before_action :require_user!
before_action :set_policy

def show
render json: @policy, serializer: REST::NotificationPolicySerializer
end

def update
@policy.update!(resource_params)
render json: @policy, serializer: REST::NotificationPolicySerializer
end

private

def set_policy
@policy = NotificationPolicy.find_or_initialize_by(account: current_account)

with_read_replica do
@policy.summarize!
end
end

def resource_params
params.permit(
:filter_not_following,
:filter_not_followers,
:filter_new_accounts,
:filter_private_mentions
)
end
end
75 changes: 75 additions & 0 deletions app/controllers/api/v1/notifications/requests_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# frozen_string_literal: true

class Api::V1::Notifications::RequestsController < Api::BaseController
before_action -> { doorkeeper_authorize! :read, :'read:notifications' }, only: :index
before_action -> { doorkeeper_authorize! :write, :'write:notifications' }, except: :index

before_action :require_user!
before_action :set_request, except: :index

after_action :insert_pagination_headers, only: :index

def index
with_read_replica do
@requests = load_requests
@relationships = relationships
end

render json: @requests, each_serializer: REST::NotificationRequestSerializer, relationships: @relationships
end

def accept
AcceptNotificationRequestService.new.call(@request)
render_empty
end

def dismiss
@request.update!(dismissed: true)
render_empty
end

private

def load_requests
requests = NotificationRequest.where(account: current_account).where(dismissed: truthy_param?(:dismissed)).includes(:last_status, from_account: [:account_stat, :user]).to_a_paginated_by_id(
limit_param(DEFAULT_ACCOUNTS_LIMIT),
params_slice(:max_id, :since_id, :min_id)
)

NotificationRequest.preload_cache_collection(requests) do |statuses|
cache_collection(statuses, Status)
end
end

def relationships
StatusRelationshipsPresenter.new(@requests.map(&:last_status), current_user&.account_id)
end

def set_request
@request = NotificationRequest.where(account: current_account).find(params[:id])
end

def insert_pagination_headers
set_pagination_headers(next_path, prev_path)
end

def next_path
api_v1_notifications_requests_url pagination_params(max_id: pagination_max_id) unless @requests.empty?
end

def prev_path
api_v1_notifications_requests_url pagination_params(min_id: pagination_since_id) unless @requests.empty?
end

def pagination_max_id
@requests.last.id
end

def pagination_since_id
@requests.first.id
end

def pagination_params(core_params)
params.slice(:dismissed).permit(:dismissed).merge(core_params)
end
end
7 changes: 4 additions & 3 deletions app/controllers/api/v1/notifications_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def browserable_account_notifications
current_account.notifications.without_suspended.browserable(
types: Array(browserable_params[:types]),
exclude_types: Array(browserable_params[:exclude_types]),
from_account_id: browserable_params[:account_id]
from_account_id: browserable_params[:account_id],
include_filtered: truthy_param?(:include_filtered)
)
end

Expand Down Expand Up @@ -78,10 +79,10 @@ def pagination_since_id
end

def browserable_params
params.permit(:account_id, types: [], exclude_types: [])
params.permit(:account_id, :include_filtered, types: [], exclude_types: [])
end

def pagination_params(core_params)
params.slice(:limit, :account_id, :types, :exclude_types).permit(:limit, :account_id, types: [], exclude_types: []).merge(core_params)
params.slice(:limit, :account_id, :types, :exclude_types, :include_filtered).permit(:limit, :account_id, :include_filtered, types: [], exclude_types: []).merge(core_params)
end
end
2 changes: 2 additions & 0 deletions app/helpers/languages_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ module LanguagesHelper
mn: ['Mongolian', 'Монгол хэл'].freeze,
mr: ['Marathi', 'मराठी'].freeze,
ms: ['Malay', 'Bahasa Melayu'].freeze,
'ms-Arab': ['Jawi Malay', 'بهاس ملايو'].freeze,
mt: ['Maltese', 'Malti'].freeze,
my: ['Burmese', 'ဗမာစာ'].freeze,
na: ['Nauru', 'Ekakairũ Naoero'].freeze,
Expand Down Expand Up @@ -196,6 +197,7 @@ module LanguagesHelper
kab: ['Kabyle', 'Taqbaylit'].freeze,
ldn: ['Láadan', 'Láadan'].freeze,
lfn: ['Lingua Franca Nova', 'lingua franca nova'].freeze,
moh: ['Mohawk', 'Kanienʼkéha'].freeze,
pdc: ['Pennsylvania Dutch', 'Pennsilfaani-Deitsch'].freeze,
sco: ['Scots', 'Scots'].freeze,
sma: ['Southern Sami', 'Åarjelsaemien Gïele'].freeze,
Expand Down
7 changes: 6 additions & 1 deletion app/models/concerns/account/associations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ module Account::Associations
has_many :circles, inverse_of: :account, dependent: :destroy
has_many :antennas, inverse_of: :account, dependent: :destroy
has_many :mentions, inverse_of: :account, dependent: :destroy
has_many :notifications, inverse_of: :account, dependent: :destroy
has_many :conversations, class_name: 'AccountConversation', dependent: :destroy, inverse_of: :account
has_many :scheduled_statuses, inverse_of: :account, dependent: :destroy
has_many :scheduled_expiration_statuses, inverse_of: :account, dependent: :destroy

# Notifications
has_many :notifications, inverse_of: :account, dependent: :destroy
has_one :notification_policy, inverse_of: :account, dependent: :destroy
has_many :notification_permissions, inverse_of: :account, dependent: :destroy
has_many :notification_requests, inverse_of: :account, dependent: :destroy

# Pinned statuses
has_many :status_pins, inverse_of: :account, dependent: :destroy
has_many :pinned_statuses, -> { reorder('status_pins.created_at DESC') }, through: :status_pins, class_name: 'Status', source: :status
Expand Down
11 changes: 10 additions & 1 deletion app/models/notification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# type :string
# filtered :boolean default(FALSE), not null
#

class Notification < ApplicationRecord
Expand Down Expand Up @@ -112,7 +113,7 @@ def target_status
end

class << self
def browserable(types: [], exclude_types: [], from_account_id: nil)
def browserable(types: [], exclude_types: [], from_account_id: nil, include_filtered: false)
requested_types = if types.empty?
TYPES
else
Expand All @@ -122,6 +123,7 @@ def browserable(types: [], exclude_types: [], from_account_id: nil)
requested_types -= exclude_types.map(&:to_sym)

all.tap do |scope|
scope.merge!(where(filtered: false)) unless include_filtered || from_account_id.present?
scope.merge!(where(from_account_id: from_account_id)) if from_account_id.present?
scope.merge!(where(type: requested_types)) unless requested_types.size == TYPES.size
end
Expand Down Expand Up @@ -182,6 +184,8 @@ def from_account_web
after_initialize :set_from_account
before_validation :set_from_account

after_destroy :remove_from_notification_request

private

def set_from_account
Expand All @@ -196,4 +200,9 @@ def set_from_account
self.from_account_id = activity&.id
end
end

def remove_from_notification_request
notification_request = NotificationRequest.find_by(account_id: account_id, from_account_id: from_account_id)
notification_request&.reconsider_existence!
end
end
16 changes: 16 additions & 0 deletions app/models/notification_permission.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: notification_permissions
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
class NotificationPermission < ApplicationRecord
belongs_to :account
belongs_to :from_account, class_name: 'Account'
end
36 changes: 36 additions & 0 deletions app/models/notification_policy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: notification_policies
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# filter_not_following :boolean default(FALSE), not null
# filter_not_followers :boolean default(FALSE), not null
# filter_new_accounts :boolean default(FALSE), not null
# filter_private_mentions :boolean default(TRUE), not null
# created_at :datetime not null
# updated_at :datetime not null
#

class NotificationPolicy < ApplicationRecord
belongs_to :account

has_many :notification_requests, primary_key: :account_id, foreign_key: :account_id, dependent: nil, inverse_of: false

attr_reader :pending_requests_count, :pending_notifications_count

MAX_MEANINGFUL_COUNT = 100

def summarize!
@pending_requests_count = pending_notification_requests.first
@pending_notifications_count = pending_notification_requests.last
end

private

def pending_notification_requests
@pending_notification_requests ||= notification_requests.where(dismissed: false).limit(MAX_MEANINGFUL_COUNT).pick(Arel.sql('count(*), coalesce(sum(notifications_count), 0)::bigint'))
end
end
53 changes: 53 additions & 0 deletions app/models/notification_request.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# frozen_string_literal: true

# == Schema Information
#
# Table name: notification_requests
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# from_account_id :bigint(8) not null
# last_status_id :bigint(8) not null
# notifications_count :bigint(8) default(0), not null
# dismissed :boolean default(FALSE), not null
# created_at :datetime not null
# updated_at :datetime not null
#

class NotificationRequest < ApplicationRecord
include Paginable

MAX_MEANINGFUL_COUNT = 100

belongs_to :account
belongs_to :from_account, class_name: 'Account'
belongs_to :last_status, class_name: 'Status'

before_save :prepare_notifications_count

def self.preload_cache_collection(requests)
cached_statuses_by_id = yield(requests.filter_map(&:last_status)).index_by(&:id) # Call cache_collection in block

requests.each do |request|
request.last_status = cached_statuses_by_id[request.last_status_id] unless request.last_status_id.nil?
end
end

def reconsider_existence!
return if dismissed?

prepare_notifications_count

if notifications_count.positive?
save
else
destroy
end
end

private

def prepare_notifications_count
self.notifications_count = Notification.where(account: account, from_account: from_account).limit(MAX_MEANINGFUL_COUNT).count
end
end
16 changes: 16 additions & 0 deletions app/serializers/rest/notification_policy_serializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

class REST::NotificationPolicySerializer < ActiveModel::Serializer
attributes :filter_not_following,
:filter_not_followers,
:filter_new_accounts,
:filter_private_mentions,
:summary

def summary
{
pending_requests_count: object.pending_requests_count.to_s,
pending_notifications_count: object.pending_notifications_count.to_s,
}
end
end
Loading

0 comments on commit fa96bf2

Please sign in to comment.