Abaixo, você encontrará uma coleção de operações em massa que podem ser iniciadas via linha de comando. Será necessário acesso SSH; portanto, se você for um cliente hospedado, precisará entrar em contato com a equipe do Discourse para executar esses comandos.
Antes de trabalhar com o console, é extremamente importante que você tenha um backup recente. Erros sempre podem acontecer!
A primeira coisa a fazer é entrar no container do seu site:
cd /var/discourse
./launcher enter app
Guias Adicionais:
- Performing bulk actions as a moderator
- Como definir os níveis de rastreamento de tags historicamente
- (Obsolete) Set category tracking level defaults historically
- Change ownership of all posts by a specific user
- Replace a string in all posts
- Edit a user preference for everyone or a subset of users
- Modify trust level for all users
- Apply auto-close to existing topics
- Logout all users through the rails console
- Convert all existing topics in category to wikis
Alterar status do tópico
Antes de executar os comandos a seguir, execute rails c para entrar no console.
-
Remover todos os tópicos de uma categoria da listagem (exclui ação de postagem)
Você pode substituir
visibleporclosedouarchivede ajustar os valores verdadeiro/falso conforme necessáriocat_id = Category.find_by_slug('admins').id Topic.where(category_id: cat_id, visible: true).update_all(visible: false) -
Remover todos os tópicos de uma categoria da listagem (inclui ação de postagem)
cat_id = Category.find_by_slug("admins").id Topic.where(category_id: cat_id, visible: true).find_each do |topic| topic.update_status('visible', false, Discourse.system_user) end -
Fechar todos os tópicos criados antes de uma data específica (inclui ação de postagem)
Topic.where(closed: false).where("created_at < '2015-01-01'").find_each do |topic| topic.update_status('closed', true, Discourse.system_user) end
Movendo tópicos
Mover uma coleção de tópicos de uma categoria para outra
rails c
topic_ids = [12,16,29]
cat_to = Category.find_by_slug('faq')
Topic.where(id: topic_ids).update_all(category_id: cat_to.id)
Category.update_stats
Usuários
Excluir subconjunto de usuários
Excluir usuários que nunca publicaram e não visitaram desde uma data específica
rails c
User.joins(:user_stat).where("user_stats.post_count = 0 AND previous_visit_at <= '2016-05-20'::timestamp").destroy_all
Suspender um conjunto de usuários com base em critérios
Definir quem será registrado como responsável pela suspensão dos usuários
rails c
logger = StaffActionLogger.new(User.find_by(username_lower: "tshenry"))
Criar um período de suspensão e um motivo
suspend_till = DateTime.new(2057,12,31)
reason = 'Completed Course'
Neste exemplo, nossos critérios de usuário serão a membresia em um grupo.
target_group = Group.find_by_name("summer_students")
users = User.joins(:group_users).where(group_users: {group_id: target_group.id})
Suspender cada usuário com base nos valores estabelecidos acima:
users.find_each do |u|
u.suspended_till = suspend_till
u.suspended_at = DateTime.now
u.save!
logger.log_user_suspend(u,reason)
putc '.'
end
Atualizar motivos de suspensão de usuários
Talvez você tenha suspenso usuários que concluíram uma aula (veja o exemplo acima), e agora você deseja adicionar o ano da aula, pois você ministrou aulas em vários anos.
UserHistory.where(action: 10, details: "Completed Course").update_all(details: "Completed 2018 Course")
Reativar usuários
Se você precisar reativar usuários em massa, digamos porque eles faziam parte de uma turma do ano anterior e estão retornando este ano, você pode fazê-lo conforme mostrado abaixo. No exemplo, estamos encontrando usuários pelo ID deles.
user_list = [1, 3, 5, 7, 11]
users = User.where("id in (?)", user_list)
users.each do |user|
user.suspended_till = nil
user.suspended_at = nil
user.save!
StaffActionLogger.new(User.find(-1)).log_user_unsuspend(user)
DiscourseEvent.trigger(:user_unsuspended, user: user)
end
Exportar/Importar
Exportar/Importar todas as configurações do site
Para simplesmente imprimir todas as configurações que foram alteradas no seu site, execute:
rake site_settings:export
Se você quiser exportar as configurações para um arquivo:
rake site_settings:export > saved_settings.yml
Se você quiser importar configurações de um arquivo:
rake site_settings:import < saved_settings.yml
Exportar/Importar categorias
Existem duas opções para exportação e um método para lidar com a importação.
Exportar um conjunto de categorias completas
Primeiro, obtenha uma lista dos IDs das suas categorias:
rake categories:list
Em seguida, separe os IDs das categorias por espaço na tarefa rake de exportação. Por exemplo:
rake export:categories["12 6"]
Exportar a estrutura de categorias do seu site
Isso é essencialmente copiar o “esqueleto” do seu site Discourse. Inclui todas as categorias, juntamente com quaisquer grupos associados às permissões de categoria existentes. Não inclui tópicos:
rake export:category_structure
Se você quiser a estrutura de categorias, juntamente com quaisquer grupos associados às permissões de categoria e quaisquer membros desses grupos:
rake export:category_structure[true]
Importar um arquivo de categoria
Use o nome do arquivo exportado como no exemplo abaixo:
rake import:file["category-export-2019-05-16-052430.json"]
Exportar/Importar grupos
Exportar todos os grupos de usuários
rake export:groups
Exportar todos os grupos de usuários, incluindo usuários
rake export:groups[true]
Importar um arquivo de grupo
Use o nome do arquivo exportado como no exemplo abaixo:
rake import:file["group-export-2019-05-16-052430.json"]
Definir permissões para múltiplas categorias
Note que isso removerá quaisquer restrições de acesso existentes que você configurou para as categorias envolvidas. Certifique-se de incluir todas as permissões relevantes.
-
Obter uma lista de categorias, juntamente com seus IDs
rails c Category.all.pluck("name", "id") -
Criar um array com os IDs das categorias que você deseja atingir.
category_ids = [6,7,8,10] -
Alterar as permissões. A função
set_permissionspode utilizar os seguintes parâmetros::full,:create_post,:readonly-
Uma única permissão. Por exemplo, tornar um conjunto de categorias apenas para equipe:
Category.where(id: category_ids).find_each do |category| category.set_permissions(:staff => :full) category.save! end -
Múltiplas permissões. Por exemplo, tornar um conjunto de categorias somente leitura para usuários normais:
Category.where(id: category_ids).find_each do |category| category.set_permissions(:everyone => :readonly, :staff => :full) category.save! end -
Permissões de grupo de usuários. Por exemplo, conceder a um grupo permissões totais e a outro grupo somente leitura para um conjunto de categorias:
artists_group = Group.find_by_name("artists") buyers_group = Group.find_by_name("buyers") Category.where(id: category_ids).find_each do |category| category.set_permissions(artists_group.id => :full, buyers_group.id => :readonly) category.save! end
-
Marcar em massa todos os tópicos com base em uma palavra-chave
O script a seguir permitirá que você marque tópicos com base na presença de uma palavra-chave no título do tópico ou em suas postagens. Comece criando um array de palavras-chave:
rails c
keywords = ['apples','oranges']
Em seguida, precisamos definir um método:
def tag_by_keyword(word, tag_name)
tag = Tag.find_by_name(tag_name) || Tag.create(name: tag_name)
keyword_topics = Topic.joins(:posts).where("topics.title ~* :keyword or posts.raw ~* :keyword", keyword: "\\y#{word}\\y").distinct
keyword_topics.each do |topic|
if topic.tags.exclude?(tag)
topic.tags << tag
end
end
end
E finalmente execute cada palavra-chave através do método. O seguinte marcará cada tópico relevante com uma tag chamada “fruit”:
keywords.each { |word| tag_by_keyword(word, 'fruit') }
Marcar em massa todos os tópicos dentro de uma categoria
Modelo: rake tags:bulk_tag_category["<tag>|<tag>",<category_id>]
Isso seria particularmente útil ao tentar converter uma categoria em uma tag.
Primeiro, use a seguinte tarefa rake para encontrar o ID da categoria relevante.
rake categories:list
Marcar todos os tópicos da categoria que você especificar. Neste exemplo, você estaria marcando todos os tópicos na categoria com ID 6 com a tag “support”.
isso removerá todas as outras tags de cada tópico.
rake tags:bulk_tag_category["support",6]
Adicionar todas as tags a todos os tópicos da categoria que você especificar. Neste exemplo, você estaria adicionando a tag “support” a todos os tópicos na categoria com ID 6, mantendo as tags existentes.
rake tags:bulk_tag_category["support",6,true]
Mover todos os tópicos com uma tag específica para uma única categoria
Ao tentar reestruturar seu site Discourse, você pode descobrir que deseja mover uma coleção de tópicos sem acionar nenhuma notificação. Uma maneira de fazer isso é criar uma tag temporária, aplicar a tag aos tópicos apropriados, mover os tópicos para uma categoria específica usando o código abaixo e, finalmente, excluir a tag temporária.
Obter a tag.
rails c
tag = Tag.find_by_name("tutorial")
Obter categoria de destino.
- Para categorias regulares:
cat_to = Category.find_by_slug('guides')
- Para subcategorias:
cat_to = Category.find_by_slug('child-slug','parent-slug')
Mover os tópicos marcados para a categoria de destino.
Topic.joins(:topic_tags).where("topic_tags.tag_id = ?", tag.id).update_all(category_id: cat_to.id)
Atualizar as contagens de tópicos das categorias afetadas.
Category.update_stats
CategoryTagStat.update_topic_counts
Mover todos os tópicos de uma categoria para outra
Encontre os IDs das categorias com a seguinte tarefa rake:
rake categories:list
O primeiro valor deve ser o ID da categoria de origem. O segundo valor deve ser o ID da categoria de destino.
rake categories:move_topics[15,6]
Script do Console Rails
cat_from_id = XX # Categoria de onde mover os tópicos
cat_to_id = XX # Categoria para onde mover os tópicos
Topic.where(category_id: cat_from_id).update_all(category_id: cat_to_id)
Category.update_stats
CategoryTagStat.update_topic_counts
Alterar proprietário de todos os tópicos em categorias
Encontre os IDs das categorias com a seguinte tarefa rake:
rake categories:list
Especifique o novo proprietário e as categorias para operar. As categorias devem ser um array de IDs de categoria; as categorias 1, 2 e 3 no exemplo:
rails c
user = User.find_by(username_lower: "lowercase-username")
categories = [1, 2, 3]
Obter todos os IDs de tópicos para as categorias dadas e alterar o proprietário da primeira postagem em todos os tópicos correspondentes.
topics = Topic.where(category_id: categories).pluck(:id)
topics.each do |topic|
PostOwnerChanger.new(
post_ids: Post.where(topic_id: topic).where(post_number: 1).pluck(:id),
topic_id: topic,
new_owner: user,
acting_user: Discourse.system_user,
skip_revision: true
).change_owner!
end
Conceder uma medalha a todos os membros do grupo
Conceder uma medalha a todos os usuários que pertencem a um grupo específico. O primeiro valor é o ID do grupo e o segundo é o ID da medalha.
rails c
Group.find_by_name("event_participants").id
Badge.find_by_name("event_badge").id
exit
rake groups:grant_badge[42,102]
Observe que a tarefa rake acima apenas concede uma medalha; ela não revogará uma medalha concedida anteriormente se um usuário não fizer mais parte do grupo especificado. Se você precisar revogar medalhas em massa para todos os usuários que não fazem mais parte de um grupo, pode executar o seguinte:
rails c
badge_id = Badge.find_by_name("Some Group Member").id
group = Group.find_by_name("Some_Group")
group_user_id = group.users.pluck("id")
userBadge = UserBadge.where.not(user_id: group_user_id).where(badge_id: badge_id)
userBadge.each do |ub|
BadgeGranter.revoke(ub, revoked_by: Discourse.system_user)
end
exit
Garantir que todos os usuários estejam no nível de confiança automático
Digamos que você definiu o nível de confiança padrão para novos ou convidados usuários para um valor que não está funcionando exatamente como esperado (como TL4). Agora você deseja alterá-lo para que seus usuários estejam no nível de confiança que seriam automaticamente, dados seus estatísticas atuais. Os seguintes comandos garantirão que todos os usuários estejam no nível de confiança que deveriam estar de acordo com Understanding Discourse Trust Levels. Nota: usuários com níveis de confiança bloqueados não serão afetados.
Garantir que todos os usuários estejam definidos para o nível de confiança correto:
rails c
User.all.find_each do |user|
Promotion.recalculate(user)
end
Atualizar as estatísticas do grupo para refletir as alterações:
Group.ensure_consistency!
Scripts de manutenção de tópicos
Os seguintes scripts Ruby demonstram como realizar manutenção automatizada em tópicos com base em datas de atividade e outros critérios. Esses scripts combinam consultas SQL para identificar tópicos com código Ruby para executar ações sobre eles e devem ser executados via console rails do seu site.
Cada script segue um padrão semelhante:
- Uma consulta SQL que identifica tópicos relevantes
- Código Ruby que processa cada tópico e aplica as ações desejadas
- Tratamento básico de erros e registro de log
Esses scripts podem ser personalizados por:
- Ajustando períodos de tempo (por exemplo, ‘6 MONTH’, ‘1 YEAR’, ‘2 YEAR’)
- Alterando seleções de categorias para corresponder à estrutura do seu fórum
- Modificando quais ações tomar (fechar, remover da listagem ou mover)
- Adicionando condições adicionais, como contagem de postagens ou limites de visualização
Fechar, Remover da Listagem e Mover Tópicos Inativos
Este script identifica tópicos que atendem aos seguintes critérios:
- Em uma categoria específica
- Abertos
- Não resolvidos (usando o plugin Discourse Solved)
- Sem atividade recente dentro de um período específico
Em seguida, executa múltiplas ações:
- Fecha-os,
- Remove-os da listagem e
- Move-os para uma categoria designada para conteúdo desatualizado
Consulta SQL
WITH topic_list AS (
SELECT ua.target_topic_id, MAX(ua.created_at) "created_at"
FROM user_actions ua
INNER JOIN topics t ON t.id = ua.target_topic_id
INNER JOIN categories c ON c.id = t.category_id
LEFT JOIN discourse_solved_solved_topics solved ON solved.topic_id = t.id
WHERE t.closed = false
AND t.category_id = [CATEGORY_ID]
AND solved.topic_id IS NULL
AND t.deleted_at IS NULL
GROUP BY ua.target_topic_id
HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[TIME_PERIOD]'))
ORDER BY "created_at" DESC
)
SELECT '' AS total, target_topic_id AS topic_id, created_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY created_at DESC
SQL Combinado + Script
sql = "WITH topic_list AS (
SELECT ua.target_topic_id, MAX(ua.created_at) \"created_at\"
FROM user_actions ua
INNER JOIN topics t ON t.id = ua.target_topic_id
INNER JOIN categories c ON c.id = t.category_id
LEFT JOIN discourse_solved_solved_topics solved ON solved.topic_id = t.id
WHERE t.closed = false
AND t.category_id = [CATEGORY_ID]
AND solved.topic_id IS NULL
AND t.deleted_at IS NULL
GROUP BY ua.target_topic_id
HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[TIME_PERIOD]'))
ORDER BY \"created_at\" DESC
)
SELECT '' AS total, target_topic_id AS topic_id, created_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY created_at DESC"
results = ActiveRecord::Base.connection.execute(sql)
user = Discourse.system_user
destination_category = Category.find([DESTINATION_CATEGORY_ID])
puts "Found #{results.count} topics to process"
results.each do |row|
begin
topic = Topic.find(row["topic_id"])
# 1. Mover para a categoria de destino
topic.update!(category_id: destination_category.id)
puts "#{topic.id} moved to destination category"
# 2. Fechar o tópico
topic.update_status('closed', true, user, until: nil)
puts "#{topic.id} is closed"
# 3. Remover da listagem o tópico
topic.update_status('visible', false, user, until: nil)
puts "#{topic.id} is unlisted"
# Tratamento de Erros
rescue => e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Fechar Tópicos Resolvidos sem Atividade Recente
Este script fecha tópicos resolvidos que estão inativos por um período definido. Isso pode ajudar a manter seu fórum organizado, preservando ao mesmo tempo tópicos resolvidos valiosos.
Este script identifica tópicos que atendem aos seguintes critérios:
- Em uma categoria específica
- Abertos
- Resolvidos (usando o plugin Discourse Solved)
- Sem atividade recente dentro de um período específico
Consulta SQL
WITH topic_list AS (
SELECT ua.target_topic_id, MAX(ua.created_at) "created_at"
FROM user_actions ua
INNER JOIN topics t ON t.id = ua.target_topic_id
INNER JOIN categories c ON c.id = t.category_id
INNER JOIN discourse_solved_solved_topics solved ON solved.topic_id = t.id
WHERE t.closed = false
AND t.category_id IN ([CATEGORY_IDS])
AND t.deleted_at IS NULL
GROUP BY ua.target_topic_id
HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[TIME_PERIOD]'))
ORDER BY "created_at" DESC
)
SELECT '' AS total, target_topic_id AS topic_id, created_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY created_at DESC
SQL Combinado + Script
sql = "WITH topic_list AS (
SELECT ua.target_topic_id, MAX(ua.created_at) \"created_at\"
FROM user_actions ua
INNER JOIN topics t ON t.id = ua.target_topic_id
INNER JOIN categories c ON c.id = t.category_id
INNER JOIN discourse_solved_solved_topics solved ON solved.topic_id = t.id
WHERE t.closed = false
AND t.category_id IN ([CATEGORY_IDS])
AND t.deleted_at IS NULL
GROUP BY ua.target_topic_id
HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[TIME_PERIOD]'))
ORDER BY \"created_at\" DESC
)
SELECT '' AS total, target_topic_id AS topic_id, created_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY created_at DESC"
results = ActiveRecord::Base.connection.execute(sql)
user = Discourse.system_user
puts "Found #{results.count} topics to process"
results.each do |row|
begin
topic = Topic.find(row["topic_id"])
# Fechar o tópico
topic.update_status('closed', true, user, until: nil)
puts "#{topic.id} is closed"
# Tratamento de Erros
rescue => e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Arquivar Tópicos Fechados Anteriormente
Este script identifica tópicos que foram fechados anteriormente antes de uma data específica e os move para uma categoria de arquivo, removendo-os da listagem.
Consulta SQL
WITH topic_list AS (
SELECT
t.id AS topic_id,
tt.execute_at AS closed_at
FROM topics t
INNER JOIN categories c ON c.id = t.category_id
LEFT JOIN topic_timers tt ON tt.topic_id = t.id AND tt.status_type IN (1, 8)
WHERE t.closed = true
AND t.category_id IN ([CATEGORY_IDS])
AND t.deleted_at IS NULL
AND tt.execute_at IS NOT NULL
AND tt.execute_at <= (CURRENT_DATE - INTERVAL '[TIME_PERIOD]')
ORDER BY tt.execute_at DESC
)
SELECT '' AS total, topic_id, closed_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY closed_at DESC
SQL Combinado + Script
sql = "WITH topic_list AS (
SELECT
t.id AS topic_id,
tt.execute_at AS closed_at
FROM topics t
INNER JOIN categories c ON c.id = t.category_id
LEFT JOIN topic_timers tt ON tt.topic_id = t.id AND tt.status_type IN (1, 8)
WHERE t.closed = true
AND t.category_id IN ([CATEGORY_IDS])
AND t.deleted_at IS NULL
AND tt.execute_at IS NOT NULL
AND tt.execute_at <= (CURRENT_DATE - INTERVAL '[TIME_PERIOD]')
ORDER BY tt.execute_at DESC
)
SELECT '' AS total, topic_id, closed_at
FROM topic_list
UNION
SELECT ''||COUNT(*), 0, CURRENT_DATE
FROM topic_list
ORDER BY closed_at DESC"
results = ActiveRecord::Base.connection.execute(sql)
user = Discourse.system_user
archive_category = Category.find([ARCHIVE_CATEGORY_ID])
puts "Found #{results.count} topics to process"
results.each do |row|
begin
topic = Topic.find(row["topic_id"])
# 1. Mover para a categoria de arquivo
topic.update!(category_id: archive_category.id)
puts "#{topic.id} moved to archive category"
# 2. Remover da listagem o tópico
topic.update_status('visible', false, user, until: nil)
puts "#{topic.id} is unlisted"
# Tratamento de Erros
rescue => e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Tarefas rake destrutivas
Excluir categorias inteiras
O seguinte permitirá que você destrua múltiplas categorias, juntamente com quaisquer subcategorias e tópicos que pertençam a essas categorias.
Imprimir uma lista de IDs de categoria
rake categories:list
Destruir um conjunto de categorias com base em seus IDs
rake destroy:categories[10,11,12,18,30]
Excluir todos os tópicos em uma categoria
Remover todas as mensagens pessoais
rake destroy:private_messages
Destruir todos os grupos
rake destroy:groups
Destruir todos os usuários não administradores
rake destroy:users
Destruir estatísticas do site
rake destroy:stats
Anonimizar todos os usuários, exceto equipe
rake users:anonymize_all
Excluir permanentemente um conjunto de postagens
A seguinte tarefa rake excluirá permanentemente uma lista de postagens com base em seus IDs. Se uma postagem for a primeira postagem de um tópico, todas as postagens nesse tópico serão excluídas permanentemente. Antes de poder executar a tarefa com sucesso, a configuração do site can_permanently_delete deve estar habilitada.
Uma vez que uma postagem é excluída por esta tarefa, ela não existirá mais no banco de dados e não poderá ser recuperada.
Existem duas abordagens possíveis:
-
Opção 1 – Passar uma lista separada por vírgula de IDs de postagem como argumento
rake destroy:posts[4,8,15,16,23,42] -
Opção 2 – Especificar um arquivo de texto com uma lista separada por vírgula de IDs de postagem (ideal para grandes conjuntos de postagens).
cat post_ids.txt | rake destroy:posts
Tentei incluir as tarefas rake mais úteis neste tópico, mas existem muitas outras incluídas no Discourse. Se você quiser ver uma lista abrangente, pode usar o seguinte:
Todas as tarefas que possuem descrições
rake --tasks
Todas as tarefas, incluindo aquelas que não possuem descrições
rake -AT