Skip to content

Commit e6a4986

Browse files
committed
🚧 chrome extension in progress
1 parent ab042e9 commit e6a4986

6 files changed

Lines changed: 377 additions & 0 deletions

File tree

background.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
async function getCurrentTab() {
2+
let queryOptions = { active: true, currentWindow: true }
3+
let [tab] = await chrome.tabs.query(queryOptions)
4+
console.log(tab)
5+
6+
const url = new URL(tab.url)
7+
console.log(url.searchParams.get('target'))
8+
tab.url = url.searchParams.get('target')
9+
}
10+
11+
chrome.tabs.onUpdated.addListener(() => {
12+
getCurrentTab()
13+
})

background.ts

Whitespace-only changes.

example.js

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
// ==UserScript==
2+
// @name Open the F**king URL Right Now
3+
// @description 自动跳转某些网站不希望用户直达的外链
4+
// @author OldPanda
5+
// @match http://t.cn/*
6+
// @match https://weibo.cn/sinaurl?*
7+
// @match https://www.jianshu.com/go-wild?*
8+
// @match http*://link.zhihu.com/?*
9+
// @match https://www.douban.com/link2/?url=*
10+
// @match https://link.ld246.com/forward?goto=*
11+
// @match https://mp.weixin.qq.com/*
12+
// @match http://redir.yy.duowan.com/warning.php?url=*
13+
// @match https://weixin110.qq.com/cgi-bin/mmspamsupport-bin/newredirectconfirmcgi*
14+
// @match https://link.csdn.net/?target=*
15+
// @match https://steamcommunity.com/linkfilter/?url=*
16+
// @match https://game.bilibili.com/linkfilter/?url=*
17+
// @match https://www.oschina.net/action/GoToLink?url=*
18+
// @match https://developers.weixin.qq.com/community/middlepage/href?href=*
19+
// @match https://docs.qq.com/scenario/link.html?url=*
20+
// @match https://www.pixiv.net/jump.php?url=*
21+
// @match https://www.chinaz.com/go.shtml?url=*
22+
// @match http://www.360doc.com/content/*
23+
// @match https://nga.178.com/read.php?*
24+
// @match https://bbs.nga.cn/read.php?*
25+
// @match http*://c.pc.qq.com/*
26+
// @match https://www.yuque.com/r/goto?url=*
27+
// @match https://www.mcbbs.net/plugin.php?id=link_redirect&target=*
28+
// @match https://link.juejin.cn/?target=*
29+
// @match http*://www.360doc.cn/outlink.html?url=*
30+
// @match https://jump2.bdimg.com/safecheck/index?url=*
31+
// @match http*://iphone.myzaker.com/zaker/link.php?*
32+
// @match https://www.tianyancha.com/security?target=*
33+
// @match https://afdian.net/link?target=*
34+
// @match https://mail.qq.com/cgi-bin/readtemplate*
35+
// @match https://link.logonews.cn/?*
36+
// @match https://link.uisdc.com/?redirect=*
37+
// @version 0.15.0
38+
// @run-at document-idle
39+
// @namespace https://old-panda.com/
40+
// @require https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js
41+
// @license GPLv3 License
42+
// ==/UserScript==
43+
44+
const $ = jQuery.noConflict(true)
45+
;(function () {
46+
'use strict'
47+
48+
const curURL = window.location.href
49+
50+
function rstrip(str, regex) {
51+
let i = str.length - 1
52+
while (i >= 0) {
53+
if (!str[i].match(regex)) {
54+
break
55+
}
56+
i--
57+
}
58+
return str.substring(0, i + 1)
59+
}
60+
61+
/**
62+
* Split concatenated URL string into separate URLs.
63+
* @param {String} str
64+
*/
65+
function splitMultiURLs(str) {
66+
let results = new Array()
67+
let entry = ''
68+
while (str.length > 0) {
69+
if (str.indexOf('http:') === -1 && str.indexOf('https:') === -1) {
70+
entry += str
71+
str = ''
72+
results.push(rstrip(entry, /[@:%_\+~#?&=,$^\*]/g))
73+
break
74+
}
75+
76+
if (str.startsWith('http:')) {
77+
entry += 'http:'
78+
str = str.substring('http:'.length)
79+
} else if (str.startsWith('https:')) {
80+
entry += 'https:'
81+
str = str.substring('https:'.length)
82+
} else {
83+
return results
84+
}
85+
86+
let nextIndex = Math.min(
87+
str.indexOf('https:') === -1 ? Number.MAX_SAFE_INTEGER : str.indexOf('https:'),
88+
str.indexOf('http:') === -1 ? Number.MAX_SAFE_INTEGER : str.indexOf('http:')
89+
)
90+
if (nextIndex > 0) {
91+
entry += str.substring(0, nextIndex)
92+
str = str.substring(nextIndex)
93+
}
94+
results.push(rstrip(entry, /[@:%_\+~#?&=,$^\*]/g))
95+
entry = ''
96+
}
97+
return results
98+
}
99+
100+
/**
101+
* Replace url with clickable `<a>` tag in html content.
102+
* @param {String} url
103+
*/
104+
function replaceSingleURL(url) {
105+
$('#js_content').html((_, html) => {
106+
return html.replace(url, `<a target="_blank" rel="noopener noreferrer" href="${url}">${url}</a>`)
107+
})
108+
}
109+
110+
/**
111+
* Make urls clickable again on Weixin Media Platform.
112+
*/
113+
function enableURLs() {
114+
let existingLinks = new Set()
115+
$('a').each(function () {
116+
existingLinks.add(this.href)
117+
})
118+
119+
let content = $('#js_content').text()
120+
let urls = content.matchAll(
121+
/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g
122+
)
123+
let replaced = new Set()
124+
for (let value of urls) {
125+
let urlStr = $.trim(value[0])
126+
for (let url of splitMultiURLs(urlStr)) {
127+
if (
128+
!url ||
129+
replaced.has(url) ||
130+
url.includes('localhost') ||
131+
url.includes('127.0.0.1') ||
132+
existingLinks.has(url)
133+
) {
134+
continue
135+
}
136+
if (url.endsWith('.') && url[url.length - 2].match(/\d/g)) {
137+
url = url.substring(0, url.length - 2)
138+
}
139+
replaceSingleURL(url)
140+
replaced.add(url)
141+
}
142+
}
143+
}
144+
145+
function redirect(fakeURLStr, trueURLParam, enableBase64 = false) {
146+
let fakeURL = new URL(fakeURLStr)
147+
let trueURL = fakeURL.searchParams.get(trueURLParam)
148+
if (enableBase64) trueURL = window.atob(trueURL)
149+
if (trueURL.indexOf('http://') !== 0 && trueURL.indexOf('https://') !== 0) {
150+
trueURL = 'https://' + trueURL
151+
}
152+
window.location.replace(trueURL)
153+
}
154+
155+
/**
156+
* @function
157+
* @name match
158+
* @param {...string} patterns
159+
* @description check if current URL matchs given patterns
160+
*/
161+
const match = (...patterns) => patterns.some(p => curURL.includes(p))
162+
163+
/**
164+
* @function
165+
* @name matchRegex
166+
* @param {...string} patterns regex patterns
167+
* @description check if current URL matchs given regex patterns
168+
*/
169+
const matchRegex = (...patterns) => patterns.some(p => curURL.search(p) > -1)
170+
171+
/**
172+
* @enum {string}
173+
* @name fuckers
174+
* @description all link pattern needed deal with
175+
*/
176+
const fuckers = {
177+
weibo: 'http://t.cn/', // 微博网页版
178+
weibo2: 'https://weibo.cn/sinaurl?',
179+
// http://t.cn/RgAKoPE
180+
// https://weibo.cn/sinaurl?u=https%3A%2F%2Fwww.freebsd.org%2F
181+
// https://weibo.cn/sinaurl?toasturl=https%3A%2F%2Ftime.geekbang.org%2F
182+
// https://weibo.cn/sinaurl?luicode=10000011&lfid=230259&u=http%3A%2F%2Ft.cn%2FA6qHeVlf
183+
jianshu: 'https://www.jianshu.com/go-wild?',
184+
zhihu: 'https://link.zhihu.com/?',
185+
zhihu2: 'http://link.zhihu.com/?',
186+
// https://link.zhihu.com/?target=https%3A%2F%2Ftime.geekbang.org%2F
187+
// https://link.zhihu.com/?target=https%3A%2F%2Fwww.freebsd.org%2F
188+
// https://link.zhihu.com/?utm_oi=35221042888704&target=https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import
189+
douban: 'https://www.douban.com/link2/?url=',
190+
dilian: 'https://link.ld246.com/forward?goto=',
191+
theWorst: 'https://mp.weixin.qq.com/',
192+
theWorst2: 'https://weixin110.qq.com/cgi-bin/mmspamsupport-bin/newredirectconfirmcgi',
193+
yy: 'http://redir.yy.duowan.com/warning.php?url=',
194+
csdn: 'https://link.csdn.net/?target=',
195+
steam: 'https://steamcommunity.com/linkfilter/?url=',
196+
gamebilibili: 'https://game.bilibili.com/linkfilter/?url=',
197+
oschina: 'https://www.oschina.net/action/GoToLink?url=',
198+
weixindev: 'https://developers.weixin.qq.com/community/middlepage/href?href=',
199+
qqdocs: 'https://docs.qq.com/scenario/link.html?url=',
200+
pixiv: 'https://www.pixiv.net/jump.php?url=',
201+
chinaz: 'https://www.chinaz.com/go.shtml?url=',
202+
doc360: 'http://www.360doc.com/content/',
203+
nga: 'https://nga.178.com/read.php?',
204+
nga2: 'https://bbs.nga.cn/read.php?',
205+
qq: 'http://c.pc.qq.com/(middlem|index).html',
206+
qq2: 'https://c.pc.qq.com/(middlem|index).html',
207+
yuque: 'https://www.yuque.com/r/goto?url=',
208+
mcbbs: 'https://www.mcbbs.net/plugin.php?id=link_redirect&target=',
209+
juejin: 'https://link.juejin.cn/?target=',
210+
doc360_2: 'http://www.360doc.cn/outlink.html?url=',
211+
doc360_3: 'https://www.360doc.cn/outlink.html?url=',
212+
tieba: 'https://jump2.bdimg.com/safecheck/index?url=',
213+
zaker: 'http://iphone.myzaker.com/zaker/link.php?',
214+
zaker2: 'https://www.360doc.cn/outlink.html?url=',
215+
tianyancha: 'https://www.tianyancha.com/security?target=',
216+
afdian: 'https://afdian.net/link?target=',
217+
qqmail: 'https://mail.qq.com/cgi-bin/readtemplate',
218+
logonews: 'https://link.logonews.cn/?',
219+
uisdc: 'https://link.uisdc.com/?redirect='
220+
}
221+
222+
$(document).ready(function () {
223+
if (match(fuckers.weibo, fuckers.weibo2)) {
224+
const link = $('.wrap .link').first().text() || document.querySelector('.open-url').children[0].href
225+
window.location.replace(link)
226+
}
227+
if (match(fuckers.jianshu)) {
228+
redirect(curURL, 'url')
229+
}
230+
if (match(fuckers.zhihu, fuckers.zhihu2)) {
231+
redirect(curURL, 'target')
232+
}
233+
if (match(fuckers.douban)) {
234+
redirect(curURL, 'url')
235+
}
236+
if (match(fuckers.dilian)) {
237+
redirect(curURL, 'goto')
238+
}
239+
if (match(fuckers.theWorst)) {
240+
enableURLs()
241+
}
242+
if (match(fuckers.yy)) {
243+
redirect(curURL, 'url')
244+
}
245+
if (match(fuckers.theWorst2)) {
246+
window.location.replace($('.weui-msg__desc').first().text())
247+
}
248+
if (match(fuckers.csdn)) {
249+
redirect(curURL, 'target')
250+
}
251+
if (match(fuckers.steam)) {
252+
redirect(curURL, 'url')
253+
}
254+
if (match(fuckers.gamebilibili)) {
255+
redirect(curURL, 'url')
256+
}
257+
if (match(fuckers.oschina)) {
258+
redirect(curURL, 'url')
259+
}
260+
if (match(fuckers.weixindev)) {
261+
redirect(curURL, 'href')
262+
}
263+
if (match(fuckers.qqdocs)) {
264+
redirect(curURL, 'url')
265+
}
266+
if (match(fuckers.pixiv)) {
267+
redirect(curURL, 'url')
268+
}
269+
if (match(fuckers.chinaz)) {
270+
redirect(curURL, 'url')
271+
}
272+
if (match(fuckers.doc360)) {
273+
$('#articlecontent table tbody tr td#artContent').find('a').off('click')
274+
}
275+
if (match(fuckers.nga, fuckers.nga2)) {
276+
$('#m_posts #m_posts_c a').prop('onclick', null).off('click')
277+
}
278+
if (matchRegex(fuckers.qq, fuckers.qq2)) {
279+
redirect(curURL, 'pfurl')
280+
}
281+
if (match(fuckers.yuque)) {
282+
redirect(curURL, 'url')
283+
}
284+
if (match(fuckers.mcbbs)) {
285+
redirect(curURL, 'target')
286+
}
287+
if (match(fuckers.juejin)) {
288+
redirect(curURL, 'target')
289+
}
290+
if (match(fuckers.doc360_2, fuckers.doc360_3)) {
291+
redirect(curURL, 'url')
292+
}
293+
if (match(fuckers.tieba)) {
294+
window.location.replace(document.getElementsByClassName('btn')[0].getAttribute('href'))
295+
}
296+
if (match(fuckers.zaker, fuckers.zaker2)) {
297+
redirect(curURL, 'b', true)
298+
}
299+
if (match(fuckers.tianyancha)) {
300+
redirect(curURL, 'target')
301+
}
302+
if (match(fuckers.afdian)) {
303+
redirect(curURL, 'target')
304+
}
305+
if (match(fuckers.qqmail)) {
306+
redirect(curURL, 'gourl')
307+
}
308+
if (match(fuckers.logonews)) {
309+
redirect(curURL, 'url')
310+
}
311+
if (match(fuckers.uisdc)) {
312+
redirect(curURL, 'redirect')
313+
}
314+
})
315+
})()

manifest.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"name": "Fuck Redirect",
3+
"description": "rebuild the superhighway of the information age",
4+
"version": "1.0",
5+
"manifest_version": 3,
6+
"background": {
7+
"service_worker": "background.js",
8+
"type": "module"
9+
},
10+
// "externally_connectable": {
11+
// "matches": ["https://link.juejin.cn/?target=*"]
12+
// }
13+
"permissions": ["tabs"]
14+
}

src/index.ts

Whitespace-only changes.

src/util/index.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
const lastIndexOfPro = (str: string, search: string | RegExp) => {
2+
let i = str.length - 1
3+
while (i >= 0) {
4+
if (!str[i].match(search)) {
5+
return i
6+
}
7+
i -= 1
8+
}
9+
return -1
10+
}
11+
12+
const includesPro = (str: string, search: string | RegExp) => str.search(search) >= 0
13+
14+
const substringLastIndex = (str: string, search: string | RegExp) =>
15+
str.substring(0, lastIndexOfPro(str, search) + 1)
16+
17+
// const splitMulti = (str: string) => {
18+
// const results = new Array()
19+
// }
20+
21+
const createUrl = (url: string | URL) => new URL(url)
22+
23+
const isValidUrl = (url: string) => includesPro(url, /^https?:\/\//)
24+
25+
const isInvalidUrl = (url: string) => !isValidUrl(url)
26+
27+
const redirect = (fakeUrl: string | URL, realUrlParam: string) => {
28+
fakeUrl = createUrl(fakeUrl)
29+
let realUrl = fakeUrl.searchParams.get(realUrlParam)
30+
realUrl = decodeURIComponent(realUrl)
31+
if (isInvalidUrl(realUrl)) {
32+
realUrl = 'https://' + realUrl
33+
}
34+
window.location.replace(realUrl)
35+
}

0 commit comments

Comments
 (0)