Baha imgur upload

add upload to imgur in bahamut

// ==UserScript==
// @name         Baha imgur upload
// @namespace    https://blog.maple3142.net/
// @version      0.7.4
// @description  add upload to imgur in bahamut
// @author       maple3142
// @match        https://*.gamer.com.tw/*
// @match        https://blog.maple3142.net/bahamut-imgur-upload.html
// @require      https://code.jquery.com/jquery-3.2.1.min.js
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

;(function($) {
	'use strict'
	/*
	 * ALBUM_TO_UPLOAD 是你想要上傳的目標相簿 id
	 * 例如相簿 https://imgur.com/a/C8763 的 id 是 C8763
	 * 請把他貼到 GM_getValue('ALBUM_TO_UPLOAD','') 後面的引號中,變成 GM_getValue('ALBUM_TO_UPLOAD','C8763')
	 * 這樣可以確保 id 不會在腳本更新後被清除,不過如果要修改的需要自己去腳本管理器的儲存空間修改
	 * Tampermonkey 直接在編輯頁面上面的 Storage 頁面修改就好,其他我就不知道了
	 */
	const ALBUM_TO_UPLOAD = GM_getValue('ALBUM_TO_UPLOAD', '')
	if (ALBUM_TO_UPLOAD) GM_setValue('ALBUM_TO_UPLOAD', ALBUM_TO_UPLOAD)

	const debounce = delay => fn => {
		let de = false
		return (...args) => {
			if (de) return
			de = true
			fn(...args)
			setTimeout(() => (de = false), delay)
		}
	}
	const qs = o =>
		Object.keys(o)
			.map(k => k + '=' + encodeURIComponent(o[k]))
			.join('&')
	const insertToRte = c => {
		// copy from utility_fx.js
		let a
		a = bahaRte.win.getSelection()
		a.getRangeAt &&
			a.rangeCount &&
			((a = a.getRangeAt(0)), a.deleteContents(), (c = a.createContextualFragment(c)), a.insertNode(c))
	}
	const insertUrlToField = url => {
		if (unsafeWindow.bahaRte != null) {
			// full rte editor
			const ht = $('<div>')
				.append($('<img>').attr('src', url))
				.html()
			insertToRte(ht)
		} else if ($('#balaTextId').length) {
			// guild/bala reply
			const id = $('#balaTextId')
				.html()
				.trim()
			const $tx = $('#' + id)
			$tx.val($tx.val() + url)
		} else if ($('#msgtalk').length) {
			// guild/bala new
			const $msgtalk = $('#msgtalk')
			$msgtalk.val($msgtalk.val() + url)
		} else if (
			typeof Forum !== 'undefined' &&
			typeof Forum.C !== 'undefined' &&
			typeof Forum.C.quills !== 'undefined'
		) {
			// quick reply
			const q = Forum.C.quills[0]
			const { index } = q.getSelection() || {}
			q.insertEmbed(index || 0, 'image', url)
		} else {
			//others
			prompt('暫時還不支援這種編輯器,不過可以複製下方的網址來貼上', url)
		}
	}
	unsafeWindow.balaInsertImage = () => (insertUrlToField($('#bhImgImageUrl').val()), egg.lightbox.close()) // polyfill original buggy image insert
	const isOldImgBoxChecked = i => $(`input[name=bhImgMode][value=${i}]`).prop('checked')
	if (location.hostname === 'blog.maple3142.net') {
		const access_token = /access_token=(.*?)&/.exec(location.hash)[1]
		if (access_token) {
			GM_setValue('access_token', access_token)
		}
	} else {
		if (typeof Dropzone !== 'undefined') {
			// hook dropzone instances
			Dropzone.instances = []
			const _Dropzone = Dropzone
			const Dropzone$ = function(...o) {
				const i = new _Dropzone(...o)
				_Dropzone.instances.push(i)
				return i
			}
			unsafeWindow.Dropzone = Object.assign(Dropzone$, _Dropzone)
		}
		const observer = new MutationObserver(
			debounce(10)(_ => {
				// new image box
				if ($('.tab-menu__item1.active').css('display') === 'block') {
					// 上傳圖片 tab1 打開了
					if ($('#imgur_uplbtn').length) return // ignore it if exists
					const $uplbtn = $('<button>')
						.addClass('btn')
						.addClass('btn-insert')
						.addClass('btn-primary')
						.addClass('unchecked')
						.attr('id', 'imgur_uplbtn')
						.text('imgur 模式: 停用')
					const $cancelbtn = $('.dialogify .btn:contains(取消)')
					$('.dialogify .btn.btn-insert.btn-primary').before($uplbtn)
					$uplbtn.on('click', e => {
						e.preventDefault()
						e.stopPropagation()
						if (!chk_isAuthorized()) {
							login()
							return
						}
						imgurEnable = !imgurEnable
						if (imgurEnable) $uplbtn.removeClass('unchecked').text('imgur 模式: 啟用')
						else $uplbtn.addClass('unchecked').text('imgur 模式: 停用')
					})
					// Dropzone handling
					let imgurEnable = false
					const dz = Dropzone.instances[Dropzone.instances.length - 1]
					if (dz.hooked) return
					dz.hooked = true
					dz.on('sending', (e, xhr, fd) => {
						if (imgurEnable) dzupload(xhr)
					})
					const originalcb = dz._callbacks.success[1]
					dz._callbacks.success[1] = (file, r) => {
						console.log('dz success', r, originalcb)
						if (r.token) {
							// normal baha file upload
							originalcb.apply(dz, [file, r])
						} else {
							$cancelbtn.click()
							insertUrlToField(r.data.link)
						}
					}

					document.onpaste = e => {
						const { items } = e.clipboardData
						for (let i = 0; i < items.length; i++) {
							// It doesn't have iterator protocol...
							const item = items[i]
							if (item.kind === 'file') {
								dz.addFile(item.getAsFile())
							}
						}
					}
				} else {
					$('#imgur_uplbtn').remove()
				}

				if ($('.tab-menu__item3.active').css('display') === 'block') {
					if ($('#imgur_urlcvt').length) return
					const $urlinput = $('#insertImageUrl')
					const $cvtbutton = $('<button>')
						.attr('id', 'imgur_urlcvt')
						.addClass('btn')
						.addClass('btn-primary')
						.text('轉換為 imgur 網址')
					$urlinput.after($cvtbutton)
					$cvtbutton.on('click', e => {
						e.preventDefault()
						if (!chk_isAuthorized()) {
							login()
							return
						}
						const url = $urlinput.val()
						if (!url) {
							alert('請輸入網址')
							return
						}
						$cvtbutton.text('圖片上傳中, 請稍候...').show()
						upload(url)
							.then(r => {
								$urlinput.val(r.data.link)
								$cvtbutton.text('轉換為 imgur 網址')
							})
							.catch(e => {
								console.error(e)
								alert('上傳失敗')
								$cvtbutton.text('轉換為 imgur 網址')
							})
					})
				} else {
					$('#bahaimgur_cvt').remove()
				}

				// old image box
				if (isOldImgBoxChecked(1) && !$('#imgurold_upl').length) {
					const $uplbtn = $('<button>')
						.text('上傳 imgur')
						.css('margin-left', '3px')
					const $uplfile = $('<input>')
						.attr('type', 'file')
						.width(220)
					const $wrap = $('<div>').attr('id', 'imgurold_upl')
					$('#bhImgModeUpload').append($wrap.append($uplfile).append($uplbtn))
					$uplbtn.on('click', e => {
						e.preventDefault()
						e.stopPropagation()
						if (!chk_isAuthorized()) {
							login()
							return
						}
						const file = $uplfile[0].files[0]
						if (!file) return //no file
						$uplbtn.text('上傳中...')
						upload(file)
							.then(r => {
								insertUrlToField(r.data.link)
								egg.lightbox.close()
							})
							.catch(e => {
								console.error(e)
								alert('上傳失敗')
								egg.lightbox.close()
							})
					})
				} else if (isOldImgBoxChecked(3) && !$('#imgurold_cvt').length) {
					const $urlinput = $('#bhImgImageUrl')
					const $cvtbutton = $('<button>')
						.text('轉換為 imgur 網址')
						.css('display', 'block')
						.attr('id', 'imgurold_cvt')
					$urlinput
						.after($cvtbutton)
						.parent()
						.css('display', 'flex')
						.css('flex-direction', 'column')
						.css('align-items', 'center')

					$cvtbutton.on('click', e => {
						e.preventDefault()
						if (!chk_isAuthorized()) {
							login()
							return
						}
						const url = $urlinput.val()
						if (!url) {
							alert('請輸入網址')
							return
						}
						$cvtbutton.text('圖片上傳中, 請稍候...').show()
						upload(url)
							.then(r => {
								$urlinput.val(r.data.link)
								$cvtbutton.text('轉換為 imgur 網址')
							})
							.catch(e => {
								console.error(e)
								alert('上傳失敗')
								$cvtbutton.text('轉換為 imgur 網址')
							})
					})
				}
			})
		)
		observer.observe(document.body, { attributes: true, childList: true, characterData: true, subtree: true })
	}
	function getInitialUploadData() {
		const data = new FormData()
		if (ALBUM_TO_UPLOAD) {
			data.append('album', ALBUM_TO_UPLOAD)
		}
		return data
	}
	function upload(image) {
		const data = getInitialUploadData()
		data.append('image', image)
		return fetch('https://api.imgur.com/3/image', {
			method: 'POST',
			credentials: 'omit',
			body: data,
			headers: {
				Authorization: `Bearer ${GM_getValue('access_token')}`
			}
		})
			.then(r => r.json())
			.then(r => {
				if (!r.success) throw new Error(r)
				return r
			})
	}
	function dzupload(xhr) {
		const data = getInitialUploadData()
		const fd$ = new Promise(res => {
			xhr._send = xhr.send
			xhr.send = res
		})
		return fd$.then(fd => {
			xhr.withCredentials = false
			xhr.open('POST', 'https://api.imgur.com/3/image')
			xhr.setRequestHeader('Authorization', `Bearer ${GM_getValue('access_token')}`)
			data.append('image', fd.get('dzfile'))
			xhr._send(data)
		})
	}
	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'
		)
	}
	const css = document.createElement('style')
	css.textContent = `.btn.unchecked{box-shadow: inset 0 1px 1px rgba(0,0,0,0.2);opacity:0.5;}`
	document.body.appendChild(css)
})(jQuery)