From 7565a48b941c0d2237b0c90a4e0e906b5581e161 Mon Sep 17 00:00:00 2001 From: 8cy <50817549+8cy@users.noreply.github.com> Date: Sat, 23 May 2020 02:25:46 -0700 Subject: DARLING in the FRANXX --- .gitattributes | 2 + .vscode/settings.json | 5 + README.md | 1 + axios.min.js | 3 + background.js | 602 ++++++++++++++++++++++++++++++++++++++++++++++++ backup/logo-128x128.png | Bin 0 -> 35419 bytes backup/logo-48x48.png | Bin 0 -> 24050 bytes backup/logo.png | Bin 0 -> 59261 bytes content.css | 21 ++ content.js | 111 +++++++++ logo-128x128.png | Bin 0 -> 17342 bytes logo-48x48.png | Bin 0 -> 3857 bytes logo.png | Bin 0 -> 43010 bytes manifest.json | 36 +++ settings.html | 103 +++++++++ settings.js | 42 ++++ 16 files changed, 926 insertions(+) create mode 100644 .gitattributes create mode 100644 .vscode/settings.json create mode 100644 README.md create mode 100644 axios.min.js create mode 100644 background.js create mode 100644 backup/logo-128x128.png create mode 100644 backup/logo-48x48.png create mode 100644 backup/logo.png create mode 100644 content.css create mode 100644 content.js create mode 100644 logo-128x128.png create mode 100644 logo-48x48.png create mode 100644 logo.png create mode 100644 manifest.json create mode 100644 settings.html create mode 100644 settings.js diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfe0770 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +# Auto detect text files and perform LF normalization +* text=auto diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..da0a6e6 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "strelizia" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..3a6bc5d --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# strelizia-extension \ No newline at end of file diff --git a/axios.min.js b/axios.min.js new file mode 100644 index 0000000..6dfa1da --- /dev/null +++ b/axios.min.js @@ -0,0 +1,3 @@ +/* axios v0.15.3 | (c) 2016 by Matt Zabriskie */ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(5),u=r(a);u.Axios=i,u.create=function(e){return r(o.merge(a,e))},u.Cancel=n(22),u.CancelToken=n(23),u.isCancel=n(19),u.all=function(e){return Promise.all(e)},u.spread=n(24),e.exports=u,e.exports.default=u},function(e,t,n){"use strict";function r(e){return"[object Array]"===C.call(e)}function o(e){return"[object ArrayBuffer]"===C.call(e)}function s(e){return"undefined"!=typeof FormData&&e instanceof FormData}function i(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function a(e){return"string"==typeof e}function u(e){return"number"==typeof e}function c(e){return"undefined"==typeof e}function f(e){return null!==e&&"object"==typeof e}function p(e){return"[object Date]"===C.call(e)}function d(e){return"[object File]"===C.call(e)}function l(e){return"[object Blob]"===C.call(e)}function h(e){return"[object Function]"===C.call(e)}function m(e){return f(e)&&h(e.pipe)}function y(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function w(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function g(){return"undefined"!=typeof window&&"undefined"!=typeof document&&"function"==typeof document.createElement}function v(e,t){if(null!==e&&"undefined"!=typeof e)if("object"==typeof e||r(e)||(e=[e]),r(e))for(var n=0,o=e.length;n=200&&e<300}};c.headers={common:{Accept:"application/json, text/plain, */*"}},s.forEach(["delete","get","head"],function(e){c.headers[e]={}}),s.forEach(["post","put","patch"],function(e){c.headers[e]=s.merge(u)}),e.exports=c},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t){r.forEach(e,function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])})}},function(e,t,n){"use strict";var r=n(2),o=n(8),s=n(11),i=n(12),a=n(13),u=n(9),c="undefined"!=typeof window&&window.btoa&&window.btoa.bind(window)||n(14);e.exports=function(e){return new Promise(function(t,f){var p=e.data,d=e.headers;r.isFormData(p)&&delete d["Content-Type"];var l=new XMLHttpRequest,h="onreadystatechange",m=!1;if("undefined"==typeof window||!window.XDomainRequest||"withCredentials"in l||a(e.url)||(l=new window.XDomainRequest,h="onload",m=!0,l.onprogress=function(){},l.ontimeout=function(){}),e.auth){var y=e.auth.username||"",w=e.auth.password||"";d.Authorization="Basic "+c(y+":"+w)}if(l.open(e.method.toUpperCase(),s(e.url,e.params,e.paramsSerializer),!0),l.timeout=e.timeout,l[h]=function(){if(l&&(4===l.readyState||m)&&(0!==l.status||l.responseURL&&0===l.responseURL.indexOf("file:"))){var n="getAllResponseHeaders"in l?i(l.getAllResponseHeaders()):null,r=e.responseType&&"text"!==e.responseType?l.response:l.responseText,s={data:r,status:1223===l.status?204:l.status,statusText:1223===l.status?"No Content":l.statusText,headers:n,config:e,request:l};o(t,f,s),l=null}},l.onerror=function(){f(u("Network Error",e)),l=null},l.ontimeout=function(){f(u("timeout of "+e.timeout+"ms exceeded",e,"ECONNABORTED")),l=null},r.isStandardBrowserEnv()){var g=n(15),v=(e.withCredentials||a(e.url))&&e.xsrfCookieName?g.read(e.xsrfCookieName):void 0;v&&(d[e.xsrfHeaderName]=v)}if("setRequestHeader"in l&&r.forEach(d,function(e,t){"undefined"==typeof p&&"content-type"===t.toLowerCase()?delete d[t]:l.setRequestHeader(t,e)}),e.withCredentials&&(l.withCredentials=!0),e.responseType)try{l.responseType=e.responseType}catch(e){if("json"!==l.responseType)throw e}"function"==typeof e.onDownloadProgress&&l.addEventListener("progress",e.onDownloadProgress),"function"==typeof e.onUploadProgress&&l.upload&&l.upload.addEventListener("progress",e.onUploadProgress),e.cancelToken&&e.cancelToken.promise.then(function(e){l&&(l.abort(),f(e),l=null)}),void 0===p&&(p=null),l.send(p)})}},function(e,t,n){"use strict";var r=n(9);e.exports=function(e,t,n){var o=n.config.validateStatus;n.status&&o&&!o(n.status)?t(r("Request failed with status code "+n.status,n.config,null,n)):e(n)}},function(e,t,n){"use strict";var r=n(10);e.exports=function(e,t,n,o){var s=new Error(e);return r(s,t,n,o)}},function(e,t){"use strict";e.exports=function(e,t,n,r){return e.config=t,n&&(e.code=n),e.response=r,e}},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(2);e.exports=function(e,t,n){if(!t)return e;var s;if(n)s=n(t);else if(o.isURLSearchParams(t))s=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&"undefined"!=typeof e&&(o.isArray(e)&&(t+="[]"),o.isArray(e)||(e=[e]),o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),s=i.join("&")}return s&&(e+=(e.indexOf("?")===-1?"?":"&")+s),e}},function(e,t,n){"use strict";var r=n(2);e.exports=function(e){var t,n,o,s={};return e?(r.forEach(e.split("\n"),function(e){o=e.indexOf(":"),t=r.trim(e.substr(0,o)).toLowerCase(),n=r.trim(e.substr(o+1)),t&&(s[t]=s[t]?s[t]+", "+n:n)}),s):s}},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){function e(e){var t=e;return n&&(o.setAttribute("href",t),t=o.href),o.setAttribute("href",t),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}var t,n=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");return t=e(window.location.href),function(n){var o=r.isString(n)?e(n):n;return o.protocol===t.protocol&&o.host===t.host}}():function(){return function(){return!0}}()},function(e,t){"use strict";function n(){this.message="String contains an invalid character"}function r(e){for(var t,r,s=String(e),i="",a=0,u=o;s.charAt(0|a)||(u="=",a%1);i+=u.charAt(63&t>>8-a%1*8)){if(r=s.charCodeAt(a+=.75),r>255)throw new n;t=t<<8|r}return i}var o="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";n.prototype=new Error,n.prototype.code=5,n.prototype.name="InvalidCharacterError",e.exports=r},function(e,t,n){"use strict";var r=n(2);e.exports=r.isStandardBrowserEnv()?function(){return{write:function(e,t,n,o,s,i){var a=[];a.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&a.push("expires="+new Date(n).toGMTString()),r.isString(o)&&a.push("path="+o),r.isString(s)&&a.push("domain="+s),i===!0&&a.push("secure"),document.cookie=a.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}()},function(e,t,n){"use strict";function r(){this.handlers=[]}var o=n(2);r.prototype.use=function(e,t){return this.handlers.push({fulfilled:e,rejected:t}),this.handlers.length-1},r.prototype.eject=function(e){this.handlers[e]&&(this.handlers[e]=null)},r.prototype.forEach=function(e){o.forEach(this.handlers,function(t){null!==t&&e(t)})},e.exports=r},function(e,t,n){"use strict";function r(e){e.cancelToken&&e.cancelToken.throwIfRequested()}var o=n(2),s=n(18),i=n(19),a=n(5);e.exports=function(e){r(e),e.headers=e.headers||{},e.data=s(e.data,e.headers,e.transformRequest),e.headers=o.merge(e.headers.common||{},e.headers[e.method]||{},e.headers||{}),o.forEach(["delete","get","head","post","put","patch","common"],function(t){delete e.headers[t]});var t=e.adapter||a.adapter;return t(e).then(function(t){return r(e),t.data=s(t.data,t.headers,e.transformResponse),t},function(t){return i(t)||(r(e),t&&t.response&&(t.response.data=s(t.response.data,t.response.headers,e.transformResponse))),Promise.reject(t)})}},function(e,t,n){"use strict";var r=n(2);e.exports=function(e,t,n){return r.forEach(n,function(n){e=n(e,t)}),e}},function(e,t){"use strict";e.exports=function(e){return!(!e||!e.__CANCEL__)}},function(e,t){"use strict";e.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},function(e,t){"use strict";e.exports=function(e,t){return e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,"")}},function(e,t){"use strict";function n(e){this.message=e}n.prototype.toString=function(){return"Cancel"+(this.message?": "+this.message:"")},n.prototype.__CANCEL__=!0,e.exports=n},function(e,t,n){"use strict";function r(e){if("function"!=typeof e)throw new TypeError("executor must be a function.");var t;this.promise=new Promise(function(e){t=e});var n=this;e(function(e){n.reason||(n.reason=new o(e),t(n.reason))})}var o=n(22);r.prototype.throwIfRequested=function(){if(this.reason)throw this.reason},r.source=function(){var e,t=new r(function(t){e=t});return{token:t,cancel:e}},e.exports=r},function(e,t){"use strict";e.exports=function(e){return function(t){return e.apply(null,t)}}}])}); +//# sourceMappingURL=axios.min.map \ No newline at end of file diff --git a/background.js b/background.js new file mode 100644 index 0000000..af5299d --- /dev/null +++ b/background.js @@ -0,0 +1,602 @@ +/* global chrome axios */ + +const storage = chrome.storage.local; + +const isFirefox = typeof InstallTrigger !== 'undefined'; + +chrome.runtime.onInstalled.addListener((details) => { + if (details.reason == 'update') { + + storage.get((items) => { + + let newItems = {}; + + if (items.textDomain) { + newItems.domain = items.textDomain; + storage.remove('textDomain'); + } + + if (items.textToken) { + newItems.token = items.textToken; + storage.remove('textToken'); + } + + storage.set(newItems); + + }); + + } +}); + +const contexts = ['image', 'video', 'audio']; + +let config = {}; + +storage.get({ + domain: '', + panelURL: '/dashboard', + token: '', + lastAlbum: null, + autoCopyUrl: false +}, (items) => { + config = items; + createContextMenus(); +}); + +chrome.storage.onChanged.addListener((changes) => { + for (const key in changes) { + config[key] = changes[key].newValue; + if (key === 'token') createContextMenus(); + } +}); + +function createContextMenus() { + + if (!config.domain) return; + + /* == Not the best way to do this but when have I ever done something efficiently? == */ + chrome.contextMenus.removeAll(() => { + + console.log('Removed old Context Menus'); + + /* == Parent Context Menu == */ + contextMenus.parent = chrome.contextMenus.create({ + title: 'strelizia', + contexts: ['all'], + onclick: () => chrome.tabs.create({ url: config.domain + config.panelURL }) + }); + + /* == Upload normally == */ + chrome.contextMenus.create({ + title: 'Send to safe', + parentId: contextMenus.parent, + contexts: contexts, + onclick: (info) => upload(info.srcUrl, info.pageUrl) + }); + + /* == Screenshot page == */ + chrome.contextMenus.create({ + title: 'Screenshot page', + parentId: contextMenus.parent, + contexts: ['page'], + onclick: () => { + chrome.tabs.captureVisibleTab({ format: 'png' }, (data) => { + let blob = b64toBlob(data.replace('data:image/png;base64,', ''), 'image/png'); + uploadScreenshot(blob); + }); + } + }); + + /* == Screenshot selection == */ + chrome.contextMenus.create({ + title: 'Screenshot selection', + parentId: contextMenus.parent, + contexts: ['page'], + onclick: () => { + chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { + chrome.tabs.sendMessage(tabs[0].id, 'check', (response) => { + if (response) { + chrome.tabs.sendMessage(tabs[0].id, 'select'); + } else { + chrome.tabs.insertCSS(null, { file: 'content.css' }); + chrome.tabs.executeScript(null, { file: 'content.js' }, () => { + chrome.tabs.sendMessage(tabs[0].id, 'select'); + }); + } + }); + }); + } + }); + + if (config.token) { + + /* == Separator == */ + chrome.contextMenus.create({ + parentId: contextMenus.parent, + contexts: contexts, + type: 'separator' + }); + + /* == Refresh Album List == */ + chrome.contextMenus.create({ + title: 'Refresh Albums List', + parentId: contextMenus.parent, + contexts: contexts, + onclick: createContextMenus + }); + + /* == Separator == */ + chrome.contextMenus.create({ + parentId: contextMenus.parent, + contexts: contexts, + type: 'separator' + }); + + axios.get(config.domain + '/api/albums', { + headers: { token: config.token } + }).then((list) => { + + if (list.data.albums.length === 0) { + + chrome.contextMenus.create({ + title: 'No Albums Available', + parentId: contextMenus.parent, + contexts: contexts, + type: 'normal', + enabled: false + }); + + } else { + + const lastAlbum = list.data.albums.find(a => a.id === config.lastAlbum); + + contextMenus.lastAlbum = chrome.contextMenus.create({ + title: `Upload to: ${lastAlbum ? lastAlbum.name : 'None'}`, + parentId: contextMenus.parent, + contexts: contexts, + enabled: !!lastAlbum, + onclick: (info) => upload(info.srcUrl, info.pageUrl, lastAlbum.id, lastAlbum.name) + }); + + /* == Separator == */ + chrome.contextMenus.create({ + parentId: contextMenus.parent, + contexts: contexts, + type: 'separator' + }); + + contextMenus.albumsParent = chrome.contextMenus.create({ + title: 'Upload to:', + parentId: contextMenus.parent, + contexts: contexts, + type: 'normal', + enabled: false + }); + + list.data.albums.forEach((album) => { + console.log(album.id, album.name); + contextMenus.createAlbumMenu(album.id, album.name); + }); + + } + + }).catch((err) => { + + console.log(err); + + chrome.contextMenus.create({ + title: 'Error Getting Albums', + parentId: contextMenus.parent, + contexts: contexts, + type: 'normal', + enabled: false + }); + + }); + + } + + }); + +} + +let contextMenus = { + parent: null, + albumsParent: null, + lastAlbum: null, + createAlbumMenu: (id, name, enabled = true) => { + chrome.contextMenus.create({ + title: name.replace('&', '&&'), + parentId: contextMenus.parent, + // parentId: contextMenus.albumsParent, + contexts, enabled, + onclick: (info) => upload(info.srcUrl, info.pageUrl, id, name) + }); + } +}; + +let refererHeader = null; +let contentURL = ''; +let recentlyUploaded = new Map(); + +let opt_extraInfoSpec = ['blocking', 'requestHeaders']; + +const chromeVersionCheck = navigator.userAgent.match(/Chrome\/(\d+)/); + +if (chromeVersionCheck && parseInt(chromeVersionCheck[1]) >= 72) + opt_extraInfoSpec.push('extraHeaders'); + +/* == We need to set this header for image sources that check it for auth or to prevent hotlinking == */ +chrome.webRequest.onBeforeSendHeaders.addListener((details) => { + + if (details.tabId === -1 && details.method === 'GET' && refererHeader !== null) { + + details.requestHeaders.push({ + name: 'Referer', + value: refererHeader + }); + + details.requestHeaders.push({ + name: 'Referrer', + value: refererHeader + }); + + } + + return {requestHeaders: details.requestHeaders}; + +}, { urls: [''] }, opt_extraInfoSpec); + +function upload(url, pageURL, albumID, albumName) { + + if (albumID) + storage.set({ lastAlbum: albumID }, () => { + chrome.contextMenus.update(contextMenus.lastAlbum, { + enabled: true, + title: `Upload to: ${albumName}`, + onclick: (info) => upload(info.srcUrl, info.pageUrl, albumID, albumName) + }); + }); + + let notification = createNotification('basic', 'Retriving file...', null, true); + + refererHeader = pageURL; + + axios.get(url, { responseType: 'blob' }).then((file) => { + + refererHeader = null; + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'progress', + message: 'Uploading...', + progress: 0 + }); + } + + let data = new FormData(); + data.append('files[]', file.data, 'upload' + fileExt(file.data.type)); + + let options = { + method: 'POST', + url: `${config.domain}/api/upload`, + data, + headers: { + token: config.token + }, + onUploadProgress: (progress) => { + if (!isFirefox) { + chrome.notifications.update(notification, { + progress: Math.round((progress.loaded * 100) / progress.total) + }); + } + } + }; + + if (albumID && config.token) + options.url = options.url + '/' + albumID; + + axios.request(options).then((response) => { + + if (response.data.success === true || response.data.files) { + + recentlyUploaded.set(notification, response.data.files[0].name); + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: 'Upload Complete!', + contextMessage: response.data.files[0].url, + buttons: config.autoCopyUrl ? [] : [{ title: 'Copy to clipboard' }, { title: 'Delete Upload' }] + }); + } else { + createNotification('basic', 'Upload Complete!'); + } + + if (config.autoCopyUrl) + copyText(response.data.files[0].url); + + contentURL = response.data.files[0].url; + + setTimeout(() => chrome.notifications.clear(notification), 5000); + + } else { + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: response.data.description || response.data.message, + contextMessage: url, + }); + } else { + createNotification('basic', response.data.description || response.data.message); + } + + } + + }).catch((err) => { + + console.error(err); + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: 'Error!', + contextMessage: err.toString(), + }); + } else { + createNotification('basic', `Error!\n${err.toString()}`); + } + + }); + + }); + +} + +function deleteFile(filename) { + let headers = { + token: config.token + }; + axios.get(`${config.domain}/api/uploads/0`, { headers }).then(response => { + let file = response.data.files.find(a => a.name === filename); + return axios.post(`${config.domain}/api/upload/delete`, { id: file.id }, { headers }).then(res => { + if (res.data.success) { + createNotification('basic', `File ${filename} was deleted!`); + } else { + createNotification('basic', 'Error\nUnable to delete the file.'); + } + }); + }).catch(() => { + createNotification('basic', 'Error\nUnable to delete the file.'); + }); +} + +function uploadScreenshot(blob, albumID) { + + let notification = createNotification('progress', 'Uploading...', null, true, 0); + + let data = new FormData(); + + data.append('files[]', blob, 'upload.png'); + + let options = { + method: 'POST', + url: `${config.domain}/api/upload`, + data, + headers: { + token: config.token + }, + onUploadProgress: (progress) => { + if (!isFirefox) { + chrome.notifications.update(notification, { + progress: Math.round((progress.loaded * 100) / progress.total) + }); + } + } + }; + + if (albumID && config.token) + options.url = options.url + '/' + albumID; + + axios.request(options).then((response) => { + + if (response.data.success === true || response.data.files) { + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: 'Upload Complete!', + contextMessage: response.data.files[0].url, + buttons: config.autoCopyUrl ? [] : [{ title: 'Copy to clipboard' }] + }); + } else { + createNotification('basic', 'Upload Complete!'); + } + + if (config.autoCopyUrl) + copyText(response.data.files[0].url); + + contentURL = response.data.files[0].url; + + setTimeout(() => chrome.notifications.clear(notification), 5000); + + } else { + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: response.data.description || response.data.message + }); + } else { + createNotification('basic', response.data.description || response.data.message); + } + + } + + }).catch((err) => { + + console.error(err); + + if (!isFirefox) { + chrome.notifications.update(notification, { + type: 'basic', + message: 'Error!', + contextMessage: err.toString(), + }); + } else { + createNotification('basic', `Error!\n${err.toString()}`); + } + + }); + +} + +chrome.runtime.onMessage.addListener((request) => { + + if ('coordinates' in request) { + + let pos = request.coordinates; + + chrome.tabs.captureVisibleTab({ format: 'png' }, (data) => { + + const canvas = document.createElement('canvas'); + const ctx = canvas.getContext('2d'); + + const img = new Image(); + + img.onload = () => { + + let resHeight = Math.abs(pos[0].y - pos[1].y); + let resWidth = Math.abs(pos[0].x - pos[1].x); + + if (resHeight === 0 || resWidth === 0) return; + + let posX = pos[0].x < pos[1].x + ? pos[0].x + : pos[1].x; + let posY = pos[0].y < pos[1].y + ? pos[0].y + : pos[1].y; + + canvas.height = resHeight; + canvas.width = resWidth; + + ctx.drawImage(img, -posX, -posY); + + let imageData = canvas.toDataURL(); + + let blob = b64toBlob(imageData.replace('data:image/png;base64,', ''), 'image/png'); + + uploadScreenshot(blob); + + }; + + img.src = data; + + }); + + } + +}); + +function createNotification(type, message, altText, sticky, progress) { + + let notificationContent = { + type, + title: 'strelizia', + message, + iconUrl: 'logo-128x128.png' + }; + + if (typeof InstallTrigger === 'undefined') // Does not work with firefox. + notificationContent.requireInteraction = sticky || false; + + if (altText && typeof altText === 'string') + notificationContent.contextMessage = altText; + + if (progress && typeof progress === 'number') + notificationContent.progress = progress; + + let id = 'notification_' + Date.now(); + + chrome.notifications.create(id, notificationContent); + + return id; + +} + +chrome.notifications.onClicked.addListener((id) => { + chrome.notifications.clear(id); +}); + +chrome.notifications.onClosed.addListener((id) => { + recentlyUploaded.delete(id); + contentURL = ''; +}); + +chrome.notifications.onButtonClicked.addListener((id, index) => { + if (!config.autoCopyUrl && index === 0) copyText(contentURL); + if (index === 1) deleteFile(recentlyUploaded.get(id)); + chrome.notifications.clear(id); +}); + +const mimetypes = { + 'image/png': '.png', + 'image/jpeg': '.jpg', + 'image/gif': '.gif', + 'image/bmp': '.bmp', + 'image/x-icon': '.ico', + 'video/mp4': '.mp4', + 'video/webm': '.webm', + 'video/quicktime': '.mov', + 'audio/mp4': '.mp4a', + 'audio/mpeg': '.mp3', + 'audio/ogg': '.ogg', + 'audio/x-aac': '.aac', + 'audio/x-wav': '.wav' +}; + +function fileExt(mimetype) { + return mimetypes[mimetype] || '.' + mimetype.split('/')[1]; +} + +function copyText(text) { + let input = document.createElement('textarea'); + document.body.appendChild(input); + input.value = text; + input.focus(); + input.select(); + document.execCommand('Copy'); + input.remove(); +} + +// http://stackoverflow.com/a/16245768 +function b64toBlob(b64Data, contentType, sliceSize) { + + contentType = contentType || ''; + sliceSize = sliceSize || 512; + + let byteCharacters = atob(b64Data); + let byteArrays = []; + + for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) { + + let slice = byteCharacters.slice(offset, offset + sliceSize); + + let byteNumbers = new Array(slice.length); + + for (let i = 0; i < slice.length; i++) { + byteNumbers[i] = slice.charCodeAt(i); + } + + let byteArray = new Uint8Array(byteNumbers); + + byteArrays.push(byteArray); + + } + + let blob = new Blob(byteArrays, { type: contentType }); + + return blob; +} \ No newline at end of file diff --git a/backup/logo-128x128.png b/backup/logo-128x128.png new file mode 100644 index 0000000..29c1a5b Binary files /dev/null and b/backup/logo-128x128.png differ diff --git a/backup/logo-48x48.png b/backup/logo-48x48.png new file mode 100644 index 0000000..4f21545 Binary files /dev/null and b/backup/logo-48x48.png differ diff --git a/backup/logo.png b/backup/logo.png new file mode 100644 index 0000000..94b6797 Binary files /dev/null and b/backup/logo.png differ diff --git a/content.css b/content.css new file mode 100644 index 0000000..7f070b1 --- /dev/null +++ b/content.css @@ -0,0 +1,21 @@ +#loli-lasso { + position: fixed; + border: 1px dotted; + background: rgba(255, 255, 255, 0.1); + display: none; + left: 0; + right: 0; + width: 0; + height: 0; + z-index: 999; +} + +body.loli-filter:after { + content: ''; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 998; +} \ No newline at end of file diff --git a/content.js b/content.js new file mode 100644 index 0000000..25e3de3 --- /dev/null +++ b/content.js @@ -0,0 +1,111 @@ +let loliLasso = document.createElement('div'); +loliLasso.setAttribute('id', 'loli-lasso'); +document.body.appendChild(loliLasso); + +let firstPos; +let secondPos; + +const captureFunctions = { + mousedown: (event) => { + + if (event.buttons !== 1) return; + + setStyles('#loli-lasso', { + display: 'block', + top: event.clientY + 'px', + left: event.clientX + 'px' + }); + + firstPos = { x: event.clientX, y: event.clientY }; + + }, + mousemove: (event) => { + + if (event.buttons !== 1) return + + const originalTop = $('#loli-lasso').style.top; + const originalLeft = $('#loli-lasso').style.left; + + const height = event.clientY - firstPos.y; + const width = event.clientX - firstPos.x; + + setStyles('#loli-lasso', { + top: (height > 0) + ? originalTop + : event.clientY + 'px', + height: (height > 0) + ? height + 'px' + : (firstPos.y - event.clientY) + 'px', + left: (width > 0) + ? originalLeft + : event.clientX + 'px', + width: (width > 0) + ? width + 'px' + : (firstPos.x - event.clientX) + 'px' + }); + }, + mouseup: (event) => { + + if (event.which !== 1) return; + + document.body.classList.remove('loli-filter'); + + setStyles('body', { + cursor: 'initial', + userSelect: 'initial' + }); + + setStyles('#loli-lasso', { + display: 'none', + top: 0, left: 0, + height: 0, width: 0 + }); + + secondPos = { + x: (event.clientX < window.innerWidth) + ? event.clientX + : window.innerWidth, + y: (event.clientY < window.innerHeight) + ? event.clientY + : window.innerHeight + }; + + document.removeEventListener('mousedown', captureFunctions.mousedown); + document.removeEventListener('mousemove', captureFunctions.mousemove); + document.removeEventListener('mouseup', captureFunctions.mouseup); + + setTimeout(() => chrome.runtime.sendMessage({ coordinates: [firstPos, secondPos] }), 100); + + } +}; + +chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { + + if (request === 'select') { + + setStyles('body', { + cursor: 'crosshair', + userSelect: 'none' + }); + + document.body.classList.add('loli-filter'); + + document.addEventListener('mousedown', captureFunctions.mousedown); + document.addEventListener('mousemove', captureFunctions.mousemove); + document.addEventListener('mouseup', captureFunctions.mouseup); + + } else if (request === 'check') { + + sendResponse(true); + + } + +}); + +const $ = (el) => document.querySelector(el); + +function setStyles(element, styles) { + let el = document.querySelector(element); + for (let style in styles) + el.style[style] = styles[style]; +} \ No newline at end of file diff --git a/logo-128x128.png b/logo-128x128.png new file mode 100644 index 0000000..c13dd29 Binary files /dev/null and b/logo-128x128.png differ diff --git a/logo-48x48.png b/logo-48x48.png new file mode 100644 index 0000000..3fed93d Binary files /dev/null and b/logo-48x48.png differ diff --git a/logo.png b/logo.png new file mode 100644 index 0000000..0ca96d2 Binary files /dev/null and b/logo.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..be28db0 --- /dev/null +++ b/manifest.json @@ -0,0 +1,36 @@ + { + "manifest_version": 2, + "name": "strelizia Uploader", + "description": "Uploader for strelizia", + "version": "2019.1.24.1", + "version_name": "Biribiri", + "options_ui": { + "page": "settings.html", + "chrome_style": false, + "open_in_tab": true + }, + "icons": { + "48": "logo-48x48.png", + "128": "logo-128x128.png" + }, + "permissions": [ + "contextMenus", + "storage", + "notifications", + "tabs", + "webRequest", + "webRequestBlocking", + "" + ], + "background": { + "scripts": [ + "axios.min.js", + "background.js" + ], + "persistent": true + }, + "web_accessible_resources": [ + "content.js", + "content.css" + ] + } diff --git a/settings.html b/settings.html new file mode 100644 index 0000000..50e753f --- /dev/null +++ b/settings.html @@ -0,0 +1,103 @@ + + + + strelizia Settings + + + + +
+ +

+ +

+ +

+ This page will help you setup your strelizia extension so you can rehost images/audio/videos by right clicking on them. For this to work you need to provide the domain were strelizia is running. If you want to keep track of your uploads and be able to create albums to store them, you should create an account on the website and paste the token here, so that every upload gets tied to your account, enabling you to go back to the site and see all of your uploaded files. +

+ +

Domain on which strelizia is running:

+ + +

Your strelizia token (optional):

+ + +

+ +

+ + +

+ + + + + +
+ + diff --git a/settings.js b/settings.js new file mode 100644 index 0000000..4b8535d --- /dev/null +++ b/settings.js @@ -0,0 +1,42 @@ +const storage = chrome.storage.local; +const background = chrome.extension.getBackgroundPage(); + +document.addEventListener('DOMContentLoaded', () => { + storage.get({ domain: '', token: '', autoCopyUrl: false }, (items) => { + for (key in items) { + let el = document.getElementById(key); + if (el) { + if (el.type === 'checkbox') + el.checked = items[key]; + else + el.value = items[key]; + } + } + }); +}); + +document.getElementById('save').addEventListener('click', () => { + + const textDomain = document.getElementById('domain').value; + const textToken = document.getElementById('token').value; + const autoCopyUrl = document.getElementById('autoCopyUrl').checked; + + if (!textDomain) + return alert('strelizia domain is required!'); + + storage.set({ + domain: textDomain, + token: textToken, + autoCopyUrl: autoCopyUrl + }, () => { + background.createContextMenus(); + let notification = background.createNotification('basic', 'Settings Saved!'); + setTimeout(() => chrome.notifications.clear(notification), 5000); + }); + +}); + +document.getElementById('domain').addEventListener('blur', function() { + if (this.value.slice(-1) === '/') + this.value = this.value.slice(0, -1); +}); \ No newline at end of file -- cgit v1.2.3