does anyone else have uncontrollable urges to meow

This commit is contained in:
May 2023-12-26 13:29:06 -08:00
parent afbb29c949
commit 8fb2a55bdd
7 changed files with 176 additions and 14 deletions

View file

@ -1,8 +1,8 @@
{ {
"maxDiscordFiles": 50, "maxDiscordFiles": 500,
"maxDiscordFileSize": 10485760, "maxDiscordFileSize": 10485760,
"targetGuild": "906767804575928390", "targetGuild": "906767804575928390",
"targetChannel": "1160783463696302182", "targetChannel": "1024080525993971913",
"requestTimeout": 120000, "requestTimeout": 120000,
"maxUploadIdLength": 30, "maxUploadIdLength": 30,
"accounts": { "accounts": {

14
package-lock.json generated
View file

@ -17,6 +17,7 @@
"axios": "^0.27.2", "axios": "^0.27.2",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
"bytes": "^3.1.2", "bytes": "^3.1.2",
"commander": "^11.1.0",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"dotenv": "^16.0.2", "dotenv": "^16.0.2",
"express": "^4.18.1", "express": "^4.18.1",
@ -757,6 +758,14 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==",
"engines": {
"node": ">=16"
}
},
"node_modules/concat-stream": { "node_modules/concat-stream": {
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
@ -2420,6 +2429,11 @@
"delayed-stream": "~1.0.0" "delayed-stream": "~1.0.0"
} }
}, },
"commander": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz",
"integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="
},
"concat-stream": { "concat-stream": {
"version": "1.6.2", "version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",

View file

@ -25,6 +25,7 @@
"axios": "^0.27.2", "axios": "^0.27.2",
"body-parser": "^1.20.0", "body-parser": "^1.20.0",
"bytes": "^3.1.2", "bytes": "^3.1.2",
"commander": "^11.1.0",
"cookie-parser": "^1.4.6", "cookie-parser": "^1.4.6",
"dotenv": "^16.0.2", "dotenv": "^16.0.2",
"express": "^4.18.1", "express": "^4.18.1",

123
src/server/cli.ts Normal file
View file

@ -0,0 +1,123 @@
import fs from "fs"
import { stat } from "fs/promises"
import Files from "./lib/files"
import { program } from "commander"
import { basename } from "path"
import { Writable } from "node:stream"
const pkg = require(`${process.cwd()}/package.json`)
let config = require(`${process.cwd()}/config.json`)
// init data
if (!fs.existsSync(__dirname + "/../../.data/"))
fs.mkdirSync(__dirname + "/../../.data/")
// discord
let files = new Files(config)
program
.name("monocli")
.description("Quickly run monofile to execute a query or so")
.version(pkg.version)
program.command("list")
.alias("ls")
.description("List files in the database")
.action(() => {
Object.keys(files.files).forEach(e => console.log(e))
})
program.command("download")
.alias("dl")
.description("Download a file from the database")
.argument("<id>", "ID of the file you'd like to download")
.option("-o, --output <path>", 'Folder or filename to output to')
.action(async (id, options) => {
await (new Promise<void>(resolve => setTimeout(() => resolve(), 1000)))
let fp = files.files[id]
if (!fp)
throw `file ${id} not found`
let out = options.output as string || `./`
if (fs.existsSync(out) && (await stat(out)).isDirectory())
out = `${out.replace(/\/+$/, "")}/${fp.filename}`
;(await files.readFileStream(id)).pipe(
fs.createWriteStream(out)
)
})
program.command("upload")
.alias("up")
.description("Upload a file to the instance")
.argument("<file>", "Path to the file you'd like to upload")
.option("-id, --fileid <id>", 'Custom file ID to use')
.action(async (file, options) => {
await (new Promise<void>(resolve => setTimeout(() => resolve(), 1000)))
if (!(fs.existsSync(file) && (await stat(file)).isFile()))
throw `${file} is not a file`
let writable = files.writeFileStream({
filename: basename(file),
mime: "application/octet-stream",
size: (await stat(file)).size,
uploadId: options.fileid
})
if (!(writable instanceof Writable))
throw JSON.stringify(writable, null, 3)
;(await fs.createReadStream(file)).pipe(
writable
)
console.log(`started: ${file}`)
writable.on("drain", () => {
console.log("Drain")
})
writable.on("finish", () => {
console.log("Finished!")
})
writable.on("error", (e) => {
console.error(e)
})
})
program.command("memup")
.description("Upload a file to the instance (no stream)")
.argument("<file>", "Path to the file you'd like to upload")
.option("-id, --fileid <id>", 'Custom file ID to use')
.action(async (file, options) => {
await (new Promise<void>(resolve => setTimeout(() => resolve(), 1000)))
if (!(fs.existsSync(file) && (await stat(file)).isFile()))
throw `${file} is not a file`
let buf = fs.readFileSync(file)
let id = files.uploadFile({
filename: basename(file),
mime: "application/octet-stream",
uploadId: options.fileid
}, buf)
console.log(`uploaded: ${await id}`)
})
program.parse()

View file

@ -1,4 +1,19 @@
import fetch, { type RequestInit, type Response, Headers } from "node-fetch" import { type RequestInfo, type RequestInit, type Response, Headers } from "node-fetch"
// I jerk off to skibidi toilet. His smile is so fucking hot, oh my god, oh.
// The voices are getting louder, help me. Oh god, i want to put it inside that toilet and make him beg.
// Whenever i see skibidi toilet cum comes out like a waterfall.
// Whenever my classmates say anything about toilets the entire school gets flooded with cum everywhere.
// Dafuqboom is truly the best artist of all time.
let ftch_dft: (url: URL | RequestInfo, init?:RequestInit) => Promise<Response>
const fetch = async (url: URL | RequestInfo, init?:RequestInit) => {
if (ftch_dft) return ftch_dft(url, init)
else {
ftch_dft = (await import("node-fetch")).default;
return ftch_dft(url, init)
}
}
const base = "https://discord.com/api/v10" const base = "https://discord.com/api/v10"
const buckets = new Map<string, DiscordAPIBucket>() const buckets = new Map<string, DiscordAPIBucket>()
@ -64,14 +79,14 @@ class DiscordAPIBucket {
let rd = extractRatelimitData(base) let rd = extractRatelimitData(base)
this.parent = rest this.parent = rest
this.name = rd.bucket_name this.name = rd.bucket_name || Math.random().toString()
this.limit = rd.limit this.limit = rd.limit
this.remaining = rd.remaining this.remaining = rd.remaining
this.expires = rd.expires this.expires = rd.expires
this.expirationHold = this.expirationHold =
setTimeout( setTimeout(
this.destroy, this.destroy.bind(this),
parseFloat(base.get("x-ratelimit-reset-after")!) parseFloat(base.get("x-ratelimit-reset-after")!)
) )
@ -81,7 +96,6 @@ class DiscordAPIBucket {
* @description Renders this bucket invalid * @description Renders this bucket invalid
*/ */
destroy() { destroy() {
buckets.delete(this.name) buckets.delete(this.name)
this.dead = true this.dead = true
this.linked_routes.forEach((v) => routeConnections.delete(v)) this.linked_routes.forEach((v) => routeConnections.delete(v))

View file

@ -79,9 +79,12 @@ export class Client {
let returned = await this.rest.fetch(`/channels/${this.targetChannel}/messages`, { let returned = await this.rest.fetch(`/channels/${this.targetChannel}/messages`, {
method: "POST", method: "POST",
body: fd body: fd,
headers: fd.getHeaders()
}) })
return (await returned.json() as APIMessage) let response = (await returned.json() as APIMessage)
console.log(JSON.stringify(response, null, 4))
return response
} }
} }

View file

@ -114,9 +114,11 @@ namespace StreamHelpers {
private newmessage_debounce : boolean = true private newmessage_debounce : boolean = true
api: API api: API
files: Files
constructor( api: API, targetSize: number ) { constructor( files: Files, targetSize: number ) {
this.api = api this.files = files
this.api = files.api
this.targetSize = targetSize this.targetSize = targetSize
} }
@ -152,7 +154,11 @@ namespace StreamHelpers {
if (this.buffer[0]) return this.buffer[0] if (this.buffer[0]) return this.buffer[0]
else { else {
// startmessage.... idk // startmessage.... idk
await this.startMessage(0); await this.startMessage(
this.messages.length < Math.ceil(this.targetSize/this.files.config.maxDiscordFileSize/10)
? 10
: Math.ceil(this.targetSize/this.files.config.maxDiscordFileSize) - this.messages.length*10
);
return this.buffer[0] return this.buffer[0]
} }
} }
@ -165,12 +171,13 @@ export default class Files {
config: Configuration config: Configuration
api: API api: API
files: { [key: string]: FilePointer } = {} files: { [key: string]: FilePointer } = {}
data_directory: string = `${process.cwd()}/.data`
constructor(config: Configuration) { constructor(config: Configuration) {
this.config = config this.config = config
this.api = new API(process.env.TOKEN!, config.targetChannel) this.api = new API(process.env.TOKEN!, config.targetChannel)
readFile(process.cwd() + "/.data/files.json") readFile(this.data_directory+ "/files.json")
.then((buf) => { .then((buf) => {
this.files = JSON.parse(buf.toString() || "{}") this.files = JSON.parse(buf.toString() || "{}")
}) })
@ -215,7 +222,7 @@ export default class Files {
) )
if (validation) return validation if (validation) return validation
let buf = new StreamHelpers.StreamBuffer(this.api, metadata.size) let buf = new StreamHelpers.StreamBuffer(this, metadata.size)
let fs_obj = this let fs_obj = this
let wt = new Writable({ let wt = new Writable({
@ -398,7 +405,7 @@ export default class Files {
*/ */
async write(): Promise<void> { async write(): Promise<void> {
await writeFile( await writeFile(
process.cwd() + "/.data/files.json", this.data_directory + "/files.json",
JSON.stringify( JSON.stringify(
this.files, this.files,
null, null,