Перейти к содержимому

Переход с другого телефона

В городе, где уже есть телефон, за годы накопилось множество вещей: номера, которые люди выучили наизусть, переписки, фотографии, @handles. Потерять всё это — настоящая цена смены телефона, и именно поэтому большинство серверов её никогда не меняют. Этот инструмент читает таблицы старого телефона и записывает наши.

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

ОткудаЕго таблицыПо чему он индексирует всё
lb-phonephone_*по номеру телефона, а phone_phones превращает его во владельца
Quasar Smartphone Proqs_phone_*по scope_id — один телефон, а не один человек
NPWDnpwd_*по идентификатору фреймворка, а его номера уже лежат в users
qb-phoneplayer_contacts, phone_messages…по citizenid, который на QBCore является владельцем этого телефона

Старый телефон он никогда не трогает. Ни один оператор не пишет в таблицу, которая не наша. Данные lb-phone после этого остаются ровно такими, какими были, и именно поэтому путь назад прост: удалите наши строки.

Репетиция настоящая. DryRun включён по умолчанию. Он читает всё то же, что читает настоящий запуск, вычисляет каждую строку, которую записал бы, не записывает ни одной и выводит количество. Это тот же код — репетиция, которая пошла бы коротким путём, была бы репетицией ничего.

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

-- shared/config/import.lua
Config.Import = {
From = 'lb-phone', -- or false, which is where it starts
DryRun = true, -- read the count first
Numbers = 'keep', -- their old numbers move across
Crypto = 'cash', -- sell their coins at their own price
}

Перезапустите один раз и прочитайте консоль:

[mic_phone import] lb-phone — REHEARSAL, nothing was written
[mic_phone import] contacts 482
[mic_phone import] messages 19104
[mic_phone import] numbers 137
[mic_phone import] photos 2210
[mic_phone import] social 96
[mic_phone import] · a phone whose owner is not in `users` any more was skipped (×8)
[mic_phone import] · lb-phone does not say whether an alarm repeats, so its alarms arrive as one-off alarms

Затем DryRun = false, перезапустите ещё раз, а потом установите From = false.

Если этих таблиц нет в этой базе данных, он так и говорит и ничего не делает, так что указание неверного телефона стоит вам одной строки в консоли.

Всё ниже — про lb-phone, самый полный из четырёх. Чем отличается каждый из остальных, описано дальше.

Из lb-phoneСтановится
phone_phonesномер в users, батарея, настройки телефона
его settings.appsглавный экран — тот же док, те же приложения на тех же страницах
phone_phone_contactsконтакты, с избранным и картинками
phone_message_*переписки, группы и счётчики непрочитанных
phone_phone_callsнедавние, по строке на каждую сторону, включая пропущенные
phone_photosбиблиотека, фото и видео
phone_mail_*почта, прочитанная и непрочитанная
phone_maps_locationsсохранённые места
phone_marketplace_posts, phone_yellow_pages_postsобъявления
Instagram, Twitter, TikTok, TinderInstapic, Twixel, Klipz, Flinder — handle’ы, имена, картинки, био, посты, подписки и галочка верификации
phone_darkchat_*даркнет: комната, кто в ней был, что было сказано
phone_notes, phone_clock_alarmsзаметки и будильники — в будильниках lb-phone не указано, повторяются ли они, поэтому они приходят как разовые
phone_cryptoсм. Крипто ниже

На обоих телефонах картинки — это URL, поэтому ничего не скачивается и не загружается заново. Фотографии игрока продолжают работать в первый же день, потому что они никогда не принадлежали ни одному из телефонов.

Отчёт говорит о каждом из этих пунктов вслух, а не оставляет кому-то замечать это самому.

  • Обои и рингтоны. Их файлы называются по-своему, а наши — по-своему. Неверная картинка хуже, чем картинка по умолчанию.
  • Пароли социальных сетей. См. ниже — аккаунты переносятся, пароли — нет.
  • Режим полёта, намеренно. Импортировать переключатель, который кто-то оставил включённым, — значит импортировать телефон, который не работает, и игрока, который не понимает почему.
  • Фотоальбомы. Все картинки лежат в библиотеке; альбомы не восстанавливаются.

Лучше всех сделан из четырёх, и соответствие в трёх местах точное, а не приблизительное:

  • Счётчики непрочитанных пересчитываются, а не копируются. Quasar хранит last_read_message_id; наш хранит число. Поэтому число вычисляется — сколько сообщений в этой переписке пришло после последнего прочитанного, — и оно верно, даже если собственный счётчик успел разойтись.
  • В недавних уже указано incoming, outgoing и missed, а это наши три слова.
  • Фото знает, что оно видео, с его длиной и постером, поэтому приходит как видео.

Заметки (закреплённые остаются закреплёнными), будильники, записи календаря и напоминания тоже переносятся: открытое напоминание со сроком становится записью календаря, напоминание без даты сохраняет свои слова как заметка, а завершённое остаётся позади. Quasar умеет повторять будильник только по выходным, чего этот телефон не умеет, поэтому такие приходят как разовые.

Закреплённые и отключённые переписки сохраняют оба признака. Почта приходит вместе с папкой, в которой лежала, — черновики и корзина остаются позади, потому что неотправленный черновик не стоит переноса. Что не переносится: их настройки и главный экран, которые лежат в JSON-блобе собственной формы Quasar, и их id из App Store, которые не наши.

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

Самый простой — по причине, которую стоит назвать вслух: NPWD уже хранит номер в users.phone_number, а это та же колонка, которую читает этот телефон. На стандартном сервере NPWD переносить нечего, и отчёт так и говорит, а не притворяется, что работает.

Его переписки называются строкой из входящих в них номеров, а не id, поэтому соединение идёт по этой строке. Имя профиля в его Twitter становится @handle; в Match имени пользователя нет вообще, поэтому аккаунт Flinder индексируется по номеру персонажа. У фотографий нет собственной даты, поэтому библиотека датируется по порядку, в котором они были сделаны. Заметки переносятся так же, датируясь по порядку написания. В объявлениях нет цены, и они приходят с нулём.

Самый старый и меньше всех похожий на нас — но личность достаётся бесплатно, потому что на QBCore этот телефон уже использует citizenid, по которому qb-phone индексирует всё.

Основная работа — его переписки. В qb-phone переписок нет: phone_messages — это одна строка на человека на номер, где весь разговор лежит как JSON-массив, записываемый отдельно с каждой стороны. Поэтому одна и та же переписка существует дважды, и две копии не обязаны совпадать. Каждая пара номеров поэтому строится один раз, с той стороны, где в ней больше сообщений, — слияние придумало бы порядок, а импорт обоих дал бы каждому каждое сообщение дважды. Переписка без временных меток сохраняет свой порядок и раскладывается с интервалом в минуту.

Номера лежат в players.charinfo в виде JSON, а не в колонке, поэтому их считывают оттуда и записывают туда, где их хранит этот телефон. Его твиты содержат имя, а не аккаунт, поэтому для каждого персонажа создаётся один аккаунт Twixel по его имени.

Numbers = 'keep' — это смысл всей затеи: номер на визитке и в контактах у всех остальных по-прежнему до человека дозванивается.

Номер всегда записывается только в пустую колонку. Если у персонажа здесь уже есть номер и он другой, это конфликт: он подсчитывается, называется в отчёте, и ничего не перезаписывается. Старые номера также сохраняют свой прежний вид — 1234567890, а не 555-###-#### этого телефона, — это косметика, и она влияет только на номера, которые будут выданы позже.

Numbers = 'ours' оставляет их в покое и позволяет этому телефону выдавать свои. Старые контакты будут указывать в никуда, поэтому это только для города, который начинает заново.

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

Аккаунт приходит с пометкой «импортирован». Когда его владелец впервые открывает приложение, телефон сообщает Этот аккаунт перешёл со старого телефона. Выберите для него пароль, и это становится новым паролем.

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

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

  • 'cash' — продать по собственной цене старого телефона и записать в кошелёк как движение средств. Никто ничего не выигрывает и не теряет, и ни о чём не нужно договариваться.
  • 'skip' — оставить как есть. Их накопления остаются в их таблицах, и с ними можно разобраться вручную.
  • таблица — ваше собственное соответствие, когда накопления должны сохраниться как монеты:
Crypto = { qbit = 'santo', lifeinvader = 'vine' },

Ничего старого телефона не затронуто, поэтому:

  1. Удалите наши строки для того шага, который оказался неверным, — отчёт называет их.
  2. Удалите квитанцию: DELETE FROM mic_phone_json WHERE owner = '@import'.
  3. Config.Import.Again = true — и запустите снова.

Skip пропускает отдельные шаги по именам, которые выводит отчёт:

Skip = { 'photos', 'crypto' },