自动推送Aria2视频链接下载,解放双手

背景介绍

背景还是有必要介绍一下的。

因为百度云已经把小电影封杀的都成了8秒教育片,115的会员费高的离谱,于是它们的替代品hei科li线云就急需出现了。

为了下载百度云的普通文件,有一个专门为了推送百度云的下载链接到Aria2的Chrome扩展BaiduExporter,还有针对115的Chrome扩展115exporter

根据他们的思路,扩展是可以解决以前那种纯手工的复制粘贴办法的,于是研究了一下他们的代码。

  • 首先是找到下载的链接,这个功能以前已经实现了。
  • 然后是把找到的链接推送到Aira2服务器(当然,首先肯定要自己先建好Aira2服务器,最好外网可以访问的那种)

其中Aira2服务器可以参考Aria2英文官网,不管你是把Aira2安装到哪里,都可以在网上找到对应的教程。

然后通过代码推送链接,我只是研究了一下BaiduExporter项目的相关代码,了解了最基础的用法。

再深一点的功能,我也没有用到,我也不了解。

这些就足够了,于是开始吧。

以下目标网站都是代表的http://lx点heikeyun点net

以前原始的办法

参考你不知道Aria2的下载速度有多快!

现今的科技自动化

这里可以详细的分析一下怎么把扩展程序无缝结合到目标网站。

目标网站使用的UI是MZUI

需要注意的是扩展程序是不能直接调用目标网站的JS的,如果有交叉的JS,我的解决办法是把它的代码复制一份,放到自己的扩展程序中。

项目中添加了jquery-3.3.1.min.jsmzui.jstoURL.js,其中前两个是网上下载的,最后一个是解析下载地址需要用到的js。

另外项目主要的功能都放到了myHeike.js中。

先添加Aira2下载按钮(方法startListen)

主要代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
...
this.startListen = function () {
this.initHeike();
var target4 = $("#target4");
var btns = target4.find(".content");
var btnmain = $("#btnmain");
var btn = '<button type="button" class="btn success" id="aria2btn"><i class="icon icon-cloud-download" style="margin-right: 6px;"></i>Aria2</button>';
btns.append(btn);
$("#aria2btn").attr("style", btnmain.attr('style'));
$("#aria2btn").bind('click', (obj) => {
this.getDownloadURL();
});
$.messager.show('程序初始化成功!', {type: 'success', placement: 'center'});
}
...

根据目标网站的html代码,添加一个类似的按钮Aria2,并绑定了点击事件this.getDownloadURL()

得到下载链接(方法:getDownloadURL)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
...
this.getDownloadURL = function () {
var that = $($(this.dItem.currentTarget)[0]);
var obj = this;
var data = that.attr('data');
$.ajax({
type: "post",
url: "CommonAjax.ashx?type=DownUrl",
data: "{'d':'" + data + "','tp':'web'}",
dataType: "json",
async: true,
beforeSend: () => {$.messager.show('正在获取下载地址……', {type: 'info', placement: 'center'});},
success: function (d) {
if (d.IsOk) {

//web
obj.sendUrl(bcone(d.DownUrl));

} else {
$.messager.show(d.Msg, {type: 'danger', placement: 'center'});
return;
}
},
error: function (err) {
$.messager.show(err, {type: 'danger', placement: 'center'});; return;
}
});
}
...

需要注意,代码都封装在一起,里面的this每次指向的并不是当前的js类。这个就把我弄的头晕了。

当然这个方法是参考的目标网站的js,因为扩展程序都是在网页上运行的,所以设备都确定为'tp': 'web'

得到下载地址后,就需要使用方法sendURL方法把链接推送到Aira2服务器。

推送Aira2下载链接(方法:sendUrl)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
this.sendUrl = function (path) {
$.messager.show('已经取得下载地址,正在推送到Aira2服务器', {type: 'success', placement: 'center'});
var rpcData = {
jsonrpc : '2.0',
id : new Date().getTime(),
method : 'aria2.addUri',
params : [
[path],
{
continue : 'true',
split : '10',
'max-connection-per-server' : '10',
}
]
}
$.post(this.url, JSON.stringify(rpcData), (res) => {
if(res.error == undefined || res.error == null){

$.messager.show('任务添加成功,请返回Aria2查看任务', {type: 'success', placement: 'center'});
}
})
}
...

这是最基础的发送下载URL到Aria2服务器的方法,其中rpcDataparams参数,可能加入的字段应该有好多,只是暂时只用了这几个字段而已。

推送方法直接使用$.post方法,把rpcData转成json格式的数据就可以推送过去了。返回的数据,当出现错误的时候(暂时没有遇到),就不能添加成功。

当然出现错误时的提示功能还需要完善。

到此为止,其实就实现了全部的核心功能。
但是很多时候是不能把Aria2服务器的地址直接写到程序里的,那样可移植性就很差了,需要加入自定义Aria2服务器的界面。
存储自定义字段的值,可以使用浏览器自带的localStorage,明文存储应该也没多大影响。因为毕竟客户端程序,能实现复杂的加密也不现实。

自定义Aria2服务器的方法

根据需要,选择浏览。

在目标网页的指定页面,左下角加入了一个按钮,默认是隐藏的,点击后可以弹出自定义界面。

自定义界面(方法:initHeike)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
...
this.initHeike = function () {
$.messager.show('正在初始化程序……', {type: 'info', placement: 'center'});
var list = $("#partial").find('.list').children();
$.each(list, (i, v) => {
$(v).bind('click', (item) => {
this.dItem = item;
$($('.display-backdrop')[0]).remove();
});
});
var rpcHtml = '<div id="target66" class="" style="width: 340px; background: #FFF; position: absolute; left: 10px; z-index: 6666; display: none;">' +
'<div class="heading">' +
'<div class="title"><strong>设置Aira服务器</strong></div>' +
'</div>' +
'<div class="content article box">' +
'<div class="control has-label-left has-icon-right">' +
'URL(类似:http://localhost:6800/jsonrpc):<input name="rpcURL" type="text" id="rpcURL" class="input" placeholder="Aria2服务器地址" style="width: 90%; display: block; padding-left: 10px;">' +
'Token(如果没有Token可以留空):<input name="rpcToken" type="text" id="rpcToken" class="input" placeholder="Token" style="width: 50%; display: inline-block; padding-left: 10px; margin-right: 10px">当前状态:<span id="status"></span>' +
'<div><input type="button" name="btnCheckRPC" value="测试连接" id="btnCheckRPC" class="btn primary circle" style="margin-top: 10px; margin-right: 10px;">' +
'<input type="button" name="btnSaveRPC" value="保存" id="btnSaveRPC" class="btn success outline circle" style="margin-top: 10px;"></div>' +
'</div>' +
'<div class="control has-label-left has-icon-right"><hr>首次使用本插件,需要设置Aira2服务器。</div>' +
'</div>' +
'</div>';
var rpcset = '<nav id="fabNav66" class="affix dock-bottom dock-left fab has-padding dock-auto shadow-none" style="margin-left: 70px;">' +
'<a id="rpcBtn" class="btn circle primary layer"><i class="icon icon-cog" style="margin-right: 4px;"></i></a>' +
'</nav>';

$("#partial").append(rpcset);

$('body').append(rpcHtml);
$('#rpcURL').val(this.url == null ? '' : this.url);
$('#rpcToken').val(this.token == null ? '' : this.token);
if(this.rpcStatus == '1'){
setStatus('#status', '已连接', 'green');
}else{
setStatus('#status', '未连接', 'red');
}
$('#rpcURL, #rpcToken').blur( () => {
if($('#rpcURL').val() != this.url || $('#rpcToken').val() != this.token){
setStatus('#status', '测试连接', 'red');
this.rpcStatus = '0';
}

});
$('#btnCheckRPC').click( () => {
this.getRPCVersion($('#rpcURL').val(), $('#rpcToken').val());
});
$('#btnSaveRPC').click( () => {
localStorage.setItem('url', $('#rpcURL').val());
localStorage.setItem('token', $('#rpcToken').val());
localStorage.setItem('rpcStatus', this.rpcStatus);
});
$('#target66').css('top', ($('#fabNav66').offset().top - $('#target66').height() - 10) + 'px');
$('#fabNav66').click( () => {
//$('#shade66').show();
$('#target66').slideToggle();

});
if(this.url != null && this.rpcStatus == '1'){
$('#rpcBtn').append('已连接');
}else{
$('#rpcBtn').append('未连接');
}
}
...

此段程序可能比较啰嗦,主要是用来控制界面的显示。

填写好Aira2服务器地址后,需要测试Aria2服务器是否可用。这里就需要用到getRPCVersion方法测试其连通性。

测试Aira2服务器是否可用(方法:getRPCVersion)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
...
this.getRPCVersion = function (aria2Url, aria2Token) {
var aria2 = {
url : aria2Url,
token : aria2Token,
}
var rpcData = {
jsonrpc : '2.0',
method : 'aria2.getVersion',
id : 1,
params : []
}
$.post(aria2.url, JSON.stringify(rpcData), (res) => {
var ver = '';
if(res != null && res != undefined){
var d = res.result.version;
if(d != null && d != undefined){
ver = d;
}
console.log(res);
}
if(ver == ''){
setStatus('#status', '连接错误', 'red');
this.rpcStatus = 0;
$('#rpcBtn').html($('#rpcBtn').html().replace("已", "未"));
}
else{
setStatus('#status', '已连接', 'green');
this.rpcStatus = 1;
$('#rpcBtn').html($('#rpcBtn').html().replace("未", "已"));
}
}).fail( () => {
setStatus('#status', '连接错误', 'red');
this.rpcStatus = 0;
$('#rpcBtn').html($('#rpcBtn').html().replace("已", "未"));
});
}
...

这个和推送URL方法类似,只是发送的参数有点不一样。

如果Aria2服务器地址没有问题,就会返回Aria2的版本号。

如果连接不成功,可能什么都不返回,连接都不会成功,估计是404。

尾声

我几乎把整个代码都贴上来了。

我就是啰嗦而且找不到重点。

我把代码放到了Github上HeiKeExport

程序目前是有问题的,我只在两台电脑上测试过,一台是本机,也就是开发这个扩展程序的电脑,扩展测试正常,打包扩展程序HeiKeExport.crx;另一台安装安装前面打包的扩展程序HeiKeExport.crx,提示程序出错。

但是把整个代码解压到新电脑以后,新电脑开启开发者模式,加载正在开发的扩展程序,是没有问题的。

于是,我怀疑是新电脑的Chrome版本的问题。