Merge branch 'main' into glitch-soc/merge-upstream
Conflicts: - `README.md`: Upstream updated copyright year, we don't mention it so kept our version. - `app/controllers/admin/dashboard_controller.rb`: Not really a conflict, upstream change (removing the spam checker) too close to glitch-soc changes. Ported upstream changes. - `app/models/form/admin_settings.rb`: Same. - `app/services/remove_status_service.rb`: Same. - `app/views/admin/settings/edit.html.haml`: Same. - `config/settings.yml`: Same. - `config/environments/production.rb`: Not a real conflict, upstream added a default HTTP header, but we have extra headers in glitch-soc. Added the header.
This commit is contained in:
17
db/migrate/20210306164523_account_ids_to_timestamp_ids.rb
Normal file
17
db/migrate/20210306164523_account_ids_to_timestamp_ids.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
class AccountIdsToTimestampIds < ActiveRecord::Migration[5.1]
|
||||
def up
|
||||
# Set up the accounts.id column to use our timestamp-based IDs.
|
||||
safety_assured do
|
||||
execute("ALTER TABLE accounts ALTER COLUMN id SET DEFAULT timestamp_id('accounts')")
|
||||
end
|
||||
|
||||
# Make sure we have a sequence to use.
|
||||
Mastodon::Snowflake.ensure_id_sequences_exist
|
||||
end
|
||||
|
||||
def down
|
||||
execute("LOCK accounts")
|
||||
execute("SELECT setval('accounts_id_seq', (SELECT MAX(id) FROM accounts))")
|
||||
execute("ALTER TABLE accounts ALTER COLUMN id SET DEFAULT nextval('accounts_id_seq')")
|
||||
end
|
||||
end
|
9
db/migrate/20210322164601_create_account_summaries.rb
Normal file
9
db/migrate/20210322164601_create_account_summaries.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class CreateAccountSummaries < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_view :account_summaries, materialized: true
|
||||
|
||||
# To be able to refresh the view concurrently,
|
||||
# at least one unique index is required
|
||||
safety_assured { add_index :account_summaries, :account_id, unique: true }
|
||||
end
|
||||
end
|
@@ -0,0 +1,5 @@
|
||||
class CreateFollowRecommendations < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_view :follow_recommendations
|
||||
end
|
||||
end
|
@@ -0,0 +1,9 @@
|
||||
class CreateFollowRecommendationSuppressions < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :follow_recommendation_suppressions do |t|
|
||||
t.references :account, null: false, foreign_key: { on_delete: :cascade }, index: { unique: true }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
10
db/migrate/20210416200740_create_canonical_email_blocks.rb
Normal file
10
db/migrate/20210416200740_create_canonical_email_blocks.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
class CreateCanonicalEmailBlocks < ActiveRecord::Migration[6.1]
|
||||
def change
|
||||
create_table :canonical_email_blocks do |t|
|
||||
t.string :canonical_email_hash, null: false, default: '', index: { unique: true }
|
||||
t.belongs_to :reference_account, null: false, foreign_key: { on_cascade: :delete, to_table: 'accounts' }
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
75
db/schema.rb
75
db/schema.rb
@@ -2,15 +2,15 @@
|
||||
# of editing this file, please use the migrations feature of Active Record to
|
||||
# incrementally modify your database, and then regenerate this schema definition.
|
||||
#
|
||||
# Note that this schema.rb definition is the authoritative source for your
|
||||
# database schema. If you need to create the application database on another
|
||||
# system, you should be using db:schema:load, not running all the migrations
|
||||
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
|
||||
# you'll amass, the slower it'll run and the greater likelihood for issues).
|
||||
# This file is the source Rails uses to define your schema when running `bin/rails
|
||||
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
||||
# be faster and is potentially less error prone than running all of your
|
||||
# migrations from scratch. Old migrations may fail to apply correctly if those
|
||||
# migrations use external dependencies or application code.
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
ActiveRecord::Schema.define(version: 2021_04_16_200740) do
|
||||
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
@@ -142,7 +142,7 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
t.index ["target_account_id"], name: "index_account_warnings_on_target_account_id"
|
||||
end
|
||||
|
||||
create_table "accounts", force: :cascade do |t|
|
||||
create_table "accounts", id: :bigint, default: -> { "timestamp_id('accounts'::text)" }, force: :cascade do |t|
|
||||
t.string "username", default: "", null: false
|
||||
t.string "domain"
|
||||
t.string "secret", default: "", null: false
|
||||
@@ -280,6 +280,15 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
t.index ["status_id"], name: "index_bookmarks_on_status_id"
|
||||
end
|
||||
|
||||
create_table "canonical_email_blocks", force: :cascade do |t|
|
||||
t.string "canonical_email_hash", default: "", null: false
|
||||
t.bigint "reference_account_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["canonical_email_hash"], name: "index_canonical_email_blocks_on_canonical_email_hash", unique: true
|
||||
t.index ["reference_account_id"], name: "index_canonical_email_blocks_on_reference_account_id"
|
||||
end
|
||||
|
||||
create_table "conversation_mutes", force: :cascade do |t|
|
||||
t.bigint "conversation_id", null: false
|
||||
t.bigint "account_id", null: false
|
||||
@@ -406,6 +415,13 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
t.index ["tag_id"], name: "index_featured_tags_on_tag_id"
|
||||
end
|
||||
|
||||
create_table "follow_recommendation_suppressions", force: :cascade do |t|
|
||||
t.bigint "account_id", null: false
|
||||
t.datetime "created_at", precision: 6, null: false
|
||||
t.datetime "updated_at", precision: 6, null: false
|
||||
t.index ["account_id"], name: "index_follow_recommendation_suppressions_on_account_id", unique: true
|
||||
end
|
||||
|
||||
create_table "follow_requests", force: :cascade do |t|
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
@@ -986,6 +1002,7 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
add_foreign_key "blocks", "accounts", name: "fk_4269e03e65", on_delete: :cascade
|
||||
add_foreign_key "bookmarks", "accounts", on_delete: :cascade
|
||||
add_foreign_key "bookmarks", "statuses", on_delete: :cascade
|
||||
add_foreign_key "canonical_email_blocks", "accounts", column: "reference_account_id"
|
||||
add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade
|
||||
add_foreign_key "conversation_mutes", "conversations", on_delete: :cascade
|
||||
add_foreign_key "custom_filters", "accounts", on_delete: :cascade
|
||||
@@ -998,6 +1015,7 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
add_foreign_key "favourites", "statuses", name: "fk_b0e856845e", on_delete: :cascade
|
||||
add_foreign_key "featured_tags", "accounts", on_delete: :cascade
|
||||
add_foreign_key "featured_tags", "tags", on_delete: :cascade
|
||||
add_foreign_key "follow_recommendation_suppressions", "accounts", on_delete: :cascade
|
||||
add_foreign_key "follow_requests", "accounts", column: "target_account_id", name: "fk_9291ec025d", on_delete: :cascade
|
||||
add_foreign_key "follow_requests", "accounts", name: "fk_76d644b0e7", on_delete: :cascade
|
||||
add_foreign_key "follows", "accounts", column: "target_account_id", name: "fk_745ca29eac", on_delete: :cascade
|
||||
@@ -1081,4 +1099,47 @@ ActiveRecord::Schema.define(version: 2021_03_08_133107) do
|
||||
SQL
|
||||
add_index "instances", ["domain"], name: "index_instances_on_domain", unique: true
|
||||
|
||||
create_view "account_summaries", materialized: true, sql_definition: <<-SQL
|
||||
SELECT accounts.id AS account_id,
|
||||
mode() WITHIN GROUP (ORDER BY t0.language) AS language,
|
||||
mode() WITHIN GROUP (ORDER BY t0.sensitive) AS sensitive
|
||||
FROM (accounts
|
||||
CROSS JOIN LATERAL ( SELECT statuses.account_id,
|
||||
statuses.language,
|
||||
statuses.sensitive
|
||||
FROM statuses
|
||||
WHERE ((statuses.account_id = accounts.id) AND (statuses.deleted_at IS NULL))
|
||||
ORDER BY statuses.id DESC
|
||||
LIMIT 20) t0)
|
||||
WHERE ((accounts.suspended_at IS NULL) AND (accounts.silenced_at IS NULL) AND (accounts.moved_to_account_id IS NULL) AND (accounts.discoverable = true) AND (accounts.locked = false))
|
||||
GROUP BY accounts.id;
|
||||
SQL
|
||||
add_index "account_summaries", ["account_id"], name: "index_account_summaries_on_account_id", unique: true
|
||||
|
||||
create_view "follow_recommendations", sql_definition: <<-SQL
|
||||
SELECT t0.account_id,
|
||||
sum(t0.rank) AS rank,
|
||||
array_agg(t0.reason) AS reason
|
||||
FROM ( SELECT accounts.id AS account_id,
|
||||
((count(follows.id))::numeric / (1.0 + (count(follows.id))::numeric)) AS rank,
|
||||
'most_followed'::text AS reason
|
||||
FROM ((follows
|
||||
JOIN accounts ON ((accounts.id = follows.target_account_id)))
|
||||
JOIN users ON ((users.account_id = follows.account_id)))
|
||||
WHERE ((users.current_sign_in_at >= (now() - 'P30D'::interval)) AND (accounts.suspended_at IS NULL) AND (accounts.moved_to_account_id IS NULL) AND (accounts.silenced_at IS NULL) AND (accounts.locked = false) AND (accounts.discoverable = true))
|
||||
GROUP BY accounts.id
|
||||
HAVING (count(follows.id) >= 5)
|
||||
UNION ALL
|
||||
SELECT accounts.id AS account_id,
|
||||
(sum((status_stats.reblogs_count + status_stats.favourites_count)) / (1.0 + sum((status_stats.reblogs_count + status_stats.favourites_count)))) AS rank,
|
||||
'most_interactions'::text AS reason
|
||||
FROM ((status_stats
|
||||
JOIN statuses ON ((statuses.id = status_stats.status_id)))
|
||||
JOIN accounts ON ((accounts.id = statuses.account_id)))
|
||||
WHERE ((statuses.id >= (((date_part('epoch'::text, (now() - 'P30D'::interval)) * (1000)::double precision))::bigint << 16)) AND (accounts.suspended_at IS NULL) AND (accounts.moved_to_account_id IS NULL) AND (accounts.silenced_at IS NULL) AND (accounts.locked = false) AND (accounts.discoverable = true))
|
||||
GROUP BY accounts.id
|
||||
HAVING (sum((status_stats.reblogs_count + status_stats.favourites_count)) >= (5)::numeric)) t0
|
||||
GROUP BY t0.account_id
|
||||
ORDER BY (sum(t0.rank)) DESC;
|
||||
SQL
|
||||
end
|
||||
|
22
db/views/account_summaries_v01.sql
Normal file
22
db/views/account_summaries_v01.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
SELECT
|
||||
accounts.id AS account_id,
|
||||
mode() WITHIN GROUP (ORDER BY language ASC) AS language,
|
||||
mode() WITHIN GROUP (ORDER BY sensitive ASC) AS sensitive
|
||||
FROM accounts
|
||||
CROSS JOIN LATERAL (
|
||||
SELECT
|
||||
statuses.account_id,
|
||||
statuses.language,
|
||||
statuses.sensitive
|
||||
FROM statuses
|
||||
WHERE statuses.account_id = accounts.id
|
||||
AND statuses.deleted_at IS NULL
|
||||
ORDER BY statuses.id DESC
|
||||
LIMIT 20
|
||||
) t0
|
||||
WHERE accounts.suspended_at IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.discoverable = 't'
|
||||
AND accounts.locked = 'f'
|
||||
GROUP BY accounts.id
|
38
db/views/follow_recommendations_v01.sql
Normal file
38
db/views/follow_recommendations_v01.sql
Normal file
@@ -0,0 +1,38 @@
|
||||
SELECT
|
||||
account_id,
|
||||
sum(rank) AS rank,
|
||||
array_agg(reason) AS reason
|
||||
FROM (
|
||||
SELECT
|
||||
accounts.id AS account_id,
|
||||
count(follows.id) / (1.0 + count(follows.id)) AS rank,
|
||||
'most_followed' AS reason
|
||||
FROM follows
|
||||
INNER JOIN accounts ON accounts.id = follows.target_account_id
|
||||
INNER JOIN users ON users.account_id = follows.account_id
|
||||
WHERE users.current_sign_in_at >= (now() - interval '30 days')
|
||||
AND accounts.suspended_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.locked = 'f'
|
||||
AND accounts.discoverable = 't'
|
||||
GROUP BY accounts.id
|
||||
HAVING count(follows.id) >= 5
|
||||
UNION ALL
|
||||
SELECT accounts.id AS account_id,
|
||||
sum(reblogs_count + favourites_count) / (1.0 + sum(reblogs_count + favourites_count)) AS rank,
|
||||
'most_interactions' AS reason
|
||||
FROM status_stats
|
||||
INNER JOIN statuses ON statuses.id = status_stats.status_id
|
||||
INNER JOIN accounts ON accounts.id = statuses.account_id
|
||||
WHERE statuses.id >= ((date_part('epoch', now() - interval '30 days') * 1000)::bigint << 16)
|
||||
AND accounts.suspended_at IS NULL
|
||||
AND accounts.moved_to_account_id IS NULL
|
||||
AND accounts.silenced_at IS NULL
|
||||
AND accounts.locked = 'f'
|
||||
AND accounts.discoverable = 't'
|
||||
GROUP BY accounts.id
|
||||
HAVING sum(reblogs_count + favourites_count) >= 5
|
||||
) t0
|
||||
GROUP BY account_id
|
||||
ORDER BY rank DESC
|
Reference in New Issue
Block a user