Di seguito troverai una raccolta di operazioni in blocco che possono essere avviate dalla riga di comando. Avrai bisogno di accesso SSH; se sei un cliente in hosting, dovrai contattare il team di Discourse per eseguire questi comandi.
Prima di lavorare con la console è estremamente importante avere un backup recente. Gli errori possono sempre accadere!
La prima cosa da fare è accedere al contenitore del tuo sito:
cd /var/discourse
./launcher enter app
Guide aggiuntive:
- Performing bulk actions as a moderator
- Come impostare i livelli di monitoraggio dei tag storicamente
- (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
Modificare lo stato dei topic
Prima di eseguire i seguenti comandi, avvia rails c per accedere alla console.
-
Rimuovi dall’elenco tutti i topic di una categoria (esclude l’azione sui post)
Puoi sostituire
visibleconclosedoarchivede regolare i valori true/false secondo necessitàcat_id = Category.find_by_slug('admins').id Topic.where(category_id: cat_id, visible: true).update_all(visible: false) -
Rimuovi dall’elenco tutti i topic di una categoria (include l’azione sui post)
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 -
Chiudi tutti i topic creati prima di una data specifica (include l’azione sui post)
Topic.where(closed: false).where("created_at \u003c '2015-01-01'").find_each do |topic| topic.update_status('closed', true, Discourse.system_user) end
Spostare i topic
Sposta una raccolta di topic da una categoria all’altra
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
Utenti
Eliminare un sottoinsieme di utenti
Elimina gli utenti che non hanno mai pubblicato e non hanno visitato il sito da una data specifica
rails c
User.joins(:user_stat).where("user_stats.post_count = 0 AND previous_visit_at \u003c= '2016-05-20'::timestamp").destroy_all
Sospendere un insieme di utenti in base a criteri
Imposta chi verrà registrato come responsabile della sospensione degli utenti
rails c
logger = StaffActionLogger.new(User.find_by(username_lower: "tshenry"))
Crea un intervallo di tempo e un motivo per la sospensione
suspend_till = DateTime.new(2057,12,31)
reason = 'Completed Course'
In questo esempio, i nostri criteri per gli utenti saranno l’appartenenza a un gruppo.
target_group = Group.find_by_name("summer_students")
users = User.joins(:group_users).where(group_users: {group_id: target_group.id})
Sospendi ogni utente in base ai valori stabiliti sopra:
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
Aggiornare i motivi di sospensione degli utenti
Forse hai sospeso utenti che hanno completato un corso (vedi esempio sopra), e ora vuoi aggiungere l’anno del corso poiché ne hai insegnati diversi.
UserHistory.where(action: 10, details: "Completed Course").update_all(details: "Completed 2018 Course")
Riattivare gli utenti
Se devi riattivare utenti in blocco, ad esempio perché facevano parte della coorte dell’anno precedente e stanno tornando per quest’anno, puoi farlo come mostrato di seguito. Nell’esempio, stiamo cercando gli utenti per il loro ID.
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
Esportazione/Importazione
Esportare/Importare tutte le impostazioni del sito
Per stampare semplicemente tutte le impostazioni modificate sul tuo sito, esegui:
rake site_settings:export
Se vuoi esportare le impostazioni in un file:
rake site_settings:export \u003e saved_settings.yml
Se vuoi importare le impostazioni da un file:
rake site_settings:import \u003c saved_settings.yml
Esportare/Importare le categorie
Ci sono due opzioni per l’esportazione e un metodo per gestire l’importazione.
Esportare un insieme di categorie complete
Innanzitutto ottieni un elenco degli ID delle tue categorie:
rake categories:list
Poi separa gli ID delle categorie con spazi nel task rake di esportazione. Ad esempio:
rake export:categories["12 6"]
Esportare la struttura delle categorie del tuo sito
Questo equivale a copiare lo „scheletro" del tuo sito Discourse. Include ogni categoria insieme a eventuali gruppi associati alle autorizzazioni della categoria esistenti. Non include i topic:
rake export:category_structure
Se vuoi la struttura delle categorie insieme a eventuali gruppi associati alle autorizzazioni della categoria e eventuali membri di tali gruppi:
rake export:category_structure[true]
Importare un file di categoria
Usa il nome del file esportato come nell’esempio seguente:
rake import:file["category-export-2019-05-16-052430.json"]
Esportare/Importare i gruppi
Esportare tutti i gruppi di utenti
rake export:groups
Esportare tutti i gruppi di utenti inclusi gli utenti
rake export:groups[true]
Importare un file di gruppo
Usa il nome del file esportato come nell’esempio seguente:
rake import:file["group-export-2019-05-16-052430.json"]
Impostare le autorizzazioni per più categorie
Nota che questo rimuoverà eventuali restrizioni di accesso esistenti che hai impostato per le categorie coinvolte. Assicurati di includere tutte le autorizzazioni pertinenti.
-
Ottieni un elenco di categorie insieme ai loro ID
rails c Category.all.pluck("name", "id") -
Crea un array con gli ID delle categorie che desideri targeting.
category_ids = [6,7,8,10] -
Modifica le autorizzazioni. La funzione
set_permissionspuò utilizzare i seguenti parametri::full,:create_post,:readonly-
Una singola autorizzazione. Ad esempio, rendere un insieme di categorie riservato allo staff:
Category.where(id: category_ids).find_each do |category| category.set_permissions(:staff =\u003e :full) category.save! end -
Più autorizzazioni. Ad esempio, rendere un insieme di categorie in sola lettura per gli utenti normali:
Category.where(id: category_ids).find_each do |category| category.set_permissions(:everyone =\u003e :readonly, :staff =\u003e :full) category.save! end -
Autorizzazioni per gruppi di utenti. Ad esempio, concedere a un gruppo autorizzazioni complete e a un altro gruppo sola lettura per un insieme di categorie:
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 =\u003e :full, buyers_group.id =\u003e :readonly) category.save! end
-
Taggare in blocco tutti i topic in base a una parola chiave
Lo script seguente ti consentirà di taggare i topic in base alla presenza di una parola chiave nel titolo del topic o nei suoi post. Inizia creando un array di parole chiave:
rails c
keywords = ['apples','oranges']
Successivamente dobbiamo definire un metodo:
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 \u003c\u003c tag
end
end
end
Infine esegui ogni parola chiave attraverso il metodo. Il seguente taggherà ogni topic rilevante con un tag chiamato „frutta":
keywords.each { |word| tag_by_keyword(word, 'fruit') }
Taggare in blocco tutti i topic all’interno di una categoria
Modello: rake tags:bulk_tag_category["<tag>|<tag>",<category_id>]
Questo sarebbe particolarmente utile quando si cerca di convertire una categoria in un tag.
Innanzitutto, usa il seguente task rake per trovare l’ID della categoria rilevante.
rake categories:list
Tagga tutti i topic della categoria che specifichi. In questo esempio, taggeresti tutti i topic nella categoria con ID 6 con il tag „supporto“.
questo rimuoverà tutti gli altri tag da ogni topic.
rake tags:bulk_tag_category["support",6]
Aggiungi tutti i topic della categoria che specifichi. In questo esempio, aggiungeresti il tag „supporto“ a tutti i topic nella categoria con ID 6, mantenendo i tag esistenti.
rake tags:bulk_tag_category["support",6,true]
Spostare tutti i topic con un tag specifico in una singola categoria
Quando cerchi di ristrutturare il tuo sito Discourse, potresti scoprire di voler spostare una raccolta di topic senza attivare notifiche. Un modo per farlo è creare un tag temporaneo, applicarlo ai topic appropriati, spostare i topic in una categoria specifica utilizzando il codice sottostante, e infine eliminare il tag temporaneo.
Ottieni il tag.
rails c
tag = Tag.find_by_name("tutorial")
Ottieni la categoria di destinazione.
- Per le categorie normali:
cat_to = Category.find_by_slug('guides')
- Per le sottocategorie:
cat_to = Category.find_by_slug('child-slug','parent-slug')
Sposta i topic taggati nella categoria di destinazione.
Topic.joins(:topic_tags).where("topic_tags.tag_id = ?", tag.id).update_all(category_id: cat_to.id)
Aggiorna i conteggi dei topic delle categorie interessate.
Category.update_stats
CategoryTagStat.update_topic_counts
Spostare tutti i topic da una categoria all’altra
Trova gli ID delle categorie con il seguente task rake:
rake categories:list
Il primo valore dovrebbe essere l’ID della categoria di partenza. Il secondo valore dovrebbe essere l’ID della categoria di destinazione.
rake categories:move_topics[15,6]
Script della console Rails
cat_from_id = XX # Categoria da cui spostare i topic
cat_to_id = XX # Categoria in cui spostare i topic
Topic.where(category_id: cat_from_id).update_all(category_id: cat_to_id)
Category.update_stats
CategoryTagStat.update_topic_counts
Cambiare il proprietario di tutti i topic nelle categorie
Trova gli ID delle categorie con il seguente task rake:
rake categories:list
Specifica il nuovo proprietario e le categorie su cui operare. Le categorie dovrebbero essere un array di ID di categoria, le categorie 1, 2 e 3 nell’esempio:
rails c
user = User.find_by(username_lower: "lowercase-username")
categories = [1, 2, 3]
Ottieni tutti gli ID dei topic per le categorie date e cambia il proprietario del primo post in tutti i topic corrispondenti.
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
Concedere un badge a tutti i membri di un gruppo
Concedi un badge a tutti gli utenti che appartengono a un gruppo specifico. Il primo valore è l’ID del gruppo e il secondo è l’ID del badge.
rails c
Group.find_by_name("event_participants").id
Badge.find_by_name("event_badge").id
exit
rake groups:grant_badge[42,102]
Nota che il task rake sopra concede solo un badge; non revoca un badge precedentemente concesso se un utente non fa più parte del gruppo specificato. Se devi revocare in blocco i badge per tutti gli utenti che non fanno più parte di un gruppo, puoi eseguire quanto segue:
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
Assicurarsi che tutti gli utenti siano al loro livello di fiducia automatico
Supponiamo di aver impostato il livello di fiducia predefinito per gli utenti nuovi o invitati su un valore che non sta funzionando come previsto (ad esempio TL4). Ora vuoi cambiarlo in modo che i tuoi utenti siano al livello di fiducia che avrebbero automaticamente, dati i loro attuali statistiche. I seguenti comandi garantiranno che tutti gli utenti siano al livello di fiducia che dovrebbero avere secondo Understanding Discourse Trust Levels. Nota: gli utenti con livelli di fiducia bloccati non saranno influenzati.
Assicurati che tutti gli utenti siano impostati sul livello di fiducia corretto:
rails c
User.all.find_each do |user|
Promotion.recalculate(user)
end
Aggiorna le statistiche del gruppo per riflettere le modifiche:
Group.ensure_consistency!
Script di manutenzione dei topic
I seguenti script Ruby dimostrano come eseguire la manutenzione automatizzata dei topic in base alle date di attività e ad altri criteri. Questi script combinano query SQL per identificare i topic con codice Ruby per eseguire azioni su di essi e devono essere eseguiti tramite la console Rails per il tuo sito.
Ogni script segue un modello simile:
- Una query SQL che identifica i topic rilevanti
- Codice Ruby che elabora ogni topic e applica le azioni desiderate
- Gestione di base degli errori e registrazione
Questi script possono essere personalizzati:
- Regolando i periodi di tempo (ad esempio „6 MONTH“, „1 YEAR“, „2 YEAR")
- Cambiando le selezioni di categoria per corrispondere alla struttura del tuo forum
- Modificando quali azioni intraprendere (chiudere, rimuovere dall’elenco o spostare)
- Aggiungendo condizioni aggiuntive come conteggi dei post o soglie di visualizzazione
Chiudere, rimuovere dall’elenco e spostare i topic inattivi
Questo script identifica i topic che soddisfano i seguenti criteri:
- In una categoria specifica
- Aperti
- Non risolti (utilizzando il plugin Discourse Solved)
- Nessuna attività recente entro un periodo di tempo specifico
Poi esegue più azioni:
- Li chiude,
- Li rimuove dall’elenco e
- Li sposta in una categoria designata per contenuti obsoleti
Query 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) \u003c= (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 combinato + 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) \u003c= (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. Sposta nella categoria di destinazione
topic.update!(category_id: destination_category.id)
puts "#{topic.id} moved to destination category"
# 2. Chiudi il topic
topic.update_status('closed', true, user, until: nil)
puts "#{topic.id} is closed"
# 3. Rimuovi dall'elenco il topic
topic.update_status('visible', false, user, until: nil)
puts "#{topic.id} is unlisted"
# Gestione degli errori
rescue =\u003e e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Chiudere i topic risolti senza attività recente
Questo script chiude i topic risolti che sono stati inattivi per un periodo definito. Questo può aiutare a mantenere il tuo forum ordinato preservando allo stesso tempo i preziosi topic risolti.
Questo script identifica i topic che soddisfano i seguenti criteri:
- In una categoria specifica
- Aperti
- Risolti (utilizzando il plugin Discourse Solved)
- Nessuna attività recente entro un periodo di tempo specifico
Query 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) \u003c= (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 combinato + 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) \u003c= (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"])
# Chiudi il topic
topic.update_status('closed', true, user, until: nil)
puts "#{topic.id} is closed"
# Gestione degli errori
rescue =\u003e e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Archiviare i topic precedentemente chiusi
Questo script identifica i topic che sono stati precedentemente chiusi prima di una data specifica e li sposta in una categoria di archivio rimuovendoli dall’elenco.
Query 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 \u003c= (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 combinato + 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 \u003c= (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. Sposta nella categoria di archivio
topic.update!(category_id: archive_category.id)
puts "#{topic.id} moved to archive category"
# 2. Rimuovi dall'elenco il topic
topic.update_status('visible', false, user, until: nil)
puts "#{topic.id} is unlisted"
# Gestione degli errori
rescue =\u003e e
puts "Error processing topic #{row["topic_id"]}: #{e.message}"
end
end
puts "Process completed"
Task rake distruttivi
Eliminare intere categorie
Il seguente ti consentirà di distruggere più categorie, insieme a eventuali sottocategorie e topic che appartengono a quelle categorie.
Stampa un elenco di ID delle categorie
rake categories:list
Distruggi un insieme di categorie in base al loro ID
rake destroy:categories[10,11,12,18,30]
Eliminare tutti i topic in una categoria
Rimuovere tutti i messaggi personali
rake destroy:private_messages
Distruggere tutti i gruppi
rake destroy:groups
Distruggere tutti gli utenti non amministratori
rake destroy:users
Distruggere le statistiche del sito
rake destroy:stats
Anonimizzare tutti gli utenti tranne lo staff
rake users:anonymize_all
Eliminare definitivamente un insieme di post
Il seguente task rake eliminerà definitivamente un elenco di post in base al loro ID. Se un post è il primo post di un topic, tutti i post in quel topic verranno eliminati definitivamente. Prima di poter eseguire correttamente il task, l’impostazione del sito can_permanently_delete deve essere abilitata.
Una volta che un post viene eliminato da questo task, non esisterà più nel database e non potrà essere ripristinato.
Ci sono due possibili approcci:
-
Opzione 1 – Passa un elenco separato da virgola di ID dei post come argomento
rake destroy:posts[4,8,15,16,23,42] -
Opzione 2 – Specifica un file di testo con un elenco separato da virgola di ID dei post (ideale per grandi insiemi di post).
cat post_ids.txt | rake destroy:posts
Ho cercato di includere i task rake più utili in questo topic, ma ce ne sono molti altri inclusi in Discourse. Se desideri vedere un elenco completo, puoi utilizzare quanto segue:
Tutti i task che hanno descrizioni
rake --tasks
Tutti i task, inclusi quelli che non hanno descrizioni
rake -AT