commit
d068fda0fc
88
README.md
88
README.md
|
@ -1,7 +1,9 @@
|
||||||
# cohost.js
|
# cohost.js
|
||||||
|
|
||||||
Unofficial API for cohost.org
|
Unofficial API for cohost.org
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm i cohost
|
npm i cohost
|
||||||
```
|
```
|
||||||
|
@ -11,46 +13,68 @@ npm i cohost
|
||||||
```js
|
```js
|
||||||
const cohost = require("cohost");
|
const cohost = require("cohost");
|
||||||
|
|
||||||
(async function() {
|
(async function () {
|
||||||
// Create User and authenticate
|
// Create User and authenticate
|
||||||
let user = new cohost.User();
|
let user = new cohost.User();
|
||||||
await user.login("YOUR_EMAIL", "YOUR_PASSWORD");
|
await user.login("YOUR_EMAIL", "YOUR_PASSWORD");
|
||||||
|
|
||||||
// Get first Project of user
|
// Get first Project of user
|
||||||
let [ project ] = await user.getProjects();
|
let [project] = await user.getProjects();
|
||||||
|
|
||||||
// Create Post
|
// Create Post
|
||||||
await cohost.Post.create(project, {
|
await cohost.Post.create(project, {
|
||||||
postState: 1,
|
postState: 1,
|
||||||
headline: "hello world from cohost.js",
|
headline: "hello world from cohost.js",
|
||||||
adultContent: false,
|
adultContent: false,
|
||||||
blocks: [],
|
blocks: [],
|
||||||
cws: [],
|
cws: [],
|
||||||
tags: [],
|
tags: []
|
||||||
});
|
});
|
||||||
|
|
||||||
// Get Posts of Project
|
// Get Posts of Project
|
||||||
let posts = await project.getPosts();
|
let posts = await project.getPosts();
|
||||||
|
|
||||||
|
// Create a draft with attachments
|
||||||
|
|
||||||
|
// 1. Create a draft
|
||||||
|
const draftId = await cohost.Post.create(myProject, basePost);
|
||||||
|
|
||||||
|
// 2. Upload the attachment
|
||||||
|
const attachmentData = await myProject.uploadAttachment(
|
||||||
|
draftId,
|
||||||
|
path.resolve(__dirname, "./02-15_One_pr.png")
|
||||||
|
);
|
||||||
|
|
||||||
|
// 3. Add the attachment block to the draft and publish it
|
||||||
|
await cohost.Post.update(myProject, draftId, {
|
||||||
|
...basePost,
|
||||||
|
postState: 1,
|
||||||
|
blocks: [
|
||||||
|
...basePost.blocks,
|
||||||
|
{ type: "attachment", attachment: { ...attachmentData } }
|
||||||
|
]
|
||||||
|
});
|
||||||
})();
|
})();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
Works:
|
Works:
|
||||||
* Logging in
|
|
||||||
* Getting the posts of a project
|
- Logging in
|
||||||
* Creating a post
|
- Getting the posts of a project
|
||||||
|
- Creating a post
|
||||||
|
|
||||||
Doesn't work:
|
Doesn't work:
|
||||||
* Editing a post: possible, haven't done it
|
|
||||||
* Sharing a post: possible, haven't done it
|
- Editing a post: possible, haven't done it
|
||||||
* Liking a post: possible, haven't done it
|
- Sharing a post: possible, haven't done it
|
||||||
* Getting notifications: possible, haven't done it
|
- Liking a post: possible, haven't done it
|
||||||
* Uploading attachments: possible, haven't done it
|
- Getting notifications: possible, haven't done it
|
||||||
* Getting the home feed: possible, haven't done it
|
- Getting the home feed: possible, haven't done it
|
||||||
* Editing profiles: possible, haven't done it
|
- Editing profiles: possible, haven't done it
|
||||||
* Getting followers and following: possible, haven't done it
|
- Getting followers and following: possible, haven't done it
|
||||||
* Getting bookmarks and bookmarking: possible, haven't done it
|
- Getting bookmarks and bookmarking: possible, haven't done it
|
||||||
* Getting a post by its ID: **seems impossible? endpoint seems to be disabled**
|
- Getting a post by its ID: **seems impossible? endpoint seems to be disabled**
|
||||||
* Getting posts from a tag: haven''t checked
|
- Getting posts from a tag: haven''t checked
|
||||||
* ...everything else
|
- ...everything else
|
||||||
|
|
477
lib.js
477
lib.js
|
@ -1,12 +1,16 @@
|
||||||
const _fetch = require("node-fetch");
|
const _fetch = require("node-fetch");
|
||||||
const crypto = require("crypto");
|
const crypto = require("crypto");
|
||||||
|
const needle = require("needle");
|
||||||
const { decode } = require("./lib/b64arraybuffer");
|
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";
|
const API_BASE = "https://cohost.org/api/v1";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches an API endpoint.
|
* Fetches an API endpoint.
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
* @param {string} method HTTP method to use
|
* @param {string} method HTTP method to use
|
||||||
* @param {string} endpoint Relative endpoint to fetch
|
* @param {string} endpoint Relative endpoint to fetch
|
||||||
|
@ -15,254 +19,311 @@ const API_BASE = "https://cohost.org/api/v1";
|
||||||
* @param {boolean} [complex=false] Whether to return {headers, body}, or just the body
|
* @param {boolean} [complex=false] Whether to return {headers, body}, or just the body
|
||||||
* @returns Response, JSON parsed if parsable, string if not
|
* @returns Response, JSON parsed if parsable, string if not
|
||||||
*/
|
*/
|
||||||
async function fetch(method, endpoint, cookies = "", data, complex = false) {
|
async function fetch(
|
||||||
let url = API_BASE + endpoint + (method == "GET" && data ? "?" + new URLSearchParams(data).toString() : "");
|
method,
|
||||||
|
endpoint,
|
||||||
|
cookies = "",
|
||||||
|
data,
|
||||||
|
complex = false,
|
||||||
|
headers = {}
|
||||||
|
) {
|
||||||
|
let url =
|
||||||
|
API_BASE +
|
||||||
|
endpoint +
|
||||||
|
(method == "GET" && data ? "?" + new URLSearchParams(data).toString() : "");
|
||||||
|
|
||||||
let req = await _fetch(url, {
|
let req = await _fetch(url, {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
"Cookie": cookies
|
Cookie: cookies
|
||||||
},
|
},
|
||||||
body: (method != "GET" && data) ? JSON.stringify(data) : undefined
|
body: method != "GET" && data ? JSON.stringify(data) : undefined
|
||||||
});
|
});
|
||||||
|
|
||||||
let res = await req.text();
|
let res = await req.text();
|
||||||
try {
|
try {
|
||||||
res = JSON.parse(res);
|
res = JSON.parse(res);
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
if (req.status >= 400) {
|
if (req.status >= 400) {
|
||||||
throw JSON.stringify(res);
|
throw JSON.stringify(res);
|
||||||
|
} else {
|
||||||
|
if (complex) {
|
||||||
|
return {
|
||||||
|
headers: req.headers,
|
||||||
|
body: res
|
||||||
|
};
|
||||||
} else {
|
} else {
|
||||||
if (complex) {
|
return res;
|
||||||
return {
|
|
||||||
headers: req.headers,
|
|
||||||
body: res
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a cohost User (e.g. john.doe@gmail.com)
|
* Represents a cohost User (e.g. john.doe@gmail.com)
|
||||||
*/
|
*/
|
||||||
class User {
|
class User {
|
||||||
/**
|
/**
|
||||||
* Authenticates the User.
|
* Authenticates the User.
|
||||||
* This should always be called before using this instance or its references.
|
* This should always be called before using this instance or its references.
|
||||||
*
|
*
|
||||||
* @param {string} email E-mail address
|
* @param {string} email E-mail address
|
||||||
* @param {string} password Password
|
* @param {string} password Password
|
||||||
*/
|
*/
|
||||||
async login(email, password) {
|
async login(email, password) {
|
||||||
const { salt } = await fetch(
|
const { salt } = await fetch("GET", "/login/salt", undefined, { email });
|
||||||
"GET",
|
|
||||||
"/login/salt",
|
|
||||||
undefined,
|
|
||||||
{ email }
|
|
||||||
);
|
|
||||||
|
|
||||||
const hash = crypto.pbkdf2Sync(Buffer.from(password, "utf8"), decode(salt), 200000, 128, "sha384")
|
|
||||||
const clientHash = Buffer.from(hash).toString("base64");
|
|
||||||
|
|
||||||
const res = await fetch(
|
const hash = crypto.pbkdf2Sync(
|
||||||
"POST",
|
Buffer.from(password, "utf8"),
|
||||||
"/login",
|
decode(salt),
|
||||||
undefined,
|
200000,
|
||||||
{ email, clientHash },
|
128,
|
||||||
true
|
"sha384"
|
||||||
);
|
);
|
||||||
|
const clientHash = Buffer.from(hash).toString("base64");
|
||||||
|
|
||||||
this.sessionCookie = res.headers.get("set-cookie").split(";")[0];
|
const res = await fetch(
|
||||||
|
"POST",
|
||||||
|
"/login",
|
||||||
|
undefined,
|
||||||
|
{ email, clientHash },
|
||||||
|
true
|
||||||
|
);
|
||||||
|
|
||||||
this.userId = res.body.userId;
|
this.sessionCookie = res.headers.get("set-cookie").split(";")[0];
|
||||||
this.email = res.body.email;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
this.userId = res.body.userId;
|
||||||
* Get Projects the User has edit permissions on.
|
this.email = res.body.email;
|
||||||
*
|
}
|
||||||
* @returns {Project[]} User's projects
|
|
||||||
*/
|
|
||||||
async getProjects() {
|
|
||||||
return (await fetch(
|
|
||||||
"GET",
|
|
||||||
"/projects/edited",
|
|
||||||
this.sessionCookie
|
|
||||||
)).projects.map(x => new Project(this, x));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Notifications of the User. Docs TBD
|
* Get Projects the User has edit permissions on.
|
||||||
*/
|
*
|
||||||
async getNotifications(offset = 0, limit = 20) {
|
* @returns {Project[]} User's projects
|
||||||
return (await fetch(
|
*/
|
||||||
"GET",
|
async getProjects() {
|
||||||
"/notifications/list",
|
return (
|
||||||
this.sessionCookie,
|
await fetch("GET", "/projects/edited", this.sessionCookie)
|
||||||
{ offset, limit }
|
).projects.map(x => new Project(this, x));
|
||||||
))
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* Get Notifications of the User. Docs TBD
|
||||||
|
*/
|
||||||
|
async getNotifications(offset = 0, limit = 20) {
|
||||||
|
return await fetch("GET", "/notifications/list", this.sessionCookie, {
|
||||||
|
offset,
|
||||||
|
limit
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a cohost Project (e.g. @mog)
|
* Represents a cohost Project (e.g. @mog)
|
||||||
*/
|
*/
|
||||||
class Project {
|
class Project {
|
||||||
constructor(user, data) {
|
constructor(user, data) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.populate(data);
|
this.populate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Project. Docs TBD
|
* Creates a Project. Docs TBD
|
||||||
*/
|
*/
|
||||||
static async create(user, data) {
|
static async create(user, data) {
|
||||||
return await fetch(
|
return await fetch("POST", "/project", user.sessionCookie, data);
|
||||||
"POST",
|
}
|
||||||
"/project",
|
|
||||||
user.sessionCookie,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
populate(data) {
|
populate(data) {
|
||||||
this.id = data.projectId;
|
this.id = data.projectId;
|
||||||
this.handle = data.handle;
|
this.handle = data.handle;
|
||||||
this.displayName = data.displayName;
|
this.displayName = data.displayName;
|
||||||
this.dek = data.dek;
|
this.dek = data.dek;
|
||||||
this.description = data.description;
|
this.description = data.description;
|
||||||
this.avatarURL = data.avatarURL;
|
this.avatarURL = data.avatarURL;
|
||||||
this.headerURL = data.headerURL;
|
this.headerURL = data.headerURL;
|
||||||
this.privacy = data.privacy;
|
this.privacy = data.privacy;
|
||||||
this.pronouns = data.pronouns;
|
this.pronouns = data.pronouns;
|
||||||
this.url = data.url;
|
this.url = data.url;
|
||||||
this.flags = data.flags;
|
this.flags = data.flags;
|
||||||
this.avatarShape = data.avatarShape;
|
this.avatarShape = data.avatarShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number} [page=0] Page of posts to get, 20 posts per page
|
* @param {number} [page=0] Page of posts to get, 20 posts per page
|
||||||
* @returns {object[]}
|
* @returns {object[]}
|
||||||
*/
|
*/
|
||||||
async getPosts(page = 0) {
|
async getPosts(page = 0) {
|
||||||
let res = await fetch(
|
let res = await fetch(
|
||||||
"GET",
|
"GET",
|
||||||
`/project/${encodeURIComponent(this.handle)}/posts?page=${encodeURIComponent(page.toString())}`,
|
`/project/${encodeURIComponent(
|
||||||
this.user.sessionCookie
|
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
|
||||||
|
);
|
||||||
|
|
||||||
|
return await res;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a cohost Post
|
* Represents a cohost Post
|
||||||
*/
|
*/
|
||||||
class Post {
|
class Post {
|
||||||
constructor(user, data) {
|
constructor(user, data) {
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.populate(data);
|
this.populate(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostMarkdownBlock
|
* @typedef {Object} PostMarkdownBlock
|
||||||
* @property {string} content
|
* @property {string} content
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostAttachmentBlock
|
* @typedef {Object} PostAttachmentBlock
|
||||||
* @property {string} fileURL
|
* @property {string} fileURL
|
||||||
* @property {string} attachmentId
|
* @property {string} attachmentId
|
||||||
*/
|
* @property {string} altText
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostBlock
|
* @typedef {Object} PostBlock
|
||||||
* @property {string} type Type of block. Currently available: 'markdown' and 'attachment'
|
* @property {string} type Type of block. Currently available: 'markdown' and 'attachment'
|
||||||
* @property {PostMarkdownBlock} [markdown] Should only be present if type is 'markdown'
|
* @property {PostMarkdownBlock} [markdown] Should only be present if type is 'markdown'
|
||||||
* @property {PostAttachmentBlock} [attachment] Should only be present if type is 'attachment'
|
* @property {PostAttachmentBlock} [attachment] Should only be present if type is 'attachment'
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} PostCreate
|
* @typedef {Object} PostCreate
|
||||||
* @property {number} postState 1 for published, 0 for draft? or pending maybe?
|
* @property {number} postState 1 for published, 0 for draft
|
||||||
* @property {string} headline Headline
|
* @property {string} headline Headline
|
||||||
* @property {boolean} adultContent Does the post contain adult content?
|
* @property {boolean} adultContent Does the post contain adult content?
|
||||||
* @property {PostBlock[]} blocks Blocks (docs TBD)
|
* @property {PostBlock[]} blocks Blocks (docs TBD)
|
||||||
* @property {string[]} cws Content Warnings
|
* @property {string[]} cws Content Warnings
|
||||||
* @property {string[]} tags Tags (docs TBD)
|
* @property {string[]} tags Tags (docs TBD)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param {Project} project Project to post to
|
* @param {Project} project Project to post to
|
||||||
* @param {PostCreate} data
|
* @param {PostCreate} data
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
static async create(project, data) {
|
static async create(project, data) {
|
||||||
let { postId } = await fetch(
|
let { postId } = await fetch(
|
||||||
"POST",
|
"POST",
|
||||||
`/project/${encodeURIComponent(project.handle)}/posts`,
|
`/project/${encodeURIComponent(project.handle)}/posts`,
|
||||||
project.user.sessionCookie,
|
project.user.sessionCookie,
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
|
|
||||||
// return await Post.getById(project, postId);
|
return postId;
|
||||||
return postId;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Endpoint is disabled;
|
/** see {@link create} */
|
||||||
// static async getById(project, id) {
|
static async update(project, postId, data) {
|
||||||
// let data = await fetch(
|
await fetch(
|
||||||
// "GET",
|
"PUT",
|
||||||
// `/project_posts/${id}`,
|
`/project/${encodeURIComponent(project.handle)}/posts/${postId}`,
|
||||||
// project.user.sessionCookie
|
project.user.sessionCookie,
|
||||||
// );
|
data
|
||||||
|
);
|
||||||
|
|
||||||
// return new Post(user, data);
|
return postId;
|
||||||
// }
|
}
|
||||||
|
|
||||||
/**
|
// Endpoint is disabled;
|
||||||
* @private
|
// static async getById(project, id) {
|
||||||
*/
|
// let data = await fetch(
|
||||||
populate(data) {
|
// "GET",
|
||||||
this.id = data.postId;
|
// `/project_posts/${id}`,
|
||||||
this.headline = data.headline;
|
// project.user.sessionCookie
|
||||||
this.publishedAt = new Date(data.publishedAt);
|
// );
|
||||||
this.filename = data.filename;
|
|
||||||
this.transparentShareOfPostId = data.transparentShareOfPostId;
|
// return new Post(user, data);
|
||||||
this.state = data.state;
|
// }
|
||||||
this.numComments = data.numComments;
|
|
||||||
this.numSharedComments = data.numSharedComments;
|
/**
|
||||||
this.cws = data.cws;
|
* @private
|
||||||
this.tags = data.tags;
|
*/
|
||||||
this.blocks = data.blocks;
|
populate(data) {
|
||||||
this.plainTextBody = data.plainTextBody;
|
this.id = data.postId;
|
||||||
this.project = new Project(this.user, data.postingProject);
|
this.headline = data.headline;
|
||||||
this.shareTree = data.shareTree;
|
this.publishedAt = new Date(data.publishedAt);
|
||||||
this.relatedProjects = data.relatedProjects;
|
this.filename = data.filename;
|
||||||
this.effectiveAdultContent = data.effectiveAdultContent;
|
this.transparentShareOfPostId = data.transparentShareOfPostId;
|
||||||
this.isEditor = data.isEditor;
|
this.state = data.state;
|
||||||
this.contributorBlockIncomingOrOutgoing = data.contributorBlockIncomingOrOutgoing;
|
this.numComments = data.numComments;
|
||||||
this.hasAnyContributorMuted = data.hasAnyContributorMuted;
|
this.numSharedComments = data.numSharedComments;
|
||||||
this.isLiked = data.isLiked;
|
this.cws = data.cws;
|
||||||
this.canShare = data.canShare;
|
this.tags = data.tags;
|
||||||
this.canPublish = data.canPublish;
|
this.blocks = data.blocks;
|
||||||
this.singlePostPageUrl = data.singlePostPageUrl;
|
this.plainTextBody = data.plainTextBody;
|
||||||
this.renderInIframe = data.renderInIframe;
|
this.project = new Project(this.user, data.postingProject);
|
||||||
this.postPreviewIFrameUrl = data.postPreviewIFrameUrl;
|
this.shareTree = data.shareTree;
|
||||||
this.postEditUrl = data.postEditUrl;
|
this.relatedProjects = data.relatedProjects;
|
||||||
}
|
this.effectiveAdultContent = data.effectiveAdultContent;
|
||||||
|
this.isEditor = data.isEditor;
|
||||||
|
this.contributorBlockIncomingOrOutgoing =
|
||||||
|
data.contributorBlockIncomingOrOutgoing;
|
||||||
|
this.hasAnyContributorMuted = data.hasAnyContributorMuted;
|
||||||
|
this.isLiked = data.isLiked;
|
||||||
|
this.canShare = data.canShare;
|
||||||
|
this.canPublish = data.canPublish;
|
||||||
|
this.singlePostPageUrl = data.singlePostPageUrl;
|
||||||
|
this.renderInIframe = data.renderInIframe;
|
||||||
|
this.postPreviewIFrameUrl = data.postPreviewIFrameUrl;
|
||||||
|
this.postEditUrl = data.postEditUrl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
User,
|
User,
|
||||||
Project,
|
Project,
|
||||||
Post,
|
Post
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,28 +8,35 @@ for (var i = 0; i < chars.length; i++) {
|
||||||
|
|
||||||
function encode(arraybuffer) {
|
function encode(arraybuffer) {
|
||||||
var bytes = new Uint8Array(arraybuffer),
|
var bytes = new Uint8Array(arraybuffer),
|
||||||
i, len = bytes.length, base64 = "";
|
i,
|
||||||
|
len = bytes.length,
|
||||||
|
base64 = "";
|
||||||
|
|
||||||
for (i = 0; i < len; i+=3) {
|
for (i = 0; i < len; i += 3) {
|
||||||
base64 += chars[bytes[i] >> 2];
|
base64 += chars[bytes[i] >> 2];
|
||||||
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
base64 += chars[((bytes[i] & 3) << 4) | (bytes[i + 1] >> 4)];
|
||||||
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
base64 += chars[((bytes[i + 1] & 15) << 2) | (bytes[i + 2] >> 6)];
|
||||||
base64 += chars[bytes[i + 2] & 63];
|
base64 += chars[bytes[i + 2] & 63];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((len % 3) === 2) {
|
if (len % 3 === 2) {
|
||||||
base64 = base64.substring(0, base64.length - 1) + "=";
|
base64 = base64.substring(0, base64.length - 1) + "=";
|
||||||
} else if (len % 3 === 1) {
|
} else if (len % 3 === 1) {
|
||||||
base64 = base64.substring(0, base64.length - 2) + "==";
|
base64 = base64.substring(0, base64.length - 2) + "==";
|
||||||
}
|
}
|
||||||
|
|
||||||
return base64;
|
return base64;
|
||||||
};
|
}
|
||||||
|
|
||||||
function decode(base64) {
|
function decode(base64) {
|
||||||
var bufferLength = base64.length * 0.75,
|
var bufferLength = base64.length * 0.75,
|
||||||
len = base64.length, i, p = 0,
|
len = base64.length,
|
||||||
encoded1, encoded2, encoded3, encoded4;
|
i,
|
||||||
|
p = 0,
|
||||||
|
encoded1,
|
||||||
|
encoded2,
|
||||||
|
encoded3,
|
||||||
|
encoded4;
|
||||||
|
|
||||||
if (base64[base64.length - 1] === "=") {
|
if (base64[base64.length - 1] === "=") {
|
||||||
bufferLength--;
|
bufferLength--;
|
||||||
|
@ -39,13 +46,13 @@ function decode(base64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var arraybuffer = new ArrayBuffer(bufferLength),
|
var arraybuffer = new ArrayBuffer(bufferLength),
|
||||||
bytes = new Uint8Array(arraybuffer);
|
bytes = new Uint8Array(arraybuffer);
|
||||||
|
|
||||||
for (i = 0; i < len; i+=4) {
|
for (i = 0; i < len; i += 4) {
|
||||||
encoded1 = lookup[base64.charCodeAt(i)];
|
encoded1 = lookup[base64.charCodeAt(i)];
|
||||||
encoded2 = lookup[base64.charCodeAt(i+1)];
|
encoded2 = lookup[base64.charCodeAt(i + 1)];
|
||||||
encoded3 = lookup[base64.charCodeAt(i+2)];
|
encoded3 = lookup[base64.charCodeAt(i + 2)];
|
||||||
encoded4 = lookup[base64.charCodeAt(i+3)];
|
encoded4 = lookup[base64.charCodeAt(i + 3)];
|
||||||
|
|
||||||
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
bytes[p++] = (encoded1 << 2) | (encoded2 >> 4);
|
||||||
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
bytes[p++] = ((encoded2 & 15) << 4) | (encoded3 >> 2);
|
||||||
|
@ -53,6 +60,6 @@ function decode(base64) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return arraybuffer;
|
return arraybuffer;
|
||||||
};
|
}
|
||||||
|
|
||||||
module.exports = {encode, decode};
|
module.exports = { encode, decode };
|
||||||
|
|
|
@ -9,10 +9,12 @@
|
||||||
"version": "0.0.2",
|
"version": "0.0.2",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
|
"needle": "^3.1.0",
|
||||||
"node-fetch": "2"
|
"node-fetch": "2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"husky": "^8.0.1",
|
"husky": "^7.0.0",
|
||||||
"lint-staged": "^13.0.3",
|
"lint-staged": "^13.0.3",
|
||||||
"prettier": "^2.7.1"
|
"prettier": "^2.7.1"
|
||||||
}
|
}
|
||||||
|
@ -175,20 +177,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/debug": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "3.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ms": "2.1.2"
|
"ms": "^2.1.1"
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">=6.0"
|
|
||||||
},
|
|
||||||
"peerDependenciesMeta": {
|
|
||||||
"supports-color": {
|
|
||||||
"optional": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/eastasianwidth": {
|
"node_modules/eastasianwidth": {
|
||||||
|
@ -260,20 +253,31 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/husky": {
|
"node_modules/husky": {
|
||||||
"version": "8.0.1",
|
"version": "7.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz",
|
||||||
"integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
|
"integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"bin": {
|
"bin": {
|
||||||
"husky": "lib/bin.js"
|
"husky": "lib/bin.js"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=14"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/typicode"
|
"url": "https://github.com/sponsors/typicode"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/indent-string": {
|
"node_modules/indent-string": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||||
|
@ -361,6 +365,29 @@
|
||||||
"url": "https://opencollective.com/lint-staged"
|
"url": "https://opencollective.com/lint-staged"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/lint-staged/node_modules/debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"supports-color": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/lint-staged/node_modules/ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/listr2": {
|
"node_modules/listr2": {
|
||||||
"version": "4.0.5",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz",
|
||||||
|
@ -616,6 +643,25 @@
|
||||||
"node": ">=8.6"
|
"node": ">=8.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/mimic-fn": {
|
"node_modules/mimic-fn": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||||
|
@ -629,10 +675,25 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
"dev": true
|
},
|
||||||
|
"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": {
|
"node_modules/node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
|
@ -828,6 +889,16 @@
|
||||||
"tslib": "^2.1.0"
|
"tslib": "^2.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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/shebang-command": {
|
"node_modules/shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
@ -1197,12 +1268,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "4.3.4",
|
"version": "3.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.1.2"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eastasianwidth": {
|
"eastasianwidth": {
|
||||||
|
@ -1256,11 +1326,19 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"husky": {
|
"husky": {
|
||||||
"version": "8.0.1",
|
"version": "7.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/husky/-/husky-8.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz",
|
||||||
"integrity": "sha512-xs7/chUH/CKdOCs7Zy0Aev9e/dKOMZf3K1Az1nar3tzlv0jfqnYtu235bstsWTmXOR0EfINrPa97yy4Lz6RiKw==",
|
"integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
"indent-string": {
|
"indent-string": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
|
||||||
|
@ -1316,6 +1394,23 @@
|
||||||
"pidtree": "^0.6.0",
|
"pidtree": "^0.6.0",
|
||||||
"string-argv": "^0.3.1",
|
"string-argv": "^0.3.1",
|
||||||
"yaml": "^2.1.1"
|
"yaml": "^2.1.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"debug": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ms": "2.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"listr2": {
|
"listr2": {
|
||||||
|
@ -1503,6 +1598,19 @@
|
||||||
"picomatch": "^2.3.1"
|
"picomatch": "^2.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
},
|
||||||
"mimic-fn": {
|
"mimic-fn": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||||
|
@ -1510,10 +1618,19 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||||
"dev": true
|
},
|
||||||
|
"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": {
|
"node-fetch": {
|
||||||
"version": "2.6.7",
|
"version": "2.6.7",
|
||||||
|
@ -1636,6 +1753,16 @@
|
||||||
"tslib": "^2.1.0"
|
"tslib": "^2.1.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=="
|
||||||
|
},
|
||||||
"shebang-command": {
|
"shebang-command": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
"author": "mogery",
|
"author": "mogery",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"mime-types": "^2.1.35",
|
||||||
|
"needle": "^3.1.0",
|
||||||
"node-fetch": "2"
|
"node-fetch": "2"
|
||||||
},
|
},
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|
Loading…
Reference in New Issue