bilibili_console 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.bundle/config +2 -2
- data/.gitignore +4 -3
- data/Gemfile +10 -10
- data/Gemfile.lock +3 -9
- data/LICENSE +20 -20
- data/README.md +106 -75
- data/Rakefile +11 -11
- data/bilibili_console.gemspec +21 -21
- data/bin/banner.txt +9 -9
- data/bin/bilic +123 -0
- data/lib/bilibili_console/api.rb +30 -0
- data/lib/bilibili_console/base.rb +109 -109
- data/lib/bilibili_console/fav.rb +154 -147
- data/lib/bilibili_console/http/http.rb +75 -75
- data/lib/bilibili_console/http/response_body.rb +28 -28
- data/lib/bilibili_console/login.rb +103 -102
- data/lib/bilibili_console/manga.rb +24 -24
- data/lib/bilibili_console/version.rb +10 -10
- data/lib/bilibili_console/video.rb +193 -123
- data/lib/bilibili_console.rb +69 -69
- data/rubocop.yml +1 -1
- metadata +9 -36
- data/bin/bili-console +0 -63
@@ -1,28 +1,28 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2021 leejoker
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require_relative 'http'
|
9
|
-
|
10
|
-
# response body
|
11
|
-
module BiliHttp
|
12
|
-
# response body
|
13
|
-
class ResponseBody
|
14
|
-
attr_accessor :code, :message, :ts, :data, :status
|
15
|
-
|
16
|
-
def initialize(json)
|
17
|
-
@code = json[:code]
|
18
|
-
@message = json[:message]
|
19
|
-
@ts = json[:ts]
|
20
|
-
@status = json[:status]
|
21
|
-
@data = json[:data]
|
22
|
-
end
|
23
|
-
|
24
|
-
def to_s
|
25
|
-
"code: #{@code}, message: #{@message}, ts: #{@ts}, data: #{@data}, status: #{@status}"
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2021 leejoker
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
require_relative 'http'
|
9
|
+
|
10
|
+
# response body
|
11
|
+
module BiliHttp
|
12
|
+
# response body
|
13
|
+
class ResponseBody
|
14
|
+
attr_accessor :code, :message, :ts, :data, :status
|
15
|
+
|
16
|
+
def initialize(json)
|
17
|
+
@code = json[:code]
|
18
|
+
@message = json[:message]
|
19
|
+
@ts = json[:ts]
|
20
|
+
@status = json[:status]
|
21
|
+
@data = json[:data]
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
"code: #{@code}, message: #{@message}, ts: #{@ts}, data: #{@data}, status: #{@status}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,102 +1,103 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2021 leejoker
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require_relative 'http/http'
|
9
|
-
require_relative 'base'
|
10
|
-
|
11
|
-
require '
|
12
|
-
|
13
|
-
|
14
|
-
module
|
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
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2021 leejoker
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
require_relative 'http/http'
|
9
|
+
require_relative 'base'
|
10
|
+
require_relative 'api'
|
11
|
+
require 'rqrcode'
|
12
|
+
require 'json'
|
13
|
+
|
14
|
+
# login module
|
15
|
+
module Bilibili
|
16
|
+
include BiliHttp
|
17
|
+
# bilibili user info
|
18
|
+
class UserInfo
|
19
|
+
attr_accessor :face, :level_info, :uid, :money, :moral, :uname, :vip_type
|
20
|
+
|
21
|
+
def initialize(json)
|
22
|
+
return if json.nil?
|
23
|
+
|
24
|
+
@face = json[:face]
|
25
|
+
@level_info = json[:level_info]
|
26
|
+
@uid = json[:mid]
|
27
|
+
@money = json[:money]
|
28
|
+
@moral = json[:moral]
|
29
|
+
@uname = json[:moral]
|
30
|
+
@vip_type = json[:vipType]
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_json(*opt)
|
34
|
+
{
|
35
|
+
face: @face,
|
36
|
+
level_info: @level_info,
|
37
|
+
uid: @uid,
|
38
|
+
money: @money,
|
39
|
+
moral: @moral,
|
40
|
+
uname: @uname,
|
41
|
+
vip_type: @vip_type
|
42
|
+
}.to_json(*opt)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# login class
|
47
|
+
class Login < BilibiliBase
|
48
|
+
attr_accessor :url, :oauth_key
|
49
|
+
|
50
|
+
def login_url
|
51
|
+
data = get_jsonl(Api::Login::QRCODE)
|
52
|
+
@url = data[:url]
|
53
|
+
@oauth_key = data[:oauthKey]
|
54
|
+
end
|
55
|
+
|
56
|
+
def show_qrcode
|
57
|
+
qr = RQRCode::QRCode.new(@url)
|
58
|
+
pic = qr.as_ansi(
|
59
|
+
light: "\033[47m", dark: "\033[40m",
|
60
|
+
fill_character: ' ',
|
61
|
+
quiet_zone_size: 1
|
62
|
+
)
|
63
|
+
puts pic
|
64
|
+
end
|
65
|
+
|
66
|
+
def login_user_info
|
67
|
+
set_http_cookie
|
68
|
+
data = get_jsona(Api::Login::USERINFO)
|
69
|
+
if data.code != '-101'
|
70
|
+
Bilibili::UserInfo.new(data)
|
71
|
+
else
|
72
|
+
puts 'Cookie已失效'
|
73
|
+
clean_cookie
|
74
|
+
login_user_info
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def login
|
79
|
+
login_url
|
80
|
+
show_qrcode
|
81
|
+
print '已完成扫码?[y/n]'
|
82
|
+
over = $stdin.gets.chomp
|
83
|
+
return nil unless over == 'y'
|
84
|
+
|
85
|
+
post_form_jsonl(Api::Login::INFO, { oauthKey: @oauth_key })
|
86
|
+
puts 'Login Success !!!'
|
87
|
+
save_cookie
|
88
|
+
'success'
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def set_http_cookie
|
94
|
+
cookies = @http_client.login_http.cookies
|
95
|
+
if cookies.nil? || cookies.empty?
|
96
|
+
login
|
97
|
+
@http_client.api_http.cookies = @http_client.login_http.cookies
|
98
|
+
else
|
99
|
+
@http_client.api_http.cookies = cookies
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -1,24 +1,24 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2021 leejoker
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require_relative 'http/http'
|
9
|
-
|
10
|
-
|
11
|
-
module
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2021 leejoker
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
require_relative 'http/http'
|
9
|
+
require_relative 'api'
|
10
|
+
|
11
|
+
# video module
|
12
|
+
module Bilibili
|
13
|
+
include BiliHttp
|
14
|
+
|
15
|
+
# bilibili video interfaces
|
16
|
+
class Manga < BilibiliBase
|
17
|
+
def check_in
|
18
|
+
cur_header = {
|
19
|
+
'User-Agent': 'Mozilla/5.0 BiliDroid/6.4.0 (bbcallen@gmail.com) os/android model/M1903F11I mobi_app/android build/6040500 channel/bili innerVer/6040500 osVer/9.0.0 network/2'
|
20
|
+
}
|
21
|
+
post_jsonm(Api::Manga::CHECK_IN, cur_header, { 'platform' => 'android' })
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2021 10344742
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
module Bilibili
|
9
|
-
VERSION = '0.0.
|
10
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2021 10344742
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
module Bilibili
|
9
|
+
VERSION = '0.0.3'
|
10
|
+
end
|
@@ -1,123 +1,193 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
# Copyright (c) 2021 leejoker
|
4
|
-
#
|
5
|
-
# This software is released under the MIT License.
|
6
|
-
# https://opensource.org/licenses/MIT
|
7
|
-
|
8
|
-
require_relative 'http/http'
|
9
|
-
|
10
|
-
require 'fileutils'
|
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
|
-
data
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
76
|
-
end
|
77
|
-
result
|
78
|
-
end
|
79
|
-
|
80
|
-
def download_video_by_bv(bv_id,
|
81
|
-
urls = video_url_list(bv_id,
|
82
|
-
return nil if urls.empty?
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2021 leejoker
|
4
|
+
#
|
5
|
+
# This software is released under the MIT License.
|
6
|
+
# https://opensource.org/licenses/MIT
|
7
|
+
|
8
|
+
require_relative 'http/http'
|
9
|
+
require_relative 'api'
|
10
|
+
require 'fileutils'
|
11
|
+
|
12
|
+
# video module
|
13
|
+
module Bilibili
|
14
|
+
include BiliHttp
|
15
|
+
# video page list
|
16
|
+
class PageInfo
|
17
|
+
attr_accessor :cid, :page, :from, :part, :duration, :vid, :weblink
|
18
|
+
|
19
|
+
def initialize(json)
|
20
|
+
return if json.nil?
|
21
|
+
|
22
|
+
@cid = json[:cid]
|
23
|
+
@page = json[:page]
|
24
|
+
@from = json[:from]
|
25
|
+
@part = json[:part]
|
26
|
+
@duration = json[:duration]
|
27
|
+
@vid = json[:vid]
|
28
|
+
@weblink = json[:weblink]
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_json(*opt)
|
32
|
+
{
|
33
|
+
cid: @cid,
|
34
|
+
page: @page,
|
35
|
+
from: @from,
|
36
|
+
part: @part,
|
37
|
+
duration: @duration,
|
38
|
+
vid: @vid,
|
39
|
+
weblink: @weblink
|
40
|
+
}.to_json(*opt)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# bilibili video interfaces
|
45
|
+
class Video < BilibiliBase
|
46
|
+
def video_page_list(bv_id)
|
47
|
+
return nil if bv_id.nil?
|
48
|
+
|
49
|
+
url = "#{Api::Video::PAGE_LIST}?bvid=#{bv_id}"
|
50
|
+
datas = get_jsona(url)
|
51
|
+
return nil if datas.nil?
|
52
|
+
|
53
|
+
datas.map do |d|
|
54
|
+
Bilibili::PageInfo.new(d)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_video_url(bv_id, cid, video_qn = '720')
|
59
|
+
qn = BilibiliBase.video_qn[video_qn]
|
60
|
+
url = "#{Api::Video::PLAY_URL}?bvid=#{bv_id}&cid=#{cid}&qn=#{qn}&fnval=0&fnver=0&fourk=1"
|
61
|
+
data = get_jsona(url)
|
62
|
+
data[:durl]
|
63
|
+
end
|
64
|
+
|
65
|
+
def video_url_list(bv_id, video_qn = '720')
|
66
|
+
result = []
|
67
|
+
page_list = video_page_list(bv_id)
|
68
|
+
return nil if page_list.nil?
|
69
|
+
|
70
|
+
page_list.each do |page|
|
71
|
+
get_video_url(bv_id, page.cid, video_qn).each do |down_url|
|
72
|
+
order = down_url[:order] < 10 ? "0#{down_url[:order]}" : down_url[:order]
|
73
|
+
result << { 'name': "#{page.part}_#{order}.flv", 'url': down_url[:url].to_s, 'prefix': page.part,
|
74
|
+
'order': "#{page.page}#{order}", 'bv': bv_id.to_s }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
def download_video_by_bv(bv_id, options)
|
81
|
+
urls = video_url_list(bv_id, options[:qn])
|
82
|
+
return nil if urls.empty?
|
83
|
+
|
84
|
+
urls = page_slice(urls, options[:start], options[:end], options[:page])
|
85
|
+
download_path = "#{File.expand_path(@options['download_path'].to_s, __dir__)}/#{bv_id}/"
|
86
|
+
url_array = []
|
87
|
+
urls.map { |url| download_file(url, download_path) }.each_with_index do |u, i|
|
88
|
+
same_part = same_part?(u, i)
|
89
|
+
url_array << u[:file_path]
|
90
|
+
combine_media(url_array, "#{download_path}#{u[:prefix]}.flv") unless same_part
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
private
|
95
|
+
|
96
|
+
def page_slice(urls, start_page, end_page, page)
|
97
|
+
if page.nil?
|
98
|
+
start_page = start_page.to_i - 1
|
99
|
+
if end_page.nil?
|
100
|
+
urls.slice(start_page, urls.size - start_page)
|
101
|
+
elsif start_page < end_page.to_i
|
102
|
+
urls.slice(start_page, end_page.to_i)
|
103
|
+
else
|
104
|
+
raise 'start should not less than or equals to end'
|
105
|
+
end
|
106
|
+
else
|
107
|
+
[] << urls[page.to_i - 1]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def next?(array, index)
|
112
|
+
!array[index + 1].nil?
|
113
|
+
end
|
114
|
+
|
115
|
+
def same_part?(array, idx)
|
116
|
+
next?(array, idx) && array[idx][:prefix] == array[idx + 1][:prefix]
|
117
|
+
end
|
118
|
+
|
119
|
+
def download_file(url, dir)
|
120
|
+
file_path = check_path(dir, url[:name])
|
121
|
+
url[:file_path] = file_path
|
122
|
+
puts "开始下载文件到: #{file_path}, 视频地址:#{url[:url]}"
|
123
|
+
headers = generate_headers
|
124
|
+
wget_download(url[:url], headers['User-Agent'], headers['Referer'], headers['Cookie'], file_path)
|
125
|
+
dest_file_exist?(file_path)
|
126
|
+
url
|
127
|
+
end
|
128
|
+
|
129
|
+
def check_path(dir, filename)
|
130
|
+
FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
|
131
|
+
"#{dir}#{filename}"
|
132
|
+
end
|
133
|
+
|
134
|
+
def create_cookie_str(cookies)
|
135
|
+
cookie_array = cookies['/'].map do |key, value|
|
136
|
+
"#{key}=#{value}; "
|
137
|
+
end
|
138
|
+
cookie_array.join
|
139
|
+
end
|
140
|
+
|
141
|
+
def generate_headers
|
142
|
+
headers = BiliHttp.headers
|
143
|
+
{
|
144
|
+
'User-Agent' => headers[:"User-Agent"],
|
145
|
+
'Referer' => headers[:Referer],
|
146
|
+
'Cookie' => create_cookie_str(load_cookie)
|
147
|
+
}
|
148
|
+
end
|
149
|
+
|
150
|
+
def combine_media(files, dest)
|
151
|
+
return if files.size.zero?
|
152
|
+
|
153
|
+
if files.size == 1
|
154
|
+
FileUtils.mv(files[0], dest)
|
155
|
+
files.clear
|
156
|
+
return
|
157
|
+
end
|
158
|
+
|
159
|
+
return if files.select! { |file| File.exist?(file) }.size.zero?
|
160
|
+
|
161
|
+
`ffmpeg -i concat:"#{files.join('|')}" -c copy #{dest}`
|
162
|
+
files.clear
|
163
|
+
end
|
164
|
+
|
165
|
+
def dest_file_exist?(dest)
|
166
|
+
if File.exist?(dest)
|
167
|
+
local = File.new(dest).size
|
168
|
+
raise 'file size is zero' if local.zero?
|
169
|
+
|
170
|
+
true
|
171
|
+
else
|
172
|
+
false
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def wget_file_size(command)
|
177
|
+
result = `#{command} -o -`
|
178
|
+
hash = {}
|
179
|
+
result.split("\n").filter { |n| n.include?(':') }.each do |line|
|
180
|
+
a = line.split(':')
|
181
|
+
hash[a[0].strip] = a[1].strip
|
182
|
+
end
|
183
|
+
hash['Content-Length'].to_i
|
184
|
+
end
|
185
|
+
|
186
|
+
def wget_download(url, user_agent, referer, cookie, dest)
|
187
|
+
config_path = File.expand_path((@options['config_path']).to_s, __dir__)
|
188
|
+
File.write("#{config_path}/cookie", cookie) unless File.exist?("#{config_path}/cookie")
|
189
|
+
command = "wget '#{url}' --referer '#{referer}' --user-agent '#{user_agent}' --load-cookie='#{config_path}/cookie' "
|
190
|
+
`#{command} -c -O "#{dest}"`
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|