agora-ruby 0.1.0

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.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +11 -0
  6. data/Gemfile.lock +56 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +187 -0
  9. data/Rakefile +6 -0
  10. data/agora-ruby.gemspec +29 -0
  11. data/bin/console +13 -0
  12. data/bin/setup +8 -0
  13. data/lib/agora/cloud_recording/client.rb +139 -0
  14. data/lib/agora/config.rb +12 -0
  15. data/lib/agora/dynamic_key/access_token.rb +55 -0
  16. data/lib/agora/dynamic_key/rtc_token_builder.rb +112 -0
  17. data/lib/agora/dynamic_key/rtm_token_builder.rb +46 -0
  18. data/lib/agora/dynamic_key/sign.rb +73 -0
  19. data/lib/agora/dynamic_key.rb +13 -0
  20. data/lib/agora/dynamic_key2/access_token.rb +220 -0
  21. data/lib/agora/dynamic_key2/apaas_token_builder.rb +73 -0
  22. data/lib/agora/dynamic_key2/chat_token_builder.rb +42 -0
  23. data/lib/agora/dynamic_key2/education_token_builder.rb +73 -0
  24. data/lib/agora/dynamic_key2/fpa_token_builder.rb +21 -0
  25. data/lib/agora/dynamic_key2/rtc_token_builder.rb +215 -0
  26. data/lib/agora/dynamic_key2/rtm_token_builder.rb +22 -0
  27. data/lib/agora/dynamic_key2/util.rb +60 -0
  28. data/lib/agora/dynamic_key2.rb +12 -0
  29. data/lib/agora/errors.rb +14 -0
  30. data/lib/agora/version.rb +3 -0
  31. data/lib/agora-ruby.rb +18 -0
  32. data/sample/README.md +12 -0
  33. data/sample/apaas_token_builder_sample.rb +29 -0
  34. data/sample/chat_token_builder_sample.rb +23 -0
  35. data/sample/education_token_builder_sample.rb +29 -0
  36. data/sample/fpa_token_builder_sample.rb +16 -0
  37. data/sample/rtc_token_builder2_sample.rb +55 -0
  38. data/sample/rtc_token_builder_sample.rb +40 -0
  39. data/sample/rtm_token_builder_sample.rb +27 -0
  40. data/token_compare.md +143 -0
  41. metadata +101 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4086d655e80b6377412e1830af2f16b3b7f4fc2f5cc746c9e50a1cc56cee72dc
4
+ data.tar.gz: c28cf48f91c5e343b03c3ce1eaedb92bdc8774bae19a68b82a6cde0c9aaa52ce
5
+ SHA512:
6
+ metadata.gz: 7a8ffc3b500fae010a7971a30a59be3aa3cbcce48bc735adbb92f8c3c1d488b0add121e10640a1995c7bf561a94caadd84b1e03c2a4be9a023e3449e1c1348ad
7
+ data.tar.gz: c36b354a9f070c5c09b8f9425260c9a28bcbc97d6db08063a29e3e779300a64eb3c3e93d1238e486da412794c152cefbf58ba00b2402371d3feb5d38724739e6
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ language: ruby
3
+ cache: bundler
4
+ rvm:
5
+ - 2.7.4
6
+ before_install: gem install bundler -v 2.1.4
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in agora-ruby.gemspec
4
+ gemspec
5
+
6
+ gem "rake", "~> 13.0"
7
+ gem "rspec", "~> 3.0"
8
+
9
+ group :test do
10
+ gem "webmock", "~> 3.0"
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,56 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ agora-ruby (0.1.0)
5
+ httparty (~> 0.20)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ addressable (2.8.7)
11
+ public_suffix (>= 2.0.2, < 7.0)
12
+ bigdecimal (3.1.9)
13
+ crack (1.0.0)
14
+ bigdecimal
15
+ rexml
16
+ csv (3.3.4)
17
+ diff-lcs (1.4.4)
18
+ hashdiff (1.1.2)
19
+ httparty (0.23.1)
20
+ csv
21
+ mini_mime (>= 1.0.0)
22
+ multi_xml (>= 0.5.2)
23
+ mini_mime (1.1.5)
24
+ multi_xml (0.6.0)
25
+ public_suffix (5.1.1)
26
+ rake (13.0.6)
27
+ rexml (3.4.1)
28
+ rspec (3.10.0)
29
+ rspec-core (~> 3.10.0)
30
+ rspec-expectations (~> 3.10.0)
31
+ rspec-mocks (~> 3.10.0)
32
+ rspec-core (3.10.1)
33
+ rspec-support (~> 3.10.0)
34
+ rspec-expectations (3.10.1)
35
+ diff-lcs (>= 1.2.0, < 2.0)
36
+ rspec-support (~> 3.10.0)
37
+ rspec-mocks (3.10.2)
38
+ diff-lcs (>= 1.2.0, < 2.0)
39
+ rspec-support (~> 3.10.0)
40
+ rspec-support (3.10.2)
41
+ webmock (3.25.1)
42
+ addressable (>= 2.8.0)
43
+ crack (>= 0.3.2)
44
+ hashdiff (>= 0.4.0, < 2.0.0)
45
+
46
+ PLATFORMS
47
+ ruby
48
+
49
+ DEPENDENCIES
50
+ agora-ruby!
51
+ rake (~> 13.0)
52
+ rspec (~> 3.0)
53
+ webmock (~> 3.0)
54
+
55
+ BUNDLED WITH
56
+ 2.1.4
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 yfscret
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,187 @@
1
+ # 声网(Agora)Ruby 客户端
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/agora-ruby.svg)](https://badge.fury.io/rb/agora-ruby) <!-- 发布后可更新 -->
4
+
5
+ 本 Ruby gem 提供了对接声网 Agora RESTful API 的客户端,当前聚焦于云端录制功能。它简化了录制任务的发起、停止、查询,以及录制文件上传到第三方云存储平台(如阿里云 OSS、Amazon S3 等)的流程。
6
+
7
+ ## 安装
8
+
9
+ 在你的 Gemfile 中添加:
10
+
11
+ ```ruby
12
+ gem 'agora-ruby'
13
+ ```
14
+
15
+ 然后执行:
16
+
17
+ ```bash
18
+ $ bundle install
19
+ ```
20
+
21
+ 或者直接安装:
22
+
23
+ ```bash
24
+ $ gem install agora-ruby
25
+ ```
26
+
27
+ ## 配置
28
+
29
+ 在使用本 gem 前,你需要配置声网和第三方云存储的相关参数。推荐在 Rails 项目中放在 `config/initializers/agora.rb`,普通 Ruby 项目可在初始化阶段配置:
30
+
31
+ ```ruby
32
+ Agora.configure do |config|
33
+ # 声网相关配置(必填)
34
+ config.app_id = '你的声网 App ID'
35
+ config.customer_key = '你的声网 RESTFUL API 客户 ID'
36
+ config.customer_secret = '你的声网 RESTFUL API 客户密钥'
37
+
38
+ # 第三方云存储平台配置(必填,vendor 需根据实际平台填写)
39
+ # 支持的 vendor 及编号如下:
40
+ # 1:Amazon S3
41
+ # 2:阿里云 OSS
42
+ # 3:腾讯云 COS
43
+ # 5:Microsoft Azure
44
+ # 6:谷歌云 GCS
45
+ # 7:华为云 OBS
46
+ # 8:百度智能云 BOS
47
+ config.oss_vendor = 2 # 2 表示阿里云 OSS
48
+ config.oss_region = 1 # 区域编号,具体见官方文档 https://doc.shengwang.cn/doc/cloud-recording/restful/api/reference
49
+ config.oss_bucket = '你的云存储 bucket 名称'
50
+ config.oss_access_key = '你的云存储 Access Key'
51
+ config.oss_secret_key = '你的云存储 Secret Key'
52
+ config.oss_filename_prefix = ["directory1","directory2"] # 录制文件在第三方云存储中的存储位置, directory1/directory2/xxx.m3u8
53
+ end
54
+ ```
55
+
56
+ **安全提示:** 强烈建议通过环境变量或 Rails credentials 等安全方式管理密钥,不要将密钥明文写入代码。
57
+
58
+ ## 使用方法
59
+
60
+ 配置完成后,可通过 `Agora::CloudRecording::Client` 管理云端录制。
61
+
62
+ ### 典型场景:直播连线录制
63
+
64
+ 假设你在直播间(频道名:`"live-chat-123"`)与用户连线,需要录制用户的视频、用户音频和你的音频,录制文件自动上传到阿里云 OSS。
65
+
66
+ ```ruby
67
+ # 确保已完成上述配置
68
+ begin
69
+ client = Agora::CloudRecording::Client.new
70
+ cname = "live-chat-123"
71
+ my_uid = "1888" # 你的 UID
72
+ recording_bot_uid = "#{my_uid}#{rand(1000)}" # 录制机器人 UID,需唯一
73
+ record_uid = "110560" # 需要录制的用户 UID
74
+
75
+ # 1. 获取录制资源 resourceId
76
+ # acquire 的 clientRequest 可为空,除非有特殊需求
77
+ puts "获取录制资源..."
78
+ acquire_response = client.acquire(cname, recording_bot_uid)
79
+ resource_id = acquire_response["resourceId"]
80
+ puts "resourceId: #{resource_id}"
81
+
82
+ # 2. 获取 token
83
+ # 你需要为 recording_bot_uid 生成一个有效的声网 Token(可用你自己的 Token 服务)
84
+ app_id = 'xxxxxxx'
85
+ app_certificate = 'xxxxxxxx'
86
+ token_expiration_in_seconds = 3600 * 24
87
+ privilege_expiration_in_seconds = 3600 * 24
88
+ token = Agora::AgoraDynamicKey2::RtcTokenBuilder.build_token_with_uid(
89
+ app_id, app_certificate, cname, recording_bot_uid,
90
+ Agora::AgoraDynamicKey2::RtcTokenBuilder::ROLE_PUBLISHER,
91
+ token_expiration_in_seconds, privilege_expiration_in_seconds
92
+ )
93
+
94
+ # 3. 启动录制
95
+ recording_config = {
96
+ streamTypes: 2, # 录制音视频
97
+ channelType: 1, # 直播模式
98
+ audioProfile: 2, # 音频质量, 音频编码,双声道,编码码率约 192 Kbps。
99
+ # 只录制指定用户的视频,和你与用户的音频
100
+ subscribeVideoUids: [record_uid],
101
+ subscribeAudioUids: [my_uid, record_uid],
102
+ transcodingConfig: {
103
+ width: 720,
104
+ height: 1280,
105
+ bitrate: 3420,
106
+ fps: 30
107
+ }
108
+ }
109
+
110
+ recording_file_config = {
111
+ avFileType: ["hls", "mp4"] # 同时录制 HLS 和 MP4
112
+ }
113
+
114
+ puts "启动录制..."
115
+ start_response = client.start(
116
+ resource_id,
117
+ cname,
118
+ recording_bot_uid,
119
+ token,
120
+ 'mix', # 合流录制,若需单流录制可用 'individual'
121
+ recording_config,
122
+ recording_file_config
123
+ )
124
+ sid = start_response["sid"] # 录制会话 ID
125
+ puts "录制已启动,SID: #{sid}"
126
+
127
+ # 录制中(实际业务中可根据需求控制时长)
128
+ puts "录制中..."
129
+
130
+ # 4. 可选:查询录制状态
131
+ puts "查询录制状态..."
132
+ query_response = client.query(resource_id, sid)
133
+ puts "状态查询结果: #{query_response}"
134
+ # 可根据 query_response["serverResponse"]["status"] 判断录制状态
135
+
136
+ # 5. 停止录制
137
+ puts "停止录制..."
138
+ stop_response = client.stop(resource_id, sid, cname, recording_bot_uid, 'mix', client_request = { async_stop: true })
139
+ puts "停止结果: #{stop_response}"
140
+ # 文件上传 OSS 可能有延迟,可通过 stop_response["serverResponse"]["fileList"] 获取文件列表
141
+
142
+ puts "录制流程结束,请到 OSS 查看文件: #{Agora.config.oss_bucket}/#{stop_response["serverResponse"]["fileList"][0]['fileName']}"
143
+
144
+ rescue Agora::Errors::ConfigurationError => e
145
+ puts "配置错误: #{e.message}"
146
+ rescue Agora::Errors::APIError => e
147
+ puts "API 错误: #{e.message}"
148
+ puts "响应码: #{e.response&.code}"
149
+ puts "响应体: #{e.response&.body}"
150
+ rescue StandardError => e
151
+ puts "发生未知错误: #{e.message}"
152
+ puts e.backtrace.join("\n")
153
+ end
154
+ ```
155
+
156
+ ### API 方法说明
157
+
158
+ `Agora::CloudRecording::Client` 提供如下方法:
159
+
160
+ * `acquire(cname, uid, client_request = {})`:获取录制资源 resourceId。
161
+ * `start(resource_id, cname, uid, token, mode = 'mix', recording_config = {}, recording_file_config = {}, storage_config = {})`:启动录制。
162
+ * `mode`:'mix'(合流,默认)或 'individual'(单流)。
163
+ * `recording_config`:录制参数(如 streamTypes、subscribeVideoUids、subscribeAudioUids、transcodingConfig 等,详见官方文档)。
164
+ * `recording_file_config`:输出文件类型(如 avFileType: ["hls", "mp4"])。
165
+ * `storage_config`:云存储参数(如 fileNamePrefix,可覆盖默认值)。
166
+ * `query(resource_id, sid, mode = 'mix')`:查询录制状态。
167
+ * `stop(resource_id, sid, cname, uid, mode = 'mix', client_request = {})`:停止录制。
168
+
169
+ 详细参数和更多高级用法请参考 [声网云端录制 RESTful API 文档](https://doc.shengwang.cn/doc/cloud-recording/restful/cloud-recording/overview)。
170
+
171
+ ## 开发与贡献
172
+
173
+ 克隆本仓库后,运行 `bin/setup` 安装依赖。测试可用 `rake spec`(建议补充测试用例)。你也可以用 `bin/console` 进入交互式环境。
174
+
175
+ 本地安装 gem 可用 `bundle exec rake install`。如需发布新版本,修改 `version.rb` 后执行 `bundle exec rake release`,会自动打 tag 并推送到 RubyGems(需先配置好发布信息)。
176
+
177
+ ## 贡献
178
+
179
+ 欢迎通过 Pull Request 或 Issue 反馈和贡献代码,详见 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。
180
+
181
+ ## 许可证
182
+
183
+ 本项目基于 [MIT License](https://opensource.org/licenses/MIT) 开源。
184
+
185
+ ## 行为准则
186
+
187
+ 所有参与本项目的人都需遵守 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,29 @@
1
+ require_relative 'lib/agora/version'
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "agora-ruby"
5
+ spec.version = Agora::VERSION
6
+ spec.authors = ["yfscret"]
7
+ spec.email = ["yfscret@gmail.com"]
8
+
9
+ spec.summary = %q{A Ruby client for Agora.io RESTful APIs, starting with Cloud Recording.}
10
+ spec.description = %q{This gem provides an easy-to-use interface for interacting with Agora.io's RESTful services, initially focusing on cloud recording functionalities, including uploading to Aliyun OSS.}
11
+ spec.homepage = "https://rubygems.org/gems/agora-ruby"
12
+ spec.license = "MIT"
13
+ spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0")
14
+
15
+ spec.metadata["homepage_uri"] = spec.homepage
16
+ spec.metadata["source_code_uri"] = "https://github.com/yfscret/agora-ruby"
17
+ spec.metadata["changelog_uri"] = "https://github.com/yfscret/agora-ruby"
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.add_dependency "httparty", "~> 0.20"
29
+ end
data/bin/console ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+
5
+ # You can add fixtures and/or initialization code here to make experimenting
6
+ # with your gem easier. You can also use a different console, if you like.
7
+
8
+ # (If you use this, don't forget to add pry to your Gemfile!)
9
+ # require "pry"
10
+ # Pry.start
11
+
12
+ require "irb"
13
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,139 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ module Agora
5
+ module CloudRecording
6
+ class Client
7
+ include HTTParty
8
+ # base_uri 通过 Agora.config.base_url 设置
9
+
10
+ attr_reader :app_id, :customer_key, :customer_secret, :oss_vendor, :oss_region, :oss_bucket, :oss_access_key, :oss_secret_key, :oss_filename_prefix
11
+
12
+ def initialize
13
+ @config = Agora.config # 使用 Agora.config 获取配置实例
14
+ unless @config && @config.app_id && @config.customer_key && @config.customer_secret
15
+ raise Agora::Errors::ConfigurationError, "声网 App ID, Customer ID, 和 Customer Certificate 必须配置。"
16
+ end
17
+ unless @config.oss_bucket && @config.oss_access_key && @config.oss_secret_key && @config.oss_region && @config.oss_vendor
18
+ raise Agora::Errors::ConfigurationError, "云存储的 Bucket, Access Key, Secret Key, Region, 和 Vendor 必须配置。"
19
+ end
20
+
21
+ self.class.base_uri @config.base_url # 设置 base_uri
22
+
23
+ @app_id = @config.app_id
24
+ @customer_key = @config.customer_key
25
+ @customer_secret = @config.customer_secret
26
+ @oss_vendor = @config.oss_vendor
27
+ @oss_region = @config.oss_region
28
+ @oss_bucket = @config.oss_bucket
29
+ @oss_access_key = @config.oss_access_key
30
+ @oss_secret_key = @config.oss_secret_key
31
+ @oss_filename_prefix = @config.oss_filename_prefix
32
+ end
33
+
34
+ def acquire(cname, uid, client_request = {})
35
+ path = "/v1/apps/#{@app_id}/cloud_recording/acquire"
36
+ body = {
37
+ cname: cname,
38
+ uid: uid,
39
+ clientRequest: client_request
40
+ }.to_json
41
+
42
+ headers = {
43
+ 'Authorization' => basic_auth_header,
44
+ 'Content-Type' => 'application/json'
45
+ }
46
+ # 注意:HTTParty 的 post/get 方法是类方法
47
+ handle_response(self.class.post(path, body: body, headers: headers))
48
+ end
49
+
50
+ def start(resource_id, cname, uid, token, mode = 'mix', recording_config = {}, recording_file_config = {}, storage_config = {})
51
+ path = "/v1/apps/#{@app_id}/cloud_recording/resourceid/#{resource_id}/mode/#{mode}/start"
52
+
53
+ default_storage_config = {
54
+ vendor: @oss_vendor,
55
+ region: @oss_region,
56
+ bucket: @oss_bucket,
57
+ accessKey: @oss_access_key,
58
+ secretKey: @oss_secret_key,
59
+ fileNamePrefix: @oss_filename_prefix
60
+ }
61
+
62
+ body = {
63
+ cname: cname,
64
+ uid: uid,
65
+ clientRequest: {
66
+ token: token,
67
+ recordingConfig: default_recording_config.merge(recording_config),
68
+ recordingFileConfig: default_recording_file_config.merge(recording_file_config),
69
+ storageConfig: default_storage_config.merge(storage_config)
70
+ }
71
+ }.to_json
72
+
73
+ headers = {
74
+ 'Authorization' => basic_auth_header,
75
+ 'Content-Type' => 'application/json'
76
+ }
77
+ handle_response(self.class.post(path, body: body, headers: headers))
78
+ end
79
+
80
+ def query(resource_id, sid, mode = 'mix')
81
+ path = "/v1/apps/#{@app_id}/cloud_recording/resourceid/#{resource_id}/sid/#{sid}/mode/#{mode}/query"
82
+ headers = { 'Authorization' => basic_auth_header }
83
+ handle_response(self.class.get(path, headers: headers))
84
+ end
85
+
86
+ def stop(resource_id, sid, cname, uid, mode = 'mix', client_request = {})
87
+ path = "/v1/apps/#{@app_id}/cloud_recording/resourceid/#{resource_id}/sid/#{sid}/mode/#{mode}/stop"
88
+ body = {
89
+ cname: cname,
90
+ uid: uid,
91
+ clientRequest: client_request
92
+ }.to_json
93
+
94
+ headers = {
95
+ 'Authorization' => basic_auth_header,
96
+ 'Content-Type' => 'application/json'
97
+ }
98
+ handle_response(self.class.post(path, body: body, headers: headers))
99
+ end
100
+
101
+ private
102
+
103
+ def basic_auth_header
104
+ "Basic " + Base64.strict_encode64("#{@customer_key}:#{@customer_secret}")
105
+ end
106
+
107
+ def handle_response(response)
108
+ if response.success?
109
+ response.parsed_response
110
+ else
111
+ error_message = "声网 API 错误: #{response.code}"
112
+ parsed_body = response.parsed_response
113
+ if parsed_body.is_a?(Hash)
114
+ reason = parsed_body['reason']
115
+ message = parsed_body['message']
116
+ error_message += " - 原因: #{reason}" if reason
117
+ error_message += " - 信息: #{message}" if message && message != reason # 避免重复信息
118
+ end
119
+ raise Agora::Errors::APIError.new(error_message, response)
120
+ end
121
+ end
122
+
123
+ def default_recording_config
124
+ {
125
+ maxIdleTime: 30,
126
+ streamTypes: 2,
127
+ channelType: 1,
128
+ }
129
+ end
130
+
131
+ def default_recording_file_config
132
+ {
133
+ avFileType: ["hls", "mp4"]
134
+ }
135
+ end
136
+
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,12 @@
1
+ module Agora
2
+ class Config
3
+ attr_accessor :app_id, :customer_key, :customer_secret,
4
+ :oss_vendor, :oss_region, :oss_bucket,
5
+ :oss_access_key, :oss_secret_key,
6
+ :base_url, :oss_filename_prefix
7
+
8
+ def initialize
9
+ @base_url = 'https://api.sd-rtn.com'
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,55 @@
1
+ module Agora::AgoraDynamicKey
2
+ module Privilege
3
+ JOIN_CHANNEL = 1
4
+ PUBLISH_AUDIO_STREAM = 2
5
+ PUBLISH_VIDEO_STREAM = 3
6
+ PUBLISH_DATA_STREAM = 4
7
+ RTM_LOGIN = 1000 # for RTM Only
8
+ end
9
+
10
+ class AccessToken
11
+ VERSION = "006"
12
+
13
+ ONE_DAY = 864_00
14
+ SEED = 2 ** 32 - 1
15
+
16
+ attr_accessor :app_id, :channel_name, :app_certificate,
17
+ :uid, :privileges, :privilege_expired_ts,
18
+ :salt, :expired_ts
19
+
20
+ def initialize args={}
21
+ @app_id = args[:app_id]
22
+ @channel_name = args.fetch(:channel_name, "")
23
+ @app_certificate = args[:app_certificate]
24
+ @uid = "#{args.fetch(:uid, "")}"
25
+ @privileges = {}
26
+ @privilege_expired_ts = args[:privilege_expired_ts]
27
+ @salt = SecureRandom.rand(SEED)
28
+ @expired_ts = Time.now.to_i + ONE_DAY
29
+ end
30
+
31
+ def add_privilege privilege, ts
32
+ privileges[privilege] = ts
33
+ end
34
+
35
+ alias grant add_privilege
36
+
37
+ def build
38
+ Sign.encode self
39
+ end
40
+
41
+ def build!
42
+ Sign.encode! self
43
+ end
44
+
45
+ def from_string token
46
+ Sign.decode token
47
+ end
48
+
49
+ def self.generate! payload={}, &block
50
+ token = AccessToken.new payload
51
+ block.call token
52
+ token.build!
53
+ end
54
+ end
55
+ end