🚧 working file upload

pull/1/head
Damien Erambert 2022-07-31 21:53:37 +02:00
parent c56fbd5bc8
commit be05d836ea
No known key found for this signature in database
GPG Key ID: 519179F777AE5A0F
3 changed files with 214 additions and 51 deletions

131
lib.js
View File

@ -1,6 +1,11 @@
const _fetch = require("node-fetch");
const _fetch = require('node-fetch')
const crypto = require("crypto");
const needle = require('needle');
const { decode } = require("./lib/b64arraybuffer");
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const API_BASE = "https://cohost.org/api/v1";
@ -15,14 +20,14 @@ const API_BASE = "https://cohost.org/api/v1";
* @param {boolean} [complex=false] Whether to return {headers, body}, or just the body
* @returns Response, JSON parsed if parsable, string if not
*/
async function fetch(method, endpoint, cookies = "", data, complex = false) {
async function fetch(method, endpoint, cookies = "", data, complex = false, headers = {}) {
let url = API_BASE + endpoint + (method == "GET" && data ? "?" + new URLSearchParams(data).toString() : "");
let req = await _fetch(url, {
method,
headers: {
"Content-Type": "application/json",
"Cookie": cookies
"Cookie": cookies,
},
body: (method != "GET" && data) ? JSON.stringify(data) : undefined
});
@ -112,54 +117,86 @@ class User {
* Represents a cohost Project (e.g. @mog)
*/
class Project {
constructor(user, data) {
this.user = user;
this.populate(data);
}
constructor(user, data) {
this.user = user;
this.populate(data);
}
/**
* Creates a Project. Docs TBD
*/
static async create(user, data) {
return await fetch(
"POST",
"/project",
user.sessionCookie,
data
);
}
/**
* Creates a Project. Docs TBD
*/
static async create(user, data) {
return await fetch("POST", "/project", user.sessionCookie, data);
}
/**
* @private
*/
populate(data) {
this.id = data.projectId;
this.handle = data.handle;
this.displayName = data.displayName;
this.dek = data.dek;
this.description = data.description;
this.avatarURL = data.avatarURL;
this.headerURL = data.headerURL;
this.privacy = data.privacy;
this.pronouns = data.pronouns;
this.url = data.url;
this.flags = data.flags;
this.avatarShape = data.avatarShape;
}
/**
* @private
*/
populate(data) {
this.id = data.projectId;
this.handle = data.handle;
this.displayName = data.displayName;
this.dek = data.dek;
this.description = data.description;
this.avatarURL = data.avatarURL;
this.headerURL = data.headerURL;
this.privacy = data.privacy;
this.pronouns = data.pronouns;
this.url = data.url;
this.flags = data.flags;
this.avatarShape = data.avatarShape;
}
/**
* @param {number} [page=0] Page of posts to get, 20 posts per page
* @returns {object[]}
*/
async getPosts(page = 0) {
let res = await fetch(
"GET",
`/project/${encodeURIComponent(this.handle)}/posts?page=${encodeURIComponent(page.toString())}`,
this.user.sessionCookie
);
/**
* @param {number} [page=0] Page of posts to get, 20 posts per page
* @returns {object[]}
*/
async getPosts(page = 0) {
let res = await fetch(
"GET",
`/project/${encodeURIComponent(
this.handle
)}/posts?page=${encodeURIComponent(page.toString())}`,
this.user.sessionCookie
);
return res.items.map(x => new Post(this.user, x));
}
return res.items.map((x) => new Post(this.user, x));
}
async uploadAttachment(postId, filename) {
const fileContentType = mime.lookup(filename);
const fileContentLength = fs.statSync(filename).size;
const S3Parameters = await fetch(
"POST",
`/project/${encodeURIComponent(
this.handle
)}/posts/${postId}/attach/start`,
this.user.sessionCookie,
{
filename: path.basename(filename),
content_type: fileContentType,
content_length: fileContentLength,
}
);
await needle('post', S3Parameters.url, {
...S3Parameters.requiredFields,
file: {
file: filename,
content_type: fileContentType
}
}, {multipart: true});
const res = fetch(
"POST",
`/project/${encodeURIComponent(
this.handle
)}/posts/${postId}/attach/finish/${S3Parameters.attachmentId}`,
this.user.sessionCookie
)
console.log(await res)
}
}
/**

129
package-lock.json generated
View File

@ -1,17 +1,78 @@
{
"name": "cohost",
"version": "0.0.1",
"version": "0.0.2",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "cohost",
"version": "0.0.1",
"version": "0.0.2",
"license": "MIT",
"dependencies": {
"mime-types": "^2.1.35",
"needle": "^3.1.0",
"node-fetch": "2"
}
},
"node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/needle": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz",
"integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==",
"dependencies": {
"debug": "^3.2.6",
"iconv-lite": "^0.6.3",
"sax": "^1.2.4"
},
"bin": {
"needle": "bin/needle"
},
"engines": {
"node": ">= 4.4.x"
}
},
"node_modules/node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -31,6 +92,16 @@
}
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@ -52,6 +123,50 @@
}
},
"dependencies": {
"debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"requires": {
"ms": "^2.1.1"
}
},
"iconv-lite": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
"requires": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
}
},
"mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
},
"mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"requires": {
"mime-db": "1.52.0"
}
},
"ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"needle": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/needle/-/needle-3.1.0.tgz",
"integrity": "sha512-gCE9weDhjVGCRqS8dwDR/D3GTAeyXLXuqp7I8EzH6DllZGXSUyxuqqLh+YX9rMAWaaTFyVAg6rHGL25dqvczKw==",
"requires": {
"debug": "^3.2.6",
"iconv-lite": "^0.6.3",
"sax": "^1.2.4"
}
},
"node-fetch": {
"version": "2.6.7",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
@ -60,6 +175,16 @@
"whatwg-url": "^5.0.0"
}
},
"safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sax": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
},
"tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",

View File

@ -10,12 +10,13 @@
"author": "mogery",
"license": "MIT",
"dependencies": {
"mime-types": "^2.1.35",
"needle": "^3.1.0",
"node-fetch": "2"
},
"directories": {
"lib": "lib"
},
"devDependencies": {},
"repository": {
"type": "git",
"url": "git+https://github.com/mogery/cohost.js.git"
@ -24,4 +25,4 @@
"url": "https://github.com/mogery/cohost.js/issues"
},
"homepage": "https://github.com/mogery/cohost.js#readme"
}
}