ask.discourse.org — хорошая отправная точка. Вот пример скрипта на Rails:
MAX_MESSAGES = 1000 # Опциональный лимит для тестирования
SECONDS_BETWEEN_MESSAGES = 3 # Интервал в 3 секунды
Rails.logger.info "Запуск скрипта массовой рассылки сообщений..."
# Определите содержимое вашего сообщения
message_title = "Добро пожаловать в наше сообщество"
message_body = "Привет! Мы очень рады видеть вас здесь. Дайте нам знать, если у вас возникнут вопросы!"
# Получите пользователей, отсортированных по последнему времени активности
users = User.where(active: true)
.where.not(staged: true) # Исключить пользователей в режиме тестирования
.order(last_seen_at: :desc)
.limit(MAX_MESSAGES)
Rails.logger.info "Найдено активных пользователей для рассылки: #{users.count}."
users.each_with_index do |user, index|
begin
Rails.logger.info "Добавление сообщения в очередь для #{user.username} (#{index + 1}/#{users.count})..."
PostCreator.create!(
Discourse.system_user,
title: message_title,
raw: message_body,
archetype: Archetype.private_message,
target_usernames: user.username,
skip_validations: true
)
Rails.logger.info "Сообщение успешно добавлено в очередь для #{user.username}."
# Подождите указанный интервал перед обработкой следующего пользователя
sleep(SECONDS_BETWEEN_MESSAGES)
rescue => e
Rails.logger.error "Не удалось отправить сообщение пользователю #{user.username}: #{e.message}"
end
end
Rails.logger.info "Скрипт массовой рассылки завершен!"
Я не вносил никаких изменений, и пользователь system отправил личные сообщения всем пользователям в моем тестовом экземпляре:
@Canapin, во-первых, какой потрясающий никнейм… но ваш ответ ещё впечатляющий! Это именно то, что мы планируем сделать. Вот немного подробнее.
У нас 3,5 миллиона пользователей. Мы не планируем отправлять сообщения всем сразу. Идея в том, чтобы запускать этот скрипт, возможно, партиями по 10 тысяч, затем делать перерыв на несколько дней, оценивать активность, проверять репутацию отправителя и затем начинать заново, и так далее.
Мы хотели бы отправлять это от имени администратора с профилем, а не от «системы». Предполагаю, это возможно?
Да, просто замените system на нужное имя пользователя в скрипте.
Извините, я пробежался по коду, там нет system для замены, значит, это нужно сделать другим способом.
Скорее всего, вам стоит использовать менеджер сессий, например screen или tmux, чтобы ваш скрипт мог работать в фоновом режиме.
Я также предполагаю, что вы захотите иметь возможность останавливать скрипт по желанию и перезапускать его позже от того же пользователя, на котором он остановился.
Поскольку я не программист (имею в виду, кроме как выводить hello world…), я предоставлю другим дать советы по правильной настройке этой функции, а также безопасной рассылке миллионам пользователей
@Canapin Всё логично, спасибо. Да, я думаю, что можно просто подсчитать количество записей, через которые система должна пройти, чтобы она сама остановилась, но я понимаю и другие варианты.
Если у кого-то есть идеи, как сделать это более автоматизированным (например, запускать пакетами по 10 тысяч пользователей), буду рад услышать.
Да. Если бы я создавал такой скрипт, я бы настроил его так, чтобы можно было возобновить работу с последнего пользователя в случае, если скрипт будет принудительно остановлен (перезагрузка сервера, сбой и т. д.).
MAX_MESSAGES = 1000 # Опциональный лимит для тестирования
SECONDS_BETWEEN_MESSAGES = 3 # Интервал в 3 секунды
SENDER_USERNAME = "coco"
message_sender = User.find_by(username: SENDER_USERNAME)
if message_sender.nil?
Rails.logger.error "Пользователь отправителя '#{message_sender_username}' не найден!"
exit
end
Rails.logger.info "Запуск скрипта массовой рассылки сообщений..."
# Определите содержимое вашего сообщения
message_title = "Добро пожаловать в наше сообщество"
message_body = "Привет! Мы очень рады видеть вас здесь. Дайте знать, если у вас возникнут вопросы!"
# Получите пользователей, отсортированных по времени последнего посещения
users = User.where(active: true)
.where.not(staged: true) # Исключить пользователей в стадии обработки
.order(last_seen_at: :desc)
.limit(MAX_MESSAGES)
Rails.logger.info "Найдено #{users.count} активных пользователей для рассылки."
users.each_with_index do |user, index|
begin
Rails.logger.info "Добавление сообщения в очередь для #{user.username} (#{index + 1}/#{users.count})..."
PostCreator.create!(
message_sender,
title: message_title,
raw: message_body,
archetype: Archetype.private_message,
target_usernames: user.username,
skip_validations: true
)
Rails.logger.info "Сообщение успешно добавлено в очередь для #{user.username}."
# Подождите указанный интервал перед обработкой следующего пользователя
sleep(SECONDS_BETWEEN_MESSAGES)
rescue => e
Rails.logger.error "Не удалось отправить сообщение пользователю #{user.username}: #{e.message}"
end
end
Rails.logger.info "Скрипт массовой рассылки сообщений завершен!"
Ещё один вопрос. Есть ли у кого-нибудь идея, как отслеживать, на каком этапе находится скрипт? Например, мы отправили 10 000 писем и остановились. Затем хотим продолжить с того же места. Как узнать, с какой записи нужно начать?