// ==UserScript==
// @name youtube广告拦截
// @namespace http://tampermonkey.net/
// @version 1.1.4
// @description 拦截所有youtube广告,不留白,不闪屏,体验第一。已适配移动端,支持自定义拦截
// @author hua
// @match https://www.youtube.com/*
// @match https://m.youtube.com/*
// @connect https://update.greasyfork.icu/
// @grant unsafeWindow
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// @run-at document-start
// @license MIT
// ==/UserScript==
const open_config_keyword = '2333'
let open_recommend_shorts = GM_getValue("open_recommend_shorts", false);
let open_recommend_movie = GM_getValue("open_recommend_movie", false);
let open_recommend_popular = GM_getValue("open_recommend_popular", false);
let open_recommend_liveroom = GM_getValue("open_recommend_liveroom", false);
const script_url = 'https://update.greasyfork.icu/scripts/480192/youtube%E5%B9%BF%E5%91%8A%E6%8B%A6%E6%88%AA.user.js'
let href = location.href
let home_page_ytInitialData_ad_rule
let watch_page_ytInitialData_ad_rule
let ytInitialPlayerResponse_ad_rule
let open_debugger = false
let isinint = false
let mobile_web
url_observer()
init()
function init() {
log('初始化开始!', 0)
config_init()
let ytInitialPlayerResponse_value = unsafeWindow['ytInitialPlayerResponse']
Object.defineProperty(unsafeWindow, 'ytInitialPlayerResponse', {
get: function () {
return ytInitialPlayerResponse_value
},
set: function (value) {
let start_time = new Date().getTime()
value && obj_process(value, ytInitialPlayerResponse_ad_rule, true)
log('ytInitialPlayerResponse 时间:', new Date().getTime() - start_time, 1);
ytInitialPlayerResponse_value = value
}
});
let ytInitialData_value = unsafeWindow['ytInitialData']
Object.defineProperty(unsafeWindow, 'ytInitialData', {
get: function () {
return ytInitialData_value
},
set: function (value) {
let start_time = new Date().getTime()
if (/watch/.test(href)) {
value && obj_process(value, watch_page_ytInitialData_ad_rule, true)
ytInitialData_value = value
} else {
value && obj_process(value, home_page_ytInitialData_ad_rule, true)
ytInitialData_value = value
}
log('ytInitialData 时间:', new Date().getTime() - start_time, 1);
}
});
Object.defineProperty(navigator, 'userAgent', {
get: function () {
return 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36'
}
})
let origin_creatElement = document.createElement
document.createElement.toString = origin_creatElement.toString
document.createElement = function () {
let node = origin_creatElement.apply(this, arguments)
if (arguments[0] === 'template') {
let innerhtml_getter = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML").get;
let innerhtml_setter = Object.getOwnPropertyDescriptor(Element.prototype, "innerHTML").set;
Object.defineProperty(node, 'innerHTML', {
get: function () {
return innerhtml_getter.call(node)
},
set: function (value) {
// if (value.toString().indexOf('ytd-continuation-item-renderer')>-1){
// if (href.indexOf('https://www.youtube.com/watch')>-1){
// value = ''
// log(value);
// log('弹窗去掉------->ytd-continuation-item-renderer');
// }
// }
if (value.toString().indexOf('yt-mealbar-promo-renderer') > -1) {
log('弹窗去掉------->yt-mealbar-promo-renderer', 1);
value = ''
}
innerhtml_setter.call(node, value)
}
})
}
return node
}
async function deal_resposn(name,response,rule){
const responseClone = response.clone();
let result = await responseClone.text()
let start_time = new Date().getTime()
result = text_process(result, rule, 'insert', true)
log(name+' 时间:', new Date().getTime() - start_time, 1);
return new Response(result, response)
}
const originFetch = fetch;
unsafeWindow.fetch = (uri, options) => {
async function fetch_request(response) {
let url = response.url
return_response = response
if (url.indexOf('youtubei/v1/next') > -1) {
return await deal_resposn('next',response,watch_page_ytInitialData_ad_rule)
}
if (url.indexOf('youtubei/v1/player') > -1) {
return await deal_resposn('player', response, ytInitialPlayerResponse_ad_rule)
}
if (url.indexOf('youtubei/v1/browse') > -1) {
return await deal_resposn('browse', response, home_page_ytInitialData_ad_rule)
}
if (url.indexOf('https://m.youtube.com/youtubei/v1/guide') > -1) {
return await deal_resposn('guide', response, home_page_ytInitialData_ad_rule)
}
return return_response
}
return originFetch(uri, options).then(fetch_request);
}
document.addEventListener('DOMContentLoaded', function () {
!mobile_web && search_listener()
checke_update()
})
isinint = true
log('初始化结束!', 0)
}
function config_init() {
let column_recommend_rule
let item_label_fifter_rule
let watch_page_item_label_fifter_rule
let home_page_item_label_fifter_rule
mobile_web = href.indexOf('https://m.youtube.com/') > -1
ytInitialPlayerResponse_ad_rule = watch_page_ytInitialData_ad_rule = home_page_ytInitialData_ad_rule = null
//打开直播频道
let open_live_channel = false
if (href.indexOf('channel/UC4R8DWoMoI7CAwX8_LjQHig') > -1) open_live_channel = true
if (mobile_web) {
column_recommend_rule = 'reelShelfRenderer.title.runs[0].text......=- ~='
mobile_web_extra_column_recommend_rule = 'pivotBarItemRenderer.title.runs[0].text.....=- ~='
// 直播规则
let ad_label = 'metadataBadgeRenderer.label.....=- ~=赞助商广告'
if (!open_recommend_movie) ad_label += '|免费(含广告)'
item_label_fifter_rule = [ad_label]
home_page_item_label_fifter_rule = watch_page_item_label_fifter_rule = item_label_fifter_rule
if (!open_recommend_liveroom || open_live_channel) {
item_label_fifter_rule.push('text.accessibility.accessibilityData.label........=- ~=直播')
home_page_item_label_fifter_rule = item_label_fifter_rule
watch_page_item_label_fifter_rule = item_label_fifter_rule
}
} else {
column_recommend_rule = 'richShelfRenderer.title.runs[0].text......=- ~='
let ad_label
if (href.indexOf('watch') > -1) {
ad_label = 'metadataBadgeRenderer.label.....=- ~=赞助商广告'
} else {
ad_label = 'metadataBadgeRenderer.label......=- ~=赞助商广告'
}
if (!open_recommend_movie) ad_label += '|免费(含广告)'
item_label_fifter_rule = [ad_label]
home_page_item_label_fifter_rule = watch_page_item_label_fifter_rule = item_label_fifter_rule
if (!open_recommend_liveroom || open_live_channel) {
item_label_fifter_rule.push('text.accessibility.accessibilityData.label........=- ~=直播')
watch_page_item_label_fifter_rule = item_label_fifter_rule.concat(['metadataBadgeRenderer.label.....=- ~=直播'])
home_page_item_label_fifter_rule = item_label_fifter_rule.concat(['metadataBadgeRenderer.label......=- ~=直播'])
}
}
let column_recommend_list = []
if (!open_recommend_shorts) column_recommend_list.push('Shorts')
if (!open_recommend_movie) column_recommend_list.push('免费 Primetime 电影')
if (!open_recommend_popular) column_recommend_list.push('时下流行')
if (column_recommend_list.length > 0) {
column_recommend_rule += column_recommend_list.join('|')
if (mobile_web) mobile_web_extra_column_recommend_rule += column_recommend_list.join('|')
}
home_page_ytInitialData_ad_rule = [
'title.runs[0].text......=- ~=YouTube Premium|你对这个视频有何看法?|此推荐内容怎么样?',
'richGridRenderer.masthead=-',
'videoOwnerRenderer=- /.purchaseButton.buttonRenderer.text.simpleText~=试用',
'adSlotRenderer..=-',
]
if (home_page_item_label_fifter_rule) home_page_ytInitialData_ad_rule = home_page_ytInitialData_ad_rule.concat(home_page_item_label_fifter_rule)
if (!open_recommend_shorts || !open_recommend_movie || !open_recommend_popular) {
home_page_ytInitialData_ad_rule.push(column_recommend_rule)
if (mobile_web) {
home_page_ytInitialData_ad_rule.push(mobile_web_extra_column_recommend_rule)
}
}
watch_page_ytInitialData_ad_rule = [
'tvfilmOfferModuleRenderer=- /.masthead$exist',
'merchandiseShelfRenderer=-',
'adSlotRenderer.=-'
]
if (watch_page_item_label_fifter_rule) watch_page_ytInitialData_ad_rule = watch_page_ytInitialData_ad_rule.concat(watch_page_item_label_fifter_rule)
ytInitialPlayerResponse_ad_rule = [
"abs:playerAds=-",
"abs:adPlacements=-",
"abs:adBreakHeartbeatParams=-",
"abs:adSlots=-",
]
if (isinint) {
setTimeout(search_listener, 500)
}
}
function search_listener() {
const search_selector = href.indexOf('https://m.youtube.com/') > -1 ? 'input.searchbox-input.title' : 'input[id="search"]'
const search_input_node = document.querySelector(search_selector)
if (search_input_node) {
search_input_node.oninput = function (event) {
if (open_config_keyword === this.value) {
setTimeout(function () {
if (search_input_node.value === open_config_keyword) {
display_config_win()
}
}, 500)
}
};
}
}
function url_observer() {
if (unsafeWindow.navigation) {
navigation.addEventListener('navigate', (event) => {
url_change(event)
});
return
}
const _historyWrap = function (type) {
const orig = unsafeWindow.history[type];
const e = new Event(type);
return function () {
const rv = orig.apply(this, arguments);
e.arguments = arguments;
unsafeWindow.dispatchEvent(e);
return rv;
};
};
unsafeWindow.history.pushState = _historyWrap('pushState');
unsafeWindow.history.replaceState = _historyWrap('replaceState');
unsafeWindow.addEventListener('replaceState', function (event) {
url_change()
})
unsafeWindow.addEventListener('pushState', function (event) {
url_change()
});
unsafeWindow.addEventListener('popstate', function (event) {
url_change()
})
unsafeWindow.addEventListener('hashchange', function (event) {
url_change()
})
}
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 log() {
let arguments_arr = [...arguments]
let flag = arguments_arr.pop()
if (flag === 0 || open_debugger) console.log(...arguments_arr);
}
function display_config_win() {
const css_str = '#set_list { z-index:9999999999; display: flex; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%); padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; background-color: #fff; border: 1px solid #ccc; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 10px; } #set_button { margin: 0 10px; display: inline-block; padding: 5px 10px; background-color: #3498db; color: #fff; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } #set_button:hover { background-color: #2980b9; }'
const style = document.createElement("style");
style.innerText = css_str;
document.querySelector('body').appendChild(style)
const config_info = {
"open_recommend_movie": "电影推荐",
"open_recommend_shorts": "Shorts推荐",
"open_recommend_liveroom": "直播推荐",
"open_recommend_popular": "时下流行",
}
const container = document.createElement("div");
container.id = "set_list"
for (let key in config_info) {
let label = document.createElement("label")
let input = document.createElement("input")
input.id = key
input.type = 'checkbox'
input.checked = eval(key)
label.appendChild(input)
let span = document.createElement("span")
span.textContent = config_info[key]
span.style.userSelect = 'none'
label.appendChild(span)
container.appendChild(label)
}
let button = document.createElement("button")
button.id = "set_button"
button.textContent = '保存'
button.onclick = function () {
for (let key in config_info) {
GM_setValue(key, document.querySelector('#' + key).checked);
}
document.querySelector('body').removeChild(container)
}
container.appendChild(button)
document.querySelector('body').appendChild(container)
let search_list_node = document.querySelector('body > div.gstl_50.sbdd_a')
if (search_list_node) {
search_list_node.style.display = 'none'
}
}
function display_update_win() {
function btn_click() {
btn = this
if (btn.id === 'go_btn') {
location.href = script_url
}
document.querySelector('body').removeChild(container)
}
const css_str = "#update_tips_win { z-index:9999999999; display: flex; position: fixed; bottom: 20px; right: 20px; padding: 10px 20px; background-color: #fff; border: 1px solid #ccc; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); border-radius: 10px; } .btn { margin: 0 10px; display: inline-block; padding: 5px 10px; background-color: #3498db; color: #fff; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s ease; } .btn:hover { background-color: #2980b9; }";
const style = document.createElement("style");
style.innerText = css_str;
document.querySelector('body').appendChild(style)
const container = document.createElement("div")
container.id = "update_tips_win"
const span = document.createElement("span")
span.textContent = GM_info.script.name + '有更新了!!'
container.appendChild(span)
const go_btn = document.createElement("button")
go_btn.textContent = 'GO'
go_btn.id = 'go_btn'
go_btn.className = 'btn'
go_btn.onclick = btn_click
container.appendChild(go_btn)
const no_btn = document.createElement("button")
no_btn.textContent = 'NO'
no_btn.className = 'btn'
no_btn.id = 'no_btn'
no_btn.onclick = btn_click
container.appendChild(no_btn)
document.querySelector('body').appendChild(container)
}
function checke_update() {
let last_check_time = GM_getValue('last_check_time', 0)
if ((new Date().getTime() - last_check_time) < 1000 * 60 * 60 * 24) return
GM_xmlhttpRequest({
method: 'GET',
url: script_url,
onload: function (response) {
const onlineScript = response.responseText;
// 从线上脚本中提取版本号和元数据信息
const onlineMeta = onlineScript.match(/@version\s+([^\s]+)/i);
const onlineVersion = onlineMeta ? onlineMeta[1] : '';
if (onlineVersion > GM_info.script.version) {
display_update_win()
}
}
});
GM_setValue('last_check_time', new Date().getTime())
}
function text_process(data, values, mode, traverse_all) {
mode = mode || 'cover'
if (mode === 'reg') {
for (let value of values) {
let patten_express = value.split(SPLIT_TAG)[0]
let replace_value = value.split(SPLIT_TAG)[1]
let patten = new RegExp(patten_express, "g")
data = data.replace(patten, replace_value)
}
}
if (mode === 'cover') {
data = values[0]
}
if (mode === 'insert') {
traverse_all = traverse_all || false
let json_data = JSON.parse(data)
obj_process(json_data, values, traverse_all)
data = JSON.stringify(json_data)
}
return data
}
function obj_process(json_obj, express_list, traverse_all = false) {
let abs_path_info_list = []
let relative_path_info_list = []
let relative_path_list = []
let relative_short_path_list = []
if (!json_obj) return
function add_data_to_abs_path(path, relative_path, operator, value, condition, array_index, path_extral) {
let tmp
path = path.replace(/\.[\d\w\-\_\$@]+/g, function (match) {
return '["' + match.slice(1) + '"]'
})
if (array_index !== "*") {
tmp = {}
path = path + (array_index ? '[' + array_index + ']' : '')
tmp.path = path
tmp.relative_path = relative_path
tmp.operator = operator
tmp.value = value
tmp.condition = condition
tmp.path_extral = path_extral
abs_path_info_list.push(tmp)
return
}
let array_length
try {
array_length = eval(path + '.length')
if (!array_length) return
} catch (error) {
return
}
for (let tmp_index = array_length - 1; tmp_index >= 0; tmp_index--) {
tmp = {}
tmp.path = path + "[" + tmp_index + "]"
tmp.operator = operator
tmp.value = value
tmp.condition = condition
tmp.path_extral = path_extral
tmp.relative_path = relative_path
abs_path_info_list.push(tmp)
}
}
express_list.forEach(express => {
let reg
let express_type = typeof (express)
let matchs
let conditions
let value
reg = /^(abs:)?([a-zA-Z_0-9\.\*\[\]]*)((=\-|~=|=))(.*)?/
if (express_type === 'string') {
matchs = express.match(reg)
} else {
matchs = express.value.match(reg)
conditions = express.conditions
}
let abs = matchs[1]
let path = matchs[2]
let path_extral_match = path.match(/\/?\.+$/)
let path_extral
if (path_extral_match) {
path_extral = {}
let len
if (path_extral_match[0].indexOf('/') === 0) {
len = path_extral_match[0].length - 1
path_extral['child'] = len
} else {
len = path_extral_match[0].length
path_extral['parent'] = len
}
path = path.slice(0, path.length - len)
}
let operator = matchs[3]
if (express_type === 'string') {
let tmp_value = matchs[5] || ''
let split_index = tmp_value.indexOf(' ')
if (split_index > -1) {
value = tmp_value.substring(0, split_index)
conditions = tmp_value.substring(split_index + 1)
conditions = {
'value': [conditions]
}
} else {
value = tmp_value
}
}
matchs = path.match(/\[(\*?\d*)\]$/)
let array_index
if (matchs) {
path = path.replace(/\[(\*?\d*)\]$/, '')
array_index = matchs[1]
}
if (abs) {
add_data_to_abs_path('json_obj.' + path, path, operator, value, conditions, array_index, path_extral)
} else {
relative_path_list.push(path)
let tmp_short_path = path.split('.').pop()
relative_short_path_list.push(tmp_short_path)
relative_path_info_list.push({
"path": path,
"operator": operator,
"value": value,
"conditions": conditions,
"array_index": array_index,
"path_extral": path_extral
})
}
})
if (relative_path_list.length > 0) {
let dec_list = []
let dec_index_list = []
obj_property_traverse(json_obj, '', {
"short_keys": relative_short_path_list,
"real_keys": relative_path_list
}, dec_list, dec_index_list, traverse_all)
for (let i = 0; i < dec_index_list.length; i++) {
let real_index = dec_index_list[i]
let real_path_info = relative_path_info_list[real_index]
let tmp_path = 'json_obj' + dec_list[i]
add_data_to_abs_path(tmp_path, real_path_info.path, real_path_info.operator, real_path_info.value, real_path_info.conditions, real_path_info.array_index, real_path_info.path_extral)
}
}
abs_path_info_list.sort((a, b) => a > b ? 1 : -1)
for (let path_info of abs_path_info_list) {
if (!obj_conditional(path_info, json_obj)) continue
let operator = path_info.operator
let path = path_info.path
let value = path_info.value
let path_extral = path_info.path_extral
if (path_extral) {
let positions = []
let regex = /\]/g
while ((match = regex.exec(path)) !== null) {
positions.push(match.index);
}
if (positions.length === 0) continue
if ('parent' in path_extral) {
if (positions.length - path_extral['parent'] - 1 < 0) continue
split_index = positions[positions.length - path_extral['parent'] - 1] + 1
path = path.slice(0, split_index)
}
}
if (operator === '=-') {
let math = path.match(/(.*)\[(\d+)\]$/)
if (math) {
let arr_express = math[1]
let index = math[2]
eval(arr_express + '.splice(' + index + ',1)')
log(`依据:${path_info.relative_path}${!path_info.path_extral ? '' : JSON.stringify(path_info.path_extral)}${path_info.operator} ${!path_info.condition ? '' : JSON.stringify(path_info.condition)}`, 1);
log('删除属性-->' + arr_express + '[' + index + ']', 1);
} else {
eval('delete ' + path)
log(`依据:${path_info.relative_path}${!path_info.path_extral ? '' : JSON.stringify(path_info.path_extral)}${path_info.operator} ${!path_info.condition ? '' : JSON.stringify(path_info.condition)}`, 1);
log('删除属性-->' + path, 1);
}
}
if (operator === '~=') {
let search_value = value.split(SPLIT_TAG)[0]
let replace_value = value.split(SPLIT_TAG)[1]
eval(path + '=' + path + '.replace(new RegExp(search_value, "g"), replace_value)')
}
if (operator === '=') {
let type_ = eval('typeof (' + path + ')')
if (value.match(/\{.*\}/)) value = JSON.parse(value)
if (typeof (value) === 'string' && value.match(/\[.*\]/)) value = JSON.parse(value)
if (value === 'undefined') value = undefined
if (value === 'null') value = null
if (type_ === 'number' && !isNaN(value)) value = Number(value)
eval(path + '=value')
log(`依据:${path_info.relative_path}${!path_info.path_extral ? '' : JSON.stringify(path_info.path_extral)}${path_info.operator} ${!path_info.condition ? '' : JSON.stringify(path_info.condition)}`, 1);
log('修改属性-->' + path, 1);
}
}
}
function obj_conditional(express_info, json_obj) {
//json_obj 在eval里直接调用
if (!express_info['condition']) return true
let condition_infos = express_info['condition']
// 与
for (let condition_list of Object.values(condition_infos)) {
let result = false
for (let condition of condition_list) {
let reg = /^([a-zA-Z_0-9\/\.\[\]]*)?(.*)/
let match = condition.match(reg)
let condition_path = match[1]
let mod
if (condition_path) {
if (condition_path.indexOf('/') === 0) {
mod = 'child'
} else if (condition_path.indexOf('.') === 0) {
mod = 'parent'
} else {
mod = 'other'
}
} else {
condition_path = express_info.path
}
let conditional_express = match[2]
if (mod === 'child') {
condition_path = express_info.path + condition_path.slice(1).replace(/\.[\d\w\-\_\$@]+/g, function (match) {
return '["' + match.slice(1) + '"]'
})
}
if (mod === 'parent') {
let reg = /^\.+/
let matchs = condition_path.match(reg)
let positions = []
let regex = /\]/g
while ((match = regex.exec(express_info.path)) !== null) {
positions.push(match.index);
}
if (positions.length > 0) {
let split_index = positions[positions.length - matchs[0].length - 1] + 1
let short_condition_path = condition_path.replace(reg, '')
if (!/^\[/.test(short_condition_path)) {
short_condition_path = '.' + short_condition_path
}
condition_path = express_info.path.slice(0, split_index) + short_condition_path.replace(/\.[\d\w\-\_\$@]+/g, function (match) {
return '["' + match.slice(1) + '"]'
})
}
}
if (mod === 'other') {
condition_path = ('json_obj.' + condition_path).replace(/\.[\d\w\-\_\$@]+/g, function (match) {
return '["' + match.slice(1) + '"]'
})
}
let condition_value
try {
condition_value = eval(condition_path)
} catch (error) {
continue
}
result = value_conditional(condition_value, conditional_express)
result && log('条件成立-->', condition_value, 1);
if (result) break
}
if (!result) return false
}
return true
}
function obj_property_traverse(obj, cur_path, dec_infos, dec_list, dec_index_list, traverse_all = false) {
if (Array.isArray(obj)) {
obj.forEach((tmp_obj, index) => {
let tmp_path = cur_path + '[' + index + ']'
if (!tmp_obj || typeof (tmp_obj) !== 'object') return
obj_property_traverse(tmp_obj, tmp_path, dec_infos, dec_list, dec_index_list, traverse_all)
})
return
}
Object.keys(obj).forEach((key) => {
let tmp_path = cur_path + '.' + key
let deal = false
for (let i = 0; i < dec_infos["short_keys"].length; i++) {
if (dec_infos["short_keys"][i] === key) {
let len = dec_infos["real_keys"][i].length
if (tmp_path.slice(tmp_path.length - len) === dec_infos["real_keys"][i]) {
dec_list.push(tmp_path)
dec_index_list.push(i)
if (!deal && traverse_all && typeof (obj[key]) === 'object') {
obj_property_traverse(obj[key], tmp_path, dec_infos, dec_list, dec_index_list, traverse_all)
}
deal = true
}
}
}
let value = obj[key]
if (deal || !value || typeof (value) !== 'object') return
obj_property_traverse(value, tmp_path, dec_infos, dec_list, dec_index_list, traverse_all)
})
}
function value_conditional(value, condition_express) {
function excute_eval(express) {
try {
return eval(express)
} catch (error) {
return false
}
}
let reg = /(\$text|\$value|\$exist|\$notexist)?((>=|<=|>|<|~=|=))?(.*)/
let match = condition_express.match(reg)
let condition_type = match[1] || '$text'
let condition_operator = match[2]
let condition_test_value = match[4]
if (condition_type === '$value') {
if (!['>=', '<=', '>', '<', '='].includes(condition_operator)) return false
if (condition_operator === '=') condition_operator = '==='
return excute_eval(value + condition_operator + condition_test_value)
}
if (condition_type === '$exist') {
return excute_eval('value !== undefined && value !== null')
}
if (condition_type === '$notexist') {
return excute_eval('value === undefined || value === null')
}
if (condition_type === '$text') {
if (typeof (value) === 'object') value = JSON.stringify(value)
if (['>=', '<=', '>', '<'].includes(condition_operator)) {
return excute_eval(value.length + condition_operator + condition_test_value.length)
}
if (['=', '~='].includes(condition_operator)) {
return condition_operator === '=' ? value === condition_test_value : new RegExp(condition_test_value).test(value)
}
}
return false
}