|
|
@@ -9,100 +9,92 @@ const processes = {};
|
|
|
const NO_HTTP_CACHE = {
|
|
|
'Cache-Control': 'no-cache, no-store, must-revalidate',
|
|
|
};
|
|
|
+const OPTIONS = {
|
|
|
+ meta: {
|
|
|
+ headers: { ...NO_HTTP_CACHE, Accept: 'text/x-userscript-meta' },
|
|
|
+ },
|
|
|
+ script: {
|
|
|
+ headers: NO_HTTP_CACHE,
|
|
|
+ },
|
|
|
+};
|
|
|
|
|
|
-function doCheckUpdate(script) {
|
|
|
- const update = {
|
|
|
- checking: true,
|
|
|
- };
|
|
|
- const res = {
|
|
|
- cmd: CMD_SCRIPT_UPDATE,
|
|
|
- data: {
|
|
|
- where: {
|
|
|
- id: script.props.id,
|
|
|
- },
|
|
|
- update,
|
|
|
- },
|
|
|
- };
|
|
|
+// resolves to true if successfully updated
|
|
|
+export default function checkUpdate(script) {
|
|
|
+ const { id } = script.props;
|
|
|
+ const promise = processes[id] || (processes[id] = doCheckUpdate(script));
|
|
|
+ return promise;
|
|
|
+}
|
|
|
+
|
|
|
+async function doCheckUpdate(script) {
|
|
|
+ const { id } = script.props;
|
|
|
+ try {
|
|
|
+ const { data: { update } } = await parseScript({
|
|
|
+ id,
|
|
|
+ code: await downloadUpdate(script),
|
|
|
+ update: { checking: false },
|
|
|
+ });
|
|
|
+ if (getOption('notifyUpdates')) {
|
|
|
+ notify({
|
|
|
+ title: i18n('titleScriptUpdated'),
|
|
|
+ body: i18n('msgScriptUpdated', [update.meta.name || i18n('labelNoName')]),
|
|
|
+ });
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ } catch (error) {
|
|
|
+ if (process.env.DEBUG) console.error(error);
|
|
|
+ } finally {
|
|
|
+ delete processes[id];
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function downloadUpdate(script) {
|
|
|
const downloadURL = (
|
|
|
script.custom.downloadURL
|
|
|
|| script.meta.downloadURL
|
|
|
|| script.custom.lastInstallURL
|
|
|
);
|
|
|
- const updateURL = script.custom.updateURL || script.meta.updateURL || downloadURL;
|
|
|
- const okHandler = ({ data }) => {
|
|
|
- const meta = parseMeta(data);
|
|
|
- if (compareVersion(script.meta.version, meta.version) < 0) return Promise.resolve();
|
|
|
- update.checking = false;
|
|
|
- update.message = i18n('msgNoUpdate');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return Promise.reject();
|
|
|
- };
|
|
|
- const errHandler = () => {
|
|
|
- update.checking = false;
|
|
|
- update.message = i18n('msgErrorFetchingUpdateInfo');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return Promise.reject();
|
|
|
+ const updateURL = (
|
|
|
+ script.custom.updateURL
|
|
|
+ || script.meta.updateURL
|
|
|
+ || downloadURL
|
|
|
+ );
|
|
|
+ if (!updateURL) throw false;
|
|
|
+ let checkingMeta = true;
|
|
|
+ const update = {};
|
|
|
+ const msg = {
|
|
|
+ cmd: CMD_SCRIPT_UPDATE,
|
|
|
+ data: {
|
|
|
+ where: { id: script.props.id },
|
|
|
+ update,
|
|
|
+ },
|
|
|
};
|
|
|
- const doUpdate = () => {
|
|
|
- if (!downloadURL) {
|
|
|
- update.message = i18n('msgNewVersion');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return Promise.reject();
|
|
|
+ announce(i18n('msgCheckingForUpdate'));
|
|
|
+ try {
|
|
|
+ const { data } = await request(updateURL, OPTIONS.meta);
|
|
|
+ const meta = parseMeta(data);
|
|
|
+ if (compareVersion(script.meta.version, meta.version) >= 0) {
|
|
|
+ announce(i18n('msgNoUpdate'), { checking: false });
|
|
|
+ } else if (!downloadURL) {
|
|
|
+ announce(i18n('msgNewVersion'), { checking: false });
|
|
|
+ } else {
|
|
|
+ announce(i18n('msgUpdating'));
|
|
|
+ checkingMeta = false;
|
|
|
+ return (await request(downloadURL, OPTIONS.script)).data;
|
|
|
}
|
|
|
- update.message = i18n('msgUpdating');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return request(downloadURL, { headers: NO_HTTP_CACHE })
|
|
|
- .then(({ data }) => data, () => {
|
|
|
- update.checking = false;
|
|
|
- update.message = i18n('msgErrorFetchingScript');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return Promise.reject();
|
|
|
- });
|
|
|
- };
|
|
|
- if (!updateURL) return Promise.reject();
|
|
|
- update.message = i18n('msgCheckingForUpdate');
|
|
|
- sendMessageOrIgnore(res);
|
|
|
- return request(updateURL, {
|
|
|
- headers: {
|
|
|
- ...NO_HTTP_CACHE,
|
|
|
- Accept: 'text/x-userscript-meta',
|
|
|
- },
|
|
|
- })
|
|
|
- .then(okHandler, errHandler)
|
|
|
- .then(doUpdate);
|
|
|
-}
|
|
|
-
|
|
|
-export default function checkUpdate(script) {
|
|
|
- const { id } = script.props;
|
|
|
- let promise = processes[id];
|
|
|
- if (!promise) {
|
|
|
- let updated = false;
|
|
|
- promise = doCheckUpdate(script)
|
|
|
- .then(code => parseScript({
|
|
|
- id,
|
|
|
- code,
|
|
|
- update: {
|
|
|
- checking: false,
|
|
|
- },
|
|
|
- }))
|
|
|
- .then((res) => {
|
|
|
- const { data: { update } } = res;
|
|
|
- updated = true;
|
|
|
- if (getOption('notifyUpdates')) {
|
|
|
- notify({
|
|
|
- title: i18n('titleScriptUpdated'),
|
|
|
- body: i18n('msgScriptUpdated', [update.meta.name || i18n('labelNoName')]),
|
|
|
- });
|
|
|
- }
|
|
|
- })
|
|
|
- .catch((err) => {
|
|
|
- if (process.env.DEBUG) console.error(err);
|
|
|
- })
|
|
|
- .then(() => {
|
|
|
- delete processes[id];
|
|
|
- return updated;
|
|
|
+ } catch (error) {
|
|
|
+ announce(
|
|
|
+ checkingMeta ? i18n('msgErrorFetchingUpdateInfo') : i18n('msgErrorFetchingScript'),
|
|
|
+ { error },
|
|
|
+ );
|
|
|
+ }
|
|
|
+ throw update.error;
|
|
|
+ function announce(message, { error, checking = !error } = {}) {
|
|
|
+ Object.assign(update, {
|
|
|
+ message,
|
|
|
+ checking,
|
|
|
+ // `null` is sendable in Chrome unlike `undefined`
|
|
|
+ error: error?.url || error || null,
|
|
|
});
|
|
|
- processes[id] = promise;
|
|
|
+ sendMessageOrIgnore(msg);
|
|
|
}
|
|
|
- return promise;
|
|
|
}
|