Восклицательный знак и специальные символы в именах пользователей

Единственная проблема возникнет, если вас не устроят имена пользователей, которые выбирает скрипт. Так что, если вам безразлично, если произойдёт что-то вроде этого:

  • clan|nickname → clan_nickname
  • [clan]nickname → clan_nickname2

то, скорее всего, у вас всё будет в порядке. И кажется крайне маловероятным, что в одном клане окажутся два человека с одинаковым никнеймом, но разными дополнительными символами, так что, думаю, у вас всё будет хорошо.

К сожалению, нам пришлось написать весь наш скрипт миграции самостоятельно. Скрипт, который был доступен на тот момент (конец 2022 года), определённо даже не находился в «готовом» состоянии. Отсутствовали фрагменты кода, на которые были даны ссылки, а другие фрагменты вообще не имели смысла.

Одной из задач, с которой нам пришлось справиться, было переименование пользователей, чьи имена не соответствовали стандартам Discourse. У нас было более 10 000 пользователей, поэтому мы просто присваивали имя пользователя полю «имя пользователя» (user name), которое не имеет таких ограничений. Если имя пользователя нарушало какие-либо правила, мы заменяли его на MD5-хэш этого имени. Затем мы дали пользователям один месяц, чтобы они могли свободно изменить своё имя и вернуть его к варианту, похожему на оригинальное.

Вот фрагмент кода:

    public static string ParseName(string text)
    {
        var reservedName = new string[] { "user", "system", "moderators" };
        var result = NormalizeText(text);

        // Если зарезервировано, изменяем
        if (reservedName.Contains(result, StringComparer.OrdinalIgnoreCase))
            result = text.ToLower().ToMD5();

        // Неверные символы (кроме букв и цифр)
        else if (!Regex.IsMatch(result, @"^[a-zA-Z0-9_.-]*$"))
            result = text.ToLower().ToMD5();

        // Неверные повторяющиеся символы
        else if (Regex.IsMatch(result, @"[-_.]{2,}"))
            result = text.ToLower().ToMD5();

        // Неверные завершающие символы
        else if (Regex.IsMatch(result, @"/[\p{L}\p{N}]+$/"))
            result = text.ToLower().ToMD5();

        // Путаница с расширениями файлов
        else if (Regex.IsMatch(result, @"/\.(js|json|css|htm|html|xml|jpg|jpeg|png|gif|bmp|ico|tif|tiff|woff)$/i"))
            result = text.ToLower().ToMD5();

        // Точки в начале или в конце
        else if (result.StartsWith(".") || result.EndsWith("."))
            result = text.ToLower().ToMD5();

        // Не более 60 символов
        result = result.Truncate(60);

        return result;
    }

Мы использовали этот файл как справочник для определения ограничений. Возможно, с тех пор что-то изменилось, поэтому будьте внимательны.

Вы основывали его на существующем скрипте импорта? Если бы вы это сделали, он бы вызывал discourse/lib/user_name_suggester.rb at main · discourse/discourse · GitHub и всё работало бы.

Нет, мы отказались от этого скрипта, так как он был невероятно медленным при обработке форума с более чем 10 миллионами ответов.

Мы написали всё с нуля на C#. Миграция всего, кроме аватарок, и создание редиректов для соответствия различным форматам URL заняла около 4–5 часов. Второй запуск скрипта с особым параметром также обновил аватарки для всех активных пользователей за последние 6 месяцев и добавил все необходимые редиректы, просканировав ответы и найдя старый формат URL.

Это заняло примерно пару дней, но процесс можно было выполнять в фоновом режиме, так как для нас главное было запустить форум со всем контентом менее чем за сутки.

Отличная работа! Это очень круто.

Кстати, существующие скрипты пропускают уже существующий контент, поэтому финальный импорт, скорее всего, занял бы меньше часа, особенно если указать дату последних импортированных данных. Однако первый запуск был бы очень болезненным.

Да, я знаю, что оно тоже возобновилось, но старый контент был настолько испорчен (форум проходил миграцию в начале 2000-х), что скрипт чаще всего не работал или очень быстро начинал работать крайне медленно.

Поверьте, если бы мы могли избежать трёх месяцев написания и тестирования, мы бы так и сделали! :smiley: