import { IPicGo , IPluginConfig , IUpyunConfig } from '../../types' ; import crypto from 'crypto' ; import MD5 from 'md5' ; import { Options } from 'request-promise-native' ; import { IBuildInEvent } from '../../utils/enum' ; const generateSignature = ( options , fileName ) : string => { const path = options . path || '' ; const operator = options . operator ; const password = options . password ; const md5Password = MD5 ( password ) ; const date = new Date ( ) . toUTCString ( ) ; const uri = `/${ options . bucket }/${ encodeURI ( path ) }${ encodeURI ( fileName ) }` ; const value = `PUT&${ uri }&${ date }` ; const sign = crypto . createHmac ( 'sha1' , md5Password ) . update ( value ) . digest ( 'base64' ) ; return `UPYUN ${ operator }:${ sign }` ; } ; const postOptions = ( options , fileName , signature , image ) : Options => { const bucket = options . bucket ; const path = options . path || '' ; return { method : 'PUT' , url : `https://v0.api.upyun.com/${ bucket }/${ encodeURI ( path ) }${ encodeURI ( fileName ) }` , headers : { Authorization : signature , Date : new Date ( ) . toUTCString ( ) } , body : image , resolveWithFullResponse : true } ; } ; const handle = async ( ctx ) : Promise < IPicGo > => { const upyunOptions = ctx . getConfig < IUpyunConfig > ( 'picBed.upyun' ) ; if ( ! upyunOptions ) { throw new Error ( 'Can\'t find upYun config' ) ; } try { const imgList = ctx . output ; const path = upyunOptions . path || '' ; for ( const img of imgList ) { if ( img . fileName && img . buffer ) { let image = img . buffer ; if ( ! image && img . base64Image ) { image = Buffer . from ( img . base64Image , 'base64' ) ; } const signature = generateSignature ( upyunOptions , img . fileName ) ; const options = postOptions ( upyunOptions , img . fileName , signature , image ) ; const body = await ctx . Request . request ( options ) ; if ( body . statusCode === 200 ) { delete img . base64Image ; delete img . buffer ; img . imgUrl = `${ upyunOptions . url }/${ path }${ img . fileName }${ upyunOptions . options }` ; } else { throw new Error ( 'Upload failed' ) ; } } } return ctx ; } catch ( err ) { if ( err . message === 'Upload failed' ) { ctx . emit ( IBuildInEvent . NOTIFICATION , { title : '上传失败' , body : '请检查你的配置项是否正确' } ) ; } else { const body = JSON . parse ( err . error ) ; ctx . emit ( IBuildInEvent . NOTIFICATION , { title : '上传失败' , body : `错误码：${ body . code as string }，请打开浏览器粘贴地址查看相关原因` , text : 'http://docs.upyun.com/api/errno/' } ) ; } throw err ; } } ; const config = ( ctx ) : IPluginConfig [ ] => { const userConfig = ctx . getConfig < IUpyunConfig > ( 'picBed.upyun' ) || { } ; const config = [ { name : 'bucket' , type : 'input' , default : userConfig . bucket || '' , required : true } , { name : 'operator' , type : 'input' , default : userConfig . operator || '' , required : true } , { name : 'password' , type : 'password' , default : userConfig . password || '' , required : true } , { name : 'url' , type : 'input' , default : userConfig . url || '' , required : true } , { name : 'options' , type : 'input' , default : userConfig . options || '' , required : true } , { name : 'path' , type : 'input' , default : userConfig . path || '' , required : false } ] ; return config ; } ; export default { name : '又拍云图床' , handle , config } ;