🏠 Home 

Tieba No App

解除百度贴吧强制 App 跳转

// ==UserScript==
// @name					Tieba No App
// @namespace			[email protected]
// @author				依然独特
// @description		解除百度贴吧强制 App 跳转
// @version				0.0.3
// @run-at				document-end
// @include				https://tieba.baidu.com/f*
// @include				https://tiebac.baidu.com/f*
// @include				https://tieba.baidu.com/p/*
// @include				https://tiebac.baidu.com/p/*
// @match					https://tieba.baidu.com/f*
// @match					https://tiebac.baidu.com/f*
// @match					https://tieba.baidu.com/p/*
// @match					https://tiebac.baidu.com/p/*
// @grant					unsafeWindow
// @license				CC-BY-4.0
// ==/UserScript==
(function () {
// Only on desktop site `PageData' will be defined
if (unsafeWindow.PageData != null) {
return
} else {
// Make Tieba thinks it is in baidu box app
Object.defineProperties(navigator, Object.getOwnPropertyDescriptors({
userAgent: 'Mozilla/5.0 baiduboxapp0'
}))
// We need `this' binding
const filterIframeSet = function (value) {
const url = new URL(value)
// Hook up baiduboxapp protocol
if (url.protocol === 'baiduboxapp:') {
const data = JSON.parse(decodeURIComponent(url.searchParams.get('params')))
// Hook up deeplink target
if (url.pathname === '//v7/vendor/ad/deeplink') {
const appUrl = new URL(data.appUrl)
// Hook up Tieba target
if (appUrl.protocol === 'com.baidu.tieba:') {
onTiebaUrl(appUrl)
}
}
// Ignore other targets
} else {
setIframeSrc.call(this, value)
}
}
const onTiebaUrl = url => {
const i = url.pathname.lastIndexOf('/')
const path = url.pathname.slice(2, i)
const page = url.pathname.slice(i + 1)
const data1 = restoreData1(url.searchParams)
const data = {
...data1,
param: {
...data1.param,
...restoreData2(page, url.searchParams),
}
}
// Real navigation
if ('pb' === page && data.param.tid) {
location.assign(`https://tieba.baidu.com/p/${data.param.tid}`)
}
}
const restoreData1 = searchParams => {
const {
fr: _fr,  // 'bpush'
bdid, _bdid,
qd: _qd,  // 'scheme
downchannel: _downchannel,
refer, _refer,
eqid, _eqid,
target_scheme,
obj_locate,
obj_source,
obj_name,
obj_param2,
has_token,
extdata,
...custom
} = Object.fromEntries(searchParams)
return {
param: {
obj_locate: obj_locate,
obj_obj_source: obj_source,
obj_originSource: obj_name,
clear_token: has_token,
extdata: extdata,
...custom
},
browser: obj_param2,
target_scheme,
}
}
const restoreData2 = (page, searchParams) => {
const t = Object.fromEntries(searchParams)
if ('pb' === page) {
if (t.tid) {
return { tid: t.tid }
} else {
return {
ori_ugc_nid: t.ori_ugc_nid,
ori_ugc_tid: t.ori_ugc_tid,
ori_ugc_type: t.ori_ugc_type,
ori_ugc_vid: t.ori_ugc_vid,
}
}
} else if ('frs' === page && t.kw) {
return { kw: t.kw }
} else if ('tbwebview' === page && t.url) {
return { url: t.url }
} else if ('usercenter' === page && t.portrait) {
return { portrait: t.portrait }
} else if ('topicdetail' === page && t.topic_id) {
return { topic_id: t.topic_id }
} else if ('item' === page && t.item_id) {
return { item_id: t.item_id }
} else if ('voiceRoom' === page && t.room_id) {
return { room_id: t.room_id }
} else if ('router/portal' === page && t.params) {
return { routerParams: t.params }
} else if ('searchR###ltPage' === page && t.query) {
return { query: t.query }
}
}
// Tieba uses <iframe> src to launch native activity
const { set: setIframeSrc, ...setIframeAttrs } = Object.getOwnPropertyDescriptor(HTMLIFrameElement.prototype, 'src')
Object.defineProperty(HTMLIFrameElement.prototype, 'src', {
...setIframeAttrs,
set: filterIframeSet
})
}
})()