From 1355f0a516b2c8daf27db0942a6a52dd76a642ea Mon Sep 17 00:00:00 2001 From: Bjorn Stromberg Date: Wed, 2 May 2018 22:49:18 +0900 Subject: [PATCH] v3.0.0 - 2018-05-02 --- .gitignore | 1 + CHANGELOG.md | 7 ++ build/.gitkeep | 0 package.json | 27 +++++++ test.js | 15 ---- test/urls.js | 66 +++++++++++++++++ src/background.js => webextension/index.js | 86 +++++++++++++--------- {src => webextension}/manifest.json | 5 +- 8 files changed, 156 insertions(+), 51 deletions(-) create mode 100644 build/.gitkeep create mode 100644 package.json delete mode 100644 test.js create mode 100644 test/urls.js rename src/background.js => webextension/index.js (57%) rename {src => webextension}/manifest.json (87%) diff --git a/.gitignore b/.gitignore index c4c4ffc..6dd55d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *.zip +node_modules diff --git a/CHANGELOG.md b/CHANGELOG.md index 296b373..6b70dee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Intercept Redirect +## v3.0.0 - 2018-05-02 +- Test with TAP +- Rename `src` to `webextension` +- Add `package.json` +- Add `node_modules` to `.gitignore` +- Put built web extensions in `build` directory + ## v2.0.0 - 2018-04-29 - Add Google image search redirect - Add `test.js` diff --git a/build/.gitkeep b/build/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/package.json b/package.json new file mode 100644 index 0000000..dc88dd6 --- /dev/null +++ b/package.json @@ -0,0 +1,27 @@ +{ + "name": "@bjornstar/intercept-redirect", + "version": "3.0.0", + "description": "Skip tracking redirects that serve no purpose other than to waste your precious time.", + "main": "webextension/index.js", + "dependencies": {}, + "devDependencies": { + "tap": "^11.1.4" + }, + "scripts": { + "test": "tap test/*.js" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/bjornstar/intercept-redirect.git" + }, + "keywords": [ + "webextension", + "redirect" + ], + "author": "Bjorn Stromberg ", + "license": "MIT", + "bugs": { + "url": "https://github.com/bjornstar/intercept-redirect/issues" + }, + "homepage": "https://github.com/bjornstar/intercept-redirect#readme" +} diff --git a/test.js b/test.js deleted file mode 100644 index 8c5ca43..0000000 --- a/test.js +++ /dev/null @@ -1,15 +0,0 @@ -const assert = require('assert'); - -const analyzeURL = require('./src/background.js').analyzeURL; - -const testURLs = [ - { - src: 'https://t.umblr.com/redirect?z=http%3A%2F%2Fwww.theguardian.com%2Fnews%2F2018%2Fapr%2F19%2Fwolves-of-instagram-jordan-belmont-social-media-traders', - dst: 'http://www.theguardian.com/news/2018/apr/19/wolves-of-instagram-jordan-belmont-social-media-traders' - } -]; - -testURLs.forEach(function (url) { - const redirectUrl = url.dst; - assert.deepEqual(analyzeURL({ url: url.src }), { redirectUrl }) -}); diff --git a/test/urls.js b/test/urls.js new file mode 100644 index 0000000..db0415c --- /dev/null +++ b/test/urls.js @@ -0,0 +1,66 @@ +const tap = require('tap'); + +const webExtension = require('../webextension'); +const manifest = require('../webextension/manifest.json'); +const package = require('../package.json'); + +const { analyzeURL } = webExtension; + +const urls = [ + 'https://disq.us/url?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect%3AzjHJ9CS7YTS6D6-FWtZRTF8swk4', + 'https://exit.sc/?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://l.facebook.com/l.php?u=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.co.jp/imgres?imgrefurl=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.co.jp/imgres?imgurl=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.co.jp/url?q=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.co.jp/url?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://news.url.google.com/url?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://plus.url.google.com/url?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.com/imgres?imgrefurl=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.com/imgres?imgurl=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.com/url?q=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.google.com/url?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://l.instagram.com/?u=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://l.messenger.com/l.php?u=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://slack-redir.net/link?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://steamcommunity.com/linkfilter/?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://twitter.com/i/redirect?url=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://t.umblr.com/redirect?z=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://vk.com/away.php?to=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect', + 'https://www.youtube.com/redirect?q=https%3A%2F%2Fbjornstar.com%2Fintercept-redirect' +]; + +const redirectUrl = 'https://bjornstar.com/intercept-redirect'; + +const manifestSites = manifest.permissions.filter(function (permission) { + return permission !== 'webRequest' && permission !== 'webRequestBlocking'; +}).map(function (site) { + return site.replace('*://', '').replace('/', ''); +}); + +const testSites = urls.map(function (url) { + return url.substring(8, url.indexOf('/', 8)); +}); + +const webExtensionSites = Object.keys(webExtension.sites); + +urls.forEach(function (url) { + tap.same(analyzeURL({ url }), { redirectUrl }, `Source: ${url}`); +}); + +webExtensionSites.forEach(function (site) { + tap.ok(manifestSites.indexOf(site) !== -1, `Unmatched: ${site}`); +}); + +manifestSites.forEach(function (site) { + tap.ok(webExtensionSites.indexOf(site) !== -1, `Unmatched: ${site}`); +}); + +manifestSites.forEach(function (site) { + tap.ok(testSites.indexOf(site) !== -1, `Missing tests: ${site}`); +}); + +tap.notOk(analyzeURL({ url: 'https://www.google.com/' })); +tap.notOk(analyzeURL({ url: 'https://bjornstar.com/' })); + +tap.equal(manifest.version, package.version); diff --git a/src/background.js b/webextension/index.js similarity index 57% rename from src/background.js rename to webextension/index.js index 90083f4..4e10f04 100644 --- a/src/background.js +++ b/webextension/index.js @@ -1,116 +1,134 @@ // For node compatibility so we can test. const URL = typeof window === 'undefined' ? require('url').URL : window.URL; +const googlePathnames = { + '/imgres': ['imgurl','imgrefurl'], + '/url': ['q','url'] +}; + const sites = { 'disq.us': { pathnames: { - '/url': 'url' + '/url': ['url'] }, - extra: function (s) { + extra: function (s = '') { return s.substring(0, s.lastIndexOf(':')); } }, 'exit.sc': { pathnames: { - '/': 'url' + '/': ['url'] } }, 'l.facebook.com': { pathnames: { - '/l.php': 'u' + '/l.php': ['u'] } }, 'www.google.co.jp': { - pathnames: { - '/imgres': 'imgurl', - '/url': 'url' - } + pathnames: googlePathnames }, 'news.url.google.com': { pathnames: { - '/url': 'url' + '/url': ['url'] } }, 'plus.url.google.com': { pathnames: { - '/url': 'url' + '/url': ['url'] } }, 'www.google.com': { - pathnames: { - '/imgres': 'imgurl', - '/url': 'url' - } + pathnames: googlePathnames }, 'l.instagram.com': { pathnames: { - '/': 'u' + '/': ['u'] } }, 'l.messenger.com': { pathnames: { - '/l.php': 'u' + '/l.php': ['u'] } }, 'slack-redir.net': { pathnames: { - '/link': 'url' + '/link': ['url'] } }, 'steamcommunity.com': { pathnames: { - '/linkfilter/': 'url' + '/linkfilter/': ['url'] + } + }, + 'twitter.com': { + pathnames: { + '/i/redirect': ['url'] } }, 't.umblr.com': { pathnames: { - '/redirect': 'z' + '/redirect': ['z'] } }, 'vk.com': { pathnames: { - '/away.php': 'to' + '/away.php': ['to'] } }, 'www.youtube.com': { pathnames: { - '/redirect': 'q' + '/redirect': ['q'] } } }; -function siteReducer(urls, host) { - return urls.concat(Object.keys(sites[host].pathnames).map(function (pathname) { - return `*://${host}${pathname}*`; - })); +function reduceKeyValues(o, pair) { + const [k, v] = pair.split('='); + o[k] = decodeURIComponent(v); + return o; } -const urls = Object.keys(sites).reduce(siteReducer, []); +function findKey(o, keys = []) { + for (let i = 0; i < keys.length; i += 1) { + if (o.hasOwnProperty(keys[i])) { + return o[keys[i]]; + } + } +} function analyzeURL(request) { const url = new URL(request.url); const site = sites[url.host]; - const key = site.pathnames[url.pathname]; + if (!site) { + return; + } + + const keys = site.pathnames[url.pathname]; const pairs = url.search.slice(1).split('&'); - const q = pairs.reduce((o, pair) => { - const [k, v] = pair.split('='); - o[k] = decodeURIComponent(v); - return o; - }, {}); + const q = pairs.reduce(reduceKeyValues, {}); + const value = findKey(q, keys); - const redirectUrl = (!site.extra && q[key]) || site.extra(q[key] || ''); + const redirectUrl = (site.extra && site.extra(value)) || value; return redirectUrl && { redirectUrl }; } +function reduceSites(urls, host) { + return urls.concat(Object.keys(sites[host].pathnames).map(function (pathname) { + return `*://${host}${pathname}*`; + })); +} + +const urls = Object.keys(sites).reduce(reduceSites, []); + // For node compatibility so we can test. typeof chrome === 'object' && chrome.webRequest.onBeforeRequest.addListener(analyzeURL, { urls }, ['blocking']); // For node compatibility so we can test. typeof exports === 'object' && Object.assign(exports, { analyzeURL, - siteReducer, sites }); diff --git a/src/manifest.json b/webextension/manifest.json similarity index 87% rename from src/manifest.json rename to webextension/manifest.json index bfb8005..032e84b 100644 --- a/src/manifest.json +++ b/webextension/manifest.json @@ -1,6 +1,6 @@ { "background": { - "scripts": [ "background.js" ] + "scripts": [ "index.js" ] }, "manifest_version": 2, "name": "Intercept Redirect", @@ -18,9 +18,10 @@ "*://l.messenger.com/", "*://slack-redir.net/", "*://steamcommunity.com/", + "*://twitter.com/", "*://t.umblr.com/", "*://vk.com/", "*://www.youtube.com/" ], - "version": "2.0.0" + "version": "3.0.0" }