// ==UserScript==
// @name 微软商店加速下载
// @namespace https://flutas.cqoj.xyz
// @version 11.2.32
// @description 获取微软应用包原始链接,加速下载!
// @author Xbodw
// @match https://apps.microsoft.com/detail/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant unsafeWindow
// @run-at document-end
// @license GPL-3.0
// @grant GM_xmlhttpRequest
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// @grant GM_notification
// @noframes
// ==/UserScript==
/*
Aluk Query Library
(c)2023 Flutas,All rights,Reserved.
(Powered by Xbodw)
Linense MIT
*/
window.aluk = function (select) {
return new querylist(select);
};
aluk.version = '1.4.8';
aluk.language = 'zh-cn';
var querylist = function (selector) {
var ce;
if (selector == '' || selector == undefined) {
ce = '';
return;
}
if (typeof (selector) == 'string' && aluk.checkHtml(selector) === false) {
ce = document.querySelectorAll(selector);
} else {
if (typeof (selector) == 'number') {
ce = '';
} else {
if (typeof (selector) == 'object') {
ce = new Array(selector);
} else {
if (aluk.checkHtml(selector) === true) {
ce = new Array(aluk.htmlToElement(selector));
}
}
}
}
if (ce.length > 1) {
ce.forEach(element => {
this.push(element);
});
} else {
if (ce.length > 0) {
this.push(ce[0]);
}
}
var fn = this;
this.NormalResult = document;
}
querylist.prototype = new Array();
aluk.objectToCss = function (obj) {
return Object.entries(obj)
.map(([key, value]) => `${key}: ${value};`)
//.join('\n');
}
querylist.prototype.SetCss = function (index, cssList) {
if (index > this.length - 1) {
throw new Error('Index超出了预期范围');
} else if (index == undefined || index == null) {
throw new Error('Index为空或不存在');
}
if (typeof (cssList) != 'object') {
throw new Error('Css列表必须为Object');
}
var csst = aluk.objectToCss(cssList);
this[index].style.cssText = '';
var cssaddcount = 0;
csst.forEach(h => {
this[index].style.cssText += h;
cssaddcount++;
})
return cssaddcount;
}
querylist.prototype.AppendorMoveto = function (index, index2, appender) {
var append;
if (appender instanceof querylist) {
if (index > appender.length - 1) {
throw new Error('Index超出了预期范围');
} else if (index == undefined || index == null) {
throw new Error('Index为空或不存在: 如果使用aluk querylist对象代替Element,那么请指定Index');
}
append = appender[index];
} else {
if (!aluk.isHtmlElement(appender)) {
throw new Error('请指定html元素或者aluk querylist对象');
}
append = appender;
}
if (index2 > this.length - 1) {
throw new Error('Index2超出了预期范围');
} else if (index2 == undefined || index2 == null) {
throw new Error('Index2为空或不存在: 选择第几项来插入到appender的' + index2 + '项', '那么请指定Index2');
}
append.appendChild(this[index]);
}
querylist.prototype.RemoveX = function () {
let count = 0;
this.forEach(s => {
s.remove();
count++;
})
return count;
}
querylist.prototype.continue = function (select) {
if (select == undefined || select == '') {
if (aluk.language != 'zh-cn') {
throw new Error('Your Selector was empty or undefined,please.');
} else {
throw new Error('您的选择器为空或未定义');
}
}
var newElements = [];
// 在当前 elements 数组中查找符合选择器的元素,并添加到 newElements 数组中
for (var i = 0; i < this.length; i++) {
var matches = this[i].querySelectorAll(select);
newElements.push(matches);
}
var newQueryList = new querylist('<null>');
newQueryList.shift()
newElements.forEach(y => {
y.forEach(z => {
newQueryList.push(z)
})
})
newQueryList.NormalResult = newQueryList[0];
return newQueryList;
}
querylist.prototype.gsval = function (text) {
if (text == undefined) {
var result = [];
this.forEach(e => {
result.push(e.value)
})
return result;
} else {
this.forEach(e => {
e.value = text;
})
}
}
querylist.prototype.gstext = function (text) {
if (text == undefined) {
var result = [];
this.forEach(e => {
result.push(e.innerText)
})
return result;
} else {
this.forEach(e => {
e.innerText = text;
})
}
}
querylist.prototype.newclicke = function (call) {
if (call == undefined || typeof call != 'function') {
throw new Error('函数为空');
}
this.forEach(ef => {
ef.addEventListener('click', function (e) {
call(e);
})
})
}
aluk.isHtmlElement = function (variable) {
return variable instanceof Element || variable instanceof HTMLElement;
}
aluk.createElementX = function (options) {
if (typeof (options) != 'object') {
if (aluk.language != 'zh-cn') {
throw new Error('Element Options Type Must as the Object');
} else {
throw new Error('Element选项必须是Object');
}
}
if (options.ElementType == undefined) {
if (aluk.language != 'zh-cn') {
throw new Error('Element name not specified or empty')
} else {
throw new Error('Element类型不能为空');
}
}
if (options.ElementType == '') {
if (aluk.language != 'zh-cn') {
throw new Error('Element name not specified or empty')
} else {
throw new Error('Element类型不能为空');
}
}
var result = document.createElement(options.ElementType);
if (options.Class == undefined) {
} else {
result.classList.value += options.Class;
}
if (options.id == undefined) {
} else {
result.id = options.id;
}
if (options.innerHTML == undefined) {
} else {
result.innerHTML = options.innerHTML;
}
return aluk(result);
}
aluk.htmlEscape = function (htmlStr) {
return htmlStr.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '<';
case '>':
return '>';
case '"':
return '"';
case '&':
return '&';
}
})
}
aluk.htmlUnescape = function (html) {
return html.replace(/<|>|"|&/g, match => {
switch (match) {
case '<':
return '<';
case '>':
return '>';
case '"':
return '"';
case '&':
return '&';
}
})
}
aluk.appendHTMLX = function (appender, element, options) {
if (appender == undefined) {
if (aluk.language != 'zh-cn') {
throw new Error('AppendElement name not specified or empty')
} else {
throw new Error('追加者Element类型不能为空');
}
}
if (element == undefined) {
if (aluk.language != 'zh-cn') {
throw new Error('Append HTML not specified or empty')
} else {
throw new Error('追加的HTML不能为空');
}
}
if (typeof (options) != 'boolean') {
if (options != undefined) {
if (aluk.language != 'zh-cn') {
throw new Error('Options not specified or empty')
} else {
throw new Error('选项为空或不存在');
}
}
}
let fixr = element.innerHTML;
let fixed = fixr;
if (options) {
fixed = aluk.htmlEscape(fixr);
}
appender.innerHTML += fixed;
return Promise.resolve(appender.innerHTML);
}
aluk.checkHtml = function (htmlStr) {
var reg = /<[a-z][\s\S]*>/i;
return reg.test(htmlStr);
}
aluk.htmlToElement = function (html) {
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html');
return doc.body.firstChild;
}
aluk.Request = function (method, url, data, onlyheader, resultX) {
if (typeof resultX != 'function') {
throw new Error('返回函数不能为空')
}
const xhr = new XMLHttpRequest();
xhr.open(method, url, true);
//xhr.setRequestHeader('User-Agent', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36');
if (onlyheader != undefined) {
xhr.setRequestHeader('Content-Type', onlyheader);
}
xhr.onload = function () {
if (xhr.status === 200) {
resultX(xhr.response);
} else {
resultX(xhr.statusText);
}
};
xhr.onerror = function () {
reject('Network error');
};
xhr.send(data);
}
aluk.encodeX = function (code,key) {
var keys;
if(key == undefined) {
keys = '0';
} else {
keys = key;
}
var codeb;
if (typeof code == 'object') {
codeb = JSON.stringify(code)
} else {
codeb = code;
}
var codea = window.btoa(window.encodeURI(codeb));
var lista = [];
for (var i = 0; i < codea.length; i++) {
var asciic = escape(codea.charCodeAt(i)).replace(/\%u/g, '/u');
lista.push(asciic);
} return lista;
}
aluk.decodeX = function (code,key) {
if (!Array.isArray(code)) { return }
var keys;
if(key == undefined) {
keys = '0';
} else {
keys = key;
}
var result = '';
var resultb = '';
code.forEach(e => {
var sh = unescape(String.fromCharCode(e)).replace(/\/u/g, '%u');
resultb += sh;
})
result = window.decodeURI(window.atob(resultb));
return result;
}
function Alarm(construct, title) {
this.onalarmisdiscard = null; // 初始化 onalarmisdiscard 事件为 null
this.obj = construct;
this.title = '提示';
if (title != undefined) {
this.title = title;
}
}
// 定义 show 函数
Alarm.prototype.show = function () {
// 创建提示框元素
var alarmBox = document.createElement('div');
alarmBox.className = 'alarm-box';
alarmBox.innerHTML = '<h4 id="alarm-title">' + this.title + '</h4><span id="alarm-text">' + this.obj + '</span>';
// 创建关闭按钮元素
var closeButton = document.createElement('div');
closeButton.className = 'close-button';
closeButton.innerText = '×';
alarmBox.appendChild(closeButton);
var styleElement = document.createElement('style');
styleElement.classList.add('alarmbox-style');
var cssCode = `
.alarm-box {
position: fixed;
top: 20px;
left: 0px;
right: 0px;
width: 300px;
margin: auto;
padding: 20px;
background-color: #f9f9f9;
border-radius: 5px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 9999;
}
.alarm-box .close-button {
position: absolute;
top: 10px;
right: 10px;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
cursor: pointer;
color: #888;
}
.alarm-box>* {
font-family: "Microsoft YaHei Ui Light",ui-sans-serif,system-ui,Segoe UI;
font-size: 95%;
max-width: fix-content;
}
.alarm-box .close-button:hover {
color: #000;
}
`;
styleElement.appendChild(document.createTextNode(cssCode));
document.head.appendChild(styleElement);
document.body.appendChild(alarmBox);
closeButton.onclick = 'this.parentNode.removeChild(this)';
closeButton.addEventListener('click', async function () {
await aluk('.alarmbox-style').RemoveX();
await closeButton.parentElement.remove();
if (this.onalarmisdiscard) {
this.onalarmisdiscard();
}
}.bind(this));
};
var button;
var sar;
var buyButton;
var StoreAPI = {
GetFileListfunction: function() {
GM_xmlhttpRequest({
method: "POST",
url: 'https://store.rg-adguard.net/api/GetFiles',
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
data: 'type=ProductId&url=' + window.location.pathname.split("detail/")[1] + '&ring=RP&lang=zh-CN',
onload: function (response) {
if (response.status >= 200 && response.status < 300) {
var html = response.responseText;
buyButton.querySelector('span').textContent = '下载';
var links = extractLinks(html);
var names = extractAText(html);
var htmla = ``;
if(links.length > 0) {
links.forEach(linkstr => {
let i = links.indexOf(linkstr);
let named = simplifyPackageName(names[i]);
htmla += `<a href="` + linkstr + `">` + named + `</a><br><br>`;
});
}
var alarm = new Alarm(htmla,'资源地址');
alarm.show();
} else {
// 处理错误情况
console.error("请求失败,状态码:" + response.status);
buyButton.querySelector('span').textContent = '下载';
}
},
onerror: function (response) {
// 处理网络错误或其他问题导致的请求失败
console.error("请求出错");
}
});
}
};
async function waitForElement(selector, root = document) {
while ((root.querySelector(selector)) === null) {
await new Promise(resolve => requestAnimationFrame(resolve));
}
return root.querySelector(selector);
}
function extractLinks(htmlText) {
// 定义一个正则表达式来匹配所有的<a>标签中的href属性
const linkRegex = /href="([^"]*)"/g;
let links = [];
let match;
// 使用正则表达式循环匹配HTML文本
while ((match = linkRegex.exec(htmlText)) !== null) {
// 将每次匹配到的链接添加到links数组中
links.push(match[1]);
}
return links;
}
function extractAText(htmlText) {
// 创建一个新的DOMParser实例
const parser = new DOMParser();
// 将HTML字符串解析为DOM对象
const doc = parser.parseFromString(htmlText, "text/html");
// 选择所有的<a>标签
const aTags = doc.querySelectorAll('a');
let texts = [];
// 遍历所有的<a>标签
aTags.forEach(a => {
// 获取并添加<a>标签的文本内容到texts数组中
texts.push(a.innerText); // 或者使用textContent根据需求
});
return texts;
}
function simplifyPackageName(packageName) {
const parts = packageName.split('_');
const versionAndArchitecture = parts[1];
const simplifiedName = parts[0].split('.').pop();
const arch = parts[2].split('.').pop();
const extension = packageName.split('.').pop();
return `${simplifiedName}_${versionAndArchitecture}-${arch}.${extension}`;
}
async function loader() {
sar = await waitForElement('app-index');
let productDetailsPage = await waitForElement('product-details-page',sar.shadowRoot);
console.log(productDetailsPage);
// 确保productDetailsPage非null后再继续
let buyBoxContainer = await waitForElement('.buy-box-container', productDetailsPage.shadowRoot);
let buyBox = await waitForElement('buy-box', buyBoxContainer);
let buyBoxInner = await waitForElement('.buy-box', buyBox.shadowRoot);
buyButton = await waitForElement('.buy-btn', buyBoxInner);
let buttonShadowRoot = buyButton.shadowRoot;
button = await waitForElement('a[part="base"]', buttonShadowRoot);
button.removeAttribute('href');
button.addEventListener('click',() => {
buyButton.querySelector('span').textContent = '正在获取链接';
StoreAPI.GetFileListfunction();
});
buyButton.querySelector('span').textContent = '下载';
buyButton.querySelector('img.logo').src = `data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSI2Ni41NzkxNyIgaGVpZ2h0PSI2MS40MzA2NCIgdmlld0JveD0iMCwwLDY2LjU3OTE3LDYxLjQzMDY0Ij48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMjA2LjkzMzgzLC0xNDkuMjkxMDMpIj48ZyBkYXRhLXBhcGVyLWRhdGE9InsmcXVvdDtpc1BhaW50aW5nTGF5ZXImcXVvdDs6dHJ1ZX0iIGZpbGw9Im5vbmUiIGZpbGwtcnVsZT0ibm9uemVybyIgc3Ryb2tlPSIjZmZmZmZmIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJtaXRlciIgc3Ryb2tlLW1pdGVybGltaXQ9IjEwIiBzdHJva2UtZGFzaGFycmF5PSIiIHN0cm9rZS1kYXNob2Zmc2V0PSIwIiBzdHlsZT0ibWl4LWJsZW5kLW1vZGU6IG5vcm1hbCI+PHBhdGggZD0iTTIwNy45MzM4MywyMDkuMzc5MTNsNjMuMTUyMjcsMC4zMjk4NWwtNTkuNDE3OTUsLTU5LjQxNzk1Ii8+PHBhdGggZD0iTTI3Mi4wNjYxNywxNTMuMTM3Mjd2NTYuNDczMDQiLz48L2c+PC9nPjwvc3ZnPjwhLS1yb3RhdGlvbkNlbnRlcjozMy4wNjYxNjg1MTM5NzczNzQ6MzAuNzA4OTc0NzE3NTQyOTMtLT4=`;
}
function checkElementExistence() {
if(sar == undefined || sar == null) {
loader();
}
}
(function () {
'use strict';
loader();
})();