bilibili_console 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5524a52ac2c2f6286d1ff24e51d16658eee029b0da65f79655e0ca8a1f99c820
4
+ data.tar.gz: 965192950c893a795039c810fa623c8c7081f78ff90bd5b7537f26737616ca5b
5
+ SHA512:
6
+ metadata.gz: 92699ed8ca0499d5ca0aa6f2def15b0a8707727d1e33a3f9465a79dd317d970f7a4e2d7eaad9da681c9d8e9983fb1809f129518dc0d954d790994001ec4b18b7
7
+ data.tar.gz: 3565ae71ae71ec48818e0107735674ac1d87c42fd86e913fbe3eb2bc1c21309be83890a570324cbba25af26c581bdaf655216961d188e5e3849971d61e00066d
data/.bundle/config ADDED
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_WITHOUT: "production"
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.log
2
+ *.gem
3
+ .idea
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://gems.ruby-china.com'
2
+
3
+ gemspec
4
+
5
+ gem "rake", "~> 13.0"
6
+
7
+ gem "rspec", "~> 3.0"
8
+
9
+ gem "rubocop", "~> 1.7"
10
+
data/Gemfile.lock ADDED
@@ -0,0 +1,77 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ bilibili_console (0.0.1)
5
+ down (~> 5.0)
6
+ nice_http (~> 1.8.9)
7
+ rqrcode (~> 2.0)
8
+ ruby-progressbar (~> 1.11.0)
9
+ thor (~> 1.1.0)
10
+
11
+ GEM
12
+ remote: https://gems.ruby-china.com/
13
+ specs:
14
+ addressable (2.8.0)
15
+ public_suffix (>= 2.0.2, < 5.0)
16
+ ast (2.4.2)
17
+ chunky_png (1.4.0)
18
+ diff-lcs (1.4.4)
19
+ down (5.2.2)
20
+ addressable (~> 2.5)
21
+ nice_hash (1.17.2)
22
+ string_pattern (~> 2.2, >= 2.2.2)
23
+ nice_http (1.8.9)
24
+ nice_hash (~> 1.17, >= 1.17)
25
+ parallel (1.20.1)
26
+ parser (3.0.1.1)
27
+ ast (~> 2.4.1)
28
+ public_suffix (4.0.6)
29
+ rainbow (3.0.0)
30
+ rake (13.0.3)
31
+ regexp_parser (1.8.2)
32
+ rexml (3.2.5)
33
+ rqrcode (2.0.0)
34
+ chunky_png (~> 1.0)
35
+ rqrcode_core (~> 1.0)
36
+ rqrcode_core (1.1.0)
37
+ rspec (3.10.0)
38
+ rspec-core (~> 3.10.0)
39
+ rspec-expectations (~> 3.10.0)
40
+ rspec-mocks (~> 3.10.0)
41
+ rspec-core (3.10.1)
42
+ rspec-support (~> 3.10.0)
43
+ rspec-expectations (3.10.1)
44
+ diff-lcs (>= 1.2.0, < 2.0)
45
+ rspec-support (~> 3.10.0)
46
+ rspec-mocks (3.10.2)
47
+ diff-lcs (>= 1.2.0, < 2.0)
48
+ rspec-support (~> 3.10.0)
49
+ rspec-support (3.10.2)
50
+ rubocop (1.20.0)
51
+ parallel (~> 1.10)
52
+ parser (>= 3.0.0.0)
53
+ rainbow (>= 2.2.2, < 4.0)
54
+ regexp_parser (>= 1.8, < 3.0)
55
+ rexml
56
+ rubocop-ast (>= 1.9.1, < 2.0)
57
+ ruby-progressbar (~> 1.7)
58
+ unicode-display_width (>= 1.4.0, < 3.0)
59
+ rubocop-ast (1.11.0)
60
+ parser (>= 3.0.1.1)
61
+ ruby-progressbar (1.11.0)
62
+ string_pattern (2.2.2)
63
+ regexp_parser (~> 1.3, >= 1.3.0)
64
+ thor (1.1.0)
65
+ unicode-display_width (2.0.0)
66
+
67
+ PLATFORMS
68
+ x64-mingw32
69
+
70
+ DEPENDENCIES
71
+ bilibili_console!
72
+ rake (~> 13.0)
73
+ rspec (~> 3.0)
74
+ rubocop (~> 1.7)
75
+
76
+ BUNDLED WITH
77
+ 2.2.24
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2021 leejoker
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,75 @@
1
+ # bilibili_console
2
+
3
+ #### 介绍
4
+
5
+ B站命令行客户端Ruby版
6
+
7
+ #### 软件结构
8
+
9
+ 基于ruby开发,ruby version >= 2.7
10
+
11
+ #### 安装教程
12
+
13
+ 1. 安装ruby环境,使用[rvm](https://ruby-china.org/wiki/rvm-guide)或[rbenv](https://ruby-china.org/wiki/rbenv-guide)均可
14
+ 2. 替换gem源
15
+ 3. 进入代码根目录,执行一下操作:
16
+ ```shell
17
+ $ gem build bilibili_console.gemspec
18
+ $ gem install bilibili_console-0.0.1.gem
19
+ ```
20
+
21
+ ### 使用方法
22
+
23
+ gem安装完成后即可使用**bili-console**命令
24
+
25
+ #### 帮助信息
26
+
27
+ ```shell
28
+ $ bili-console help
29
+ ```
30
+
31
+ #### 登录
32
+
33
+ ```shell
34
+ # 执行二维码登录
35
+ $ bili-console login
36
+ ```
37
+
38
+ #### 用户基本信息
39
+
40
+ ```shell
41
+ $ bili-console user
42
+ ```
43
+
44
+ #### bilibili漫画签到
45
+
46
+ ```shell
47
+ # 目前只提供漫画签到的功能
48
+ $ bili-console manga
49
+ ```
50
+
51
+ #### 功能清单
52
+
53
+ * [x] bilibili漫画签到
54
+ * [x] B站二维码登录
55
+ * [x] 查看个人信息
56
+ * [x] 根据bv下载视频
57
+ * [ ] 合并下载的视频
58
+ * [ ] 查看个人收藏夹
59
+ * [ ] 视频检索
60
+
61
+
62
+ #### 相关项目
63
+
64
+ ##### Gem依赖
65
+
66
+ * [down](https://github.com/janko/down/)
67
+ * [nice_http](https://github.com/MarioRuiz/nice_http)
68
+ * [rqrcode](https://github.com/whomwah/rqrcode/)
69
+ * [ruby-progressbar](https://github.com/jfelchner/ruby-progressbar/)
70
+ * [thor](https://github.com/rails/thor)
71
+
72
+ ##### 接口文档
73
+
74
+ * [bilibili-API-collect](https://github.com/SocialSisterYi/bilibili-API-collect) 感谢易姐的文档支持!
75
+ * [Bilibili-Manga](https://github.com/xkk2333/Bilibili-Manga) 参考了B站漫画的签到接口
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+ require "bilibili_console"
6
+
7
+ RSpec::Core::RakeTask.new(:spec)
8
+
9
+ require "rubocop/rake_task"
10
+
11
+ RuboCop::RakeTask.new
@@ -0,0 +1,21 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'bilibili_console'
3
+ s.version = '0.0.1'
4
+ s.executables << 'bili-console'
5
+ s.summary = 'bilibili console'
6
+ s.description = 'a console tool for bilibili'
7
+ s.authors = ['leejoker']
8
+ s.email = '1056650571@qq.com'
9
+ s.files = `git ls-files -z`.split("\x0").reject do |f|
10
+ f.match(%r{^(test|spec|features)/})
11
+ end
12
+ s.extra_rdoc_files = ['README.md', 'LICENSE']
13
+ s.homepage = 'https://github.com/leejoker/bilibili-console'
14
+ s.license = 'MIT'
15
+ s.required_ruby_version = ['>= 2.7']
16
+ s.add_dependency 'down', '~> 5.0'
17
+ s.add_dependency 'nice_http', '~> 1.8.9'
18
+ s.add_dependency 'rqrcode', '~> 2.0'
19
+ s.add_dependency 'ruby-progressbar', '~> 1.11.0'
20
+ s.add_dependency 'thor', '~> 1.1.0'
21
+ end
data/bin/banner.txt ADDED
@@ -0,0 +1,10 @@
1
+ ###################################################################################
2
+ # ,-----. ,-----. ,--.
3
+ # | |) /_ ,-----.' .--./ ,---. ,--,--, ,---. ,---. | | ,---.
4
+ # | .-. \'-----'| | | .-. || \( .-' | .-. || || .-. :
5
+ # | '--' / ' '--'\' '-' '| || |.-' `)' '-' '| |\ --.
6
+ # `------' `-----' `---' `--''--'`----' `---' `--' `----'
7
+ #
8
+ # 欢迎使用 Bilibili-Console
9
+ # Github: https://github.com/leejoker/bilibili-console
10
+ ####################################################################################
data/bin/bili-console ADDED
@@ -0,0 +1,63 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'thor'
4
+ require 'bilibili_console'
5
+
6
+ # bilibili-console command line
7
+ class BiliConsole < Thor
8
+ def self.exit_on_failure?
9
+ true
10
+ end
11
+
12
+ desc 'help', 'help content'
13
+ def help
14
+ banner = File.read(File.expand_path('banner.txt', __dir__))
15
+ puts <<~HELP
16
+ #{banner}
17
+
18
+ Usage: bili-console [arguments]
19
+ help help messages
20
+ login qrcode login
21
+ user user info
22
+ manga bilibili manga checkin
23
+ HELP
24
+ end
25
+
26
+ desc 'login', 'login with qrcode'
27
+ def login
28
+ bc = BilibiliConsole.new
29
+ puts bc.login
30
+ end
31
+
32
+ desc 'user', 'get user info'
33
+ def user
34
+ bc = BilibiliConsole.new
35
+ user = bc.login_user_info
36
+ puts <<~USER
37
+ uid: #{user.uid}
38
+ uname: #{user.uname}
39
+ level: #{user.level_info[:current_level]}
40
+ USER
41
+ end
42
+
43
+ desc 'manga', 'checkin bilibili manga'
44
+ def manga_checkin
45
+ bc = BilibiliConsole.new
46
+ bc.manga.load_cookie
47
+ body = bc.manga_checkin
48
+ if body.code == 'invalid_argument'
49
+ puts '您已经签到了'
50
+ else
51
+ puts '签到成功'
52
+ end
53
+ end
54
+
55
+ desc 'down', 'download video by bv code'
56
+ def download_video(bv_id)
57
+ bc = BilibiliConsole.new
58
+ bc.video.load_cookie
59
+ bc.download_video(bv_id)
60
+ end
61
+ end
62
+
63
+ BiliConsole.start
@@ -0,0 +1,109 @@
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 'fileutils'
10
+ require 'json'
11
+
12
+ # bilibili base
13
+ module Bilibili
14
+ include BiliHttp
15
+ # base class
16
+ class BilibiliBase
17
+ attr_accessor :http_client, :options
18
+
19
+ class << self
20
+ attr_accessor :video_qn
21
+ end
22
+
23
+ def initialize(http_client)
24
+ @http_client = http_client
25
+ create_request_methods
26
+ @options = {
27
+ 'config_path' => '~/.bc', 'config_file' => '~/.bc/config.json',
28
+ 'cookie_file' => '~/.bc/cookie.txt', 'download_path' => '~/.bc/download'
29
+ }
30
+ BilibiliBase.video_qn = {
31
+ '240' => 6, '360' => 16, '480' => 32, '720' => 64, '720P60' => 74, '1080' => 80,
32
+ '1080+' => 112, '1080P60' => 116, '4K' => 120, 'HDR' => 125
33
+ }
34
+ end
35
+
36
+ def save_cookie
37
+ check_config_path
38
+
39
+ @http_client.api_http.cookies = @http_client.login_http.cookies
40
+ json_str = @http_client.login_http.cookies.to_json
41
+ write_cookie(json_str)
42
+ end
43
+
44
+ def load_cookie
45
+ return {} unless File.exist?(cookie_path)
46
+
47
+ json_str = File.read(cookie_path)
48
+ return {} if json_str.nil? || json_str.empty?
49
+
50
+ JSON.parse(json_str)
51
+ end
52
+
53
+ def clean_cookie
54
+ File.open(cookie_path, 'w') do |file|
55
+ file.write('{}')
56
+ end
57
+ end
58
+
59
+ private
60
+
61
+ def check_config_path
62
+ FileUtils.mkdir_p(config_path) unless Dir.exist?(config_path)
63
+ end
64
+
65
+ def write_cookie(cookie)
66
+ File.open(cookie_path, 'w') do |file|
67
+ file.write(cookie)
68
+ end
69
+ end
70
+
71
+ def create_request_methods
72
+ methods = %w[login_http api_http manga_http]
73
+ methods.each do |method|
74
+ define_get_json_method(method)
75
+ define_post_form_json_method(method)
76
+ define_post_json_method(method)
77
+ end
78
+ end
79
+
80
+ def define_get_json_method(method_name)
81
+ new_method_name = "get_json#{method_name[0]}"
82
+ BilibiliBase.define_method(new_method_name) do |url|
83
+ @http_client.get_json(@http_client.instance_variable_get("@#{method_name}"), url)
84
+ end
85
+ end
86
+
87
+ def define_post_form_json_method(method_name)
88
+ new_method_name = "post_form_json#{method_name[0]}"
89
+ BilibiliBase.define_method(new_method_name) do |url, params|
90
+ @http_client.post_form_json(@http_client.instance_variable_get("@#{method_name}"), url, params)
91
+ end
92
+ end
93
+
94
+ def define_post_json_method(method_name)
95
+ new_method_name = "post_json#{method_name[0]}"
96
+ BilibiliBase.define_method(new_method_name) do |url, headers, req_body|
97
+ @http_client.post_json(@http_client.instance_variable_get("@#{method_name}"), url, headers, req_body)
98
+ end
99
+ end
100
+
101
+ def config_path
102
+ File.expand_path(@options['config_path'].to_s, __dir__)
103
+ end
104
+
105
+ def cookie_path
106
+ File.expand_path(@options['cookie_file'].to_s, __FILE__)
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,147 @@
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 'json'
10
+
11
+ # video module
12
+ module Bilibili
13
+ include BiliHttp
14
+ # fav list
15
+ class FavList
16
+ attr_accessor :count, :list, :season
17
+
18
+ def initialize(data)
19
+ return if data.nil?
20
+
21
+ @count = data[:count]
22
+ @season = data[:season]
23
+ @list = generate_fav_list(data[:list])
24
+ end
25
+
26
+ def generate_fav_list(data_list)
27
+ data = []
28
+ if !data_list.nil? && !data_list.empty?
29
+ data_list.each do |obj|
30
+ data << Bilibili::FavInfo.new(obj)
31
+ end
32
+ end
33
+ data
34
+ end
35
+
36
+ def to_json(*opt)
37
+ {
38
+ count: @count,
39
+ list: @list,
40
+ season: @season
41
+ }.to_json(*opt)
42
+ end
43
+ end
44
+
45
+ # bilibili fav info
46
+ class FavInfo
47
+ attr_accessor :id, :fid, :uid, :attr, :title, :fav_state, :media_count
48
+
49
+ def initialize(json)
50
+ return if json.nil?
51
+
52
+ @id = json[:id]
53
+ @fid = json[:fid]
54
+ @uid = json[:mid]
55
+ @attr = json[:attr]
56
+ @title = json[:title]
57
+ @fav_state = json[:fav_state]
58
+ @media_count = json[:media_count]
59
+ end
60
+
61
+ def to_json(*opt)
62
+ {
63
+ id: @id,
64
+ fid: @fid,
65
+ uid: @uid,
66
+ attr: @attr,
67
+ title: @title,
68
+ fav_state: @fav_state,
69
+ media_count: @media_count
70
+ }.to_json(*opt)
71
+ end
72
+ end
73
+
74
+ # fav media list
75
+ class FavResourceList
76
+ attr_accessor :info, :medias
77
+
78
+ def initialize(json)
79
+ return if json.nil?
80
+
81
+ @info = Bilibili::FavInfo.new(json[:info])
82
+ @medias = generate_media_list(json[:medias])
83
+ end
84
+
85
+ def generate_media_list(medias)
86
+ data = []
87
+ if !medias.nil? && !medias.empty?
88
+ medias.each do |media|
89
+ data << Bilibili::FavMediaInfo.new(media)
90
+ end
91
+ end
92
+ data
93
+ end
94
+
95
+ def to_json(*opt)
96
+ {
97
+ info: @info,
98
+ medias: @medias
99
+ }.to_json(*opt)
100
+ end
101
+ end
102
+
103
+ # fav media info
104
+ class FavMediaInfo
105
+ attr_accessor :id, :type, :title, :intro, :page, :bv_id
106
+
107
+ def initialize(json)
108
+ return if json.nil?
109
+
110
+ @id = json[:id]
111
+ @type = json[:type]
112
+ @title = json[:title]
113
+ @intro = json[:intro]
114
+ @page = json[:page]
115
+ @bv_id = json[:bv_id]
116
+ end
117
+
118
+ def to_json(*opt)
119
+ {
120
+ id: @id,
121
+ type: @type,
122
+ title: @title,
123
+ intro: @intro,
124
+ page: @page,
125
+ bv_id: @bv_id
126
+ }.to_json(*opt)
127
+ end
128
+ end
129
+
130
+ # bilibili video interfaces
131
+ class Fav < BilibiliBase
132
+ # list user fav folders
133
+ def list_user_fav_video(user_info)
134
+ url = "https://api.bilibili.com/x/v3/fav/folder/created/list-all?up_mid=#{user_info.uid}&type=2"
135
+ data = get_jsona(url)
136
+ Bilibili::FavList.new(data)
137
+ end
138
+
139
+ # list user fav folder videos by page
140
+ def list_fav_video(media_id, page_num = 1, page_size = 10, keyword = nil)
141
+ keyword = "&keyword=#{keyword}" unless keyword.nil?
142
+ url = "https://api.bilibili.com/x/v3/fav/resource/list?media_id=#{media_id}&pn=#{page_num}&ps=#{page_size}#{keyword}&platform=web"
143
+ data = get_jsona(url)
144
+ Bilibili::FavResourceList.new(data)
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,75 @@
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 'net/http'
9
+ require 'nice_http'
10
+ require_relative 'response_body'
11
+
12
+ # bilibili client http module
13
+ module BiliHttp
14
+ class << self
15
+ attr_accessor :headers
16
+ end
17
+
18
+ # bilibili http client
19
+ class HttpClient
20
+ attr_accessor :login_http, :api_http, :manga_http
21
+
22
+ def initialize
23
+ BiliHttp.headers = {
24
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 Edg/91.0.864.64',
25
+ 'Referer': 'https://www.bilibili.com'
26
+ }
27
+ end
28
+
29
+ # get method
30
+ def get_json(http, url)
31
+ json_data(get(http, url))
32
+ end
33
+
34
+ def get(http, url)
35
+ request = {
36
+ headers: BiliHttp.headers,
37
+ path: URI(url).request_uri
38
+ }
39
+ http.get(request).data
40
+ end
41
+
42
+ # post method with form data
43
+ def post_form_json(http, url, params)
44
+ custom_headers = BiliHttp.headers.clone
45
+ custom_headers['Content-Type'] = 'application/x-www-form-urlencoded'
46
+ request = {
47
+ headers: custom_headers,
48
+ path: URI(url).request_uri,
49
+ data: params
50
+ }
51
+ json_data(http.post(request).data)
52
+ end
53
+
54
+ # post method with json body
55
+ def post_json(http, url, headers, req_body)
56
+ headers = BiliHttp.headers.clone if headers.nil? || headers.empty?
57
+ headers['Content-Type'] = 'application/json' unless req_body.nil? || req_body.empty?
58
+ request = {
59
+ headers: headers,
60
+ path: URI(url).request_uri
61
+ }
62
+ request.merge!({ data: req_body }) unless req_body.nil? || req_body.empty?
63
+ json_data(http.post(request).data)
64
+ end
65
+
66
+ def json_data(data)
67
+ body = BiliHttp::ResponseBody.new(data.json)
68
+ if body.data.nil?
69
+ body
70
+ else
71
+ body.data
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +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
@@ -0,0 +1,102 @@
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 'rqrcode'
11
+ require 'json'
12
+
13
+ # login module
14
+ module Bilibili
15
+ include BiliHttp
16
+ # bilibili user info
17
+ class UserInfo
18
+ attr_accessor :face, :level_info, :uid, :money, :moral, :uname, :vip_type
19
+
20
+ def initialize(json)
21
+ return if json.nil?
22
+
23
+ @face = json[:face]
24
+ @level_info = json[:level_info]
25
+ @uid = json[:mid]
26
+ @money = json[:money]
27
+ @moral = json[:moral]
28
+ @uname = json[:moral]
29
+ @vip_type = json[:vipType]
30
+ end
31
+
32
+ def to_json(*opt)
33
+ {
34
+ face: @face,
35
+ level_info: @level_info,
36
+ uid: @uid,
37
+ money: @money,
38
+ moral: @moral,
39
+ uname: @uname,
40
+ vip_type: @vip_type
41
+ }.to_json(*opt)
42
+ end
43
+ end
44
+
45
+ # login class
46
+ class Login < BilibiliBase
47
+ attr_accessor :url, :oauth_key
48
+
49
+ def login_url
50
+ data = get_jsonl('https://passport.bilibili.com/qrcode/getLoginUrl')
51
+ @url = data[:url]
52
+ @oauth_key = data[:oauthKey]
53
+ end
54
+
55
+ def show_qrcode
56
+ qr = RQRCode::QRCode.new(@url)
57
+ pic = qr.as_ansi(
58
+ light: "\033[47m", dark: "\033[40m",
59
+ fill_character: ' ',
60
+ quiet_zone_size: 1
61
+ )
62
+ puts pic
63
+ end
64
+
65
+ def login_user_info
66
+ set_http_cookie
67
+ data = get_jsona('https://api.bilibili.com/nav')
68
+ if data.code != '-101'
69
+ Bilibili::UserInfo.new(data)
70
+ else
71
+ puts 'Cookie已失效'
72
+ clean_cookie
73
+ login_user_info
74
+ end
75
+ end
76
+
77
+ def login
78
+ login_url
79
+ show_qrcode
80
+ print '已完成扫码?[y/n]'
81
+ over = $stdin.gets.chomp
82
+ return nil unless over == 'y'
83
+
84
+ post_form_jsonl('https://passport.bilibili.com/qrcode/getLoginInfo', { oauthKey: @oauth_key })
85
+ puts 'Login Success !!!'
86
+ save_cookie
87
+ 'success'
88
+ end
89
+
90
+ private
91
+
92
+ def set_http_cookie
93
+ cookies = @http_client.login_http.cookies
94
+ if cookies.nil? || cookies.empty?
95
+ login
96
+ @http_client.api_http.cookies = @http_client.login_http.cookies
97
+ else
98
+ @http_client.api_http.cookies = cookies
99
+ end
100
+ end
101
+ end
102
+ end
@@ -0,0 +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
+ # video module
11
+ module Bilibili
12
+ include BiliHttp
13
+
14
+ # bilibili video interfaces
15
+ class Manga < BilibiliBase
16
+ def check_in
17
+ cur_header = {
18
+ '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'
19
+ }
20
+ post_jsonm('https://manga.bilibili.com/twirp/activity.v1.Activity/ClockIn?platform=android',
21
+ cur_header, { 'platform' => 'android' })
22
+ end
23
+ end
24
+ end
@@ -0,0 +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.1'
10
+ end
@@ -0,0 +1,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 'down'
10
+ require 'fileutils'
11
+ require 'ruby-progressbar'
12
+
13
+ # video module
14
+ module Bilibili
15
+ include BiliHttp
16
+ # video page list
17
+ class PageInfo
18
+ attr_accessor :cid, :page, :from, :part, :duration, :vid, :weblink
19
+
20
+ def initialize(json)
21
+ return if json.nil?
22
+
23
+ @cid = json[:cid]
24
+ @page = json[:page]
25
+ @from = json[:from]
26
+ @part = json[:part]
27
+ @duration = json[:duration]
28
+ @vid = json[:vid]
29
+ @weblink = json[:weblink]
30
+ end
31
+
32
+ def to_json(*opt)
33
+ {
34
+ cid: @cid,
35
+ page: @page,
36
+ from: @from,
37
+ part: @part,
38
+ duration: @duration,
39
+ vid: @vid,
40
+ weblink: @weblink
41
+ }.to_json(*opt)
42
+ end
43
+ end
44
+
45
+ # bilibili video interfaces
46
+ class Video < BilibiliBase
47
+ def video_page_list(bv_id)
48
+ return nil if bv_id.nil?
49
+
50
+ url = "https://api.bilibili.com/x/player/pagelist?bvid=#{bv_id}"
51
+ datas = get_jsona(url)
52
+ return nil if datas.nil?
53
+
54
+ datas.map do |d|
55
+ Bilibili::PageInfo.new(d)
56
+ end
57
+ end
58
+
59
+ def get_video_url(bv_id, cid, video_qn = '720')
60
+ qn = BilibiliBase.video_qn[video_qn]
61
+ url = "https://api.bilibili.com/x/player/playurl?bvid=#{bv_id}&cid=#{cid}&qn=#{qn}&fnval=0&fnver=0&fourk=1"
62
+ data = get_jsona(url)
63
+ data[:durl]
64
+ end
65
+
66
+ def video_url_list(bv_id, video_qn = '720')
67
+ result = []
68
+ page_list = video_page_list(bv_id)
69
+ return nil if page_list.nil?
70
+
71
+ page_list.each do |page|
72
+ get_video_url(bv_id, page.cid, video_qn).each do |durl|
73
+ order = durl[:order] < 10 ? "0#{durl[:order]}" : durl[:order]
74
+ result << { 'name': "#{page.part}_#{order}.flv", 'url': durl[:url].to_s }
75
+ end
76
+ end
77
+ result
78
+ end
79
+
80
+ def download_video_by_bv(bv_id, video_qn = '720')
81
+ urls = video_url_list(bv_id, video_qn)
82
+ return nil if urls.empty?
83
+
84
+ download_path = "#{File.expand_path(@options['download_path'].to_s, __dir__)}/#{bv_id}/"
85
+ urls.each do |durl|
86
+ download_file(durl[:url], download_path, durl[:name])
87
+ end
88
+ end
89
+
90
+ private
91
+
92
+ def download_file(url, dir, filename)
93
+ progressbar = ProgressBar.create
94
+ total_size = 0
95
+ headers = generate_headers
96
+ FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
97
+ puts "开始下载文件: #{filename}"
98
+ Down::NetHttp.download(url,
99
+ destination: "#{dir}#{filename}",
100
+ headers: headers,
101
+ content_length_proc: proc { |size| total_size = size },
102
+ progress_proc: proc { |cursize| progressbar.progress = cursize.to_f / total_size * 100.0 })
103
+ end
104
+
105
+ def create_cookie_str(cookies)
106
+ cookies = cookies['/']
107
+ cookies_to_set_str = ''
108
+ cookies.each do |key, value|
109
+ cookies_to_set_str += "#{key}=#{value}; "
110
+ end
111
+ cookies_to_set_str
112
+ end
113
+
114
+ def generate_headers
115
+ headers = BiliHttp.headers
116
+ {
117
+ 'User-Agent' => headers[:"User-Agent"],
118
+ 'Referer' => headers[:Referer],
119
+ 'Cookie' => create_cookie_str(load_cookie)
120
+ }
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'bilibili_console/http/http'
4
+ require_relative 'bilibili_console/login'
5
+ require_relative 'bilibili_console/fav'
6
+ require_relative 'bilibili_console/video'
7
+ require_relative 'bilibili_console/manga'
8
+
9
+ # bilibili console main class
10
+ class BilibiliConsole
11
+ attr_accessor :http_client, :bilibili_login, :user, :fav, :video, :manga
12
+
13
+ def initialize
14
+ @http_client = BiliHttp::HttpClient.new
15
+ @bilibili_login = Bilibili::Login.new(@http_client)
16
+ @fav = Bilibili::Fav.new(@http_client)
17
+ @video = Bilibili::Video.new(@http_client)
18
+ @manga = Bilibili::Manga.new(@http_client)
19
+ end
20
+
21
+ def login
22
+ set_login_http
23
+ @bilibili_login.login
24
+ end
25
+
26
+ def login_user_info
27
+ set_login_http
28
+ set_api_http
29
+ @bilibili_login.login_user_info
30
+ end
31
+
32
+ def user_fav_list
33
+ @user = login_user_info if @user.nil?
34
+ set_api_http
35
+ @fav.list_user_fav_video(@user)
36
+ end
37
+
38
+ def list_fav_video(media_id, page_num = 1, page_size = 10, keyword = nil)
39
+ set_api_http
40
+ @fav.list_fav_video(media_id, page_num, page_size, keyword)
41
+ end
42
+
43
+ def download_video(bv_id)
44
+ set_api_http
45
+ @video.download_video_by_bv(bv_id)
46
+ end
47
+
48
+ def manga_checkin
49
+ set_manga_http
50
+ @manga.check_in
51
+ end
52
+
53
+ private
54
+
55
+ def set_login_http
56
+ @http_client.login_http = NiceHttp.new('https://passport.bilibili.com')
57
+ @http_client.login_http.cookies = @bilibili_login.load_cookie
58
+ end
59
+
60
+ def set_api_http
61
+ @http_client.api_http = NiceHttp.new('https://api.bilibili.com')
62
+ @http_client.api_http.cookies = @bilibili_login.load_cookie
63
+ end
64
+
65
+ def set_manga_http
66
+ @http_client.manga_http = NiceHttp.new('https://manga.bilibili.com')
67
+ @http_client.manga_http.cookies = @bilibili_login.load_cookie
68
+ end
69
+ end
data/rubocop.yml ADDED
@@ -0,0 +1,2 @@
1
+ Style/FrozenStringLiteralComment:
2
+ Enabled: false
data/setup.sh ADDED
@@ -0,0 +1,12 @@
1
+ #!/bin/bash
2
+
3
+ # Copyright (c) 2021 10344742
4
+ #
5
+ # This software is released under the MIT License.
6
+ # https://opensource.org/licenses/MIT
7
+
8
+ git pull
9
+ bundle install
10
+ gem build bilibili_console.gemspec
11
+ gem install bilibili_console-0.0.1.gem
12
+ echo "Install Over"
metadata ADDED
@@ -0,0 +1,136 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bilibili_console
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - leejoker
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-10-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: down
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '5.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '5.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: nice_http
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.9
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.9
41
+ - !ruby/object:Gem::Dependency
42
+ name: rqrcode
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: ruby-progressbar
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.11.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.11.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 1.1.0
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 1.1.0
83
+ description: a console tool for bilibili
84
+ email: 1056650571@qq.com
85
+ executables:
86
+ - bili-console
87
+ extensions: []
88
+ extra_rdoc_files:
89
+ - README.md
90
+ - LICENSE
91
+ files:
92
+ - ".bundle/config"
93
+ - ".gitignore"
94
+ - Gemfile
95
+ - Gemfile.lock
96
+ - LICENSE
97
+ - README.md
98
+ - Rakefile
99
+ - bilibili_console.gemspec
100
+ - bin/banner.txt
101
+ - bin/bili-console
102
+ - lib/bilibili_console.rb
103
+ - lib/bilibili_console/base.rb
104
+ - lib/bilibili_console/fav.rb
105
+ - lib/bilibili_console/http/http.rb
106
+ - lib/bilibili_console/http/response_body.rb
107
+ - lib/bilibili_console/login.rb
108
+ - lib/bilibili_console/manga.rb
109
+ - lib/bilibili_console/version.rb
110
+ - lib/bilibili_console/video.rb
111
+ - rubocop.yml
112
+ - setup.sh
113
+ homepage: https://github.com/leejoker/bilibili-console
114
+ licenses:
115
+ - MIT
116
+ metadata: {}
117
+ post_install_message:
118
+ rdoc_options: []
119
+ require_paths:
120
+ - lib
121
+ required_ruby_version: !ruby/object:Gem::Requirement
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ version: '2.7'
126
+ required_rubygems_version: !ruby/object:Gem::Requirement
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ version: '0'
131
+ requirements: []
132
+ rubygems_version: 3.2.22
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: bilibili console
136
+ test_files: []