bilibili_console 0.0.1

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 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: []