mirror of
https://github.com/filecoin-project/slate.git
synced 2024-09-11 22:07:08 +03:00
analytics: creates a file with user performance information
This commit is contained in:
parent
6a98dc7bb0
commit
bdaed6c1f8
1
.gitignore
vendored
1
.gitignore
vendored
@ -11,6 +11,7 @@ package-lock.json
|
||||
yarn.lock
|
||||
node_modules
|
||||
dist
|
||||
analytics.txt
|
||||
|
||||
200MB_BUCKET_TEST.txt
|
||||
500MB_BUCKET_TEST.txt
|
||||
|
@ -83,7 +83,7 @@ export const formatAsFilecoinConversion = (number) => {
|
||||
};
|
||||
|
||||
export const formatAsFilecoin = (number) => {
|
||||
return `${formatNumber(number)} FIL`;
|
||||
return `${number} FIL`;
|
||||
};
|
||||
|
||||
export const pluralize = (text, count) => {
|
||||
@ -171,18 +171,9 @@ export const getRemainingTime = (seconds) => {
|
||||
|
||||
export const hexToRGBA = (hex, alpha = 1) => {
|
||||
hex = hex.replace("#", "");
|
||||
var r = parseInt(
|
||||
hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2),
|
||||
16
|
||||
);
|
||||
var g = parseInt(
|
||||
hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4),
|
||||
16
|
||||
);
|
||||
var b = parseInt(
|
||||
hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6),
|
||||
16
|
||||
);
|
||||
var r = parseInt(hex.length == 3 ? hex.slice(0, 1).repeat(2) : hex.slice(0, 2), 16);
|
||||
var g = parseInt(hex.length == 3 ? hex.slice(1, 2).repeat(2) : hex.slice(2, 4), 16);
|
||||
var b = parseInt(hex.length == 3 ? hex.slice(2, 3).repeat(2) : hex.slice(4, 6), 16);
|
||||
if (alpha) {
|
||||
return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
|
||||
} else {
|
||||
@ -214,10 +205,7 @@ export const createSlug = (text, base = "untitled") => {
|
||||
return base;
|
||||
}
|
||||
|
||||
text = text
|
||||
.toString()
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
text = text.toString().toLowerCase().trim();
|
||||
|
||||
const sets = [
|
||||
{ to: "a", from: "[ÀÁÂÃÅÆĀĂĄẠẢẤẦẨẪẬẮẰẲẴẶ]" },
|
||||
|
@ -2,7 +2,7 @@ import * as Serializers from "~/node_common/serializers";
|
||||
|
||||
import { runQuery } from "~/node_common/data/utilities";
|
||||
|
||||
export default async () => {
|
||||
export default async (sanitize = true) => {
|
||||
return await runQuery({
|
||||
label: "GET_EVERY_USER",
|
||||
queryFn: async (DB) => {
|
||||
@ -12,8 +12,12 @@ export default async () => {
|
||||
return [];
|
||||
}
|
||||
|
||||
const sanitized = r.map((each) => Serializers.user(each));
|
||||
return JSON.parse(JSON.stringify(sanitized));
|
||||
if (sanitize) {
|
||||
const sanitized = r.map((each) => Serializers.user(each));
|
||||
return JSON.parse(JSON.stringify(sanitized));
|
||||
}
|
||||
|
||||
return JSON.parse(JSON.stringify(r));
|
||||
},
|
||||
errorFn: async (e) => {
|
||||
console.log({
|
||||
|
47
node_common/script-logging.js
Normal file
47
node_common/script-logging.js
Normal file
@ -0,0 +1,47 @@
|
||||
const { performance } = require("perf_hooks");
|
||||
|
||||
const TIME_START = performance.now();
|
||||
|
||||
const timeDifference = (current, previous) => {
|
||||
var msPerMinute = 60 * 1000;
|
||||
var msPerHour = msPerMinute * 60;
|
||||
var msPerDay = msPerHour * 24;
|
||||
var msPerMonth = msPerDay * 30;
|
||||
var msPerYear = msPerDay * 365;
|
||||
|
||||
var elapsed = current - previous;
|
||||
|
||||
if (elapsed < msPerMinute) {
|
||||
return Math.round(elapsed / 1000) + " seconds ago";
|
||||
} else if (elapsed < msPerHour) {
|
||||
return Math.round(elapsed / msPerMinute) + " minutes ago";
|
||||
} else if (elapsed < msPerDay) {
|
||||
return Math.round(elapsed / msPerHour) + " hours ago";
|
||||
} else if (elapsed < msPerMonth) {
|
||||
return "approximately " + Math.round(elapsed / msPerDay) + " days ago";
|
||||
} else if (elapsed < msPerYear) {
|
||||
return "approximately " + Math.round(elapsed / msPerMonth) + " months ago";
|
||||
} else {
|
||||
return "approximately " + Math.round(elapsed / msPerYear) + " years ago";
|
||||
}
|
||||
};
|
||||
|
||||
const setTime = () => {
|
||||
return `[ \x1b[33m\x1b[5m${timeDifference(performance.now(), TIME_START)}\x1b[0m ]`;
|
||||
};
|
||||
|
||||
export const error = (message, name = "ERROR ") => {
|
||||
console.log(`\x1b[1m[ \x1b[31m${name}\x1b[0m\x1b[1m ]\x1b[0m ${setTime()} ${message}`);
|
||||
};
|
||||
|
||||
export const task = (message, name = "SCRIPT") => {
|
||||
console.log(`\x1b[1m[ \x1b[32m${name}\x1b[0m\x1b[1m ]\x1b[0m ${setTime()} ${message}`);
|
||||
};
|
||||
|
||||
export const taskTimeless = (message, name = "SCRIPT") => {
|
||||
console.log(`\x1b[1m[ \x1b[32m${name}\x1b[0m\x1b[1m ]\x1b[0m ${message}`);
|
||||
};
|
||||
|
||||
export const note = (message, name = "NOOP ") => {
|
||||
console.log(`\x1b[1m[ \x1b[33m${name}\x1b[0m\x1b[1m ]\x1b[0m ${setTime()} ${message}`);
|
||||
};
|
@ -144,8 +144,6 @@ export const setupWithThread = async ({ buckets }) => {
|
||||
const res = await client.getThread("buckets");
|
||||
|
||||
buckets.withThread(res.id.toString());
|
||||
|
||||
console.log(`[ buckets ] getThread success`);
|
||||
} catch (error) {
|
||||
if (error.message !== "Thread not found") {
|
||||
throw new Error(error.message);
|
||||
@ -156,19 +154,13 @@ export const setupWithThread = async ({ buckets }) => {
|
||||
const threadID = newId.toString();
|
||||
|
||||
buckets.withThread(threadID);
|
||||
|
||||
console.log(`[ buckets ] newDB success`);
|
||||
}
|
||||
|
||||
return buckets;
|
||||
};
|
||||
|
||||
// NOTE(jim): Requires @textile/hub
|
||||
export const getBucketAPIFromUserToken = async ({
|
||||
user,
|
||||
bucketName,
|
||||
encrypted = false,
|
||||
}) => {
|
||||
export const getBucketAPIFromUserToken = async ({ user, bucketName, encrypted = false }) => {
|
||||
const token = user.data.tokens.api;
|
||||
const name = Strings.isEmpty(bucketName) ? BUCKET_NAME : bucketName;
|
||||
const identity = await PrivateKey.fromString(token);
|
||||
|
@ -17,9 +17,7 @@
|
||||
"electron-prod": "NODE_ENV=production next build && electron-builder --dir",
|
||||
"scripts": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts",
|
||||
"www-setup-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts setup-database",
|
||||
"www-seed-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts seed-database",
|
||||
"www-drop-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts drop-database",
|
||||
"www-adjust-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts adjust"
|
||||
"www-seed-database": "NODE_TLS_REJECT_UNAUTHORIZED=0 node ./scripts seed-database"
|
||||
},
|
||||
"build": {
|
||||
"appId": "com.slate",
|
||||
|
66
scripts/worker-analytics.js
Normal file
66
scripts/worker-analytics.js
Normal file
@ -0,0 +1,66 @@
|
||||
import configs from "~/knexfile";
|
||||
import knex from "knex";
|
||||
import fs from "fs";
|
||||
|
||||
import * as Data from "~/node_common/data";
|
||||
import * as Strings from "~/common/strings";
|
||||
|
||||
const envConfig = configs["development"];
|
||||
const db = knex(envConfig);
|
||||
|
||||
console.log(`RUNNING: worker-analytics.js`);
|
||||
|
||||
function sortObject(obj) {
|
||||
var arr = [];
|
||||
for (var prop in obj) {
|
||||
if (obj.hasOwnProperty(prop)) {
|
||||
arr.push({
|
||||
key: prop,
|
||||
value: obj[prop],
|
||||
});
|
||||
}
|
||||
}
|
||||
arr.sort(function (a, b) {
|
||||
return b.value - a.value;
|
||||
});
|
||||
//arr.sort(function(a, b) { a.value.toLowerCase().localeCompare(b.value.toLowerCase()); }); //use this to sort as strings
|
||||
return arr; // returns array
|
||||
}
|
||||
|
||||
const run = async () => {
|
||||
const response = await Data.getEveryUser(false);
|
||||
|
||||
let count = 0;
|
||||
let bytes = 0;
|
||||
let userMap = {};
|
||||
|
||||
response.forEach((user) => {
|
||||
count = count + 1;
|
||||
|
||||
let userBytes = 0;
|
||||
user.data.library[0].children.forEach((each) => {
|
||||
userBytes = each.size + userBytes;
|
||||
bytes = each.size + bytes;
|
||||
});
|
||||
|
||||
userMap[user.username] = userBytes;
|
||||
});
|
||||
|
||||
userMap = sortObject(userMap);
|
||||
userMap = userMap.map((each, index) => {
|
||||
return { ...each, index, value: Strings.bytesToSize(each.value) };
|
||||
});
|
||||
console.log(userMap);
|
||||
console.log("TOTAL USER COUNT", count);
|
||||
console.log("TOTAL BYTES", bytes);
|
||||
console.log("TOTAL BYTES (CONVERTED)", Strings.bytesToSize(bytes));
|
||||
|
||||
fs.writeFile("analytics.txt", JSON.stringify({ data: userMap }, null, 2), function (err) {
|
||||
if (err) return console.log(err);
|
||||
});
|
||||
};
|
||||
|
||||
run();
|
||||
|
||||
console.log(`FINISHED: worker-analytics.js`);
|
||||
console.log(` CTRL +C to return to terminal.`);
|
310
scripts/worker-heavy-stones.js
Normal file
310
scripts/worker-heavy-stones.js
Normal file
@ -0,0 +1,310 @@
|
||||
import fs from "fs-extra";
|
||||
|
||||
import * as Environment from "~/node_common/environment";
|
||||
import * as Data from "~/node_common/data";
|
||||
import * as Utilities from "~/node_common/utilities";
|
||||
import * as Strings from "~/common/strings";
|
||||
import * as Logs from "~/node_common/script-logging";
|
||||
|
||||
import { Buckets, PrivateKey } from "@textile/hub";
|
||||
import { v4 as uuid } from "uuid";
|
||||
|
||||
// 50 MB minimum
|
||||
const MINIMUM_BYTES_FOR_STORAGE = 52428800;
|
||||
const STORAGE_BOT_NAME = "STORAGE WORKER";
|
||||
const PRACTICE_RUN = false;
|
||||
const SKIP_NEW_BUCKET_CREATION = true;
|
||||
|
||||
const TEXTILE_KEY_INFO = {
|
||||
key: Environment.TEXTILE_HUB_KEY,
|
||||
secret: Environment.TEXTILE_HUB_SECRET,
|
||||
};
|
||||
|
||||
console.log(`RUNNING: worker-heavy-stones.js`);
|
||||
|
||||
const run = async () => {
|
||||
const response = await Data.getEveryUser(false);
|
||||
|
||||
const storageUsers = [];
|
||||
const writable = [];
|
||||
const slateAddresses = [];
|
||||
let bytes = 0;
|
||||
let dealUsers = 0;
|
||||
let totalUsers = 0;
|
||||
let encryptedUsers = 0;
|
||||
|
||||
// NOTE(jim): Only users who agree. Opt in by default.
|
||||
for (let i = 0; i < response.length; i++) {
|
||||
const user = response[i];
|
||||
|
||||
if (user.data.allow_automatic_data_storage) {
|
||||
storageUsers.push(user);
|
||||
dealUsers = dealUsers + 1;
|
||||
}
|
||||
|
||||
if (user.data.allow_encrypted_data_storage) {
|
||||
encryptedUsers = encryptedUsers + 1;
|
||||
}
|
||||
|
||||
totalUsers = totalUsers + 1;
|
||||
}
|
||||
|
||||
for (let i = 0; i < storageUsers.length; i++) {
|
||||
const user = storageUsers[i];
|
||||
const printData = {
|
||||
username: storageUsers[i].username,
|
||||
slateURL: `https://slate.host/${storageUsers[i].username}`,
|
||||
isForcingEncryption: user.data.allow_encrypted_data_storage,
|
||||
};
|
||||
let buckets;
|
||||
|
||||
try {
|
||||
const token = user.data.tokens.api;
|
||||
const identity = await PrivateKey.fromString(token);
|
||||
buckets = await Buckets.withKeyInfo(TEXTILE_KEY_INFO);
|
||||
await buckets.getToken(identity);
|
||||
buckets = await Utilities.setupWithThread({ buckets });
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
|
||||
let userBuckets = [];
|
||||
try {
|
||||
userBuckets = await buckets.list();
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
|
||||
let userBytes = 0;
|
||||
|
||||
for (let k = 0; k < userBuckets.length; k++) {
|
||||
try {
|
||||
const path = await buckets.listPath(userBuckets[k].key, "/");
|
||||
const data = path.item;
|
||||
|
||||
if (data.name !== "data") {
|
||||
continue;
|
||||
}
|
||||
|
||||
userBuckets[k].bucketSize = data.size;
|
||||
userBytes = userBytes + data.size;
|
||||
bytes = bytes + userBytes;
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
printData.bytes = userBytes;
|
||||
|
||||
// NOTE(jim): Skip people.
|
||||
if (userBytes < MINIMUM_BYTES_FOR_STORAGE) {
|
||||
Logs.note(`SKIP: ${user.username}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const PowergateSingleton = await Utilities.getPowergateAPIFromUserToken({
|
||||
user,
|
||||
});
|
||||
const { powerInfo, power } = PowergateSingleton;
|
||||
let balance = 0;
|
||||
let address = null;
|
||||
|
||||
try {
|
||||
if (powerInfo) {
|
||||
powerInfo.balancesList.forEach((a) => {
|
||||
balance = a.balance;
|
||||
address = a.addr.addr;
|
||||
});
|
||||
} else {
|
||||
Logs.error(`Powergate powerInfo does not exist.`);
|
||||
}
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
|
||||
let storageDeals = [];
|
||||
try {
|
||||
const listStorageResult = await power.listStorageDealRecords({
|
||||
ascending: false,
|
||||
includePending: false,
|
||||
includeFinal: true,
|
||||
});
|
||||
|
||||
listStorageResult.recordsList.forEach((o) => {
|
||||
storageDeals.push({
|
||||
dealId: o.dealInfo.dealId,
|
||||
rootCid: o.rootCid,
|
||||
proposalCid: o.dealInfo.proposalCid,
|
||||
pieceCid: o.dealInfo.pieceCid,
|
||||
addr: o.addr,
|
||||
miner: o.dealInfo.miner,
|
||||
size: o.dealInfo.size,
|
||||
// NOTE(jim): formatted size.
|
||||
formattedSize: Strings.bytesToSize(o.dealInfo.size),
|
||||
pricePerEpoch: o.dealInfo.pricePerEpoch,
|
||||
startEpoch: o.dealInfo.startEpoch,
|
||||
// NOTE(jim): just for point of reference on the total cost.
|
||||
totalSpeculatedCost: Strings.formatAsFilecoinConversion(
|
||||
o.dealInfo.pricePerEpoch * o.dealInfo.duration
|
||||
),
|
||||
duration: o.dealInfo.duration,
|
||||
activationEpoch: o.dealInfo.activationEpoch,
|
||||
time: o.time,
|
||||
pending: o.pending,
|
||||
});
|
||||
});
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
|
||||
if (balance === 0) {
|
||||
Logs.error(`OUT OF FUNDS: ${user.username}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (address) {
|
||||
slateAddresses.push(address);
|
||||
}
|
||||
|
||||
printData.address = address;
|
||||
printData.balanceAttoFil = balance;
|
||||
|
||||
Logs.taskTimeless(`\x1b[36m\x1b[1mhttps://slate.host/${user.username}\x1b[0m`);
|
||||
Logs.taskTimeless(`\x1b[36m\x1b[1m${address}\x1b[0m`);
|
||||
Logs.taskTimeless(`\x1b[36m\x1b[1m${Strings.bytesToSize(userBytes)} stored each deal.\x1b[0m`);
|
||||
Logs.taskTimeless(
|
||||
`\x1b[36m\x1b[1m${Strings.formatAsFilecoinConversion(balance)} remaining\x1b[0m`
|
||||
);
|
||||
|
||||
console.log(storageDeals);
|
||||
|
||||
// NOTE(jim): tracks all buckets.
|
||||
printData.buckets = [];
|
||||
|
||||
for (let j = 0; j < userBuckets.length; j++) {
|
||||
const keyBucket = userBuckets[j];
|
||||
let key;
|
||||
let encrypt;
|
||||
|
||||
if (keyBucket.name.startsWith("open-")) {
|
||||
Logs.note(`bucket found: open-data ${keyBucket.key}`);
|
||||
key = keyBucket.key;
|
||||
}
|
||||
|
||||
if (keyBucket.name.startsWith("encrypted-data-")) {
|
||||
Logs.note(`bucket found: encrypted-data ${keyBucket.key}`);
|
||||
key = keyBucket.key;
|
||||
}
|
||||
|
||||
if (keyBucket.name === "data" && !SKIP_NEW_BUCKET_CREATION) {
|
||||
key = null;
|
||||
encrypt = !!user.data.allow_encrypted_data_storage;
|
||||
|
||||
// NOTE(jim): Create a new bucket
|
||||
const newBucketName = encrypt ? `encrypted-data-${uuid()}` : `open-data-${uuid()}`;
|
||||
|
||||
// NOTE(jim): Get the root key of the bucket
|
||||
let items;
|
||||
try {
|
||||
const path = await buckets.listPath(keyBucket.key, "/");
|
||||
items = path.item;
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
|
||||
Logs.task(`creating new bucket: ${newBucketName}.`);
|
||||
|
||||
// NOTE(jim): Create a new bucket
|
||||
try {
|
||||
Logs.note(`attempting ...`);
|
||||
|
||||
if (!PRACTICE_RUN) {
|
||||
let newBucket = await buckets.create(newBucketName, encrypt, items.cid);
|
||||
|
||||
key = newBucket.root.key;
|
||||
|
||||
Logs.task(`created ${newBucketName} successfully.`);
|
||||
} else {
|
||||
Logs.note(`practice skipping ...`);
|
||||
}
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (key) {
|
||||
try {
|
||||
if (!PRACTICE_RUN) {
|
||||
await buckets.archive(key);
|
||||
Logs.task(`\x1b[32mNEW DEAL SUCCESSFUL !!!\x1b[0m`);
|
||||
} else {
|
||||
Logs.note(`archive skipping ...`);
|
||||
}
|
||||
|
||||
printData.buckets.push({
|
||||
key,
|
||||
success: false,
|
||||
});
|
||||
} catch (e) {
|
||||
if (e.message === `the same bucket cid is already archived successfully`) {
|
||||
printData.buckets.push({
|
||||
key,
|
||||
success: true,
|
||||
});
|
||||
} else {
|
||||
printData.buckets.push({
|
||||
key,
|
||||
success: false,
|
||||
});
|
||||
}
|
||||
|
||||
Logs.note(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writable.push(printData);
|
||||
|
||||
for (let k = 0; k < printData.buckets.length; k++) {
|
||||
let targetBucket = printData.buckets[k];
|
||||
|
||||
if (targetBucket.success) {
|
||||
try {
|
||||
Logs.task(`deleting bucket with key: ${targetBucket.key}`);
|
||||
await buckets.remove(targetBucket.key);
|
||||
Logs.task(`successfully deleted ${targetBucket.key}`);
|
||||
} catch (e) {
|
||||
Logs.error(e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("\n");
|
||||
}
|
||||
|
||||
Logs.task(`total storage per run: ${Strings.bytesToSize(bytes)}`);
|
||||
Logs.task(`total storage per run (with replication x5): ${Strings.bytesToSize(bytes * 5)}`);
|
||||
Logs.task(`creating slate-storage-addresses.json`);
|
||||
|
||||
fs.writeFile(
|
||||
"slate-storage-addresses.json",
|
||||
JSON.stringify(
|
||||
{
|
||||
rootAddress:
|
||||
"t3xhj6odc2cjj3z6kmxqugjjai2unacme65gnwigse4xx6jcpmfmi6jg6miqintibacluxi4ydlmolfpruznba",
|
||||
addresses: slateAddresses,
|
||||
},
|
||||
null,
|
||||
2
|
||||
),
|
||||
function (e) {
|
||||
if (e) return Logs.error(e.message);
|
||||
}
|
||||
);
|
||||
|
||||
console.log(`${consoleName(STORAGE_BOT_NAME)} finished. \n\n`);
|
||||
console.log(`FINISHED: worker-heavy-stones.js`);
|
||||
console.log(` CTRL +C to return to terminal.`);
|
||||
};
|
||||
|
||||
run();
|
86
slate-storage-addresses.json
Normal file
86
slate-storage-addresses.json
Normal file
@ -0,0 +1,86 @@
|
||||
{
|
||||
"rootAddress": "t3xhj6odc2cjj3z6kmxqugjjai2unacme65gnwigse4xx6jcpmfmi6jg6miqintibacluxi4ydlmolfpruznba",
|
||||
"addresses": [
|
||||
"t3qxr7b2zxue5i4afu65m4z5zqdz5reieelxq7kknjxbdm5qshu5qpy75mwn53z6cgybfsn5wwczk4a5xozn5q",
|
||||
"t3whc2f2m3oyc6ooq2efo756bgipyx3g4jsaoa5pjsmug5tnrtbunq7n6vfzrcn624p73q5iuo6qzqy7qtjolq",
|
||||
"t3xebyitlbeoyiwzwrrlpyrffyv4kassujmfo6x7eslvqno4gty5y6e2k533pghvseeps7etvfxjekguhh5vja",
|
||||
"t3xhj6odc2cjj3z6kmxqugjjai2unacme65gnwigse4xx6jcpmfmi6jg6miqintibacluxi4ydlmolfpruznba",
|
||||
"t3wtu4igmtsqyt6yje7ydsok4y3ldluudwvji6ikr3vahcvszcxvx4qx2aeoqzkkjeaaneugeqkd3k6u2a77oq",
|
||||
"t3ufy5gufgefnde7kmu6t4xqrfgvj5mppk7gawgo4dhjdspujsentra5xqab4l7akhoravpuh2u6bt7dtajs4q",
|
||||
"t3sqfigf6mtwa2gflwr2vffvw4dabvkcfwxet57y6bl6hyiir5d4d2bavvvto6qbatcw4xzrlxuniailcfbxiq",
|
||||
"t3xaq3j6o7ppihucad3kiefa3wk2bgcietkzunii64jmfvpd3kdbksnh7o43cbommojdjaw6f66w2ju4posaea",
|
||||
"t3rmc35axdjzte2qqovwigsvb54bj7slvtzs6sarouea3rhryx6lwnrmuysdsxbkdoqxcqhl6vmhej4af5kmaq",
|
||||
"t3stsrzaavir4js45znovkh5xi42pezdqrmgn5rojjlodpxjf4wcxxzxzvsf6g2s6ya7jgfh4djiwyjaiiujsa",
|
||||
"t3u2y3nedj4wwptfdsqutetswtp5vidmpgqableqypbxd3jzyemydazntcvnkrj64az7rok6r3qd2xwfw2os6a",
|
||||
"t3wbym4vrysh3bt3likgcddzoow6yenlaeerp6v7qjko22mbrfm5c7t5ryn645culqx7ghc6x6eshk6sofkjqa",
|
||||
"t3usqxiiyhroebbv6u3bql5q3yyuvzdtcsnp4c6sciuf5fte5qpomctf5lvmrm53jonor4wtxtweqkp5fkguxa",
|
||||
"t3r5tbghbwvnhtb5jfj2dkjphoclt5pxbhig2vqx4eglzhcai7sc4qoyfdiptgs4qjyv2pvpazhyjbph6wxada",
|
||||
"t3uomd73rdenajgywrcxowu7zmg3hrahau64bl57mjihnably5yvsaurlp7kz755owmv4limc6p67ei45c5uxa",
|
||||
"t3vfrps6g6sn3zouniezppfobdxavgdouxptl4dvh3asuine5haf5k5mytzev7cujohu5l3nlbqsagip7lhcwa",
|
||||
"t3ryq46h6rppl3lbhxzgxuy6kgv3jk2ccw4ftotpowcxeeveuq4ffmqgz5rubtsnlvstqa5tktvqrlu7tyf4oa",
|
||||
"t3urh7aqva2rotrsxzzxsrcsc3bsdq3y7t62qelqsm5isqlcmvvvhmrk4ryk67wdn3ydkgl66gvn7nkhjafylq",
|
||||
"t3qnk7idszraxmv64sf7wiw7oufm4uunv72pfbuv7qmzcduq6gqhoq7b2hfwf7cfl3x2ptxa32oxyyr6wnl63q",
|
||||
"t3uk63tsi2jrmtdiaq2dughsh7fpeexa6sem6525hfbq4cp2kdiejht4avxr3ky764yxb7eu6wvshgykp7oboa",
|
||||
"t3verovflndbqlk4flpwdzcn3jpssehaqysw2onuh2pteef6jerwqpiynzutvum55gotv3yxahgfflfwsjhkya",
|
||||
"t3rdc4nj2odm4uan424nhrfbztsm74rtruizkhegzintw3if5vx6zr6j7u34i2j2sq4nbml6rsrubia6uz3yxa",
|
||||
"t3qi2pocdq7p4pif7h4ukvatfo6bucojtmjg5omyms6km5g4zpr6gujxydg7nvn3m4uk3kysvwlmgaodyjuakq",
|
||||
"t3wusmc5tpgyfitx3ovtz26aijgszua3gglmddvp4osr3ac2ptqr2uafrre5i5k7cl5z7muuc2vljszfui4xva",
|
||||
"t3ukzgvcutccdrep2gs7ryekiznwqghjq5oi75n555f5ghjw2k34glbka652psduz4jvjyxge42cmjv5yvmhbq",
|
||||
"t3rfiqqk3tc53r2msjsqteu4kvu5wyym75xkf3mhsbqjvw36ehxe3v6nn6adfucgptd6yoe7uq4zwkwc7je2na",
|
||||
"t3ue5wv4yv4lwy4cretyzqvzvyxkswnwnh3ox44h62fgtu2vnycrovpgp472tbdq7nrb6kwu2473fldwg6kx4q",
|
||||
"t3rqo3puhnoqx2qjy5nt6zo6kmyietogq7qexjzid3dirlkdrgo23jupqp4zyxap2y7u5ov2kfjq2bjs64x7aq",
|
||||
"t3rmf2ptrod62xi24inrhurnyty623jr5f55nhj4kqh7x5sdyvswspbvweij7fin4myafsrom6bxcjftmd5lzq",
|
||||
"t3quikp4vuxt3wre5iskkrcwwwnrltdq73dl5epey4pkmpapm2a4ktitgs5sv2po4cq6vqv7znt7vz2qovkj6a",
|
||||
"t3uajdv2vhnuz3vu7bqbxgtvgysznggt3gfh64d5pdl32tr5n4e3ezpvdm5z7fhku5nelais6vgtq3wji7blsa",
|
||||
"t3r333pg23cos5ham25kc4u63pjyxzmhvts4a4g4wfxr2twiay6kblpoj6oiodanaiangoxgnylc4rquibztba",
|
||||
"t3qzaxfa3fq7xk3yknv6py5rrxrdn4eh4d4w7lhhfnuldgnpdhpvkmgfx3bbi7gnrzxq3qx3nnljwdj3qdmwxq",
|
||||
"t3quepkr7x7wl7rxpf5ak5vqzwmedwrzm47spkkm4mhys5w3oe46smr246lq6va5csixij63yzzywxf5rzny3q",
|
||||
"t3qwnpqt3u7v67qh6skas3klfwn234fcrtji7vvmavxypmpctp27vak563aiyt3ea7vyo6yt4fqniyewkd3pka",
|
||||
"t3wpjwxjieay6agc5qape6jwhgw5zogmtntclyzzlexe6z56rjcbjuowpgolomvzazlpe5q7jpdgc3m3q4rwna",
|
||||
"t3w53afyb6qlxieowmeo4jmmrlf6yg2dpzxcoew3rxnixymx4s6seosnxx62jir6jjw6sumaiuo322abbkysdq",
|
||||
"t3rd4xv4bt6djj7ffosq7qtlgz7pv4sgwh55duvc7btfpokbxmeekxqazjzx5dgyoar6okxhsxoodrr4tcpdaq",
|
||||
"t3qokecjlovjbpxfalscwbgsimu7h2w4ptzmoshfhm4ro4ubkfeyka4rbkkzh635apxjcvkdx3222beyspa76a",
|
||||
"t3vjv6tfve7x43b3pksrcrfuyywrwczg6z27mbsihutu5s2vxvhnujnhzizdnzu5xodmfgwsiuiskgwwp66p4q",
|
||||
"t3xgzmo4cjqy5wwghjquq5xvbvfh2zmrepsv245au44ankfe72qd4c7vdqwca5vzpbfvls36uedspi4f5wji7q",
|
||||
"t3qr672wse5si6qdnru5wyeayihus5mucakxpxjgfn5zum6dhfapasoiesoffymimiv3ynrjh3ql7ombapdqaa",
|
||||
"t3r5xruqmuuk7h2kihea6elzf7wwt2c2j55xakkykvu432tvf26etc2ljx4cssvbcxhlxompjgdnzgitgn3spq",
|
||||
"t3qyt2qgzefxbjpkpztalme27ye4m6762sfomyengjdr2u63rqola7gjlripnrkaz7uxgxg7khdwpdq5s4cxea",
|
||||
"t3w2w453fvef2kdo5vcs5wyxtiypbzg6nk7v76jx3l5ovaucll74f6zh4xlbsiizvxoatev5wbnw2ukvzntxbq",
|
||||
"t3su4zltzna2zrfit6fmxtqinv3fptfb4fa7csprxtt6alyxx2ws4olp7t7bvjvgopmaj7iyhygook662r63aa",
|
||||
"t3sq5367awbyus4lpv3oqednskwubvw77jzxjxlwxd6hyjcza7yaorki5o32chpoprb7rilp5kbnrqi3p2h3xq",
|
||||
"t3u7bthtl2k7f5rcibzrfmx6rdljgvg4za57ri6gl5ab4qvkrfefnmv6bfpqgfqxciyy2yygel6rdbbvbwe2va",
|
||||
"t3vctbb3gfwxwkyt6fnwussv4p2fv7d4okutt4suas5a3pifvga2nlruwmj75fys2yw2jzqtmtt7b32xgcnmpq",
|
||||
"t3uvqekf2xerew2q4mm3eesfttiup7bwf22vnqiktyniotynzuv7mcwi3myadaemiwqweqz7gw6vgqsnzzra7a",
|
||||
"t3ussvk7srutroy5zghmyqispbx5zsbmyck4d5cuc4hlpwn4ho5glpipnqmvgftijqkxi4ybjyz4jlgrbvpuoa",
|
||||
"t3r4irvw2zz6odhrl6pwhsfjmxpsp3lcoejsf722ph5mshvy2rxad3ubp6ekrrt6onsugrarvzwz2asbdka75q",
|
||||
"t3vkplobic7r4onyk6ounnahpzfklo3wfzxkccyf5ppm4psocqwbfkhzw74fbgp7mk6yxcnzutm3bnhcjnn45a",
|
||||
"t3sjuykzboxk7whkyui3xdcgo3sw6ld2c4vat5dmmevbyfoewsmepduxdaovduj2onpt4dmhfwxejbacyg7wea",
|
||||
"t3qb34p2usj5rl5yu4tqtos3lslaf6b3sfu54qbqzpfjmzhgcde5serunkesfflhoydhmb2dhbergtjhtph5xq",
|
||||
"t3wspizngi4bu54ovd2fad5oioktj55knc4gs2vzlpmng6kitkhbxuzm5ormjpzcqqczdlnzimhprlvmh3l5xq",
|
||||
"t3rqwdvxfjib452d4ativtcumcmgmupha3xzp24obofy5d3wtdno25bsrmahlfq4esuxow3mu5d26mbnhwfhdq",
|
||||
"t3s2f4ssatrgc5gcdz76fzafx2ziurpqhk2cjasyuf2hzjbg2ftysn7ryuxo2ucjmiz3y2aagsgcjkox3qdmaq",
|
||||
"t3qsb6pc6dkouflhjiwctnsdutv3ikzph4v2rk5bo6ulz6xo3u4axiyj6i2vg4tch7fv4z5tcpkzbzlrrez7fa",
|
||||
"t3uai5mpbqb35kmpamqa5ms5l6dxsaxo6xix32q3gqfd2ex46jg2notdyv5i65tklwv5qjjaq6ra4qlikrzpca",
|
||||
"t3r7ojjjjclqcd6c2ojp54kybeatz7kg3cshhxjxx4aagqehww5g6tk6pympccfi6w2mrelzbodjyeijrhxh2a",
|
||||
"t3uz2huvzqcmt6ctqtj2htuprrztsf7hfkfiyudsmafl7usqup7lb5rab7mpyhkphgtfd2xrf6cik3hhpyippq",
|
||||
"t3querv4g4uwn6qjnhj27nf373czskhoshcdm2wm7wp67gxffakekf7om7zq3gs6xqveix7wfrajelrl4ypv5q",
|
||||
"t3qha5puqjbgarh42zp575ma57aqw3rf2czymjabfoq3mmevqzgih4iipx5s6k4m33ocqvre2fzcp26u75ogzq",
|
||||
"t3rbvnzlok5gb7boilyiobzlaojh6rlgqvpchusyfc6jasfnnyhohnz6gmdvabwytkerpk2lo4is35ku4lq5ga",
|
||||
"t3qzvnd2cn5sqml3tbz4x7mnu3hlm2ezckt2pxl62js3ulbwln2cd3kavjw5qegaqjyyjdwm7mcrarfsxgfwxq",
|
||||
"t3veex27t4p2rnzawfn36aynumydactoylld2yyrt4jjabzxbqaysbpu2xzrulah6mypiatg2wp6uyegtppoqa",
|
||||
"t3u5ffm3d2mx2vnzvv4h3sux5kmpx2dfcqkr64yjnykkkqq5rjufxertkyg52zc72gj5gbnqomvdvafrd6hmza",
|
||||
"t3uaqwp5b67fn5x7a5irfvs6w2n5euxwvgvhimmzucypo2lm4p2pbmh522mgqpe7p4ciw2tngzdwaafhn6g3rq",
|
||||
"t3r6kvxhc76q62lctpejdykhvbcueaion7uko3tvoirvyv7fhyzby25r7htwooiflffkovmzd6lq6dyizwhcea",
|
||||
"t3vzpex72h34yt4kjbrksvqxeep5go7cwq76c2sbmqp45cecxs5qud53ogg5tm2mwihh2mmejralc4bzbxolqa",
|
||||
"t3qkm7g3vyf76mqglnvjj5immp3vkwaygzl7c4jpyirhpm3wtoucaxgvwki3gna2kynhehsbbrumwfgngt4feq",
|
||||
"t3qcsvmreumiuhknyloeg4ugliklvnxdy4lckasetxt3zewydsay2d3244oowwfutynf7plgrx5b75phf53jxa",
|
||||
"t3s7ebu6ptfoxzryiqqyyylu7q6hbumr4jvnromqcmsnjd34w3dgwzrknvvrxdlaiqruuyzhivbaioq3epqveq",
|
||||
"t3xdukxl4yoz3ai72m43dl6hpkzawads5cg2iu3zr7jplp2ulalmnalleiks7pbhvo5kcaqt63pd3v34sbxgga",
|
||||
"t3rkocg7q4sxbqbdnizy2y6bqjfrtusyo7azvql3dzogc2p5wl5uytpbjv4uyqkkf6blzmjiau4sq6el4tu27q",
|
||||
"t3rlxlrmqh66mdeurawzlrw26idtw2pd52ea5vhuvjz224oyk6uzi3yvjqpplsbfu7rslgewwgcbkqsykrhivq",
|
||||
"t3vvireffp6tuqrxovi6xy3wbrega74su2dxb2j6vui726jzmnfn2a3tlcxhg4fhuw6gjqmm5bvzpe6etnkg5q",
|
||||
"t3q4yok6riuzggj3ua3grekw6oqdleb5bgztdtrevfslwyf2z55uosbfturojfr2jf65xcew3qfc7ichwpd4la",
|
||||
"t3xh5lu2wshzsq45hwc7fcdj2vnz5qljmp4swk5h56djp6smtti4ctan2tovebysqybzfcfuqjbn5eheh4sjoq",
|
||||
"t3rojfwoaaxtv3kgtnzisbijsctd74mr6fe46gw6xno6cw5szdvrprmq4hbvjas562iyd7x26uqzsfuyd5zfla"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user