tangled
alpha
login
or
join now
nel.pet
/
pds-migrate
6
fork
atom
CLI tool for migrating PDS
6
fork
atom
overview
issues
pulls
pipelines
Data migration
nel.pet
1 year ago
733c55c6
b3fdbe63
+159
-4
2 changed files
expand all
collapse all
unified
split
Cargo.toml
src
main.rs
+1
-1
Cargo.toml
···
4
4
edition = "2021"
5
5
6
6
[dependencies]
7
7
-
atrium-api = { version = "0.25.0", default-features = false, features = ["agent"] }
7
7
+
atrium-api = { version = "0.25.0", default-features = false, features = ["agent", "bluesky"] }
8
8
atrium-xrpc-client = "0.5.11"
9
9
tokio = { version = "1.44.0", features = ["macros", "rt-multi-thread"]}
+158
-3
src/main.rs
···
1
1
use atrium_api::{
2
2
agent::atp_agent::{store::MemorySessionStore, AtpAgent},
3
3
-
com::atproto::server::{create_account, get_service_auth},
3
3
+
app::bsky::actor::{get_preferences, put_preferences},
4
4
+
com::atproto::{
5
5
+
server::{create_account, get_service_auth},
6
6
+
sync::{get_blob, get_repo, list_blobs},
7
7
+
},
4
8
types::string::{Handle, Nsid},
5
9
};
6
10
use atrium_xrpc_client::reqwest::ReqwestClient;
···
58
62
println!();
59
63
60
64
// Create new account
61
61
-
println!("First migration step is registering an account with your new PDS");
62
65
let new_pds_url = match readln(Some(
63
66
"Please type in the URL of the PDS you want to migrate to: ",
64
67
)) {
···
68
71
return;
69
72
}
70
73
};
74
74
+
println!("Creating an account on your new PDS ...");
71
75
let new_agent = AtpAgent::new(
72
76
ReqwestClient::new(&new_pds_url),
73
77
MemorySessionStore::default(),
···
177
181
)
178
182
.await
179
183
{
184
184
+
Ok(_) => (),
185
185
+
Err(err) => {
186
186
+
println!("com.atproto.server.createAccount at new PDS failed due to error: {err}");
187
187
+
return;
188
188
+
}
189
189
+
}
190
190
+
println!("Successfully created account on your new PDS!");
191
191
+
println!();
192
192
+
193
193
+
// Migrate data
194
194
+
println!("Migrating your data");
195
195
+
196
196
+
let car = match old_agent
197
197
+
.api
198
198
+
.com
199
199
+
.atproto
200
200
+
.sync
201
201
+
.get_repo(
202
202
+
get_repo::ParametersData {
203
203
+
did: old_agent.did().await.unwrap(),
204
204
+
since: None,
205
205
+
}
206
206
+
.into(),
207
207
+
)
208
208
+
.await
209
209
+
{
180
210
Ok(response) => response,
181
211
Err(err) => {
182
182
-
println!("com.atproto.server.createAccount at new PDS failed due to error: {err}");
212
212
+
println!("com.atproto.sync.getRepo at current PDS failed due to error: {err}");
213
213
+
return;
214
214
+
}
215
215
+
};
216
216
+
217
217
+
match new_agent.api.com.atproto.repo.import_repo(car).await {
218
218
+
Ok(_) => (),
219
219
+
Err(err) => {
220
220
+
println!("com.atproto.repo.importRepo at new PDS failed due to error: {err}");
221
221
+
return;
222
222
+
}
223
223
+
}
224
224
+
println!("Repository successfully migrated");
225
225
+
226
226
+
let mut listed_blobs = match old_agent
227
227
+
.api
228
228
+
.com
229
229
+
.atproto
230
230
+
.sync
231
231
+
.list_blobs(
232
232
+
list_blobs::ParametersData {
233
233
+
cursor: None,
234
234
+
did: old_agent.did().await.unwrap(),
235
235
+
limit: None,
236
236
+
since: None,
237
237
+
}
238
238
+
.into(),
239
239
+
)
240
240
+
.await
241
241
+
{
242
242
+
Ok(response) => response,
243
243
+
Err(err) => {
244
244
+
println!("com.atproto.sync.listBlobs at old PDS failed due to error: {err}");
245
245
+
return;
246
246
+
}
247
247
+
};
248
248
+
249
249
+
while listed_blobs.cursor.is_some() {
250
250
+
for cid in listed_blobs.cids.iter() {
251
251
+
let blob = match old_agent
252
252
+
.api
253
253
+
.com
254
254
+
.atproto
255
255
+
.sync
256
256
+
.get_blob(
257
257
+
get_blob::ParametersData {
258
258
+
cid: cid.to_owned(),
259
259
+
did: old_agent.did().await.unwrap(),
260
260
+
}
261
261
+
.into(),
262
262
+
)
263
263
+
.await
264
264
+
{
265
265
+
Ok(response) => response,
266
266
+
Err(err) => {
267
267
+
println!("com.atproto.sync.getBlob at current PDS failed due to error: {err}");
268
268
+
return;
269
269
+
}
270
270
+
};
271
271
+
272
272
+
match new_agent.api.com.atproto.repo.upload_blob(blob).await {
273
273
+
Ok(_) => (),
274
274
+
Err(err) => {
275
275
+
println!("com.atproto.repo.uploadBlob at new PDS failed due to error: {err}");
276
276
+
return;
277
277
+
}
278
278
+
};
279
279
+
}
280
280
+
281
281
+
listed_blobs = match old_agent
282
282
+
.api
283
283
+
.com
284
284
+
.atproto
285
285
+
.sync
286
286
+
.list_blobs(
287
287
+
list_blobs::ParametersData {
288
288
+
cursor: listed_blobs.cursor.clone(),
289
289
+
did: old_agent.did().await.unwrap(),
290
290
+
limit: None,
291
291
+
since: None,
292
292
+
}
293
293
+
.into(),
294
294
+
)
295
295
+
.await
296
296
+
{
297
297
+
Ok(response) => response,
298
298
+
Err(err) => {
299
299
+
println!("com.atproto.sync.listBlobs at old PDS failed due to error: {err}");
300
300
+
return;
301
301
+
}
302
302
+
};
303
303
+
}
304
304
+
println!("Blobs successfully migrated!");
305
305
+
306
306
+
let prefs = match old_agent
307
307
+
.api
308
308
+
.app
309
309
+
.bsky
310
310
+
.actor
311
311
+
.get_preferences(get_preferences::ParametersData {}.into())
312
312
+
.await
313
313
+
{
314
314
+
Ok(response) => response,
315
315
+
Err(err) => {
316
316
+
println!("app.bsky.actor.getPreferences at current PDS failed due to error: {err}");
183
317
return;
184
318
}
185
319
};
320
320
+
321
321
+
match new_agent
322
322
+
.api
323
323
+
.app
324
324
+
.bsky
325
325
+
.actor
326
326
+
.put_preferences(
327
327
+
put_preferences::InputData {
328
328
+
preferences: prefs.preferences.clone(),
329
329
+
}
330
330
+
.into(),
331
331
+
)
332
332
+
.await
333
333
+
{
334
334
+
Ok(_) => (),
335
335
+
Err(err) => {
336
336
+
println!("app.bsky.actor.putPreferences at new PDS failed due to error: {err}");
337
337
+
return;
338
338
+
}
339
339
+
}
340
340
+
println!("Preferences successfully migrated!");
186
341
}