Мы попробовали и столкнулись со следующими проблемами: все посты были импортированы, но заголовки тем не отображаются, а внешние изображения не загружаются. Текущий форум SMF2: https://forum.mundofotografico.com.br. Мы пытаемся мигрировать на Discourse здесь: https://discourse.fotografos.online — все темы и соответствующие описания не перенеслись, изображения не загружаются… пожалуйста, помогите! @marcozambi @miligraf @FireAllianceNX @pfaffman
Я только что приступил к процессу миграции на SMF и в данный момент импортирую сообщения в тестовую копию со скоростью около 1000 в час, так что пока всё идёт хорошо, за исключением скрипта производительности MySQL, который почему-то не принял команду ‘ALTER USER’. Я вручную выполнил ‘CREATE USER’, и после этого всё наладилось.
Я прочитал комментарий о удалённых пользователях, но не могу легко создать новых пользователей или поддельные адреса электронной почты, чтобы покрыть всех моих удалённых пользователей (мой форум работает уже более 20 лет, и, вероятно, у меня сейчас больше удалённых пользователей, чем реальных). Подозреваю, что у меня 4–5 тысяч удалённых пользователей. Не все из них писали сообщения, но многие писали, поэтому у меня, вероятно, есть сотни «пропавших» пользователей.
Сообщения импортируются как принадлежащие пользователю ‘system’, что не совсем идеально. Я задумался, сработает ли следующий подход:
- Перед импортом создать тестового пользователя, например, ‘Удалённый пользователь’.
- Узнать номер пользователя ‘Удалённый пользователь’.
- Изменить строку “user_id: user_id_from_imported_user_id(message[:id_member]) || -1,” в файле smf2.rb и заменить ‘-1’ на номер пользователя ‘Удалённый пользователь’ (думаю, что системный пользователь имеет номер -1?).
Сработает ли это? Также, есть ли другие места в файле smf2.rb, где мне потребуется внести аналогичные изменения?
Привет! Под словом «удалённые» вы имеете в виду, что они действительно удалены из базы данных SMF, или они всё ещё там, с сохранёнными именем пользователя и адресом электронной почты, но помечены как приостановленные? Как сейчас отображаются сообщения от таких «удалённых» пользователей в SMF?
Я в процессе масштабной миграции с Drupal на Discourse, тоже с давно существующего форума с множеством приостановленных пользователей. Я определённо хотел сохранить те же самые приостановленные имена пользователей и связанные с ними адреса электронной почты в Discourse, поэтому мне пришлось добавить эту функцию в скрипт импорта для Drupal для Discourse. По сути, скрипт импортирует всех пользователей как обычных активных, и если у них были какие-либо публично видимые сообщения, они также импортируются, как на оригинальном форуме. Затем, в самом конце процесса, я добавил функцию, которую взял из другого скрипта импорта, чтобы пройти по базе данных Drupal и, если пользователь был помечен как приостановленный, также приостановить учётную запись в Discourse. Код этого можно увидеть в моей истории постов здесь.
Привет. Пользователи фактически удалены, то есть в таблице smf_member больше нет их записей. В SMF нет функции приостановки пользователей. Можно заблокировать пользователей, но это кажется неуместным для аккаунтов, где пользователь скончался или потерял интерес к хобби/форуму. С точки зрения защиты данных это тоже не совсем правильно.
В сообщениях SMF для каждой записи хранятся два поля: номер участника (для удалённых пользователей он установлен в ноль) и имя отправителя, содержащее имя пользователя, опубликовавшего сообщение. Таким образом, можно увидеть, кто опубликовал сообщение, но детали пользователя (электронная почта, полное имя и т. д.) больше недоступны. При отображении их сообщения помечаются как «Гость».
Предположительно, я мог бы создать новый аккаунт для каждого пользователя, опубликовавшего сообщение с идентификатором участника, равным нулю, назначить для аккаунта фиктивный адрес электронной почты, а затем пометить пользователя как приостановленного. Если использовать уникальный, но узнаваемый формат для фиктивного адреса, можно было бы помечать аккаунты как приостановленные на основе этого формата. Однако в некоторых случаях это кажется несколько странным… создавать аккаунты для людей, о которых я знаю, что они скончались 10–15 лет назад!
У меня есть время подумать об этом… миграция прошла частично успешно, но теперь мне нужно выяснить, почему вложения не были прикреплены, почему ссылки внутри форума не были изменены и почему пароли для перенесённых пользователей не работают. Возможно, есть и другие проблемы, но сначала я займусь исправлением этих, а затем посмотрю, что ещё обнаружится.
Вы имеете в виду Postgres? Я не совсем понимаю, о чём речь.
Что я бы сделал: если ID пользователя равен 0, использовать имя пользователя в качестве ID. Затем, если функция find_username_by_import_id не находит пользователя, создать его, установив адрес электронной почты в fake_email (это функция в base.rb, которая генерирует фейковый адрес электронной почты), а имя пользователя — в то, которое у вас есть. Если вы амбициозны, в конце скрипта можно приостановить всех пользователей, у которых в адресе электронной почты содержится @email.invalid. Они не будут активны, поэтому, думаю, не так важно, приостановите вы их или нет.
Другой вариант — выполнить запрос, который каким-то образом сформирует список всех удалённых пользователей, и создать их перед началом обработки постов, но это кажется более сложным.
Если вы хотите создать пользователя с именем deleted user и сделать так, чтобы все эти посты принадлежали ему вместо system, вы можете это сделать, просто заменив -1 на номер пользователя deleted user. Вы можете создать его как обычного пользователя или пойти на хитрость и назначить ему ID пользователя -2 или что-то в этом роде.
В некоторых системах это происходит потому, что иногда вложения находятся в теле поста, а в других случаях запись о вложении хранится в базе данных.
Вы установили плагин Поддержка перенесённых хешей паролей после запуска импорта (он может мешать выполнению импорта по крайней мере в некоторых случаях)? Использует ли SMF2 хеширование паролей так же, как smf?
Извините, неверное название скрипта. Это скрипт для MySQL, упомянутый в первом сообщении.
– файл: ~/smf2/script_for_mysql_tuning.sql
ALTER USER ‘user’@‘%’ IDENTIFIED WITH mysql_native_password BY ‘pass’;
Спасибо за советы по пользователям, особенно насчёт fake_email. Моя первая задача — достаточно изучить Ruby, чтобы иметь возможность вносить изменения в скрипт импорта!
Вложения SMF2 — это записи в базе данных. Погрузившись чуть глубже, я понял, что некоторые из них были импортированы, но лишь несколько сотен из десятков тысяч. Буду продолжать поиск, чтобы понять, почему так произошло.
Ах, скорее всего, это именно то, чего мне не хватает! Я почти уверен, что SMF2 использует тот же алгоритм хеширования (соленый MD5, насколько помню), что и SMF1, так что плагин, надеюсь, решит проблему. Мне нужно выполнить ещё несколько запусков импорта, прежде чем я начну слишком беспокоиться о входе пользователей в систему.
Возникает ещё один вопрос. Есть ли способ сбросить систему, чтобы я мог выполнить ещё один импорт? Я должен был сделать резервную копию перед началом, но забыл ![]()
А, вы имеете в виду просто настройку MySQL. Понял.
Если вы уже знаете другие языки, вы, вероятно, сможете разобраться по ходу дела.
Я написал несколько импортеров, прежде чем начал серьёзно изучать Ruby. ![]()
Вот один из способов удалить и создать новую базу данных Discourse.
sv stop unicorn;DISABLE_DATABASE_ENVIRONMENT_CHECK=1 IMPORT=1 rake db:drop db:create db:migrate; sv start unicorn
Если не забыть сделать резервную копию, это может быть немного быстрее. Возможно.
Ещё один трюк: когда вы разберётесь с пользователями, можно остановить скрипт после импорта пользователей и сделать резервную копию. Это позволит отлаживать импорт постов, не импортируя снова всех пользователей.
Я знаю несколько. Я написал свою первую программу в 1976 году на бинарном машинном коде на Intel 4004. Я начинаю понимать smf2.rb, используя DuckDuckGo, чтобы разобраться в некоторых структурах кода, которые для меня новы.
Спасибо за метод удаления/создания базы данных. Пора начать заново и посмотреть, смогу ли я внести постепенные изменения в импортер для моих данных.
Мне удалось модифицировать импортер так, чтобы он создавал тестовые аккаунты с вымышленными адресами электронной почты для удалённых пользователей, и эти тестовые аккаунты являются владельцами своих соответствующих постов — это хороший старт.
Теперь я пытаюсь разобраться с вложениями, так как пока не вижу их ни в одном из импортированных постов (хотя они должны быть).
Если я создаю сообщение обычным способом через веб-интерфейс Discourse, то в таблице posts появляется запись (id=4346), в таблице uploads — две записи (id=403 и 404), а в таблице upload_references — четыре записи (403/Draft/4, 403/Post/4346, 404/Draft/4, 404/Post/4346). Также в поле image_upload_id для поста 4346 указано значение 403, а в поле cooked таблицы posts содержится HTML-код, ссылающийся на оба вложения.
Для импортированных постов я получаю запись в таблице posts для каждого импортированного сообщения из SMF и запись в таблице uploads для каждого вложения, связанного с импортированным сообщением SMF. Записи в таблице uploads ссылаются на файлы на диске, содержащие правильные изображения, так что эта часть работает корректно. Однако у меня не создаются записи в таблице upload_references для загруженных изображений, и в поле image_upload_id таблицы posts не указываются никакие id вложений.
Предполагаю, что мне нужно попытаться создать записи в таблице upload_references и заполнить поля image_upload_id и cooked в таблице posts. Но сначала хотел уточнить, нет ли другого способа связывать вложения с постами, который используется (или пытается использоваться) импортером?
Похоже, вам нужно добавить ссылку на хост/загрузку в raw. Существует функция, которая сгенерирует для вас ссылку. Я не помню, как она называется. Думаю, она находится в модели загрузок, но, возможно, её будет проще найти в каком-нибудь другом скрипте импорта, если вы не знаете, что такое модель.
Я добивался прогресса в настройке скрипта импорта под особенности моего форума, но пару дней назад всё остановилось. После последнего обновления Discourse beta я больше не могу собрать контейнер импорта. Я получаю…
> FAILED
> --------------------
> Pups::ExecError: cd /var/www/discourse && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libmariadb-dev failed with return #<Process::Status: pid 439 exit 100>
> Location of failure: /usr/local/lib/ruby/gems/3.1.0/gems/pups-1.1.1/lib/pups/exec_command.rb:117:in `spawn'
> exec failed with the params {"cd"=>"$home", "cmd"=>["echo \"gem 'mysql2'\" >> Gemfile", "apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y libmariadb-dev", "su discourse -c 'bundle config unset deployment'", "su discourse -c 'bundle install --no-deployment --path vendor/bundle --jobs 4 --without test development'"]}
> bootstrap failed with exit code 100
> ** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.
Я видел сообщения об истечении срока действия ключа yarn и исправил это. Это мешало установке пакета libmariadb-dev, но я выполнил ручную установку пакета, которая прошла успешно. Однако пересборка импорта всё ещё не работает, даже если включён шаблон импорта MySQL, несмотря на ручную установку пакета MariaDB.
Я создал новый сервер и начал с чистой установки Discourse, чтобы избежать возможных проблем с предыдущим сервером/установкой. На новом сервере возникает та же ошибка, что и на старом.
У меня нет идей, что попробовать дальше, поэтому буду рад любым предложениям!
Смотрите Apt-get update fails inside container yarn repo not signed - #5 by pfaffman. Вам нужно отредактировать шаблон mysql.
Спасибо, что указали мне правильное направление. Теперь я понимаю, где ошибся!
Мы начинаем с тестового переноса форума SMF 2 (точнее, версии 2.0.15), и одной из первых выявленных проблем стала ошибка, возникающая, когда в названии категории есть символ амперсанда (&):
Заголовки тем с тем же символом, похоже, работают нормально:

Пока что кажется, что амперсандр — единственный проблемный символ, а немецкие умлауты, например, обрабатываются корректно:
Вероятно, мы также столкнёмся с проблемами, о которых сообщалось в этой теме (удалённые пользователи, вложения, ссылки внутри форума), но импорт всё ещё выполняется, поэтому я обновлю информацию после его завершения.
В связи с этим возникает вопрос: действительно ли скорость импорта должна быть настолько низкой? В данный момент мы импортируем со скоростью 1750 элементов в минуту (изначально было ближе к 2000 элементов в минуту) на машине с процессором AMD Ryzen 5 3600 и 64 ГБ ОЗУ (Hetzner, Ubuntu 22.04), что делает общую миграцию примерно трёхдневной.
Довольно неплохая скорость.
Я полагаю, что все ещё сохраняются те проблемы, о которых сообщалось, хотя удивительное количество из них уникальны для форума. Если вы хотите, чтобы что-то исправили, и у вас есть бюджет, я с радостью помогу.
Спасибо! Я вернусь к вам, как только всё станет более конкретным.
Сейчас мы (небольшая некоммерческая организация, ориентированная на настольные ролевые игры и связанные с ними хобби) находимся на этапе оценки — есть консенсус, что нам нужно новое программное обеспечение, и на данный момент Discourse является фаворитом. Но нам предстоит собрать все задачи (миграция, новая тема, новые плагины или компоненты темы, если они потребуются) и посмотреть, уложимся ли мы в наш бюджет.
Есть ли для этого шага какая-то особая причина?
Насколько я понимаю из тщательного повторного чтения исходного сообщения, файл smf2.rb не изменяется и не патчится?
И если smf2.rb находится на хосте (например, в /var/discourse/smf2) и вы соответствующим образом настроили монтирование тома на шаге 2, то он уже монтируется внутрь гостевой системы в /shared/smf2.
Я не понимаю необходимости копировать его как отдельный шаг. Но понимание этого может стать ключом к выяснению того, почему скрипт не находит 95% вложений корректно…
Похоже, вы правы насчёт того, что копировать его не нужно. Возможно, автор изменил это, и его изменения впоследствии были перенесены в основную ветку.
Если вы получаете 5%, а не 0% вложений, значит, проблема, скорее всего, в самом скрипте.
В некоторых системах есть два способа прикрепления файлов: первый — указать файл в тексте (тогда он присутствует в исходном тексте сообщения и обрабатывается соответствующим образом), второй — прикрепить его к сообщению через метаданные или таблицу. Я предполагаю, что 95% вложений в вашей базе данных добавлены одним способом, а скрипт ищет их другим.
Но, возможно, скрипт пытается оба способа? Вам нужно найти сообщение, в котором должно быть вложение, проверить базу данных и файловую систему, чтобы понять, как оно хранится, а затем изучить код, чтобы выяснить, почему скрипт его не находит.
Спасибо, @pfaffman, это успокаивает! Я так и думал, что, скорее всего, всё именно так, но из-за таких проблем с этим импортом я начал сомневаться в своих знаниях и навыках на всех уровнях!
Спасибо за советы, всё очень ценно, @pfaffman — это попытка вернуть к жизни тот же форум, над которым я работал в прошлом году, но с большой задержкой. Это работа на благотворительной основе, но, возможно, я снова приглашу вас, если у вас будет время.
Это очень старый форум SMF2, в котором вложения хранятся в двух форматах:
<id>_<Имя_файла_БЕЗ_учёта_регистра_jpg>_<32символа_вероятно_хэш_MD5_чего-то><id>_<40символов_вероятно_хэш_SHA1_чего-то>
Я всё ещё пытаюсь понять, есть ли закономерность в сбоях.
Мое предположение (не глядя в код!) состоит в том, что одно из этих действий выполняет скрипт, а другое — нет (скорее всего, одно — это старый способ, поэтому новые посты используют другой метод, но скрипт не прошёл по старым записям и не исправил те, что используют иной метод).
Так что посмотрите на convert_message_body и поля в таблице attachments. Возможно, они по какой-то причине перешли с MD5 на SHA1 или наоборот.
Как я уже сказал, возможно, в одной из версий есть ссылка на загрузку вместо того, чтобы она была связана в таблице. В таком случае вы можете использовать gsub, чтобы найти этот шаблон, и если совпадение найдено, получить ключ, найти его в таблице, а затем вызвать create_upload с этим файлом…
Надеюсь, этого будет достаточно, чтобы вы начали работу, но, пожалуйста, свяжитесь со мной, если вам понадобится больше помощи, чем я могу оказать здесь.

