這是一個簡單的巴哈姆特 userscript
可以在上傳圖片的對話框中增加上傳到 imgur 的功能
發在場外的文章
腳本網址: https://greasyfork.org/zh-TW/scripts/36735-baha-imgur-upload
使用教學
其實就下面兩張 gif
圖片而已不過在第一次使用下面任何一個功能時會彈出一個視窗要求登入 imgur
的帳號並驗證
從電腦選取圖片上傳
把外部網址轉換成 imgur 網址
原理
基本上這個腳本的實作原理就是使用者登入後取得access_token
並將它保存下來然後上傳時用這個access_token
去向
api 伺服器上傳圖片完整的 code 可以到 greasyfork
上看
下面的 code 是 0.5 版的
取得 access_token
因為 imgur 在註冊 Application 時要提供一個 callback
網址所以我是直接把它放在 bahamut-imgur-upload.html
頁面上然後用 javascript 把access_token
從網址中取出
網址格式:
1
| https://blog.maple3142.net/bahamut-imgur-upload.html#access_token=${access_token}&expires_in=aaa&token_type=bbb&refresh_token=ccc&account_username=ddd&account_id=eee
|
這裡面重要的只有access_token
欄位,不過特別的是 query
string 不知道為什麼會被放在 hashbang 之後所以就用 regex
把access_token
給取出來,然後存在腳本的儲存空間中
1 2 3 4 5 6 7 8
|
if (location.hostname === 'blog.maple3142.net') { const access_token = /access_token=(.*?)&/.exec(location.hash)[1] if (access_token) { GM_setValue('access_token', access_token) } }
|
helpers
上傳
上傳的部分直接寫成一個函數來用,回傳一個Promise
data
部分只放一個 image 是因為 imgur 能自己判斷 image 是 base64 還是網址而
catch 的部分先寫好是因為外面的錯誤處理都是 alert 然後把上傳視窗關閉
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function upload(image) { return $.ajax({ type: 'POST', url: 'https://api.imgur.com/3/image', data: { image }, headers: { Authorization: `Bearer ${GM_getValue('access_token')}` }, dataType: 'json' }).catch(e => { console.error(e) alert('上傳失敗') egg.lightbox.close() }) }
|
其他
這邊是另外 3 個簡單的輔助函數
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function chk_isAuthorized() { return GM_getValue('access_token', null) !== null } function login() { window.open( 'https://api.imgur.com/oauth2/authorize?client_id=41e93183c27ec0e&response_type=token', 'oauth', 'height=700,width=700' ) } function readbase64(file) { return new Promise((res, rej) => { const reader = new FileReader() reader.onload = e => res(e.target.result) reader.onerror = err => rej(err) reader.readAsDataURL(file) }) }
|
UI 和主要邏輯
UI 部分稍微麻煩了一些,因為上傳框並不是本來就存在的,是用 js
生成出來的所以只好用MutationObserver
來監聽 DOM 的變化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const observer = new MutationObserver(_ => { const $origUpl = $('#bhImgModeUpload') if ($origUpl.css('display') === 'block') { } else { $('#bahaimgur').remove() }
const $origUrlinput = $('#bhImgModeInsertUrl') if ($origUrlinput.css('display') === 'block') { } else { $('#bahaimgur_cvt').remove() } }) observer.observe(document.body, { attributes: true, childList: true, characterData: true, subtree: true })
|
#bahaimgur
這是上面 observer 裡面第一個 if 的內容
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
| if ($('#imgurupl').length) return $origUpl.after(` <div id="bahaimgur"> <input type="file" accept="image/*" id="imgurupl"> <button id="imguruplbtn">上傳imgur</button> </div> `) $('#imguruplbtn').on('click', e => { e.preventDefault() e.stopPropagation() if (!chk_isAuthorized()) { login() return } const file = $('#imgurupl')[0].files[0] if (!file) return
readbase64(file) .then(image => { $('#bahaimgur').hide(), $('#bhImgMsg') .html('圖片上傳中, 請稍候...') .show(), $('#bhImgModeUpload').hide() return upload(image.split('base64,')[1]) }) .then(r => { if (!r.success) { alert('上傳失敗') egg.lightbox.close() return } if (unsafeWindow.bahaRte != null) { bahaRte.toolbar.insertUploadedImage(r.data.link) } else if ($('#balaTextId').length) { const id = $('#balaTextId').html() const $tx = $('#' + id) $tx.val($tx.val() + r.data.link) egg.lightbox.close() } else if ($('#msgtalk').length) { egg.lightbox.close() const $msgtalk = $('#msgtalk') $msgtalk.val($msgtalk.val() + r.data.link) } else { prompt('暫時還不支援這種編輯器,不過可以複製下方的網址來貼上', r.data.link) $('#bhImgMsg').hide() $('#bhImgModeUpload').show() $('#bahaimgur').show() } }) })
|
#bahaimgur_cvt
這和上面的也有點類似,不過更簡單一些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| if ($('#bahaimgur_cvt').length) return $('#bhImgImageUrl').after(`<button id="bahaimgur_cvt">轉換成imgur網址</button>`)
$('#bahaimgur_cvt').on('click', e => { e.preventDefault()
if (!chk_isAuthorized()) { login() return } const url = $('#bhImgImageUrl').val() if (!url) { alert('請輸入網址') return } $('#bhImgMsg') .html('圖片上傳中, 請稍候...') .show() upload(url).then(r => { if (!r.success) { alert('上傳失敗') egg.lightbox.close() return } $('#bhImgImageUrl').val(r.data.link) $('#bhImgMsg').hide() }) })
|