Merge commit '0ddc895282' into kb_migration

This commit is contained in:
KMY 2023-06-06 11:36:04 +09:00
commit 9027195ae3
66 changed files with 1037 additions and 250 deletions

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::InstanceAccountsDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
include LanguagesHelper
def self.with_params?
@ -14,19 +15,23 @@ class Admin::Metrics::Dimension::InstanceAccountsDimension < Admin::Metrics::Dim
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['username'], human_key: row['username'], value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { domain: params[:domain], limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT accounts.username, count(follows.*) AS value
FROM accounts
LEFT JOIN follows ON follows.target_account_id = accounts.id
WHERE accounts.domain = $1
WHERE accounts.domain = :domain
GROUP BY accounts.id, follows.target_account_id
ORDER BY value DESC
LIMIT $2
LIMIT :limit
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:domain]], [nil, @limit]])
rows.map { |row| { key: row['username'], human_key: row['username'], value: row['value'].to_s } }
end
def params

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::InstanceLanguagesDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
include LanguagesHelper
def self.with_params?
@ -14,21 +15,33 @@ class Admin::Metrics::Dimension::InstanceLanguagesDimension < Admin::Metrics::Di
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['language'], human_key: standard_locale_name(row['language']), value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { domain: params[:domain], earliest_status_id: earliest_status_id, latest_status_id: latest_status_id, limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT COALESCE(statuses.language, 'und') AS language, count(*) AS value
FROM statuses
INNER JOIN accounts ON accounts.id = statuses.account_id
WHERE accounts.domain = $1
AND statuses.id BETWEEN $2 AND $3
WHERE accounts.domain = :domain
AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
AND statuses.reblog_of_id IS NULL
GROUP BY COALESCE(statuses.language, 'und')
ORDER BY count(*) DESC
LIMIT $4
LIMIT :limit
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:domain]], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, @limit]])
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false)
end
rows.map { |row| { key: row['language'], human_key: standard_locale_name(row['language']), value: row['value'].to_s } }
def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false)
end
def params

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::LanguagesDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
include LanguagesHelper
def key
@ -10,18 +11,22 @@ class Admin::Metrics::Dimension::LanguagesDimension < Admin::Metrics::Dimension:
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['locale'], human_key: standard_locale_name(row['locale']), value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT locale, count(*) AS value
FROM users
WHERE current_sign_in_at BETWEEN $1 AND $2
WHERE current_sign_in_at BETWEEN :start_at AND :end_at
AND locale IS NOT NULL
GROUP BY locale
ORDER BY count(*) DESC
LIMIT $3
LIMIT :limit
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, @limit]])
rows.map { |row| { key: row['locale'], human_key: standard_locale_name(row['locale']), value: row['value'].to_s } }
end
end

View file

@ -0,0 +1,13 @@
# frozen_string_literal: true
module Admin::Metrics::Dimension::QueryHelper
protected
def dimension_data_rows
ActiveRecord::Base.connection.select_all(sanitized_sql_string)
end
def sanitized_sql_string
ActiveRecord::Base.sanitize_sql_array(sql_array)
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::ServersDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
def key
'servers'
end
@ -8,18 +10,30 @@ class Admin::Metrics::Dimension::ServersDimension < Admin::Metrics::Dimension::B
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['domain'] || Rails.configuration.x.local_domain, human_key: row['domain'] || Rails.configuration.x.local_domain, value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { earliest_status_id: earliest_status_id, latest_status_id: latest_status_id, limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT accounts.domain, count(*) AS value
FROM statuses
INNER JOIN accounts ON accounts.id = statuses.account_id
WHERE statuses.id BETWEEN $1 AND $2
WHERE statuses.id BETWEEN :earliest_status_id AND :latest_status_id
GROUP BY accounts.domain
ORDER BY count(*) DESC
LIMIT $3
LIMIT :limit
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, Mastodon::Snowflake.id_at(@start_at)], [nil, Mastodon::Snowflake.id_at(@end_at)], [nil, @limit]])
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at)
end
rows.map { |row| { key: row['domain'] || Rails.configuration.x.local_domain, human_key: row['domain'] || Rails.configuration.x.local_domain, value: row['value'].to_s } }
def latest_status_id
Mastodon::Snowflake.id_at(@end_at)
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::SourcesDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
def key
'sources'
end
@ -8,18 +10,22 @@ class Admin::Metrics::Dimension::SourcesDimension < Admin::Metrics::Dimension::B
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['name'] || 'web', human_key: row['name'] || I18n.t('admin.dashboard.website'), value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT oauth_applications.name, count(*) AS value
FROM users
LEFT JOIN oauth_applications ON oauth_applications.id = users.created_by_application_id
WHERE users.created_at BETWEEN $1 AND $2
WHERE users.created_at BETWEEN :start_at AND :end_at
GROUP BY oauth_applications.name
ORDER BY count(*) DESC
LIMIT $3
LIMIT :limit
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, @limit]])
rows.map { |row| { key: row['name'] || 'web', human_key: row['name'] || I18n.t('admin.dashboard.website'), value: row['value'].to_s } }
end
end

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::TagLanguagesDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
include LanguagesHelper
def self.with_params?
@ -14,20 +15,36 @@ class Admin::Metrics::Dimension::TagLanguagesDimension < Admin::Metrics::Dimensi
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['language'], human_key: standard_locale_name(row['language']), value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { tag_id: tag_id, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id, limit: @limit }]
end
def sql_query_string
<<~SQL.squish
SELECT COALESCE(statuses.language, 'und') AS language, count(*) AS value
FROM statuses
INNER JOIN statuses_tags ON statuses_tags.status_id = statuses.id
WHERE statuses_tags.tag_id = $1
AND statuses.id BETWEEN $2 AND $3
WHERE statuses_tags.tag_id = :tag_id
AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
GROUP BY COALESCE(statuses.language, 'und')
ORDER BY count(*) DESC
LIMIT $4
LIMIT :limit
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:id]], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, @limit]])
def tag_id
params[:id]
end
rows.map { |row| { key: row['language'], human_key: standard_locale_name(row['language']), value: row['value'].to_s } }
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false)
end
def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false)
end
def params

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Dimension::TagServersDimension < Admin::Metrics::Dimension::BaseDimension
include Admin::Metrics::Dimension::QueryHelper
def self.with_params?
true
end
@ -12,21 +14,37 @@ class Admin::Metrics::Dimension::TagServersDimension < Admin::Metrics::Dimension
protected
def perform_query
sql = <<-SQL.squish
dimension_data_rows.map { |row| { key: row['domain'] || Rails.configuration.x.local_domain, human_key: row['domain'] || Rails.configuration.x.local_domain, value: row['value'].to_s } }
end
def sql_array
[sql_query_string, { tag_id: tag_id, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id, limit: @limit }]
end
def sql_query_string
<<-SQL.squish
SELECT accounts.domain, count(*) AS value
FROM statuses
INNER JOIN accounts ON accounts.id = statuses.account_id
INNER JOIN statuses_tags ON statuses_tags.status_id = statuses.id
WHERE statuses_tags.tag_id = $1
AND statuses.id BETWEEN $2 AND $3
WHERE statuses_tags.tag_id = :tag_id
AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
GROUP BY accounts.domain
ORDER BY count(*) DESC
LIMIT $4
LIMIT :limit
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:id]], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, @limit]])
def tag_id
params[:id]
end
rows.map { |row| { key: row['domain'] || Rails.configuration.x.local_domain, human_key: row['domain'] || Rails.configuration.x.local_domain, value: row['value'].to_s } }
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false)
end
def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false)
end
def params

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -25,33 +27,25 @@ class Admin::Metrics::Measure::InstanceAccountsMeasure < Admin::Metrics::Measure
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $3::text))"
else
'accounts.domain = $3::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_accounts AS (
SELECT accounts.id
FROM accounts
WHERE date_trunc('day', accounts.created_at)::date = axis.period
AND #{account_matching_sql}
AND #{account_domain_sql(params[:include_subdomains])}
)
SELECT count(*) FROM new_accounts
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def time_period

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -25,34 +27,26 @@ class Admin::Metrics::Measure::InstanceFollowersMeasure < Admin::Metrics::Measur
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $3::text))"
else
'accounts.domain = $3::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_followers AS (
SELECT follows.id
FROM follows
INNER JOIN accounts ON follows.account_id = accounts.id
WHERE date_trunc('day', follows.created_at)::date = axis.period
AND #{account_matching_sql}
AND #{account_domain_sql(params[:include_subdomains])}
)
SELECT count(*) FROM new_followers
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def time_period

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -25,34 +27,26 @@ class Admin::Metrics::Measure::InstanceFollowsMeasure < Admin::Metrics::Measure:
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $3::text))"
else
'accounts.domain = $3::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_follows AS (
SELECT follows.id
FROM follows
INNER JOIN accounts ON follows.target_account_id = accounts.id
WHERE date_trunc('day', follows.created_at)::date = axis.period
AND #{account_matching_sql}
AND #{account_domain_sql(params[:include_subdomains])}
)
SELECT count(*) FROM new_follows
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def time_period

View file

@ -1,6 +1,7 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
include ActionView::Helpers::NumberHelper
def self.with_params?
@ -35,34 +36,26 @@ class Admin::Metrics::Measure::InstanceMediaAttachmentsMeasure < Admin::Metrics:
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $3::text))"
else
'accounts.domain = $3::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_media_attachments AS (
SELECT COALESCE(media_attachments.file_file_size, 0) + COALESCE(media_attachments.thumbnail_file_size, 0) AS size
FROM media_attachments
INNER JOIN accounts ON accounts.id = media_attachments.account_id
WHERE date_trunc('day', media_attachments.created_at)::date = axis.period
AND #{account_matching_sql}
AND #{account_domain_sql(params[:include_subdomains])}
)
SELECT SUM(size) FROM new_media_attachments
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def time_period

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -25,34 +27,26 @@ class Admin::Metrics::Measure::InstanceReportsMeasure < Admin::Metrics::Measure:
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $3::text))"
else
'accounts.domain = $3::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain] }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_reports AS (
SELECT reports.id
FROM reports
INNER JOIN accounts ON accounts.id = reports.target_account_id
WHERE date_trunc('day', reports.created_at)::date = axis.period
AND #{account_matching_sql}
AND #{account_domain_sql(params[:include_subdomains])}
)
SELECT count(*) FROM new_reports
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, params[:domain]]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def time_period

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -25,35 +27,35 @@ class Admin::Metrics::Measure::InstanceStatusesMeasure < Admin::Metrics::Measure
nil
end
def perform_data_query
account_matching_sql = begin
if params[:include_subdomains]
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || $5::text))"
else
'accounts.domain = $5::text'
end
end
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, domain: params[:domain], earliest_status_id: earliest_status_id, latest_status_id: latest_status_id }]
end
sql = <<-SQL.squish
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_statuses AS (
SELECT statuses.id
FROM statuses
INNER JOIN accounts ON accounts.id = statuses.account_id
WHERE statuses.id BETWEEN $3 AND $4
AND #{account_matching_sql}
WHERE statuses.id BETWEEN :earliest_status_id AND :latest_status_id
AND #{account_domain_sql(params[:include_subdomains])}
AND date_trunc('day', statuses.created_at)::date = axis.period
)
SELECT count(*) FROM new_statuses
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, params[:domain]]])
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false)
end
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false)
end
def time_period

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::NewUsersMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def key
'new_users'
end
@ -15,8 +17,12 @@ class Admin::Metrics::Measure::NewUsersMeasure < Admin::Metrics::Measure::BaseMe
User.where(created_at: previous_time_period).count
end
def perform_data_query
sql = <<-SQL.squish
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at }]
end
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_users AS (
SELECT users.id
@ -26,12 +32,8 @@ class Admin::Metrics::Measure::NewUsersMeasure < Admin::Metrics::Measure::BaseMe
SELECT count(*) FROM new_users
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::OpenedReportsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def key
'opened_reports'
end
@ -15,8 +17,12 @@ class Admin::Metrics::Measure::OpenedReportsMeasure < Admin::Metrics::Measure::B
Report.where(created_at: previous_time_period).count
end
def perform_data_query
sql = <<-SQL.squish
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at }]
end
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH new_reports AS (
SELECT reports.id
@ -26,12 +32,8 @@ class Admin::Metrics::Measure::OpenedReportsMeasure < Admin::Metrics::Measure::B
SELECT count(*) FROM new_reports
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
end

View file

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Admin::Metrics::Measure::QueryHelper
protected
def perform_data_query
measurement_data_rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
def measurement_data_rows
ActiveRecord::Base.connection.select_all(sanitized_sql_string)
end
def sanitized_sql_string
ActiveRecord::Base.sanitize_sql_array(sql_array)
end
def account_domain_sql(include_subdomains)
if include_subdomains
"accounts.domain IN (SELECT domain FROM instances WHERE reverse('.' || domain) LIKE reverse('.' || :domain::text))"
else
'accounts.domain = :domain::text'
end
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::ResolvedReportsMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def key
'resolved_reports'
end
@ -15,8 +17,12 @@ class Admin::Metrics::Measure::ResolvedReportsMeasure < Admin::Metrics::Measure:
Report.resolved.where(action_taken_at: previous_time_period).count
end
def perform_data_query
sql = <<-SQL.squish
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at }]
end
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
WITH resolved_reports AS (
SELECT reports.id
@ -26,12 +32,8 @@ class Admin::Metrics::Measure::ResolvedReportsMeasure < Admin::Metrics::Measure:
SELECT count(*) FROM resolved_reports
) AS value
FROM (
SELECT generate_series(date_trunc('day', $1::timestamp)::date, date_trunc('day', $2::timestamp)::date, interval '1 day') AS period
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, interval '1 day') AS period
) AS axis
SQL
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, @start_at], [nil, @end_at]])
rows.map { |row| { date: row['period'], value: row['value'].to_s } }
end
end

View file

@ -1,6 +1,8 @@
# frozen_string_literal: true
class Admin::Metrics::Measure::TagServersMeasure < Admin::Metrics::Measure::BaseMeasure
include Admin::Metrics::Measure::QueryHelper
def self.with_params?
true
end
@ -19,25 +21,33 @@ class Admin::Metrics::Measure::TagServersMeasure < Admin::Metrics::Measure::Base
tag.statuses.where('statuses.id BETWEEN ? AND ?', Mastodon::Snowflake.id_at(@start_at - length_of_period, with_random: false), Mastodon::Snowflake.id_at(@end_at - length_of_period, with_random: false)).joins(:account).count('distinct accounts.domain')
end
def perform_data_query
sql = <<-SQL.squish
def sql_array
[sql_query_string, { start_at: @start_at, end_at: @end_at, tag_id: tag.id, earliest_status_id: earliest_status_id, latest_status_id: latest_status_id }]
end
def sql_query_string
<<~SQL.squish
SELECT axis.*, (
SELECT count(distinct accounts.domain) AS value
FROM statuses
INNER JOIN statuses_tags ON statuses.id = statuses_tags.status_id
INNER JOIN accounts ON statuses.account_id = accounts.id
WHERE statuses_tags.tag_id = $1
AND statuses.id BETWEEN $2 AND $3
WHERE statuses_tags.tag_id = :tag_id
AND statuses.id BETWEEN :earliest_status_id AND :latest_status_id
AND date_trunc('day', statuses.created_at)::date = axis.day
)
FROM (
SELECT generate_series(date_trunc('day', $4::timestamp)::date, date_trunc('day', $5::timestamp)::date, ('1 day')::interval) AS day
SELECT generate_series(date_trunc('day', :start_at::timestamp)::date, date_trunc('day', :end_at::timestamp)::date, ('1 day')::interval) AS day
) as axis
SQL
end
rows = ActiveRecord::Base.connection.select_all(sql, nil, [[nil, params[:id].to_i], [nil, Mastodon::Snowflake.id_at(@start_at, with_random: false)], [nil, Mastodon::Snowflake.id_at(@end_at, with_random: false)], [nil, @start_at], [nil, @end_at]])
def earliest_status_id
Mastodon::Snowflake.id_at(@start_at, with_random: false)
end
rows.map { |row| { date: row['day'], value: row['value'].to_s } }
def latest_status_id
Mastodon::Snowflake.id_at(@end_at, with_random: false)
end
def tag

View file

@ -40,9 +40,9 @@ class FeedManager
def filter?(timeline_type, status, receiver)
case timeline_type
when :home
filter_from_home?(status, receiver.id, build_crutches(receiver.id, [status]))
filter_from_home?(status, receiver.id, build_crutches(receiver.id, [status]), :home)
when :list
filter_from_list?(status, receiver) || filter_from_home?(status, receiver.account_id, build_crutches(receiver.account_id, [status]))
filter_from_list?(status, receiver) || filter_from_home?(status, receiver.account_id, build_crutches(receiver.account_id, [status]), :list)
when :mentions
filter_from_mentions?(status, receiver.id)
when :tags
@ -351,10 +351,11 @@ class FeedManager
# @param [Integer] receiver_id
# @param [Hash] crutches
# @return [Boolean]
def filter_from_home?(status, receiver_id, crutches)
def filter_from_home?(status, receiver_id, crutches, timeline_type = :home)
return false if receiver_id == status.account_id
return true if status.reply? && (status.in_reply_to_id.nil? || status.in_reply_to_account_id.nil?)
return true if crutches[:languages][status.account_id].present? && status.language.present? && !crutches[:languages][status.account_id].include?(status.language)
return true if timeline_type != :list && crutches[:exclusive_list_users][status.account_id].present?
return true if crutches[:languages][status.account_id].present? && status.language.present? && !crutches[:languages][status.account_id].include?(status.language)
check_for_blocks = crutches[:active_mentions][status.id] || []
check_for_blocks.push(status.account_id)
@ -543,13 +544,16 @@ class FeedManager
arr
end
crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.filter_map(&:in_reply_to_account_id)).pluck(:target_account_id).index_with(true)
crutches[:languages] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:account_id)).pluck(:target_account_id, :languages).to_h
crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.filter_map { |s| s.account_id if s.reblog? }, show_reblogs: false).pluck(:target_account_id).index_with(true)
crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.flat_map { |s| [s.account.domain, s.reblog&.account&.domain] }.compact).pluck(:domain).index_with(true)
crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| [s.account_id, s.reblog&.account_id] }.flatten.compact).pluck(:account_id).index_with(true)
lists = List.where(account_id: receiver_id, exclusive: true)
crutches[:following] = Follow.where(account_id: receiver_id, target_account_id: statuses.filter_map(&:in_reply_to_account_id)).pluck(:target_account_id).index_with(true)
crutches[:languages] = Follow.where(account_id: receiver_id, target_account_id: statuses.map(&:account_id)).pluck(:target_account_id, :languages).to_h
crutches[:hiding_reblogs] = Follow.where(account_id: receiver_id, target_account_id: statuses.filter_map { |s| s.account_id if s.reblog? }, show_reblogs: false).pluck(:target_account_id).index_with(true)
crutches[:blocking] = Block.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
crutches[:muting] = Mute.where(account_id: receiver_id, target_account_id: check_for_blocks).pluck(:target_account_id).index_with(true)
crutches[:domain_blocking] = AccountDomainBlock.where(account_id: receiver_id, domain: statuses.flat_map { |s| [s.account.domain, s.reblog&.account&.domain] }.compact).pluck(:domain).index_with(true)
crutches[:blocked_by] = Block.where(target_account_id: receiver_id, account_id: statuses.map { |s| [s.account_id, s.reblog&.account_id] }.flatten.compact).pluck(:account_id).index_with(true)
crutches[:exclusive_list_users] = ListAccount.where(list: lists, account_id: statuses.map(&:account_id)).pluck(:account_id).index_with(true)
crutches
end