real
commit
cf45a9d54b
|
@ -0,0 +1,4 @@
|
|||
node_modules
|
||||
.env
|
||||
output-*.json
|
||||
backup/
|
|
@ -0,0 +1,45 @@
|
|||
require("dotenv").config();
|
||||
const axios = require("axios");
|
||||
|
||||
const outputKeyword = require("./output-keyword.json");
|
||||
const outputBlurhash = require("./output-blurhash.json");
|
||||
const outputFileNotes = require("./output-file_notes.json");
|
||||
|
||||
let noteIds = [
|
||||
...(outputKeyword.map(i => i.id)),
|
||||
...(outputFileNotes.map(i => i.id)),
|
||||
];
|
||||
noteIds = noteIds.filter((item, index) => noteIds.indexOf(item) == index); // Deduplicate
|
||||
const fileIds = outputBlurhash.map(i => i.id);
|
||||
|
||||
(async () => {
|
||||
console.log("Deleting notes");
|
||||
let res = await Promise.allSettled(noteIds.map(id =>
|
||||
axios.post(
|
||||
"https://lea.pet/api/notes/delete",
|
||||
JSON.stringify({ noteId: id }),
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${process.env.API_TOKEN}`
|
||||
},
|
||||
},
|
||||
)
|
||||
));
|
||||
console.log(`Done, ${res.filter((r) => r.status == "rejected").length} errors`);
|
||||
|
||||
console.log("Deleting files");
|
||||
res = await Promise.allSettled(fileIds.map(id =>
|
||||
axios.post(
|
||||
"https://lea.pet/api/drive/files/delete",
|
||||
JSON.stringify({ fileId: id }),
|
||||
{
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
Authorization: `Bearer ${process.env.API_TOKEN}`
|
||||
},
|
||||
},
|
||||
)
|
||||
));
|
||||
console.log(`Done, ${res.filter((r) => r.status == "rejected").length} errors`);
|
||||
})();
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"name": "lea.pet-spam-cleanup",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"axios": "^1.6.7",
|
||||
"dotenv": "^16.4.5",
|
||||
"pg": "^8.11.3"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,189 @@
|
|||
lockfileVersion: '6.0'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
axios:
|
||||
specifier: ^1.6.7
|
||||
version: 1.6.7
|
||||
dotenv:
|
||||
specifier: ^16.4.5
|
||||
version: 16.4.5
|
||||
pg:
|
||||
specifier: ^8.11.3
|
||||
version: 8.11.3
|
||||
|
||||
packages:
|
||||
|
||||
/asynckit@0.4.0:
|
||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
||||
dev: false
|
||||
|
||||
/axios@1.6.7:
|
||||
resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==}
|
||||
dependencies:
|
||||
follow-redirects: 1.15.5
|
||||
form-data: 4.0.0
|
||||
proxy-from-env: 1.1.0
|
||||
transitivePeerDependencies:
|
||||
- debug
|
||||
dev: false
|
||||
|
||||
/buffer-writer@2.0.0:
|
||||
resolution: {integrity: sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/combined-stream@1.0.8:
|
||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
||||
engines: {node: '>= 0.8'}
|
||||
dependencies:
|
||||
delayed-stream: 1.0.0
|
||||
dev: false
|
||||
|
||||
/delayed-stream@1.0.0:
|
||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
||||
engines: {node: '>=0.4.0'}
|
||||
dev: false
|
||||
|
||||
/dotenv@16.4.5:
|
||||
resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==}
|
||||
engines: {node: '>=12'}
|
||||
dev: false
|
||||
|
||||
/follow-redirects@1.15.5:
|
||||
resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==}
|
||||
engines: {node: '>=4.0'}
|
||||
peerDependencies:
|
||||
debug: '*'
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/form-data@4.0.0:
|
||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
||||
engines: {node: '>= 6'}
|
||||
dependencies:
|
||||
asynckit: 0.4.0
|
||||
combined-stream: 1.0.8
|
||||
mime-types: 2.1.35
|
||||
dev: false
|
||||
|
||||
/mime-db@1.52.0:
|
||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dev: false
|
||||
|
||||
/mime-types@2.1.35:
|
||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
||||
engines: {node: '>= 0.6'}
|
||||
dependencies:
|
||||
mime-db: 1.52.0
|
||||
dev: false
|
||||
|
||||
/packet-reader@1.0.0:
|
||||
resolution: {integrity: sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==}
|
||||
dev: false
|
||||
|
||||
/pg-cloudflare@1.1.1:
|
||||
resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==}
|
||||
requiresBuild: true
|
||||
dev: false
|
||||
optional: true
|
||||
|
||||
/pg-connection-string@2.6.2:
|
||||
resolution: {integrity: sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==}
|
||||
dev: false
|
||||
|
||||
/pg-int8@1.0.1:
|
||||
resolution: {integrity: sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==}
|
||||
engines: {node: '>=4.0.0'}
|
||||
dev: false
|
||||
|
||||
/pg-pool@3.6.1(pg@8.11.3):
|
||||
resolution: {integrity: sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==}
|
||||
peerDependencies:
|
||||
pg: '>=8.0'
|
||||
dependencies:
|
||||
pg: 8.11.3
|
||||
dev: false
|
||||
|
||||
/pg-protocol@1.6.0:
|
||||
resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==}
|
||||
dev: false
|
||||
|
||||
/pg-types@2.2.0:
|
||||
resolution: {integrity: sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==}
|
||||
engines: {node: '>=4'}
|
||||
dependencies:
|
||||
pg-int8: 1.0.1
|
||||
postgres-array: 2.0.0
|
||||
postgres-bytea: 1.0.0
|
||||
postgres-date: 1.0.7
|
||||
postgres-interval: 1.2.0
|
||||
dev: false
|
||||
|
||||
/pg@8.11.3:
|
||||
resolution: {integrity: sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==}
|
||||
engines: {node: '>= 8.0.0'}
|
||||
peerDependencies:
|
||||
pg-native: '>=3.0.1'
|
||||
peerDependenciesMeta:
|
||||
pg-native:
|
||||
optional: true
|
||||
dependencies:
|
||||
buffer-writer: 2.0.0
|
||||
packet-reader: 1.0.0
|
||||
pg-connection-string: 2.6.2
|
||||
pg-pool: 3.6.1(pg@8.11.3)
|
||||
pg-protocol: 1.6.0
|
||||
pg-types: 2.2.0
|
||||
pgpass: 1.0.5
|
||||
optionalDependencies:
|
||||
pg-cloudflare: 1.1.1
|
||||
dev: false
|
||||
|
||||
/pgpass@1.0.5:
|
||||
resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==}
|
||||
dependencies:
|
||||
split2: 4.2.0
|
||||
dev: false
|
||||
|
||||
/postgres-array@2.0.0:
|
||||
resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==}
|
||||
engines: {node: '>=4'}
|
||||
dev: false
|
||||
|
||||
/postgres-bytea@1.0.0:
|
||||
resolution: {integrity: sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/postgres-date@1.0.7:
|
||||
resolution: {integrity: sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dev: false
|
||||
|
||||
/postgres-interval@1.2.0:
|
||||
resolution: {integrity: sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
dependencies:
|
||||
xtend: 4.0.2
|
||||
dev: false
|
||||
|
||||
/proxy-from-env@1.1.0:
|
||||
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
|
||||
dev: false
|
||||
|
||||
/split2@4.2.0:
|
||||
resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==}
|
||||
engines: {node: '>= 10.x'}
|
||||
dev: false
|
||||
|
||||
/xtend@4.0.2:
|
||||
resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==}
|
||||
engines: {node: '>=0.4'}
|
||||
dev: false
|
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
node ./scan.js
|
||||
node ./delete.js
|
||||
|
||||
mkdir -p "backup/$(date +'%Y-%m-%d %H-%M_%S')"
|
||||
cp output-*.json "backup/$(date +'%Y-%m-%d %H-%M_%S')/"
|
|
@ -0,0 +1,80 @@
|
|||
require("dotenv").config();
|
||||
|
||||
const { Client } = require("pg");
|
||||
const fs = require("fs");
|
||||
|
||||
const KEYWORD_MATCHES = [
|
||||
"https://xn--68j5e377y.com",
|
||||
"https://荒らし.com",
|
||||
"https://ctkpaarr.org",
|
||||
"https://discord.gg/ctkpaarr",
|
||||
|
||||
];
|
||||
|
||||
const BLURHASHES = [
|
||||
"elJ+3xk9Oat6NgtKjcV[aeo0}7agoJofj?xabYkTj@j=p_jcsmWBow",
|
||||
"eRQ0Hyrq.8IV%MVD4T%gxuIUrqD%ozxuRj~q?bM{M{%M~qxuM{t6bH",
|
||||
];
|
||||
|
||||
(async () => {
|
||||
const client = new Client({
|
||||
host: process.env.PG_HOST,
|
||||
port: process.env.PG_PORT,
|
||||
user: process.env.PG_USER,
|
||||
password: process.env.PG_PASS,
|
||||
database: process.env.PG_DATABASE,
|
||||
});
|
||||
await client.connect();
|
||||
|
||||
console.log("Searching for suspicious profiles");
|
||||
|
||||
let res = await client.query(
|
||||
`SELECT note.*, "user".username, "user".host
|
||||
FROM note
|
||||
INNER JOIN "user" ON "user"."id" = note."userId"
|
||||
WHERE LENGTH("user".username) = 10
|
||||
AND "user".username = LOWER("user".username)
|
||||
AND "user"."avatarId" IS NULL
|
||||
AND "user"."bannerId" IS NULL
|
||||
AND "user"."followingCount" = 0`
|
||||
);
|
||||
console.log("Query returned " + res.rowCount + " rows");
|
||||
|
||||
const filtered = res.rows.filter((row) => {
|
||||
for (const keyword of KEYWORD_MATCHES) {
|
||||
if (row.text?.includes(keyword)) return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
console.log("Found " + filtered.length + " rows after filtering");
|
||||
|
||||
fs.writeFileSync("output-keyword.json", JSON.stringify(filtered));
|
||||
|
||||
console.log("Searching for blurhash matches");
|
||||
|
||||
res = await client.query(
|
||||
`SELECT drive_file.*
|
||||
FROM drive_file
|
||||
WHERE drive_file.blurhash = ANY($1::text[])`,
|
||||
[BLURHASHES]
|
||||
);
|
||||
|
||||
console.log("Found " + res.rowCount + " files matching blurhash");
|
||||
fs.writeFileSync("output-blurhash.json", JSON.stringify(res.rows, null, 4));
|
||||
|
||||
console.log("Searching for notes using found files");
|
||||
|
||||
const notes = await client.query(
|
||||
`SELECT *
|
||||
FROM note
|
||||
WHERE note."fileIds"::text[] && $1::text[]`,
|
||||
[res.rows.map((row) => `${row.id}`)]
|
||||
);
|
||||
|
||||
console.log("Found " + notes.rowCount + " notes matching files");
|
||||
|
||||
fs.writeFileSync("output-file_notes.json", JSON.stringify(notes.rows, null, 4));
|
||||
|
||||
await client.end();
|
||||
})();
|
Loading…
Reference in New Issue