Operaciones masivas administrativas

A continuación encontrarás una colección de operaciones masivas que se pueden iniciar desde la línea de comandos. Necesitarás acceso SSH; si eres un cliente alojado, deberás contactar al equipo de Discourse para ejecutar estos comandos.

:warning: Antes de trabajar con la consola, es extremadamente importante que tengas una copia de seguridad reciente. ¡Los errores siempre pueden ocurrir!

Lo primero que debes hacer es entrar en el contenedor de tu sitio:

cd /var/discourse
./launcher enter app

Guías adicionales:

Cambiar el estado de los temas


Antes de ejecutar los siguientes comandos, ejecuta rails c para entrar en la consola.

  • Ocultar todos los temas dentro de una categoría (excluye la acción de publicación)

    Puedes reemplazar visible por closed o archived y ajustar los valores true/false según sea necesario

    cat_id = Category.find_by_slug('admins').id
    Topic.where(category_id: cat_id, visible: true).update_all(visible: false)
    
  • Ocultar todos los temas dentro de una categoría (incluye la acción de publicación)

    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
    
  • Cerrar todos los temas creados antes de una fecha específica (incluye la acción de publicación)

    Topic.where(closed: false).where("created_at <= '2015-01-01'").find_each do |topic| 
      topic.update_status('closed', true, Discourse.system_user)
    end
    

Mover temas


Mover una colección de temas de una categoría a otra

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

Usuarios

Eliminar un subconjunto de usuarios


Eliminar usuarios que nunca han publicado y no han visitado el sitio desde una fecha 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 un conjunto de usuarios según criterios


Establecer quién será registrado como el responsable de la suspensión de los usuarios

rails c
logger = StaffActionLogger.new(User.find_by(username_lower: "tshenry"))

Crear un período de suspensión y una razón

suspend_till = DateTime.new(2057,12,31)
reason = 'Curso completado'

En este ejemplo, nuestros criterios de usuario serán la pertenencia a un grupo.

target_group = Group.find_by_name("summer_students")
users = User.joins(:group_users).where(group_users: {group_id: target_group.id})

Suspender cada usuario según los valores establecidos anteriormente:

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

Actualizar las razones de suspensión de usuarios


Quizás suspendiste usuarios que completaron un curso (véase el ejemplo arriba), y ahora quieres añadir el año del curso ya que has impartido clases durante varios años.

UserHistory.where(action: 10, details: "Curso completado").update_all(details: "Curso 2018 completado")

Levantar la suspensión de usuarios


Si necesitas levantar la suspensión de usuarios en masa, por ejemplo, porque formaban parte de la cohorte del año anterior y regresan este año, puedes hacerlo como se muestra a continuación. En el ejemplo, estamos buscando usuarios por su 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

Exportar/Importar

Exportar/Importar toda la configuración del sitio


Para simplemente imprimir todas las configuraciones que han sido modificadas en tu sitio, ejecuta:

rake site_settings:export

Si quieres exportar la configuración a un archivo:

rake site_settings:export > saved_settings.yml

Si quieres importar la configuración desde un archivo:

rake site_settings:import < saved_settings.yml

Exportar/Importar categorías


Hay dos opciones para exportar y un método para importar.

Exportar un conjunto de categorías completas

Primero obtén una lista de los IDs de tus categorías:

rake categories:list

Luego, separa los IDs de las categorías con espacios en la tarea rake de exportación. Por ejemplo:

rake export:categories["12 6"]

Exportar la estructura de categorías de tu sitio

Esto es esencialmente copiar el “esqueleto” de tu sitio Discourse. Incluye cada categoría junto con cualquier grupo asociado a los permisos de categoría existentes. No incluye temas:

rake export:category_structure

Si quieres la estructura de categorías junto con cualquier grupo asociado a los permisos de categoría y cualquier miembro de esos grupos:

rake export:category_structure[true]

Importar un archivo de categoría

Usa el nombre del archivo exportado como en el ejemplo a continuación:

rake import:file["category-export-2019-05-16-052430.json"]

Exportar/Importar grupos


Exportar todos los grupos de usuarios

rake export:groups

Exportar todos los grupos de usuarios incluyendo usuarios

rake export:groups[true]

Importar un archivo de grupo
Usa el nombre del archivo exportado como en el ejemplo a continuación:

rake import:file["group-export-2019-05-16-052430.json"]

Establecer permisos para múltiples categorías


:warning: Ten en cuenta que esto eliminará cualquier restricción de acceso existente que hayas configurado para las categorías involucradas. Asegúrate de incluir todos los permisos relevantes.

  1. Obtén una lista de categorías junto con sus IDs

    rails c
    Category.all.pluck("name", "id")
    
  2. Crea un array con los IDs de las categorías que deseas objetivo.

    category_ids = [6,7,8,10]
    
  3. Cambia los permisos. La función set_permissions puede utilizar los siguientes parámetros: :full, :create_post, :readonly

    • Un solo permiso. Por ejemplo, hacer que un conjunto de categorías sea solo para personal:

      Category.where(id: category_ids).find_each do |category| 
       category.set_permissions(:staff => :full)
       category.save!
      end
      
    • Múltiples permisos. Por ejemplo, hacer que un conjunto de categorías sea de solo lectura para usuarios normales:

      Category.where(id: category_ids).find_each do |category| 
        category.set_permissions(:everyone => :readonly, :staff => :full)
        category.save!
      end
      
    • Permisos de grupo de usuarios. Por ejemplo, otorgar permisos completos a un grupo y solo lectura a otro grupo para un conjunto de categorías:

      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
      

Etiquetar masivamente todos los temas basándose en una palabra clave

El siguiente script te permitirá etiquetar temas basándose en la presencia de una palabra clave en el título del tema o en sus publicaciones. Comienza creando un array de palabras clave:

rails c
keywords = ['manzanas','naranjas']

A continuación, necesitamos definir un 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

Y finalmente ejecuta cada palabra clave a través del método. El siguiente etiquetará cada tema relevante con una etiqueta llamada „fruta":

keywords.each { |word| tag_by_keyword(word, 'fruta') }

Etiquetar masivamente todos los temas dentro de una categoría


Plantilla: rake tags:bulk_tag_category["<etiqueta>|<etiqueta>",<id_categoria>]
Esto sería particularmente útil al intentar convertir una categoría en una etiqueta.

Primero, usa la siguiente tarea rake para encontrar el ID de la categoría relevante.

rake categories:list

Etiqueta todos los temas de la categoría que especifiques. En este ejemplo, estarías etiquetando todos los temas en la categoría con un ID de 6 con la etiqueta „soporte“. :warning: esto eliminará todas las demás etiquetas de cada tema.

rake tags:bulk_tag_category["soporte",6]

Añade todas las etiquetas a todos los temas de la categoría que especifiques. En este ejemplo, estarías añadiendo la etiqueta „soporte“ a todos los temas en la categoría con un ID de 6, manteniendo las etiquetas existentes.

rake tags:bulk_tag_category["soporte",6,true]

Mover todos los temas con una etiqueta específica a una sola categoría

Al intentar reestructurar tu sitio Discourse, es posible que desees mover una colección de temas sin generar ninguna notificación. Una forma de hacerlo es crear una etiqueta temporal, aplicarla a los temas adecuados, mover los temas a una categoría específica usando el código a continuación y, finalmente, eliminar la etiqueta temporal.

Obtén la etiqueta.

rails c
tag = Tag.find_by_name("tutorial")

Obtén la categoría de destino.

  • Para categorías regulares:
cat_to = Category.find_by_slug('guías')
  • Para subcategorías:
cat_to = Category.find_by_slug('slug-hijo','slug-padre')

Mueve los temas etiquetados a la categoría de destino.

Topic.joins(:topic_tags).where("topic_tags.tag_id = ?", tag.id).update_all(category_id: cat_to.id)

Actualiza los conteos de temas de las categorías afectadas.

Category.update_stats
CategoryTagStat.update_topic_counts

Mover todos los temas de una categoría a otra


Encuentra los IDs de categoría con la siguiente tarea rake:

rake categories:list

El primer valor debe ser el ID de la categoría de origen. El segundo valor debe ser el ID de la categoría de destino.

rake categories:move_topics[15,6]
Script de consola Rails
cat_from_id = XX # Categoría de la que mover los temas 
cat_to_id = XX  # Categoría a la que mover los temas 
Topic.where(category_id: cat_from_id).update_all(category_id: cat_to_id)
Category.update_stats
CategoryTagStat.update_topic_counts

Cambiar el propietario de todos los temas en categorías


Encuentra los IDs de categoría con la siguiente tarea rake:

rake categories:list

Especifica el nuevo propietario y las categorías sobre las que operar. Las categorías deben ser un array de IDs de categoría; las categorías 1, 2 y 3 en el ejemplo:

rails c
user = User.find_by(username_lower: "nombre-de-usuario-minúsculas")
categories = [1, 2, 3]

Obtén todos los IDs de tema para las categorías dadas y cambia el propietario de la primera publicación en todos los temas coincidentes.

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

Otorgar una insignia a todos los miembros de un grupo


Otorga una insignia a todos los usuarios que pertenecen a un grupo específico. El primer valor es el ID del grupo y el segundo es el ID de la insignia.

rails c
Group.find_by_name("participantes_evento").id
Badge.find_by_name("insignia_evento").id
exit
rake groups:grant_badge[42,102]

:warning: Ten en cuenta que la tarea rake anterior solo otorga una insignia; no revocará una insignia otorgada previamente si un usuario ya no forma parte del grupo especificado. Si necesitas revocar masivamente insignias para todos los usuarios que ya no forman parte de un grupo, puedes ejecutar lo siguiente:

rails c

badge_id = Badge.find_by_name("Miembro de algún grupo").id

group = Group.find_by_name("Algún_grupo")

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

Asegurar que todos los usuarios estén en su nivel de confianza automático


Digamos que configuraste el nivel de confianza predeterminado para usuarios nuevos o invitados a un valor que no está funcionando como esperabas (como TL4). Ahora quieres cambiarlo para que tus usuarios estén en el nivel de confianza que les correspondería automáticamente, dados sus estadísticas actuales. Los siguientes comandos asegurarán que todos los usuarios estén en el nivel de confianza que deberían según Understanding Discourse Trust Levels. Nota: los usuarios con niveles de confianza bloqueados no se verán afectados.

Asegúrate de que todos los usuarios tengan el nivel de confianza correcto:

rails c
User.all.find_each do |user|
  Promotion.recalculate(user)
end

Actualiza las estadísticas de los grupos para reflejar los cambios:

Group.ensure_consistency!

Scripts de mantenimiento de temas

Los siguientes scripts de Ruby demuestran cómo realizar mantenimiento automatizado en temas basándose en fechas de actividad y otros criterios. Estos scripts combinan consultas SQL para identificar temas con código Ruby para realizar acciones sobre ellos y deben ejecutarse a través de la consola de Rails de tu sitio.

Cada script sigue un patrón similar:

  1. Una consulta SQL que identifica los temas relevantes
  2. Código Ruby que procesa cada tema y aplica las acciones deseadas
  3. Manejo básico de errores y registro

Estos scripts se pueden personalizar mediante:

  • Ajustar períodos de tiempo (por ejemplo, „6 MESES“, „1 AÑO“, „2 AÑOS")
  • Cambiar selecciones de categorías para coincidir con la estructura de tu foro
  • Modificar qué acciones tomar (cerrar, ocultar o mover)
  • Añadir condiciones adicionales como conteos de publicaciones o umbrales de vistas

Cerrar, ocultar y mover temas inactivos

Este script identifica temas que cumplen los siguientes criterios:

  • En una categoría específica
  • Abiertos
  • Sin resolver (usando el plugin Discourse Solved)
  • Sin actividad reciente dentro de un período de tiempo específico

Luego realiza múltiples acciones:

  • Los cierra,
  • Los oculta y
  • Los mueve a una categoría designada para contenido desactualizado
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 = [ID_CATEGORIA]
        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 '[PERIODO_TIEMPO]'))
    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 + Script combinados
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 = [ID_CATEGORIA]
        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 '[PERIODO_TIEMPO]'))
    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([ID_CATEGORIA_DESTINO])

puts "Se encontraron #{results.count} temas para procesar"

results.each do |row|
    begin
    topic = Topic.find(row["topic_id"])
    
    # 1. Mover a la categoría de destino
    topic.update!(category_id: destination_category.id)
    puts "#{topic.id} movido a la categoría de destino"
    
    # 2. Cerrar el tema
    topic.update_status('closed', true, user, until: nil)
    puts "#{topic.id} está cerrado"
    
    # 3. Ocultar el tema
    topic.update_status('visible', false, user, until: nil)
    puts "#{topic.id} está oculto"

    # Manejo de errores
    rescue => e
      puts "Error al procesar el tema #{row["topic_id"]}: #{e.message}"
    end
end

puts "Proceso completado"

Cerrar temas resueltos sin actividad reciente

Este script cierra temas resueltos que han estado inactivos durante un período definido. Esto puede ayudar a mantener tu foro ordenado mientras se preservan los temas resueltos valiosos.

Este script identifica temas que cumplen los siguientes criterios:

  • En una categoría específica
  • Abiertos
  • Resueltos (usando el plugin Discourse Solved)
  • Sin actividad reciente dentro de un período de tiempo 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 ([IDS_CATEGORIAS])
        AND t.deleted_at IS NULL
    GROUP BY ua.target_topic_id
    HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[PERIODO_TIEMPO]'))
    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 + Script combinados
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 ([IDS_CATEGORIAS])
        AND t.deleted_at IS NULL
    GROUP BY ua.target_topic_id
    HAVING MAX(ua.created_at) <= (CURRENT_DATE - (INTERVAL '[PERIODO_TIEMPO]'))
    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 "Se encontraron #{results.count} temas para procesar"

results.each do |row|
    begin
    topic = Topic.find(row["topic_id"])
     
    # Cerrar el tema
    topic.update_status('closed', true, user, until: nil)
    puts "#{topic.id} está cerrado"

    # Manejo de errores
    rescue => e
      puts "Error al procesar el tema #{row["topic_id"]}: #{e.message}"
    end
end

puts "Proceso completado"

Archivar temas previamente cerrados

Este script identifica temas que fueron cerrados previamente antes de una fecha específica y los mueve a una categoría de archivo mientras los oculta.

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 ([IDS_CATEGORIAS])
        AND t.deleted_at IS NULL
        AND tt.execute_at IS NOT NULL
        AND tt.execute_at <= (CURRENT_DATE - INTERVAL '[PERIODO_TIEMPO]')
    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 + Script combinados
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 ([IDS_CATEGORIAS])
        AND t.deleted_at IS NULL
        AND tt.execute_at IS NOT NULL
        AND tt.execute_at <= (CURRENT_DATE - INTERVAL '[PERIODO_TIEMPO]')
    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([ID_CATEGORIA_ARCHIVO])

puts "Se encontraron #{results.count} temas para procesar"

results.each do |row|
    begin
    topic = Topic.find(row["topic_id"])
    
    # 1. Mover a la categoría de archivo
    topic.update!(category_id: archive_category.id)
    puts "#{topic.id} movido a la categoría de archivo"
    
    # 2. Ocultar el tema
    topic.update_status('visible', false, user, until: nil)
    puts "#{topic.id} está oculto"

    # Manejo de errores
    rescue => e
      puts "Error al procesar el tema #{row["topic_id"]}: #{e.message}"
    end
end

puts "Proceso completado"

Tareas rake destructivas


Eliminar categorías completas

Lo siguiente te permitirá destruir múltiples categorías, junto con cualquier subcategoría y tema que pertenezca a esas categorías.

Imprimir una lista de IDs de categoría

rake categories:list

Destruir un conjunto de categorías basado en su ID

rake destroy:categories[10,11,12,18,30]

Eliminar todos los temas en una categoría

Eliminar todos los mensajes personales

rake destroy:private_messages

Destruir todos los grupos

rake destroy:groups

Destruir todos los usuarios no administradores

rake destroy:users

Destruir estadísticas del sitio

rake destroy:stats

Anonimizar a todos los usuarios excepto al personal

rake users:anonymize_all

Eliminar permanentemente un conjunto de publicaciones

La siguiente tarea rake eliminará permanentemente una lista de publicaciones basada en su ID. Si una publicación es la primera en un tema, todas las publicaciones en ese tema serán eliminadas permanentemente. Antes de poder ejecutar la tarea con éxito, la configuración del sitio can_permanently_delete debe estar habilitada.

:warning: Una vez que una publicación sea eliminada por esta tarea, ya no existirá en la base de datos y no se podrá recuperar.

Hay dos enfoques posibles:

  • Opción 1 – Pasar una lista separada por comas de IDs de publicación como argumento

    rake destroy:posts[4,8,15,16,23,42]
    
  • Opción 2 – Especificar un archivo de texto con una lista separada por comas de IDs de publicación (ideal para grandes conjuntos de publicaciones).

    cat post_ids.txt | rake destroy:posts
    

He intentado incluir las tareas rake más útiles en este tema, pero hay muchas otras empaquetadas con Discourse. Si deseas ver una lista completa, puedes usar lo siguiente:

Todas las tareas que tienen descripciones

rake --tasks

Todas las tareas, incluyendo aquellas que no tienen descripciones

rake -AT
70 Me gusta
Performing bulk actions as a moderator
Ruby on rails console command
Backup only Site Settings
How to move all topics of 1 category to new tag
Error Message when editing large number of topics
Delete/Remove All Tags in Bulk
How To Apply signature to every user?
How can I directly edit Discourse database from a GUI?
Bulk open closed topics
Suggest favorite YouTube tutorials for Discourse Admins and Moderators
Error Message when editing large number of topics
How to truncate bounced email log
Is there a way to grant badge to a group of user?
What makes a successful volunteer Discourse sysadmin?
How to extend time of all suspended users by one command?
Is there a bulk administrative command to aprove users?
DiscoTOC mobile view does not work with Docs
How might we better structure #howto?
Moving from sub-categories to tags?
Moving from sub-categories to tags?
Automatic Admin settings backups
How to get rid of thousands of topics that have no value?
Setting the api key via console
Bulk Action on Users
Mass-edit (or review) category parameters
How to activate and unstage accounts for imported users
Moving a group to TL3
Bulk Category Creation via CSV
Adding bulk categories
Can I/how to convert a tag to a category?
Rake post without confirmation
A few questions about batch moving or deleting topics
Restoring Deleted Messages?
Bulk Ownership Change of First Posts by Tag – Script Review and Suggestions
What makes a successful volunteer Discourse sysadmin?
Understanding and using badges
How to recalculate all trust_levels?
Adding many categories
How to Delete Active Users whose Readtime is less or not logged in since long or not visited since long?
How to Reset Site Statistics or Recalculate?
A community template emphasizing place and intent
Docker attach gives empty new line
Change notification settings for all users per topic
Why is there a category that I can't modify
How to sort topics in Latest by creation date?
"Period" in tag
Bulk move many topics from one category to another
Can I disable choosing a default homepage in users' Interface settings?
Bulk delete all topics in a category
Update all users email watchlist with a (newly created) category
How to change owner of invite links?
Trust level names in spanish
Admin guide to tags in Discourse
Assign users a random digest time?
How to change language of all users?
Requesting help demoting users with invalid email addresses
Rake import category doesn't respect parent category
Is there a non-query way to remove a bulk of users from groups?
Set up file and image uploads to S3
Hide Muted Categories
Modify trust level for all users
Create user without sending invite
Removing specific staff action logs using the console
Is it possible to make database changes using postgres rather than rake?
Applying Watched Words to existing posts
Bulk changing subcategories doesn't select all topics?
How to update and unlock all groups?
CLI Command for Deleting Category
Apply preferences settings for all normal users globally
Switch all users to TL2
How to add multiple tags up front
Creating and configuring custom user fields
How to delete EVERYTHING from my forum and just leave the users?
Back up only the settings
Bulk mark messages and posters as spam
Bulk mark messages and posters as spam
Staff category permission change
Convert all existing topics in category to wikis
Migrate a phpBB3 forum to Discourse
Manage multiple Discourse instances from one place only
Merge categories
Bulk Importing Groups Fails
Automatically replacing some tags with categories on existing forum
Mass closing topics
User monetization with group access?
A way to trigger auto-tagging across all topics for a new watched word
Convert a category to private and add users to a specific group with access
How to mass remove PMs?
RSS Polling
Mass Revoking Badges
How to turn off forum except for staff
Cannot delete tag with 2k topics
Is it possible to limit TL0 to posting in one category?
Mass close existing topics older than x?
Mass close existing topics older than x?
How to import category with category permissions?
Bulk open closed topics
Get Error Oops The software powering this discussion forum encountered an unexpected problem after upgrade
How do I back up only forum configuration information?
Question about category populating with certain tags
How extensible can I make my installation in terms of sub domains and restricting membership to them?
Automatically re-categorize topics from an imported forum by targeting keywords in titles?
How to clear all historical statistics from dashboard
Create a category that's private to one group, but open to other groups
自定义表情符号能否支持批量删除?
Unable to Bulk Suspend/Deactivate Users in Rails Console on Discourse 3.5.0.beta5-dev
How to Disable ALL User-to-User DMs/Chat without breaking Other Features?
Move Some topics to New Instance
Structure and duplication of category contents intra discourse and between discourse sites
Is there a way to convert categories into tags?
Structuring an active support community migrating from Facebook
How to delete thousands of Personal Messages?
Multilingual Plugin :globe_with_meridians:
Moving from sub-categories to tags?
How to change topic date after import
Emoji Fluff
Export/import theme components in bulk?
Need To Reopen All Topics!
How to bulk delete old whispers
Add a tag to all topics in a category
How to Create a Script to "Bulk Remove" from a Group?
How to delete all warnings?
Marking multiple account as Suspended account
How can I directly edit Discourse database from a GUI?
Are conditions to get new Trust level cumulative?
Bulk Remove Members from a Group
Can't reverse silencing a category for a group
Assigning mod status to multiple users
Preserving site settings through migration
Limit volume of forum emails via admin
Is it possible to import a Discourse backup as a category inside an alredy existing discourse isntance?
Site rearrangement scripting: What's the best venue?
Recover deleted categories

@Taylor ¿qué pasa con la actualización masiva de todos los temas con una marca de tiempo diferente?

Digamos que quisiera que todos los temas en mi instancia de Discourse se mostraran instantáneamente como si hubieran sido creados hoy, ¿cómo lo haría?

Probablemente una modificación de esta consulta:

(Suponiendo que están en una categoría)

1 me gusta

4 publicaciones se dividieron en un nuevo tema: ¿Cómo importar categoría con permisos de categoría?

Considerando que este comando debe ejecutarse dentro del contenedor Docker, y que el pwd predeterminado dentro del contenedor al ejecutar ./launcher enter app parece ser /var/www/discourse, el comando descrito aquí parece un poco extraño por algunas razones:

  • site_settings incluye las claves de acceso secretas utilizadas para S3 y otras API. Parece que estas no deberían almacenarse en un archivo en /var/www, ya que esa es tradicionalmente la ubicación de los archivos que se sirven a la web.
  • Dado que estamos dentro del contenedor en este pwd predeterminado, esperaría que el archivo guardado aquí se pierda cuando el contenedor se detenga.

Desde dentro del contenedor, usé este comando mount | grep ^/dev/ | grep -v /etc/ para determinar que la ubicación /shared dentro del contenedor parece mapearse a /var/discourse/shared/standalone en el sistema host. Entonces, parece que tal vez el comando debería ser algo como esto:

cd /var/discourse
./launcher enter app
rake site_settings:export | grep -v key | grep -v secret > /shared/site_settings_$(date "%Y-%m-%d-%H-%M-%S").yml

Esto dejaría el archivo en una ubicación como /var/discourse/shared/standalone/site_settings_2024-08-14-15-53-11.yml en el sistema host.

Tenga en cuenta que los comandos grep adicionales canalizados aquí eliminarán cualquier línea que contenga la palabra “key” o “secret” para eliminar las claves API, pero también eliminarían las líneas que incluyeran esas palabras por razones no sensibles.

¿Esto suena correcto?

Es cierto, pero estoy bastante seguro de que Discourse no servirá la configuración. Puedes ejecutar el comando desde cualquier directorio y se asume que si estás haciendo este tipo de cosas, entiendes lo que estás haciendo.

Así que podrías simplemente

cd /shared/
mkdir -p my-settings
cd my-settings
rake ...

antes de ejecutar la tarea de rake.

Claro que el volcado tiene las claves, pero muchas de ellas ya están en texto plano en un montón de lugares (por ejemplo, si sigues los procedimientos recomendados, tus claves de S3 están en app.yml).

Sí.

2 Me gusta

oh no sabía que las tareas rake seguirían funcionando fuera del directorio raíz de la aplicación, eso tiene más sentido, sí, gracias

1 me gusta

¡Todavía me sorprende!

Pero también puedes poner la ruta completa del volcado cuando rediriges a un archivo.

Según estas instrucciones, puedo usar

rake export:groups

para exportar el conjunto de Grupos e importar nuevos Grupos usando el mismo formato. Sin embargo, cuando creo un nuevo Grupo siguiendo el formato exportado, el –trace se queja:

ActiveRecord::RecordInvalid: Validation failed: You cannot allow membership requests for a group without any owners. (ActiveRecord::RecordInvalid)

(Obtengo el mismo error si no incluyo los user_ids.)

Aquí está mi archivo de importación:

{“groups”:[{“id”:352,“name”:“NewGroup1”,“created_at”:“2026-02-18T17:56:01.807Z”,“automatic_membership_email_domains”:“”,“primary_group”:false,“title”:null,“grant_trust_level”:null,“incoming_email”:null,“bio_raw”:“This is a NewGroup.”,“allow_membership_requests”:true,“full_name”:“NewGroup1”,“default_notification_level”:3,“visibility_level”:2,“public_exit”:true,“public_admission”:false,“membership_request_template”:null,“messageable_level”:3,“mentionable_level”:3,“members_visibility_level”:2,“publish_read_state”:false,“user_ids”:[1,2]}]}

No veo ninguna forma de indicar cuál de los usuarios es un propietario.

Incluso agregué otro registro de {“group_users”:[…]} para designar un propietario, pero sigo obteniendo el mismo error.

¿Funciona esto? ¿Alguien ha importado nuevos Grupos con éxito y, de ser así, cuál es el secreto?

1 me gusta

Un poco tarde, lo siento, pero este es tu problema. Si lo cambias a false, ya sea editando el grupo antes de la exportación o modificando el archivo .json, lo tendrás resuelto.

El problema es que activar esta opción exige que haya un propietario para gestionar las solicitudes.

Después de la migración, puedes corregirlo como mejor te parezca.