Ir al contenido

Si vienes de otro teléfono

Una ciudad que ya tiene teléfono lleva años de cosas dentro: números que la gente se sabe de memoria, conversaciones, fotos, @handles. Perderlo todo es el verdadero precio de cambiar de teléfono, y es la razón por la que la mayoría de servidores nunca lo hacen. Esto lee las tablas del teléfono antiguo y escribe las nuestras.

Se puede venir desde cuatro teléfonos, y los cuatro se prueban igual: sus propias tablas se crean a partir del esquema que trae su instalador, se escribe en ellas una ciudad pequeña, se ejecuta la importación de verdad y después se comprueba cada fila que dice haber importado.

DesdeSus tablasPor qué identifica todo
lb-phonephone_*el número de teléfono, con phone_phones convirtiéndolo en un dueño
Quasar Smartphone Proqs_phone_*un scope_id: un teléfono, no una persona
NPWDnpwd_*el identificador del framework, y sus números ya están en users
qb-phoneplayer_contacts, phone_messages…citizenid, que es el dueño de este teléfono en QBCore

Nunca toca el teléfono antiguo. Ni una sola sentencia escribe en una tabla que no sea nuestra. Los datos de lb-phone quedan exactamente como estaban, y eso es lo que hace que la vuelta atrás sea sencilla: borra nuestras filas.

El ensayo es real. DryRun está activado por defecto. Lee todo lo que lee una ejecución real, calcula cada fila que escribiría, no escribe ninguna e imprime el recuento. Es el mismo código: un ensayo que tomara un atajo sería un ensayo de nada.

No puede pasar dos veces. Una ejecución real deja un recibo en la base de datos. El siguiente arranque lo encuentra y se detiene, porque una línea de config olvidada duplicaría si no cada conversación de la ciudad.

-- 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
}

Reinicia una vez y lee la consola:

[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

Después pon DryRun = false, reinicia una vez más y, al terminar, pon From = false.

Si las tablas no están en esta base de datos, lo dice y no hace nada, así que equivocarte de teléfono te cuesta una línea en la consola.

Todo lo de abajo es lb-phone, que es el más completo de los cuatro. Lo que hace distinto cada uno de los otros está más abajo.

Desde lb-phoneSe convierte en
phone_phonesel número en users, la batería, los ajustes del teléfono
su settings.appsla pantalla de inicio: el mismo dock, las mismas apps en las mismas páginas
phone_phone_contactscontactos, con favoritos e imágenes
phone_message_*conversaciones, grupos y los contadores de no leídos
phone_phone_callsrecientes, una fila por cada lado, llamadas perdidas incluidas
phone_photosla fototeca, fotos y vídeos
phone_mail_*correo, leído y sin leer
phone_maps_locationslugares guardados
phone_marketplace_posts, phone_yellow_pages_postsanuncios
Instagram, Twitter, TikTok, TinderInstapic, Twixel, Klipz, Flinder: handles, nombres, imágenes, biografías, publicaciones, seguidos y la marca de verificado
phone_darkchat_*la darknet: la sala, quién estaba en ella, qué se dijo
phone_notes, phone_clock_alarmsnotas y alarmas: las alarmas de lb-phone no dicen si se repiten, así que llegan como alarmas de una sola vez
phone_cryptoconsulta Cripto más abajo

Las imágenes son URLs en los dos teléfonos, así que no se descarga ni se vuelve a subir nada. Las fotos de un jugador siguen funcionando el primer día porque nunca fueron de ninguno de los dos teléfonos.

El informe dice cada una de estas cosas en voz alta, en lugar de dejar que alguien se dé cuenta.

  • Fondos de pantalla y tonos de llamada. Los suyos nombran sus propios archivos, los nuestros los nuestros. Una imagen equivocada es peor que la de por defecto.
  • Contraseñas de redes sociales. Mira más abajo: las cuentas se traen, las contraseñas no pueden.
  • El modo avión, a propósito. Importar un interruptor que alguien se dejó activado es importar un teléfono que no funciona y un jugador que no sabe por qué.
  • Álbumes de fotos. Todas las imágenes están en la fototeca; los álbumes no se reconstruyen.

Los otros tres, y qué tiene de distinto cada uno

Sección titulada «Los otros tres, y qué tiene de distinto cada uno»

El mejor construido de los cuatro, y el mapeo es exacto en lugar de aproximado en tres sitios:

  • Los contadores de no leídos se recalculan, no se copian. Quasar guarda last_read_message_id; nosotros guardamos un número. Así que el número se calcula (cuántos mensajes de esa conversación llegaron después del último que leyeron), lo cual es correcto aunque su propio contador se hubiera desviado.
  • Los recientes ya dicen incoming, outgoing y missed, que son nuestras tres palabras.
  • Una foto sabe que es un vídeo, con su duración y su portada, así que llega como tal.

También se traen las notas (las fijadas siguen fijadas), las alarmas, las entradas del calendario y los recordatorios: un recordatorio abierto con fecha límite se convierte en una entrada del calendario, uno sin fecha conserva sus palabras como nota, y uno terminado se queda atrás. Quasar puede repetir una alarma solo los fines de semana, cosa que este teléfono no puede, así que esas llegan como alarmas de una sola vez.

Las conversaciones fijadas y silenciadas conservan las dos cosas. El correo llega con la carpeta en la que estaba; los borradores y la papelera se quedan atrás, porque un borrador que nadie envió no merece la pena moverlo. Lo que no se trae: sus ajustes y su pantalla de inicio, que viven en un blob JSON con la forma propia de Quasar, y sus ids de la App Store, que no son los nuestros.

Una cosa que debes saber: Quasar permite que un personaje tenga más de un teléfono, y este guarda un número por personaje. El primer número que llega es el suyo; cualquier otro se nombra en el informe y no se sobrescribe nada.

El más fácil, por una razón que vale la pena decir en voz alta: NPWD ya guarda el número en users.phone_number, que es la misma columna que lee este teléfono. En un servidor NPWD por defecto no hay nada que mover, y el informe lo dice en lugar de fingir que trabaja.

Sus conversaciones se nombran con una cadena de los números que participan en lugar de con un id, así que la unión se hace por esa cadena. Su nombre de perfil de Twitter se convierte en el @handle; Match no tiene nombre de usuario en absoluto, así que una cuenta de Flinder se identifica por el número del personaje. Las fotos no tienen fecha propia, así que la fototeca se fecha por el orden en que se hicieron. Sus notas se traen de la misma forma, fechadas por el orden en que se escribieron. Los anuncios no llevan precio y llegan a cero.

El más antiguo, y el que menos se parece a nosotros, pero la identidad sale gratis, porque en QBCore este teléfono ya usa el citizenid por el que qb-phone identifica todo.

Sus conversaciones son el trabajo. qb-phone no tiene conversaciones: phone_messages es una fila por persona y por número con todo el intercambio como un array JSON, escrito desde cada lado por separado. Así que la misma conversación existe dos veces y las dos copias no tienen por qué coincidir. Por eso cada par de números se construye una sola vez, a partir del lado que tenga más contenido: fusionarlas inventaría un orden, e importar las dos le daría a todo el mundo cada mensaje dos veces. Una conversación sin marcas de tiempo conserva su orden y se reparte con un minuto de separación.

Los números viven en players.charinfo como JSON en lugar de en una columna, así que se leen de ahí y se escriben donde los guarda este teléfono. Sus tweets llevan un nombre en lugar de una cuenta, así que se crea una cuenta de Twixel por personaje a partir de su nombre.

Numbers = 'keep' es el sentido de todo el ejercicio: el número de la tarjeta de visita de alguien, y el de los contactos de todos los demás, sigue llegando a esa persona.

Un número solo se escribe en una columna vacía. Si un personaje ya tiene uno aquí y es un número distinto, eso es un conflicto: se cuenta, se nombra en el informe y no se sobrescribe nada. Sus números antiguos también conservan su formato antiguo (1234567890 en lugar del 555-###-#### de este teléfono), lo cual es estético y solo afecta a los números que se asignen a partir de entonces.

Numbers = 'ours' los deja en paz y deja que este teléfono asigne los suyos. Sus contactos antiguos no apuntarán a nadie, así que es solo para una ciudad que empieza de nuevo.

Sus contraseñas están en texto plano en una columna. Las nuestras son un hash PBKDF2 hecho en el navegador del jugador, y una no se puede obtener a partir de la otra, así que la contraseña es lo único que no se traslada, y no se guarda en ningún sitio por el camino.

La cuenta llega marcada como importada. La primera vez que su dueño abre la app, el teléfono dice Esta cuenta viene de tu teléfono antiguo. Elige una contraseña para ella, y esa es la nueva.

Esto es seguro por una razón mejor de lo que lo sería una contraseña: la fila nombra a un dueño, y el servidor sabe quién pregunta sin que se lo digan. Una contraseña que nunca fue nuestra no estaría demostrando nada.

No existe un tipo de cambio honesto entre dos mercados inventados, así que elige qué pasa en lugar de dejar que se adivine:

  • 'cash': vende al precio del propio teléfono antiguo y lo escribe en el monedero como un movimiento. Nadie gana, nadie pierde y no hay que ponerse de acuerdo en nada.
  • 'skip': déjalo. Sus tenencias se quedan en sus tablas y se pueden gestionar a mano.
  • una tabla: tu propio mapeo, cuando las tenencias deben sobrevivir como monedas:
Crypto = { qbit = 'santo', lifeinvader = 'vine' },

No se tocó nada del teléfono antiguo, así que:

  1. Borra nuestras filas del paso que haya salido mal: el informe las nombra.
  2. Borra el recibo: DELETE FROM mic_phone_json WHERE owner = '@import'.
  3. Config.Import.Again = true, y vuelve a empezar.

Skip deja fuera pasos concretos por los nombres que imprime el informe:

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