Working export/import
This commit is contained in:
102
static/App.js
102
static/App.js
@@ -384,36 +384,88 @@ export class App {
|
||||
document.body.removeChild(link);
|
||||
globalThis.URL.revokeObjectURL(url);
|
||||
}
|
||||
async importPostsForUser(userID, buffer) {
|
||||
async importPostsForUser(buffer) {
|
||||
const startTime = performance.now();
|
||||
console.log.apply(null, log("Importing posts"));
|
||||
const json = await decompressBuffer(buffer);
|
||||
const posts = JSON.parse(json);
|
||||
for (let post of posts) {
|
||||
if (post.image_data && typeof post.image_data === 'string') {
|
||||
post.image_data = await base64ToArrayBuffer(post.image_data);
|
||||
}
|
||||
if (post.post_timestamp && typeof post.post_timestamp === 'string') {
|
||||
post.post_timestamp = new Date(post.post_timestamp);
|
||||
}
|
||||
const data = JSON.parse(json);
|
||||
let postsByUser;
|
||||
let username = this.username;
|
||||
let userID = this.userID;
|
||||
if (Array.isArray(data)) {
|
||||
console.log.apply(null, log("Detected old export format"));
|
||||
postsByUser = { [this.userID]: data };
|
||||
}
|
||||
await mergeDataArray(userID, posts);
|
||||
console.log.apply(null, log(`Imported ${posts.length} posts`));
|
||||
else {
|
||||
console.log.apply(null, log("Detected new export format"));
|
||||
const { username: importedUsername, userID: importedUserID, posts } = data;
|
||||
username = importedUsername;
|
||||
userID = importedUserID;
|
||||
postsByUser = posts;
|
||||
localStorage.setItem("dandelion_username", username);
|
||||
localStorage.setItem("dandelion_id", userID);
|
||||
}
|
||||
let totalPostsImported = 0;
|
||||
const userTimings = {};
|
||||
for (const [sourceUserID, posts] of Object.entries(postsByUser)) {
|
||||
const userStartTime = performance.now();
|
||||
const postList = posts;
|
||||
for (let post of postList) {
|
||||
if (post.image_data && typeof post.image_data === 'string') {
|
||||
post.image_data = await base64ToArrayBuffer(post.image_data);
|
||||
}
|
||||
if (post.post_timestamp && typeof post.post_timestamp === 'string') {
|
||||
post.post_timestamp = new Date(post.post_timestamp);
|
||||
}
|
||||
}
|
||||
await mergeDataArray(sourceUserID, postList);
|
||||
totalPostsImported += postList.length;
|
||||
userTimings[sourceUserID] = performance.now() - userStartTime;
|
||||
}
|
||||
const totalTime = performance.now() - startTime;
|
||||
const userTimingsLog = Object.entries(userTimings)
|
||||
.map(([uid, ms]) => `${logID(uid)}: ${ms.toFixed(2)}ms`)
|
||||
.join(', ');
|
||||
console.log.apply(null, log(`Imported ${totalPostsImported} posts from ${Object.keys(postsByUser).length} users in ${totalTime.toFixed(2)}ms (${userTimingsLog})`));
|
||||
}
|
||||
async exportPostsForUser(userID) {
|
||||
let posts = await getAllData(userID);
|
||||
let output = [];
|
||||
console.log.apply(null, log("Serializing images"));
|
||||
for (let post of posts) {
|
||||
let newPost = post.data;
|
||||
if (newPost.image_data) {
|
||||
newPost.image_data = await arrayBufferToBase64(newPost.image_data);
|
||||
async exportPostsForUser() {
|
||||
console.log.apply(null, log("Exporting all posts for all users"));
|
||||
const exportStartTime = performance.now();
|
||||
const knownUsers = [...(await indexedDB.databases())]
|
||||
.map(db => db.name?.replace('user_', ''))
|
||||
.filter((userID) => userID !== undefined);
|
||||
const postsByUser = {};
|
||||
const userTimings = {};
|
||||
for (const userID of knownUsers) {
|
||||
const userStartTime = performance.now();
|
||||
const posts = await getAllData(userID);
|
||||
const output = [];
|
||||
for (let post of posts) {
|
||||
let newPost = post.data;
|
||||
if (newPost.image_data) {
|
||||
newPost.image_data = await arrayBufferToBase64(newPost.image_data);
|
||||
}
|
||||
output.push(newPost);
|
||||
}
|
||||
output.push(newPost);
|
||||
if (output.length > 0) {
|
||||
postsByUser[userID] = output;
|
||||
}
|
||||
userTimings[userID] = performance.now() - userStartTime;
|
||||
}
|
||||
let compressedData = await compressString(JSON.stringify(output));
|
||||
const totalTime = performance.now() - exportStartTime;
|
||||
const userTimingsLog = Object.entries(userTimings)
|
||||
.map(([uid, ms]) => `${logID(uid)}: ${ms.toFixed(2)}ms`)
|
||||
.join(', ');
|
||||
console.log.apply(null, log(`Exported ${Object.keys(postsByUser).length} users in ${totalTime.toFixed(2)}ms (${userTimingsLog})`));
|
||||
const exportData = {
|
||||
username: this.username,
|
||||
userID: this.userID,
|
||||
posts: postsByUser
|
||||
};
|
||||
let compressedData = await compressString(JSON.stringify(exportData));
|
||||
const d = new Date();
|
||||
const timestamp = `${d.getFullYear()}_${String(d.getMonth() + 1).padStart(2, '0')}_${String(d.getDate()).padStart(2, '0')}_${String(d.getHours()).padStart(2, '0')}_${String(d.getMinutes()).padStart(2, '0')}_${String(d.getSeconds()).padStart(2, '0')}`;
|
||||
this.downloadBinary(compressedData, `ddln_${this.username}_export_${timestamp}.json.gz`);
|
||||
this.downloadBinary(compressedData, `ddln_export_${timestamp}.json.gz`);
|
||||
}
|
||||
async importTweetArchive(userID, tweetArchive) {
|
||||
console.log.apply(null, log("Importing tweet archive"));
|
||||
@@ -760,13 +812,15 @@ export class App {
|
||||
if (!file)
|
||||
return;
|
||||
const buffer = await file.arrayBuffer();
|
||||
await this.importPostsForUser(this.userID, buffer);
|
||||
await this.importPostsForUser(buffer);
|
||||
importFilePicker.value = '';
|
||||
this.userID = localStorage.getItem("dandelion_id") || this.userID;
|
||||
this.username = localStorage.getItem("dandelion_username") || this.username;
|
||||
this.render();
|
||||
});
|
||||
let exportButton = this.button("export-button");
|
||||
exportButton.addEventListener('click', async (e) => {
|
||||
await this.exportPostsForUser(this.userID);
|
||||
await this.exportPostsForUser();
|
||||
});
|
||||
let composeButton = this.div('compose-button');
|
||||
composeButton.addEventListener('click', e => {
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user