一个下载 uc.js

一个没新意轮子,只是监听下载&投递给外部,唯一可取之处是用我熟悉的语言实现。

下载方面的痛点还是蛮多的。比如

  • github 下载的 ZIP 我希望完成后立即解压,打开文件夹,在副屏显示
  • wallhaven 下载图片立即添加到壁纸库
  • 小色网下载压缩包时获取网页源代码,记录密码

总之几乎每个常用的下载,都能更智能更自动化

当然,这个脚本无法即用。它只是提供了一种方案。
想要使用你需要粗略地了解 uc 脚本 (看几眼,问问 AI),并且精通一门其他语言。这里推荐使用 AutoHotkey。
当然如果你精通 js,这个脚本就没必要了。
对于不想编译 dll 的 AutoHotkey 用户,有个更简单的方法:AutoHotkey 进程监听窗口消息。uc 用 FindWindow 和 SendMessage 与之交互。
对于能调用 WINAPI 的 UC 脚本来说,交互应该不是问题。

脚本框架修改自 downloadSoundPlay_Fx26.uc.js


var downloadPlaySound = {

	_list: null,
	init: function sampleDownload_init() {

		if (!this._list)
		{
			globalThis.Downloads.getList(globalThis.Downloads.ALL).then(list => {
				this._list = list;
				return this._list.addView(this);
			}).then(null, Cu.reportError);
		}
	},


	onDownloadAdded: function (dl) {

		let target = dl.target;
		let path = target.path;
		let match = path.match(/[^\\\.]+$/);

		let ext;

		if (match)
		{
			ext = match[0].toLowerCase();
			if (ext == "htm" || ext == "html")
				return;
		}
		else
		{
			ext = null;
		}

		let source = dl.source;

		let url = source.url;
		let uri = Services.io.newURI(url, null, null);

		if (uri.schemeIs('data') || uri.schemeIs('blob'))
			return;

		let cookies = Services.cookies.getCookiesFromHost(uri.host, {});

		let refererInfo = source.referrerInfo?.originalReferrer;


		if (cookies.length === 0 && refererInfo)
		{
			cookies = Services.cookies.getCookiesFromHost(refererInfo.host, {});
		}

		const buf = new TextEncoder().encode(JSON.stringify({
			name: "firefox_download_call"
			, current_url: gBrowser.selectedBrowser.currentURI.spec
			, current_title: gBrowser.selectedBrowser.contentTitle
			, contentType: dl.contentType
			, currentBytes: dl.currentBytes
			, startTime: dl.startTime
			, totalBytes: dl.totalBytes
			, dl_path: path
			, dl_ext: ext
			, dl_size: target.size
			, mimeInfo: DownloadsCommon.getMimeInfo(dl)
			, Referer: refererInfo?.spec
			, url: url
			, cookies: cookies?.map((el) => el.name + '=' + el.value).join("; ")
		}));

		if (dll_add_json(buf, buf.length) == 1)
			dl.cancel();

		console.log(dl);

	},


}

downloadPlaySound.init();

对了,当前有个问题——无法获取网页源代码。好像是因为进程隔离,UC 脚本无法获取。有大佬知道如何绕过限制吗?(奇怪,cookies 都能获取,网页源无法获取)

不是无法获取网页内容,而是只能通过消息和网页进程交互

并且是对你的 dll 感兴趣,uc脚本没兴趣

dll 是我用 rust 写的,不过是个中间件,将 json 投给外部服务器

#[no_mangle]
unsafe extern "C" fn go_json(js: *const u8, len: u32) -> i32 {
	let mut sv = Vec::with_capacity(11);
	sv.extend_from_slice(&len.to_le_bytes());
	sv.extend_from_slice(&[103, 111, 95, 106, 115, 111, 110]); // go_json
	SEND(sv.as_ptr(), 11, js, len)
}

不好意思,addMenuPlus里的实现方法是一个复杂的过程吗?我看了半天没找到获取源的地方…

addMenuPlus_fx72.uc.js 有三部分,ActorParent(会被加载到界面进程)、 ActorChild(会被加载到内容进程),Script(我们平常写 UC 脚本的部分,可以操作浏览器界面),本来是要分三部分写的,addMenuPlus_fx72.uc.js 里通过小技巧多合一了。

ActorParent/ActorChild 是一对的,必须成对出现。

界面进程部分的 UC 脚本可以调用 ActorParent 向 ActorChild 发送消息
ActorParent 收到 ActorChild 发回来的消息可以传递给 Script。

如果你想获取网页源码的思路就是 ActorChild 获取全部 html 发送给 ActorParent,当然也许可以找找 Firefox 源码有没有对应的 Actor 可以利用。

更详细的说明看官方文档:JSActors — Firefox Source Docs documentation

addMenuPlus_fx72.uc.js 里这就是对网页部分操作的源码,获取 Favicon

1 个赞

了解,感谢大佬丰富的资料 :smiley: