UNPKG

picgo-plugin-gitee-uploader

Version:
282 lines (273 loc) 7.96 kB
import picgo from 'picgo' import { getNow, getPath } from './helper' import { PluginConfig, ImgType } from './interface' import urlJoin from 'url-join' import { ImgInfo } from 'picgo/dist/utils/interfaces' export class Octo { username: string = '' password: string = '' clientId: string = '' clientSecret: string = '' owner: string = '' repo: string = '' branch: string = '' path: string = '' token: string = '' customUrl: string = '' ctx: picgo baseUrl = 'https://gitee.com/api/v5' constructor({ repo, branch, path = '', token, customPath = '', customUrl = '' }: PluginConfig, ctx: picgo) { const [owner, r] = repo.split('/') if (!r) throw new Error('Error in repo name') this.owner = owner this.repo = r this.branch = branch || 'master' this.token = token this.customUrl = customUrl this.ctx = ctx this.path = getPath(path, customPath) } async getTree(sha): Promise<{ path: string; sha: string }[]> { const url = urlJoin( this.baseUrl, 'repos', this.owner, this.repo, 'git/gitee/trees', sha ) // this.ctx.log.info('url:' + url) let params = { method: 'GET', json: true, resolveWithFullResponse: true, url: url, qs: { access_token: this.token } } let result = await this.ctx.Request.request(params) // this.ctx.log.info('getTree result') // this.ctx.log.info(JSON.stringify(result.body)) if (result && result.statusCode === 200) { const { tree } = result.body return tree } else { this.ctx.log.error('getTree error') this.ctx.log.error(JSON.stringify(result)) throw result } } async getPathTree(): Promise<{ sha: string; tree: any[] }> { const { path } = this let tree = await this.getTree(this.branch) const arr = path.split('/').filter(each => each) let sha = this.branch for (let i = 0; i < arr.length; i++) { const item = tree.filter(each => arr[i].endsWith(each.path))[0] if (!item) return Promise.reject(new Error(`Can\'t find ${path}`)) sha = item.sha tree = await this.getTree(sha) } return { sha, tree } } async getDataJson(): Promise<{ lastSync: string, data: any[], sha?: string }> { const defaultRet = { lastSync: '', data: [] } const { tree } = await this.getPathTree() /* this.ctx.log.info('tree info') tree.forEach(element => { this.ctx.log.info(JSON.stringify(element)) }) */ const dataJson = tree.filter(each => each.path === 'data.json')[0] // this.ctx.log.info('dataJson info') // this.ctx.log.info(JSON.stringify(dataJson)) if (dataJson) { const url = urlJoin( this.baseUrl, 'repos', this.owner, this.repo, 'git/blobs', dataJson.sha ) // this.ctx.log.info('url:' + url) const params = { method: 'GET', json: true, resolveWithFullResponse: true, url: url, qs: { access_token: this.token } } let result = await this.ctx.Request.request(params) // this.ctx.log.info('getBlob result') // this.ctx.log.info(JSON.stringify(result.body)) if (result && result.statusCode === 200) { const buf = Buffer.from(result.body.content, result.body.encoding) const json = JSON.parse(buf.toString()) return { ...defaultRet, ...json, sha: dataJson.sha } } else { this.ctx.log.error('getBlob error') this.ctx.log.error(JSON.stringify(result)) throw result } } return defaultRet } async updateDataJson({ data, sha }) { const fileName = 'data.json' const url = this.fileOptions(fileName) // this.ctx.log.info('updateDataJson url:' + url) const params = this.uploadOptions(url, 'PUT', Buffer.from(JSON.stringify(data)).toString('base64'), `Sync dataJson by PicGo at ${getNow()}`) params.formData['sha'] = sha // this.ctx.log.info(JSON.stringify(params)) let result = await this.ctx.Request.request(params) // this.ctx.log.info('sync update data.json') // this.ctx.log.info(JSON.stringify(result)) if (result && result.statusCode === 200) { return true } else { this.ctx.log.error('sync update data.json error') this.ctx.log.error(JSON.stringify(result)) throw result } } async createDataJson(data) { const fileName = 'data.json' const url = this.fileOptions(fileName) // this.ctx.log.info('createDataJson url:' + url) const params = this.uploadOptions(url, 'POST', Buffer.from(JSON.stringify(data)).toString('base64'), `Sync dataJson by PicGo at ${getNow()}`) let result = await this.ctx.Request.request(params) /* this.ctx.log.info('sync data.json') this.ctx.log.info(JSON.stringify(result)) */ if (result && result.statusCode === 201) { return true } else { this.ctx.log.error('sync data.json error') this.ctx.log.error(JSON.stringify(result)) throw result } } async upload(img: ImgInfo) { // 取出对象中同名的属性并赋值,神奇的写法,可以取出多个 const { fileName } = img const url = this.fileOptions(fileName) // this.ctx.log.info('url:' + url) const params = this.uploadOptions(url, 'POST', img.base64Image || Buffer.from(img.buffer).toString('base64'), `Upload ${fileName} by picGo - ${getNow()}`); let result = await this.ctx.Request.request(params) /* this.ctx.log.info('upload result') this.ctx.log.info(JSON.stringify(result)) */ if (result && result.statusCode === 201) { return { // result.body.content.download_url imgUrl: this.parseUrl(result.body.content.name), sha: result.body.content.sha } } else { this.ctx.log.error('upload error') this.ctx.log.error(JSON.stringify(result)) throw result } } async removeFile(img: ImgType) { const ctx = this.ctx const url = this.fileOptions(img.fileName) const params = { method: 'DELETE', json: true, resolveWithFullResponse: true, url: url, qs: { access_token: this.token, sha: img.sha, message: `Deleted ${img.fileName} by picGo - ${getNow()}`, branch: this.branch } } let result = await this.ctx.Request.request(params) /* this.ctx.log.info('Deleted result') this.ctx.log.info(JSON.stringify(result)) */ if (result && result.statusCode === 200) { return true } else { this.ctx.log.error('deleted error') this.ctx.log.error(JSON.stringify(result)) return result } } uploadOptions = function (url, method, content, msg) { return { method: method, json: true, resolveWithFullResponse: true, url: url, formData: { access_token: this.token, content: content, message: msg, branch: this.branch } } } fileOptions = function (fileName) { return encodeURI(urlJoin( this.baseUrl, 'repos', this.owner, this.repo, 'contents', this.path, fileName )) } parseUrl(fileName) { const { owner, repo, path, customUrl, branch } = this if (customUrl) { return urlJoin(customUrl, path, fileName) } return urlJoin( `https://gitee.com/`, owner, repo, 'raw', branch, path, fileName ) } } let ins: Octo = null let _cacheOption: string = '' export function getIns(config: PluginConfig, ctx: picgo): Octo { const str = JSON.stringify(config) if (ins && _cacheOption === str) return ins _cacheOption = str ins = new Octo(config, ctx) return ins } /* istanbul ignore next */ export function clearIns() { // just for test ins = null }