Skip to content

Commit 474945f

Browse files
committed
feat: 🎸 support pull from github
1 parent e9133b6 commit 474945f

3 files changed

Lines changed: 146 additions & 103 deletions

File tree

‎index.ts‎

Lines changed: 86 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,24 @@ import { Notification } from 'electron'
33
import { getIns } from './lib/octokit'
44
import { PluginConfig } from 'picgo/dist/utils/interfaces'
55
import { getNow, zip, unzip } from './lib/helper'
6-
import { ImgType, PluginConfig as PlusConfig } from './lib/interface'
6+
import {
7+
ImgType,
8+
PluginConfig as PlusConfig,
9+
ImgZipType
10+
} from './lib/interface'
711
const PluginName = 'picgo-plugin-github-plus'
812
const UploaderName = 'githubPlus'
13+
14+
function initOcto (ctx: picgo) {
15+
const options: PlusConfig = ctx.getConfig('picBed.githubPlus')
16+
if (!options) {
17+
throw new Error("Can't find github-plus config")
18+
}
19+
const ins = getIns(options)
20+
ins.authenticate()
21+
return ins
22+
}
23+
924
function notic (title, body?: string) {
1025
const notification = new Notification({
1126
title: 'GithubPlus: ' + title,
@@ -14,75 +29,83 @@ function notic (title, body?: string) {
1429
notification.show()
1530
}
1631

17-
const guiMenu = (ctx: picgo) => {
18-
return [
19-
{
20-
label: 'Sync github',
21-
async handle (ctx: picgo) {
22-
const options: PlusConfig = ctx.getConfig('picBed.githubPlus')
23-
if (!options) {
24-
throw new Error("Can't find github-plus config")
25-
}
26-
notic('Sync...')
27-
const octokit = getIns(options)
28-
octokit.authenticate()
29-
const githubDataJson = await octokit.getDataJson().catch(e => {
30-
notic('Error in load dataJson', e.message)
31-
throw e
32-
})
33-
const uploaded: ImgType[] = ctx.getConfig('uploaded')
34-
const localDataJson = {
35-
data: uploaded.filter(each => each.type === UploaderName).map(zip),
36-
lastSync: (ctx.getConfig(PluginName) || {}).lastSync
37-
}
38-
const { sha, lastSync, data } = githubDataJson
39-
if (localDataJson.lastSync > lastSync) {
40-
try {
41-
if (sha) {
42-
await octokit.updateDataJson({
43-
data: localDataJson,
44-
sha
45-
})
46-
} else {
47-
await octokit.createDataJson(localDataJson)
48-
}
49-
} catch (e) {
50-
notic('Error in sync github', e.message)
51-
throw e
52-
}
53-
} else {
54-
const newUploaded = data
55-
.map(each => {
56-
const obj = unzip(each)
57-
return {
58-
...obj,
59-
type: UploaderName,
60-
imgUrl: octokit.parseUrl(obj.fileName)
61-
}
62-
})
63-
.concat(uploaded.filter(each => each.type !== UploaderName))
64-
ctx.saveConfig({
65-
uploaded: newUploaded,
66-
[PluginName]: {
67-
lastSync
68-
}
32+
const SyncGithubMenu = {
33+
label: 'Sync github',
34+
async handle (ctx: picgo) {
35+
const octokit = initOcto(ctx)
36+
notic('Sync...')
37+
const githubDataJson = await octokit.getDataJson().catch(e => {
38+
notic('Error in load dataJson', e.message)
39+
throw e
40+
})
41+
const uploaded: ImgType[] = ctx.getConfig('uploaded')
42+
const localDataJson = {
43+
data: uploaded.filter(each => each.type === UploaderName).map(zip),
44+
lastSync: (ctx.getConfig(PluginName) || {}).lastSync
45+
}
46+
const { sha, lastSync, data } = githubDataJson
47+
if (localDataJson.lastSync > lastSync) {
48+
try {
49+
if (sha) {
50+
await octokit.updateDataJson({
51+
data: localDataJson,
52+
sha
6953
})
54+
} else {
55+
await octokit.createDataJson(localDataJson)
7056
}
71-
notic('Symc succeed', 'Succeed to sync github')
57+
} catch (e) {
58+
notic('Error in sync github', e.message)
59+
throw e
7260
}
61+
} else {
62+
const newUploaded = data
63+
.map(each => {
64+
const obj = unzip(each)
65+
return {
66+
...obj,
67+
type: UploaderName,
68+
imgUrl: octokit.parseUrl(obj.fileName)
69+
}
70+
})
71+
.concat(uploaded.filter(each => each.type !== UploaderName))
72+
ctx.saveConfig({
73+
uploaded: newUploaded,
74+
[PluginName]: {
75+
lastSync
76+
}
77+
})
7378
}
74-
]
79+
notic('Sync succeed', 'Succeed to sync github')
80+
}
81+
}
82+
83+
const PullGithubMenu = {
84+
label: 'Pull github',
85+
handle: async (ctx: picgo) => {
86+
const octokit = initOcto(ctx)
87+
notic('Pull...')
88+
const { tree } = await octokit.getPathTree()
89+
// TODO: transform github obj to imgType
90+
const imgList: ImgType[] = tree
91+
.filter(each => /\.(jpg|png)$/.test(each.path))
92+
.map(each => {
93+
return unzip({
94+
f: each.path,
95+
id: each.sha
96+
})
97+
})
98+
// const tree =
99+
}
100+
}
101+
102+
const guiMenu = () => {
103+
return [SyncGithubMenu, PullGithubMenu]
75104
}
76105

77106
const handle = async (ctx: picgo) => {
78-
const options: PlusConfig = ctx.getConfig('picBed.githubPlus')
79107
let output = ctx.output
80-
// do something for uploading
81-
if (!options) {
82-
throw new Error("Can't find github-plus config")
83-
}
84-
const octokit = getIns(options)
85-
octokit.authenticate()
108+
const octokit = initOcto(ctx)
86109
for (let i in output) {
87110
try {
88111
const img = output[i]
@@ -110,12 +133,7 @@ async function onRemove (files: ImgType[]) {
110133
const rms = files.filter(each => each.type === UploaderName)
111134
if (rms.length === 0) return
112135
const self: picgo = this
113-
const options: PlusConfig = self.getConfig('picBed.githubPlus')
114-
if (!options) {
115-
notic('Error', "Can't find github-plus config")
116-
return
117-
}
118-
const ins = getIns(options)
136+
const ins = initOcto(self)
119137
ins.authenticate()
120138
const fail = []
121139
for (let i = 0; i < rms.length; i++) {

‎lib/interface.ts‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ export type ImgType = {
1010
fileName: string;
1111
extname: string;
1212
imgUrl: string;
13-
width: number;
14-
height: number;
13+
width?: number;
14+
height?: number;
1515
type: string;
1616
id: string;
1717
sha?: string
1818
}
1919

2020
export type ImgZipType = {
2121
f: string,
22-
w: number,
23-
h: number,
22+
w?: number,
23+
h?: number,
2424
id: string,
2525
s?: string
2626
}

‎lib/octokit.ts‎

Lines changed: 56 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@ class Octo {
1414
token: string = ''
1515
customUrl: string = ''
1616
octokit = new Octokit()
17-
constructor ({ repo, branch, path = '', token, customUrl = '' }: PluginConfig) {
18-
const [ owner, r ] = repo.split('/')
17+
constructor ({
18+
repo,
19+
branch,
20+
path = '',
21+
token,
22+
customUrl = ''
23+
}: PluginConfig) {
24+
const [owner, r] = repo.split('/')
1925
if (!r) throw new Error('Error in repo name')
2026
this.owner = owner
2127
this.repo = r
@@ -31,46 +37,41 @@ class Octo {
3137
})
3238
}
3339

34-
updateDataJson ({ data, sha }) {
35-
const { owner, repo, branch } = this
36-
return this.octokit.repos.updateFile({
40+
async getTree (sha): Promise<{ path: string; sha: string }[]> {
41+
const { owner, repo } = this
42+
const d = await this.octokit.git.getTree({
3743
owner,
38-
branch,
3944
repo,
40-
path: 'data.json',
41-
sha,
42-
message: `Sync dataJson by PicGo at ${getNow()}`,
43-
content: Buffer.from(JSON.stringify(data)).toString('base64')
45+
tree_sha: sha
4446
})
47+
const { tree } = d.data
48+
return tree
4549
}
46-
createDataJson (data) {
47-
const { owner, repo, branch } = this
48-
return this.octokit.repos.createFile({
49-
owner,
50-
repo,
51-
branch,
52-
path: 'data.json',
53-
message: `Sync dataJson by PicGo at ${getNow()}`,
54-
content: Buffer.from(JSON.stringify(data)).toString('base64')
55-
})
50+
async getPathTree (): Promise<{ sha: string; tree: any[] }> {
51+
const { path } = this
52+
let tree = await this.getTree(this.branch)
53+
const arr = path.split('/').filter(each => each)
54+
let sha = this.branch
55+
for (let i = 0; i < arr.length; i++) {
56+
const item = tree.filter(each => arr[i].endsWith(each.path))[0]
57+
if (!item) return Promise.reject(new Error(`Can\'t find ${path}`))
58+
sha = item.sha
59+
tree = await this.getTree(sha)
60+
}
61+
return { sha, tree }
5662
}
57-
5863
async getDataJson (): Promise<{
5964
lastSync: string;
6065
data: any[];
6166
sha?: string;
6267
}> {
63-
const { owner, repo, branch } = this
68+
const { owner, repo } = this
6469
const defaultRet = {
6570
lastSync: '',
6671
data: []
6772
}
68-
const d = await this.octokit.git.getTree({
69-
owner,
70-
repo,
71-
tree_sha: branch
72-
})
73-
const dataJson = d.data.tree.filter(each => each.path === 'data.json')[0]
73+
const { tree } = await this.getPathTree()
74+
const dataJson = tree.filter(each => each.path === 'data.json')[0]
7475
if (dataJson) {
7576
let content = await this.octokit.git.getBlob({
7677
owner,
@@ -87,7 +88,29 @@ class Octo {
8788
}
8889
return defaultRet
8990
}
90-
91+
updateDataJson ({ data, sha }) {
92+
const { owner, repo, branch, path } = this
93+
return this.octokit.repos.updateFile({
94+
owner,
95+
branch,
96+
repo,
97+
path: join(path, 'data.json'),
98+
sha,
99+
message: `Sync dataJson by PicGo at ${getNow()}`,
100+
content: Buffer.from(JSON.stringify(data)).toString('base64')
101+
})
102+
}
103+
createDataJson (data) {
104+
const { owner, repo, branch, path } = this
105+
return this.octokit.repos.createFile({
106+
owner,
107+
repo,
108+
branch,
109+
path: join(path, 'data.json'),
110+
message: `Sync dataJson by PicGo at ${getNow()}`,
111+
content: Buffer.from(JSON.stringify(data)).toString('base64')
112+
})
113+
}
91114
async upload (img: ImgInfo) {
92115
const { owner, repo, branch, path = '' } = this
93116
const { fileName } = img
@@ -110,8 +133,10 @@ class Octo {
110133
removeFile (img: ImgType) {
111134
const { repo, path, owner, branch } = this
112135
return this.octokit.repos.deleteFile({
113-
repo,owner, branch,
114-
path: path + img.fileName,
136+
repo,
137+
owner,
138+
branch,
139+
path: join(path, img.fileName),
115140
message: `Deleted ${img.fileName} by PicGo - ${getNow()}`,
116141
sha: img.sha
117142
})

0 commit comments

Comments
 (0)