好东西哦(⊙﹏⊙)
< Opinie na 哎呦不错哦(学会看简介 不支持黑号)
現在是
let origin_creatElement = document.createElement
document.createElement.toString = origin_creatElement.toString
document.createElement = function () {
let node = origin_creatElement.apply(this, arguments)
// ...
}
應更正為
const origin_createElement = document.createElement;
document.createElement = function (tagName, options = void 0) {
let node = origin_createElement.call(this, tagName, options);
// ...
}
document.createElement.toString = origin_createElement.toString.bind(origin_createElement);
(注意錯別字 origin_creatElement
)
非常感谢呀,我学习学习
// @match https://www.youtube.com/results*
已被原本的
// @match https://www.youtube.com/*
包含了
if (upcoming_express.includes(path_info.express)) {
那裡加了 try-catch blockif (live_express.includes(path_info.express)) {
那裡加 try-catch block除了 creatElement -> createElement 還有 rsponse -> response
語言部份,應該是反過來吧 非華文的區域就預設英文才對
user_data.language = user_data.language.indexOf('en-') === 0 ? 'en' : 'zh-CN'
修改成
user_data.language = !user_data.language.includes('zh-') ? 'en' : 'zh-CN'
body_ 你只需要string吧。UInt8Array的你不用浪費記憶體儲Cache
unsafeWindow.Request = class extends unsafeWindow.Request {
constructor(input, options = void 0) {
super(input, options);
if (options && typeof options['body'] === "string") this['body_'] = options['body'];
}
};
aaaa.indexOf(bbbb) > -1
這種寫法可以改成
aaaa.includes(bbbb)
會快一點點
document.querySelector('#' + key)
document.getElementById(key)
document.querySelector('body').removeChild(container)
container.remove()
(new Date().getTime()
Date.now()
cookie.indexOf(name) == 0
cookie.startsWith(name)
style.innerText = css_str;
style.textContent = css_str;
缺的就是大佬的指点,感谢感谢。我慢慢改好再放出来
發現Tabview Youtube運作時,發現了以下bug。
原因是 Firefox 不支持 NavigateEvent.destination
(見 https://developer.mozilla.org/en-US/docs/Web/API/NavigateEvent/destination )
建議修改下面代碼
function url_change(event = null) {
if (event && event.destination.url.indexOf('about:blank') === 0) return
href = event ? event.destination.url : location.href
log('网页url改变 href -> ' + href, 0)
config_init()
}
改成
function url_change(event = null) {
const destinationUrl = event?.destination?.url || '';
if (destinationUrl.indexOf('about:blank') === 0) return;
href = destinationUrl || location.href;
log('网页url改变 href -> ' + href, 0);
config_init();
}
詳細代碼: https://github.com/cyfung1031/userscript-supports/raw/main/tmp-480192.user.js
期待你的更新~
更新啦,大佬有空再瞧瞧。这脚本还没做Firefox的兼容,我知道不只这地方,还有其他地方也有挺大的问题的。以后再慢慢做。
另外發現使用了var的問題
這個下次更新時順便修改就好
getCookie
, copyToClipboard
, get_authorization
中的var
都應該改用let
或者const
另外個人建議整個coding部份都應使用 (function(){ ... })();
包住避免變數宣告影響外面
coding油猴会裹一层的的。get_authorization就不改了,抄的要保持原汁原味,哈哈哈
如果多個分頁同時開YouTube,2333的設定會不一致
(Tab1和Tab2同時打開。Tab1按2333改了,Tab2按2333的話會是改動前的設定)
GM_addValueChangeListener
的話可以保持設定一致,不過可能會有bug (因為數值隨時改變)GM.getValue
GM.setValue
GM_getValue
和 GM_setValue
將會被廢除)簡單的話,這樣改就可以
get_user_data_api
裡加新method
getLatestValues(tmp_user_data){
let latest_user_data = GM_getValue(channel_id);
if (latest_user_data) {
Object.assign(tmp_user_data, latest_user_data);
}
}
後面這樣改
(加 user_data_api.getLatestValues(user_data);
)
if (search_input_node.value === open_config_keyword) {
search_input_node.value = '';
user_data_api.getLatestValues(user_data);
display_config_win();
}
這個部份可以不用regexp
let positions = [];
let regex = /\]/g;
while ((match = regex.exec(express_info.path)) !== null) {
positions.push(match.index);
}
let positions = [];
let regex = /\]/g;
let match;
while ((match = regex.exec(path)) !== null) {
positions.push(match.index);
}
改為
function getPositions(path){
let positions = [];
for (let i = 0; i < path.length; i++) {
if (path[i] === ']') {
positions.push(i);
}
}
return positions;
}
/yt_shorts$/.test(page_type)
/^\[/.test(short_condition_path)
都能改為startsWith
/ endsWith
1.配置同步确实没有考虑过。考虑了一下最后我还是决定用GM_addValueChangeListener,这样全部数据都能实时同步,这样更全面一下。至于bug,好像还没发现,我再测试看看。
2. regexp 对于这个,以前就是想着不要用for,看着代码太长了,懒得写又不好看,看下正则能不能一步到位,最后发现js的正则没有这个,最后就抄现在写这一段,代码看着少一点
3..test 这些确实有几个改到的,这次都改啦 。
4. GM.setValue 这几个api确实没仔细看过。GM_setValue 改成GM.setValue 确实挺好的。不过GM_getValue 改成 GM.getValue 的话,还要加await,效果跟 GM_getValue 一样,在我的使用场景下,代码就变得复杂了,这个我觉得还是要保留的。
大佬辛苦了,感谢大佬指点。比心,更新后,期待大佬抽空去瞧瞧
1.4.3 好像改得有點多。有人回報有bug了
regexp 能改 for的話,放到最外面做一個獨立function就好看得多。
部份腳本管理器不支援 GM_setValue
GM_getValue
; 或是不能 GM.setValue
GM_getValue
這樣的組合
我覺得你都用GM_setValue
和 GM_getValue
也沒所謂
如果是簡單的東西,能不使用就不使用regexp吧。速度有差,特別是老電腦。
這種網絡資料請求的結果,盡量效能優先吧
我自己的話在這裡regexp比對之前會先試一下長度。如果長度不夠直接跳過
重覆性的.match的話,我覺得還是有必要改掉啦。for 的話不用拆字符快得多
reg = /^(abs:)?([a-zA-Z_0-9\.\*\[\]]*)((=\-|~=|=\+|=))([\s\S]*)?/;
這個雙重括號有什麼用。。沒看過
((=\-|~=|=\+|=))
([\s\S]*)?
這個寫法應該是有問題的吧
?
*
不會同時存在
你是要
/^(abs:)?([\w\d.*\[\]]+)(=-|~=|=\+|=)([^+=-~].*)?$/
才對吧?
[\.|\[]
你肯定是 [\.|\[]
而不是 [.\[]
? 應該沒|
吧
/^([a-zA-Z_0-9\/\.@\[\]]*)?(.*)/
原因和上面的一樣
應該是 /^([\w\d\/.@\[\]]*)(.*)$/
/channelId":\"(.*?)"/
前面的引號漏了應該是故意?
應該是 /channelId":"(.*)"/
if (base_url.match('https://www.youtube.com/?$')) tmp_page_type = 'yt_home';
else if (base_url.match('https://m.youtube.com/?(#searching)?$')) tmp_page_type = 'mobile_yt_home';
else if (base_url.match('https://www.youtube.com/watch$')) tmp_page_type = 'yt_watch';
else if (base_url.match('https://m.youtube.com/watch$')) tmp_page_type = 'mobile_yt_watch';
else if (base_url.match('https://www.youtube.com/results$')) tmp_page_type = 'yt_search';
else if (base_url.match('https://m.youtube.com/results$')) tmp_page_type = 'mobile_yt_search';
else if (base_url.startsWith('https://www.youtube.com/shorts')) tmp_page_type = 'yt_shorts';
else if (base_url.startsWith('https://m.youtube.com/shorts')) tmp_page_type = 'mobile_yt_shorts';
else if (base_url.match('https://www.youtubekids.com/watch$')) tmp_page_type = 'yt_kids_watch';
else if (base_url.match('https://music.youtube.com/?$')) tmp_page_type = 'yt_music_home';
else if (base_url.match('https://music.youtube.com/watch$')) tmp_page_type = 'yt_music_watch';
這堆都是寫錯吧? 為什麼match裡面是string不是regexp?
建議用 new URL(location.href)
直接分析是哪個TYPE 較好
修正如下 (當然可以再簡化)
function get_page_type() {
let tmp_page_type;
const uo = new URL(href);
const isDesktop = (uo.hostname === 'www.youtube.com');
const isMobile = (uo.hostname === 'm.youtube.com');
const isKids = (uo.hostname === 'www.youtubekids.com');
const isMusic = (uo.hostname === 'music.youtube.com');
if (isDesktop && uo.pathname === '/') tmp_page_type = 'yt_home';
else if (isMobile && uo.pathname === '/') tmp_page_type = 'mobile_yt_home';
else if (isDesktop && uo.pathname === '/watch') tmp_page_type = 'yt_watch';
else if (isMobile && uo.pathname === '/watch') tmp_page_type = 'mobile_yt_watch';
else if (isDesktop && uo.pathname === '/results') tmp_page_type = 'yt_search';
else if (isMobile && uo.pathname === '/results') tmp_page_type = 'mobile_yt_search';
else if (isDesktop && uo.pathname === '/shorts') tmp_page_type = 'yt_shorts';
else if (isMobile && uo.pathname === '/shorts') tmp_page_type = 'mobile_yt_shorts';
else if (isKids && uo.pathname === '/watch') tmp_page_type = 'yt_kids_watch';
else if (isMusic && uo.pathname === '/') tmp_page_type = 'yt_music_home';
else if (isMusic && uo.pathname === '/watch') tmp_page_type = 'yt_music_watch';
else tmp_page_type = 'other';
return tmp_page_type;
}
1. 部份腳本管理器不支援 GM_setValue GM_getValue; 这个还真不太了解额,只在用scriptcat和篡改猴,我就是感觉组合着用挺适合的。官方能出这两个种也是考虑到不同场景把
2. reg = /^(abs:)?([a-zA-Z_0-9\.\*\[\]]*)((=\-|~=|=\+|=))([\s\S]*)?/; 双重括号用来子匹配的 ((=\-|~=|=\+|=)) 这些都是用来提取规则里的操作符的
3. *?是非贪婪模式,就是尽可能匹配少的字符串,没?就是贪婪了
4. [\.|\[] 这个确实有问题,有时候脑抽就会写出来,哈哈哈
while ((match = reg.exec(basic_path)) !== null) {
positions.push(match.index);
} 字符串短的时候这个比for没差多少的,字符串稍微长一点的话,性能比for更好更快的。不信你试下
(a|b|c|d)
本身就會提取
比如說
"I love orange".match(/love\s+(apple|orange|banana)/)
matches[1]
會是orange
比如說
author_id_reg = /"channelId":"(.*?)"/;
你做這個
if (match && match.length > 1) author_id = match[1];
它match的話,match.length一定是2;也不用.*?
這個怪異寫法
.
是萬用符,包括空白和非空白。(不包括換行)
.?
是一個或沒有字元 (n=0,1).+
是一個字元或以上 (n=1,2,...).*
是沒有字元或一個字元或以上 (n=0,1,2...)base_url.match
我查了, String.prototype.match(string)
的話,參數的string會自動變成 new RegExp(string)
"my.home".match('my.home$')
會匹配成功
"my_home".match('my.home$')
也會匹配成功
我也是很好奇,所以做了一個測試
找到了也是一行的寫法
for (let i = 0; (i = path.indexOf(']', i)) >= 0; i++) {
positions.push(i);
}
這個的話在舊browser會明顯較regexp快。新Firefox則是快一點
Chrome的話還是輸RegExp一點點
詳細: https://measurethat.net/Benchmarks/ListResults/30688
document.querySelector('body')
這個可以改成 document.body
limit_eval
的部份重複了 data_process = new DATA_PROCESS();
data_process.set_obj_filter(obj_process_filter);
try {
let test_eval;
eval('test_eval = 1');
limit_eval = test_eval !== 1;
} catch (error) {
limit_eval = true;
}
裡面的 new DATA_PROCESS();
已經算好了 data_process.limit_eval
的值,不用再算一次
(雖然不明白你為何要分開一個全域一個data_process)
data_process = new DATA_PROCESS();
data_process.set_obj_filter(obj_process_filter);
limit_eval = data_process.limit_eval;
另外,limit_eval
除了存值,還有取值吧
try {
let test_eval;
const test_val = 1;
this.limit_eval = eval('test_eval = test_val') && (test_eval !== test_val);
} catch (error) {
this.limit_eval = true;
}
例如 _historyWrap 的部份
const _historyWrap = function (type) {
const orig = unsafeWindow.history[type];
const e = new Event(type);
return function () {
const rv = orig.apply(this, arguments);
try {
e.arguments = arguments;
unsafeWindow.dispatchEvent(e);
} catch (err) { }
return rv;
};
};
這樣的話就算報錯也不會影響原有的 replaceState
/ pushState
其他的騎劫也是同一道理 (包括 define_property_hook
的部份)
get_shorts_info
不清楚為何這裡你用xhr非fetch
xhr的話你除了比對 xhr.status === 200
外,還要檢查 xhr.readyState === XMLHttpRequest.DONE
if (xhr.status === 200 && xhr.readyState === XMLHttpRequest.DONE) {
另外,如果報錯 (reject),parse_shorts_list 那邊只有then和finally,抓取不了錯誤log
parse_shorts_list
parse_shorts_list
最開始應該要 if (!this.shorts_list || this.shorts_list.length === 0) return;
否則 const { id, title, views_lable, thumbnail_url } = this.shorts_list.pop();
可能會報錯 (是有這個機會啦)
(lable是指label吧?)
check_shorts_exist
看不懂 user_data.shorts_list.pop(shorts);
這個部份。首先pop沒有參數傳入的
你用了forloop,shorts
不一定是user_data.shorts_list裡的第一個
有可能本來是想寫 for (let shorts of this.shorts_list) {
嗎??
get_interval_tag
upload_date_str = shorts['upload_date']
可以是 undefined
也就是這個部份配對失敗
const upload_date_math = xhr.responseText.match(upload_date_reg);
if (upload_date_math) upload_date_str = upload_date_math[1] || '';
upload_date_str && !isNaN(new Date(upload_date_str)) && (upload_date = new Date(upload_date_str));
可以這樣改
let uploadDate;
try{
uploadDate = new Date(upload_date_str);
}catch(e){}
if (!uploadDate) return "";
get_user_data_listener
user_data = newValue;
這個不建議啦
user_data應一直都是不變的物件參考 (user_data_api和user_data都是const宣告)
改用 Object.assign(user_data, newValue)
吧
( get_channel_id
裡的 user_data = user_data_api.get();
也是啦)
deal_resposn
-> deal_response
matchs
-> matches
parseing
-> parsing
orgin_
-> origin_
let
-> const
user_data_api
, user_data
, inject_info
, shorts_parse_delay
, data_this
, origin_console
, error_messages
local_this
沒有使用,應刪掉
let page_type = ''; // let page_type;
convertPathToBracketNotation
obj_conditional 那邊也是 convertPathToBracketNotation
吧
condition_path = express_info.path + data_this.convertPathToBracketNotation(condition_path.slice(1));
condition_path = express_info.path.slice(0, split_index) + data_this.convertPathToBracketNotation(short_condition_path);
condition_path = data_this.convertPathToBracketNotation(`json_obj${is_array_obj ? '' : '.'}` + condition_path);
getCookie
getCookie
還是加個 try catch 吧。失敗至少能返回null
(decodeURIComponent
失敗會報錯)
store_user_data
這是舊版本的名稱?已經沒有這個東西。直接報錯
我猜你是指 user_data_api.set();
get_yt_api
裡的 get_subscribe_data
get_subscribe_data(retry + 1)
改為 yt_api.get_subscribe_data(retry + 1)
value_parse
裡的 value_parse(arg)
value_parse(arg)
改為 data_this.value_parse(arg)
obj_conditional
裡 is_array_obj
obj_conditional
裡 沒有 is_array_obj
mod === 'other'
那個 json_obj${is_array_obj ? '' : '.'}
會直接報錯
改成 json_obj${Array.isArray(json_obj) ? '' : '.'}
fetch_
裡的 return_response
let
/ var
/ const
return_response
,直接傳response
就可以了。沒有改動value_parse
裡的 變數沒宣告const method_info = method_match[1].match(/(.*?)\((.*)\)$/);
const method_name = method_info[1];
const method_args_string = method_info[2];
const method_args = method_args_string.split(',');
get_shorts_info
裡 xhr.onload
的 match
未宣告let match = xhr.responseText.match(author_id_reg);
get_authorization
裡 b = Vja();
的 b
未宣告const b = Vja();
update(tmp_user_data)
裡 last_version
未宣告const last_version = GM_getValue('last_version', -1);
display_update_win
裡的 btn
未宣告function btn_click() {
const btn = this;
if (btn.id === 'go_btn') {
location.href = script_url;
}
container.remove();
}
remove_popup_hander
document.addEventListener('click', remove_popup_hander);
之前加
document.removeEventListener('click', remove_popup_hander);
避免重覆 (沒有正確呼叫 remove_popup_hander
就 再次呼叫display_config_win
時)
即
document.removeEventListener('click', remove_popup_hander);
document.addEventListener('click', remove_popup_hander);
XMLHttpRequest
的部份responseText
& response
那個部份你可以直接抄修改版的代碼
DATA_PROCESS
裡的 set_obj_filter = function (obj_filter) {
是寫錯吧
set_obj_filter = function (obj_filter) {
this.obj_filter = typeof obj_filter === 'function' ? obj_filter : undefined;
};
改成
set_obj_filter (obj_filter) {
this.obj_filter = typeof obj_filter === 'function' ? obj_filter : undefined;
}
DATA_PROCESS
裡的 constructor
this.obj_filter;
改成
this.obj_filter = undefined;
config_init
一直log 語言錯誤config_init
不是只有第一次init會執行
全域加
let langProblemLogged = false;
config_init
裡改成
if (!langProblemLogged && !['zh-CN', 'zh-TW', 'zh-HK', 'en'].includes(tmp_language)) {
langProblemLogged = true;
log(`Does not support language ${tmp_language}, only supports zh-CN, zh-TW, zh-HK, en, and is compatible with English locations; there may be some errors.`, -1);
tmp_language = tmp_language.startsWith('en-') ? 'en' : 'zh-CN';
}
getPositions
原來是測試法問題
現在再做一個新測試
這次Firefox, Chrome, Safari, 都有一致結果: indexOf較快
把原本的
const reg = /\]/g;
let match;
while ((match = reg.exec(basic_path)) !== null) {
positions.push(match.index);
}
換成
for (let j = 0; (j = basic_path.indexOf(']', j)) >= 0; j++) {
positions.push(j);
}
就可以
我查了一下你講的 非贪婪模式
現在了解了,我之前都沒用過
感謝
obj_process
這個也看了一下。
我有留意到你在1.4.3搞了 get_relative_path
和改了value_parse
但好像愈搞愈複雜,也沒有看到規則有明顯的變化,所以無視了,基於1.4.2去改
詳細代碼: https://github.com/cyfung1031/userscript-supports/raw/main/tmp-480192.user.js
期待你的更新~
regexp 那裡有改過,之後才理解你講的那個 非贪婪模式
之前的應該也沒bug, 所以隨你改不改吧
比如說, path.match(/\[(.*?)\]/g)
改成了 path.match(/\[([^\(\)]*)\]/g)
這樣明確的寫法
當然 [abc[def]
這樣的話就會有分別
obj_process
裡面的函數宣告都抽出來了。
另外,for (const express of express_list) {
中的 matches
有可能匹對失敗
這個加了防錯log
cur_path + '[' + index + ']';
這個寫法可以改成 ${cur_path}[${index}]
目前W3C比較推這種寫法,也比較直觀
add_data_to_abs_path
那些參數太多了吧。直接用一個Object
再做Object.assign
就可以了吧
obj_property_traverse
裡面的參數傳來傳去會很花CPU處理
直接傳一個Object就好,裡面都是不變的Object參考
if (operator === '=')
執行次序改到前面
因為它不需要 const dec_obj = last_obj[last_key];
express_type
只判斷是否string 的部份改成boolean
path_extral_match
首先你用 [a-zA-Z_0-9\.\*\[\]]*
的話,不會有 \/
也就是 path_extral_match[0].startsWith('/')
永遠false
(或者之前的regex要改?)
然後就是用replace替代了match
relative_path_list
, relative_short_path_list
, relative_path_info_list
原本一拆三的relative_path
改成了relative_path_map
^key
是 real_keys
~key
是 short_keys
但發現 ^key
是不需要加進去所以沒加了
另外加了一個防錯,防止重覆short_keys
1. 就是非贪婪模式重覆了! 有*就不用再?
有?才是非贪婪哦,你可以试下
let test_str = '"channelId":"UC_x5XG1OV2P6uZZ5FSM9Ttw"4545646"';
2.limit_eval 的部份重複了
那个类我是要用在其他脚本。所以里面的就保留了
3. 原生函數部份應加try-catch避免問題 _historyWrap
确实挺多没加捕获的,写的时候没考虑那么多把,后面看到就改一下
4. get_shorts_info xhr.status === 200 外,還要檢查 xhr.readyState === XMLHttpRequest.DONE
这个确实不知道,得加上
5.parseshortslist 那邊只有then和finally,抓取不了錯誤log
这里不捕获错误是因为没必要,youtube会跑出来的,即使捕获了我也
6.parse_shorts_list 否則 const { id, title, views_lable, thumbnail_url } = this.shorts_list.pop(); 可能會報錯 (是有這個機會啦)
按我写的逻辑是不会报错的,因为js单线程执行。不过加上确实更严谨。得加
7.看不懂 user_data.shorts_list.pop(shorts); 這個部份。首先pop沒有參數傳入的
我也看不懂,应该是脑抽了把
8. upload_date_str = shorts['upload_date'] 可以是 undefined
确实有可能,加上if (!upload_date_str) return ''; 就好了,前面字符串
准确性已经校验过了
9.uer_data = newValue; 這個不建議啦 userdata應一直都是不變的物件參考 (userdataapi和userdata都是const宣告)
我觉得uer_data不需要特地的去固定住,现在感觉没什么太大的意义
10.deal_resposn -> deal_response
matchs -> matches
parseing -> parsing
orgin_ -> origin_
这个崩不住了。。。
11. user_data_api, user_data, inject_info, shorts_parse_delay, data_this, origin_console, error_messages let -> const
确实该
1.local_this 沒有使用,應刪掉
确实忘记了
2.let page_type = ''; // let page_type;
直接改赋值好了
3.obj_conditional 那邊也是 convertPathToBracketNotation 吧
那边好像有点差异我都有点忘了,应该不单纯是这样,到时候再理一下思路统一起来
4.getCookie 還是加個 try catch 吧。失敗至少能返回null (decodeURIComponent失敗會報錯)
确实该添加
5.store_user_data
确实忘记删了。哈哈哈
6.函式的class object漏了
get_subscribe_data(retry + 1) 改為 yt_api.get_subscribe_data(retry + 1)
这这一条确实有问题,改一下
value_parse(arg) 改為 data_this.value_parse(arg)
value_parse 裡的 value_parse(arg) 这里是可以自身调用的,上面那个是不在作用域里
1. obj_conditional 裡 is_array_obj
确实是搞错了 应该改成condition_path.startsWith('[')
2.fetch_ 裡的 return_response
以前是想着统一返回的,ok,改了
3.value_parse 裡的 變數沒宣告
确实漏了好多,感谢感谢
4.get_shorts_info 裡 xhr.onload 的 match 未宣告
感谢感谢
5.get_authorization 裡 b = Vja(); 的 b 未宣告
感谢感谢
6. update(tmp_user_data) 裡 last_version 未宣告
感谢感谢
7. display_update_win 裡的 btn 未宣告
感谢感谢
8.remove_popup_hander
确实是有隐患,不过直接在前面加document.removeEventListener('click', remove_popup_hander);
是没用的,remove_popup_hander已经不是原来的对象了,所以给popup添加了个移除函数,移除的时候
调用一下就好了
9. responseText & response 那個部份你可以直接抄修改版的代碼
这些链接都打不开,不知道干嘛
10. DATA_PROCESS 裡的 set_obj_filter = function (obj_filter) { 是寫錯吧
确实不太统一,写完都忘了
11. this.obj_filter;
不需要 this.obj_filter = undefined; 这样的,它就是undefined
12.config_init 一直log 語言錯誤
确实是个问题 ,不过有可能是会切换语言的,我测试的是时候就经常切换。只报错一次也是不太合适
13. 補充上面的 getPositions
别管这个啦,都差不多的
感谢大佬校正,比心
这些链接都打不开,不知道干嘛
按這個看看: https://raw.githack.com/cyfung1031/userscript-supports/main/tmp-480192.user.js
这些链接都打不开,不知道干嘛
按這個看看: https://raw.githubusercontent.com/cyfung1031/userscript-supports/main/tmp-480192.user.js
这些链接都打不开,问题解决了
只有全局代理才能访问,我都是用局部代理的
1.regexp
比如說, path.match(/\[(.*?)\]/g) 改成了 path.match(/\[([^\(\)]*)\]/g) 這樣明確的寫法
我觉得我这种更加容易我理解,规则如果是错的话,整体抛出来就好了,只处理对的部分的话,
感觉不太好
对于里面那些复杂的正则的话,基本是没有错误的,可能写法可以优化一下。乱改的话容易考虑不全,导致错误。
2.obj_process
裡面的函數宣告都抽出來了。
里面的函数是仅对obj_process这函数有用,拿出来是不可以单独作用的。
拿的出来的都可以作用一个独立函数去处理数据。
3.這個寫法可以改成 ${cur_path}[${index}]
模板语法,确实挺好用,有什么变量少就懒得用了
4. add_data_to_abs_path
那些參數太多了吧。直接用一個Object再做Object.assign 就可以了吧
这个确实,功能加多了就变得乱七八糟了
5.obj_property_traverse
裡面的參數傳來傳去會很花CPU處理
直接傳一個Object就好,裡面都是不變的Object參考
传obj就是传一个地址而已,把数据传进去的。
6. if (operator === '=')執行次序改到前面 因為它不需要 const dec_obj = last_obj[last_key];
也行 哈哈哈
7. express_type 只判斷是否string 的部份改成boolean
那里是留了一个功能扩展的,以后类型不只string的
8. 首先你用 [a-zA-Z_0-9\.\*\[\]]* 的話,不會有 \/
这里不是匹配path_extral的 ,[\s\S]*这个才是
9.relative_path_list, relative_short_path_list, relative_path_info_list
原本一拆三的relative_path改成了relative_path_map ^key 是 real_keys ~key 是 short_keys
还没用过map,我都是把对象当map用的,确实map点,这里慢慢来
10. 另外加了一個防錯,防止重覆short_keys
整体给个try-catch好了,单独给的意义不大
1. let array_index = undefined; // don't forget it can be undefined
array_index 后面使用会判断的
2.abs_path_info_list's entries are object-type. a < b is always false. No Sorting
这里确实是,想在这写个排序的一直没写,那条命令估计是倒序了,作用是有的。
这是测试过的
3.xhr部分
参考你的思路改了下。
obj.length >= 4
我是捕获异常让他抛出来
代码行数多的话我是不太喜欢用过多else if ,看着会比较乱,所以还是选择单if
typeof result === 'string' 这个确实也需要判断一下
get responseText()
get response()
对于这两个函数还是喜欢原来这种方式更加好点,这是直接重定向到get xhrResponseValue
这个好像也是你以前提议改的把
你參考一下吧
反正沒bug, 不會拖慢就好
應該把之前那些名字問題,變數未宣告之類的解決就好得多了
remove_popup_hander
已经不是原来的对象了
這個也是。 不想改太多的話,外面放一個變量把舊的存下來吧。 然後addEventListener前刪掉之前的
get responseText()
get response()
這兩個都只是為了抓某幾個網址的資料
像我寫的分開兩個,再進行判斷比較合適。實際操作應該只走其中一個。原本是物件就傳回物件,原本是字串就傳回字串,其他的都不管
現在這個寫法也是重定向,只是只在readyState === XMLHttpRequest.DONE
的時候改 (原本也是)
其他狀態沒改變。這是跟原本 xhrResponseValue
一樣的
但原本沒分開 responseText 和 response 兩者。
let result = super.responseText;
if (super.readyState === XMLHttpRequest.DONE) {
result = this.processResult(result);
}
return result;
避免誤判其他網絡request (像串流的)
obj.length >= 4 我是捕获异常让他抛出来
如果是這樣的話,直接寫 if(obj.length < 4) throw XXXX
這樣會比較好
否則之後你都忘掉這裡會有機會有异常
可預計的异常都先預計出來吧,就像預計 JSON.parse
會有失敗异常一樣
Javascript 的寫法很隨便,變數類型也能改,很容易出錯
更了更了,基本都有错误处理了。没有的再说哈哈哈
args.push(value_parse(arg, path_info, json_obj));
應改為
args.push(this.value_parse(arg, path_info, json_obj));
parse_value = parse_value.replace(express_, eval(express));
你是不是沒考慮 limit_eval = true
的情況?
这里不是匹配
path_extral
的 ,[\s\S]*
这个才是
let value;
reg = /^(abs:)?([a-zA-Z_0-9\.\*\[\]]*)((=\-|~=|=\+|=))([\s\S]*)?/;
if (express_type === 'string') {
matches = express.match(reg);
} else {
matches = express.value.match(reg);
conditions = express.conditions;
}
let abs = matches[1];
let path = matches[2];
let path_extral_match = path.match(/\/?\.+$/);
let path_extral;
if (path_extral_match) {
path_extral = path_extral_match[0];
path = path.replace(path_extral, '');
}
matches
是 express
或 express.value
配對 /^(abs:)?([a-zA-Z_0-9\.\*\[\]]*)((=\-|~=|=\+|=))([\s\S]*)?/;
matches[1] 是 abs:
matches[2] 是 [a-zA-Z_0-9\.\*\[\]]*
matches[3] 是 =\-|~=|=\+|=
matches[4] 是 =\-|~=|=\+|=
matches[5] 是 [\s\S]*
所以 path_extral_match
應該是 matches[5].match(/\/?\.+$/);
而不是 path.match(/\/?\.+$/);
abs_path_info_list.sort((a, b) => a < b ? 1 : -1);
還是有這個。
其他部份有時間再匯報
init_hook_collection
裡的 property 未加 try catch
1. args.push(this.value_parse(arg, path_info, json_obj));
这里确实是漏了,改成类之后没添加。非常感谢,nice
2. parse_value = parse_value.replace(express_, eval(express));
这规则还没确定该怎么做,忘记注释掉了
3. 所以 path_extral_match 應該是 matches[5].match(/\/?\.+$/); 而不是 path.match(/\/?\.+$/);
这里我上次也说错了,path_extral_match 是先从([a-zA-Z_0-9\.\*\[\]]*) 提取,然后再用(/\/?\.+$/)进行二次提取的
path_extral_match
是先从([a-zA-Z_0-9\.\*\[\]]*)
提取,然后再用(/\/?\.+$/)
进行二次提取的
所以 ([a-zA-Z_0-9\.\*\[\]]*)
要改成 ([\/a-zA-Z_0-9\.\*\[\]]*)
還是 (/\/?\.+$/)
要改成 (/\.+$/)
1.abs_path_info_list.sort((a, b) => a < b ? 1 : -1);
在没写出正确的排序之前,这句可以让脚本以奇奇怪怪的方式正常运行,不要还不行
2. init_hook_collection 裡的 property 未加 try catch
里面的函数已经做了处理了,就不在那再做一次了
1.還是 (/\/?\.+$/) 要改成 (/\.+$/)
不能改, /和. 作为开头是两种模式来的
if (name === 'playlist') {
let obj;
try {
obj = JSON.parse(result);
data_process.obj_process(obj.playerResponse, ytInitialPlayerResponse_rule, true);
data_process.obj_process(obj.response, ytInitialData_rule, true);
result = JSON.stringify(obj);
} catch (error) {
log('playlist 解析失败', error, -1);
result = origin_result;
}
is_deal = true;
}
解析失败 的話, is_deal
不應是 true
可以改成
if (name === 'playlist') {
try {
const obj = JSON.parse(result);
data_process.obj_process(obj.playerResponse, ytInitialPlayerResponse_rule, true);
data_process.obj_process(obj.response, ytInitialData_rule, true);
result = JSON.stringify(obj);
is_deal = true;
} catch (error) {
log('playlist 解析失败', error, -1);
}
}
不能改, /和. 作为开头是两种模式来的
([a-zA-Z_0-9\.\*\[\]]*)
不會提取到 \/
if (unsafeWindow.ytcfg.msgs) {
unsafeWindow.ytcfg.msgs.__lang__ && config_init(unsafeWindow.ytcfg.msgs.__lang__);
} else {
unsafeWindow.ytcfg._msgs = unsafeWindow.ytcfg.msgs;
define_property_hook(unsafeWindow.ytcfg, 'msgs', {
get: function () {
return this._msgs;
},
set: function (newValue) {
if (newValue.__lang__) config_init(newValue.__lang__);
this._msgs = newValue;
}
});
}
這個應改成
unsafeWindow.ytcfg._msgs = unsafeWindow.ytcfg.msgs;
define_property_hook(unsafeWindow.ytcfg, 'msgs', {
get: function () {
return this._msgs;
},
set: function (newValue) {
if (newValue.__lang__) config_init(newValue.__lang__);
this._msgs = newValue;
}
});
unsafeWindow.ytcfg.msgs = unsafeWindow.ytcfg._msgs
1.解析失败 的話, is_deal 不應是 true
这里确实true,处理失败也是处理了,下面的逻辑是处理通用类型的。特殊的类型不适用
2.([a-zA-Z_0-9\.\*\[\]]*) 不會提取到 \/
这里确实是,只做了一种规则,另一个种没用到都没做。还得把另一种也做了
3. unsafeWindow.ytcfg._msgs = unsafeWindow.ytcfg.msgs;
啥?上面你为什么干掉了。
Code建議修正部份
Class Function的Override需要修正,見uBO的做法
這種做法才符合類繼承。避免腳本衝突 (包括與YT自身的改動的腳本衝突)
Request
Request部份應改成
XMLHttpRequest
XMLHttpRequest 也需要更改