Skip to content

Commit

Permalink
very experimental pluralkit import
Browse files Browse the repository at this point in the history
  • Loading branch information
NyaomiDEV committed Feb 3, 2025
1 parent b127b33 commit 7218e15
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 5 deletions.
101 changes: 101 additions & 0 deletions src/lib/db/external/pluralkit.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { FrontingEntry, Member, System, Tag } from "../entities";
import { PartialBy } from "../../types";
import { newSystem } from "../tables/system";
import { getTables } from "..";
import { newTag } from "../tables/tags";
import { newMember } from "../tables/members";
import { newFrontingEntry } from "../tables/frontingEntries";

export async function importPluralKit(pkExport: any){
// WIPE AMPERSAND
await Promise.all(getTables().map(async x => x.clear()));

// SYSTEM
const systemInfo: PartialBy<System, "uuid"> = {
name: pkExport.name,
description: pkExport.description,
}
if (pkExport.avatar_url) {
try{
const request = await fetch(pkExport.avatar_url);
systemInfo.image = new File([await request.blob()], pkExport.avatar_url.split("/").pop());
}catch(e) {
// whatever
}
}
await newSystem(systemInfo);

// TAGS
const tagMapping = new Map<string, string>();
for (const pkGroup of pkExport.groups) {
const tag: PartialBy<Tag, "uuid"> = {
name: pkGroup.display_name || pkGroup.name,
description: pkGroup.description,
color: pkGroup.color ? "#" + pkGroup.color : undefined,
type: "member"
};
const uuid = await newTag(tag);
if(!uuid) return false;
tagMapping.set(pkGroup.id, uuid);
}

// MEMBERS
const memberMapping = new Map<string, string>();
for (const pkMember of pkExport.members) {
const member: PartialBy<Member, "uuid"> = {
name: pkMember.display_name || pkMember.name,
description: pkMember.description,
pronouns: pkMember.pronouns,
color: pkMember.color ? "#" + pkMember.color : undefined,
isArchived: false,
isCustomFront: false,
dateCreated: new Date(pkMember.created),
tags: pkExport.groups.filter(x => x.members.includes(pkMember.id)).map(x => tagMapping.get(x.id))
}
if (pkMember.avatar_url) {
try{
const request = await fetch(pkMember.avatar_url);
member.image = new File([await request.blob()], pkMember.avatar_url.split("/").pop());
}catch(e){
// whatever, again
}
}
const uuid = await newMember(member);
if(!uuid) return false;
memberMapping.set(pkMember.id, uuid);
}

// FRONTING ENTRIES
const frontingEntries = new Map<string, PartialBy<FrontingEntry, "uuid">>();
for(const pkSwitch of pkExport.switches.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())){
const date = new Date(pkSwitch.timestamp);

// check who left
for(const id of frontingEntries.keys()){
if(!pkSwitch.members.includes(id)){
const frontingEntry = frontingEntries.get(id)!;
frontingEntry.endTime = date;
await newFrontingEntry(frontingEntry);
frontingEntries.delete(id);
}
}

// check who's new
for(const id of pkSwitch.members){
if(!frontingEntries.has(id)){
const frontingEntry: PartialBy<FrontingEntry, "uuid"> = {
member: memberMapping.get(id)!,
startTime: date,
isMainFronter: false
}
frontingEntries.set(id, frontingEntry);
}
}

}
for(const frontingEntry of frontingEntries.values()){
await newFrontingEntry(frontingEntry);
}

return true;
}
33 changes: 32 additions & 1 deletion src/views/onboarding/1-Import.vue
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<script setup lang="ts">
import { IonContent, IonPage, IonButton, useIonRouter } from '@ionic/vue';
import { IonContent, IonPage, IonButton, useIonRouter, toastController } from '@ionic/vue';
import { ref } from 'vue';
import Spinner from '../../components/Spinner.vue';
import { importDatabaseFromBinary } from '../../lib/db/ioutils';
import { getFiles, slideAnimation } from '../../lib/util/misc';
import { importPluralKit } from '../../lib/db/external/pluralkit';
import { useTranslation } from 'i18next-vue';
import { getTables } from '../../lib/db';
const loading = ref(false);
const i18next = useTranslation();
const router = useIonRouter();
async function importFromPreviousInstallation() {
Expand All @@ -20,6 +24,29 @@
router.replace("/onboarding/end/", slideAnimation);
}
async function importFromPluralKit() {
const files = await getFiles(undefined, false);
if (files.length) {
loading.value = true;
const file = files[0];
const pkExport = JSON.parse(await file.text());
const result = await importPluralKit(pkExport);
if(!result){
await Promise.all(getTables().map(async x => x.clear()));
const statusMessage = await toastController.create({
message: i18next.t("onboarding:importScreen.errorPk"),
duration: 1500
});
await statusMessage.present();
return;
}
}
router.replace("/onboarding/end/", slideAnimation);
}
</script>

<template>
Expand All @@ -33,6 +60,10 @@
{{ $t("onboarding:importScreen.prevInstall") }}
</IonButton>

<IonButton @click="importFromPluralKit">
{{ $t("onboarding:importScreen.prevInstall") }}
</IonButton>

<IonButton fill="clear" @click="router.replace('/onboarding/system/', slideAnimation)">
{{ $t("onboarding:importScreen.startFromScratch") }}
</IonButton>
Expand Down
35 changes: 35 additions & 0 deletions src/views/options/ImportExport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { save } from '@tauri-apps/plugin-dialog';
import { writeFile } from '@tauri-apps/plugin-fs';
import { useTranslation } from 'i18next-vue';
import { importPluralKit } from '../../lib/db/external/pluralkit';
const isIOS = inject<boolean>("isIOS");
const loading = ref(false);
Expand All @@ -32,6 +33,33 @@
loading.value = false;
}
async function importPk() {
loading.value = true;
const files = await getFiles(undefined, false);
if(files.length){
const file = files[0];
const pkExport = JSON.parse(await file.text());
const result = await importPluralKit(pkExport);
if(result){
const statusMessage = await toastController.create({
message: i18next.t("importExport:status.importedPk"),
duration: 1500
});
await statusMessage.present();
} else {
const statusMessage = await toastController.create({
message: i18next.t("importExport:status.errorPk"),
duration: 1500
});
await statusMessage.present();
}
}
loading.value = false;
}
async function exportDb(){
loading.value = true;
Expand Down Expand Up @@ -103,6 +131,13 @@
<p>{{ $t("importExport:dbImport.desc") }}</p>
</IonLabel>
</IonItem>

<IonItem button @click="importPk" :detail="true">
<IonLabel>
<h3>{{ $t("importExport:pkImport.title") }}</h3>
<p>{{ $t("importExport:pkImport.desc") }}</p>
</IonLabel>
</IonItem>
</IonList>
</IonContent>
</IonPage>
Expand Down
8 changes: 7 additions & 1 deletion translations/en/importExport.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
"title": "Export your data",
"desc": "Backup your current data to a file you can store somewhere else"
},
"pkImport": {
"title": "Import your data from a PluralKit export",
"desc": "Warning! It will override any existing data"
},
"status": {
"imported": "The backup has been imported. Please restart the app.",
"importedPk": "The PluralKit export has been imported. Please restart the app.",
"exportedPwa": "The backup has been downloaded to your downloads folder.",
"exportedApp": "The backup has been exported to the location you chose.",
"error": "Error while exporting the backup."
"error": "Error while exporting the backup.",
"errorPk": "Error while importing the PluralKit export."
}
}
3 changes: 2 additions & 1 deletion translations/en/onboarding.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"simplyPlural": "Yes, Simply Plural",
"pluralKit": "Yes, PluralKit",
"startFromScratch": "No, I'll start from scratch",
"pleaseWait": "Please wait while we import your data"
"pleaseWait": "Please wait while we import your data",
"errorPk": "Error while importing the PluralKit export. Please select another option."
},
"systemInfo": {
"header": "Tell us about your system!",
Expand Down
8 changes: 7 additions & 1 deletion translations/it/importExport.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@
"title": "Esporta i tuoi dati",
"desc": "Fai il backup dei tuoi dati così da poterli tenere da qualche altra parte"
},
"pkImport": {
"title": "Importa i tuoi dati da un export di PluralKit",
"desc": "Attenzione! Questo sovvrascriverà ogni dato esistente"
},
"status": {
"imported": "Il backup è stato importato. Si prega di far ripartire l'app.",
"importedPk": "L'export di PluralKit è stato importato. Si prega di far ripartire l'app.",
"exportedPwa": "Il backup è stato scaricato nella tua cartella degli scaricati.",
"exportedApp": "Il backup è stato esportato nella posizione scelta.",
"error": "Errore durante l'esportazione del backup."
"error": "Errore durante l'esportazione del backup.",
"errorPk": "Errore durante l'importazione dell'export di PluralKit."
}
}
3 changes: 2 additions & 1 deletion translations/it/onboarding.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"simplyPlural": "Si, Simply Plural",
"pluralKit": "Si, PluralKit",
"startFromScratch": "No, inizierò da zero",
"pleaseWait": "Attendi mentre importiamo i tuoi dati"
"pleaseWait": "Attendi mentre importiamo i tuoi dati",
"errorPk": "Errore durante l'importazione dell'export di PluralKit. Per favore scegli un'altra opzione."
},
"systemInfo": {
"header": "Parlaci del tuo sistema!",
Expand Down

0 comments on commit 7218e15

Please sign in to comment.