agora_rails 1.0.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.
- checksums.yaml +7 -0
- data/README.md +91 -0
- data/lib/agora_rails/cloud_recording.rb +131 -0
- data/lib/agora_rails/configuration.rb +16 -0
- data/lib/agora_rails/stt.rb +46 -0
- data/lib/agora_rails.rb +16 -0
- data/lib/dynamic_key2/access_token.rb +220 -0
- data/lib/dynamic_key2/apaas_token_builder.rb +73 -0
- data/lib/dynamic_key2/chat_token_builder.rb +42 -0
- data/lib/dynamic_key2/education_token_builder.rb +73 -0
- data/lib/dynamic_key2/fpa_token_builder.rb +20 -0
- data/lib/dynamic_key2/rtc_token_builder.rb +215 -0
- data/lib/dynamic_key2/rtm_token_builder.rb +23 -0
- data/lib/dynamic_key2/util.rb +61 -0
- data/lib/dynamic_key2.rb +14 -0
- data/lib/generators/agora_rails/install_generator.rb +13 -0
- data/lib/generators/agora_rails/templates/agora_rails.rb +12 -0
- metadata +129 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 04a40ffed9d5e20f48386decfc354bc5fe3883a50ab12931a91770cce0f7caeb
|
4
|
+
data.tar.gz: 27875a1500f997aff4d662c2291037eee9f2a7502563d43ee9580959635b91d0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: '077592d3284b50e15f8487cd3ddb310494c0e09cb67eb95f19153dffac3a41378d34c0eb98ad5ac9e9e7c372c5a58892113c51b4c1c993174c7d7c949ad2fa13'
|
7
|
+
data.tar.gz: c588ebe7535c4a88ff6493c4efaa29ded72a11de2e65b15672bc6e5047863d4c7500cf0dbecd82f4b2d0168085462cab867cb6b819bfb6634753ad1aa7a81ee4
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# AgoraRails
|
2
|
+
|
3
|
+
AgoraRails is a Ruby gem that provides an interface for Agora.io APIs, specifically designed for Ruby on Rails. It offers functionality for generating dynamic tokens and managing cloud recording.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
```ruby
|
9
|
+
gem 'agora_rails'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
```
|
14
|
+
$ bundle install
|
15
|
+
```
|
16
|
+
|
17
|
+
## Configuration
|
18
|
+
|
19
|
+
Create an initializer file (e.g., `config/initializers/agora_rails.rb`) and add your Agora.io credentials:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
AgoraRails.configure do |config|
|
23
|
+
config.app_id = 'your_app_id'
|
24
|
+
config.app_certificate = 'your_app_certificate'
|
25
|
+
config.customer_id = 'your_customer_id'
|
26
|
+
config.customer_secret = 'your_customer_secret'
|
27
|
+
|
28
|
+
config.bucket = 'your_bucket'
|
29
|
+
config.access_key = 'your_access_key'
|
30
|
+
config.secret_key = 'your_secret_key'
|
31
|
+
config.file_prefix = 'your_file_prefix'
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
The `file_prefix` is optional and is used to store the recording files in a specific folder in your bucket. For example, if you set the file_prefix to `["agora", "calls", "v3"]`, the recording files will be stored in a folder `agora/calls/v3` in your bucket.
|
36
|
+
|
37
|
+
|
38
|
+
## Usage
|
39
|
+
|
40
|
+
### Token Generation
|
41
|
+
|
42
|
+
The token generator is taken from the [Agora Tools repo](https://github.com/AgoraIO/Tools) and uses DynamicKey2.
|
43
|
+
DynamicKey2 requires `uid` to be an integer (i.e. not a string).
|
44
|
+
|
45
|
+
Generate a token for a specific channel and user:
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
channel_name = 'my_channel'
|
49
|
+
uid = 1234
|
50
|
+
|
51
|
+
recorder = AgoraRails::CloudRecording.new
|
52
|
+
token = recorder.generate_token(channel_name, uid)
|
53
|
+
```
|
54
|
+
You can validate the token at https://api-agora.solutions/
|
55
|
+
|
56
|
+
|
57
|
+
### Cloud Recording
|
58
|
+
|
59
|
+
Start cloud recording for a channel:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
channel_name = 'my_channel'
|
63
|
+
uid = 1234
|
64
|
+
recorder = AgoraRails::CloudRecording.new
|
65
|
+
recorder.start(channel_name, uid)
|
66
|
+
```
|
67
|
+
|
68
|
+
Stop cloud recording for a channel:
|
69
|
+
|
70
|
+
If you have the CloudRecording object, you can use it to stop the recording:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
recorder.stop
|
74
|
+
```
|
75
|
+
|
76
|
+
If you don't have the CloudRecording object, you can use the following method to stop the recording:
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
recorder = AgoraRails::CloudRecording.new
|
80
|
+
recorder.stop(channel_name, sid, uid, mode)
|
81
|
+
|
82
|
+
```
|
83
|
+
|
84
|
+
|
85
|
+
## Development
|
86
|
+
|
87
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
88
|
+
|
89
|
+
#### Speech-to-Text (STT)
|
90
|
+
|
91
|
+
STT support is currently being worked on.
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'dynamic_key2'
|
2
|
+
require 'httparty'
|
3
|
+
|
4
|
+
module AgoraRails
|
5
|
+
class CloudRecording
|
6
|
+
include HTTParty
|
7
|
+
base_uri 'https://api.agora.io/v1/apps'
|
8
|
+
|
9
|
+
debug_output $stdout # uncomment this for debugging i.e. output to stdout
|
10
|
+
|
11
|
+
attr_accessor :app_id, :app_certificate, :customer_key, :customer_secret, :auth, :resource_id, :uid, :bucket, :access_key, :secret_key, :sid, :channel_name, :mode
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
self.app_id = AgoraRails.configuration.app_id
|
15
|
+
self.app_certificate = AgoraRails.configuration.app_certificate
|
16
|
+
self.customer_key = AgoraRails.configuration.customer_key
|
17
|
+
self.customer_secret = AgoraRails.configuration.customer_secret
|
18
|
+
self.auth = { username: customer_key, password: customer_secret }
|
19
|
+
self.uid = "#{rand(2_000_000_000..3_000_000_000)}"
|
20
|
+
self.mode = 'mix'
|
21
|
+
end
|
22
|
+
|
23
|
+
def acquire_resource(channel_name, uid = nil)
|
24
|
+
self.channel_name = channel_name
|
25
|
+
self.uid = uid if uid
|
26
|
+
response = self.class.post("/#{app_id}/cloud_recording/acquire",
|
27
|
+
basic_auth: auth,
|
28
|
+
headers: { 'Content-Type' => 'application/json' },
|
29
|
+
body: {
|
30
|
+
cname: channel_name,
|
31
|
+
uid: self.uid.to_s,
|
32
|
+
clientRequest: { resourceExpiredHour: 24 }
|
33
|
+
}.to_json
|
34
|
+
)
|
35
|
+
self.resource_id = handle_response(response)['resourceId']
|
36
|
+
end
|
37
|
+
|
38
|
+
def start(channel_name, uid = nil, mode = nil, recording_config = nil)
|
39
|
+
raise "Invalid Channel Name" if channel_name.nil?
|
40
|
+
self.channel_name = channel_name
|
41
|
+
self.uid = uid if uid
|
42
|
+
self.mode = mode if mode
|
43
|
+
acquire_resource(channel_name)
|
44
|
+
recording_config ||= default_recording_config(channel_name, self.uid)
|
45
|
+
|
46
|
+
response = self.class.post("/#{app_id}/cloud_recording/resourceid/#{resource_id}/mode/#{self.mode}/start",
|
47
|
+
basic_auth: auth,
|
48
|
+
headers: { 'Content-Type' => 'application/json' },
|
49
|
+
body: recording_config.to_json
|
50
|
+
)
|
51
|
+
self.sid = handle_response(response)['sid']
|
52
|
+
end
|
53
|
+
|
54
|
+
def stop(channel_name = nil, sid = nil, uid = nil, mode = nil)
|
55
|
+
raise "Invalid Channel Name" if channel_name.nil? && self.channel_name.nil?
|
56
|
+
raise "Invalid SID" if sid.nil? && self.sid.nil?
|
57
|
+
self.channel_name = channel_name if channel_name
|
58
|
+
self.sid = sid if sid
|
59
|
+
self.uid = uid if uid
|
60
|
+
self.mode = mode if mode
|
61
|
+
|
62
|
+
acquire_resource(self.channel_name) if self.resource_id.nil? # FIXME: should pass resource_id in because it is possible that the resource ID is expired or acquired for another channel
|
63
|
+
|
64
|
+
response = self.class.post("/#{app_id}/cloud_recording/resourceid/#{self.resource_id}/sid/#{self.sid}/mode/#{self.mode}/stop",
|
65
|
+
basic_auth: auth,
|
66
|
+
headers: { 'Content-Type' => 'application/json' },
|
67
|
+
body: {
|
68
|
+
cname: self.channel_name,
|
69
|
+
uid: self.uid.to_s,
|
70
|
+
clientRequest: {}
|
71
|
+
}.to_json
|
72
|
+
)
|
73
|
+
handle_response(response)
|
74
|
+
end
|
75
|
+
|
76
|
+
def query(channel_name = nil)
|
77
|
+
self.channel_name = channel_name if channel_name
|
78
|
+
response = self.class.get("/#{app_id}/cloud_recording/resourceid/#{self.resource_id}/sid/#{self.sid}/mode/#{mode}/query",
|
79
|
+
basic_auth: auth,
|
80
|
+
headers: { 'Content-Type' => 'application/json' },
|
81
|
+
)
|
82
|
+
handle_response(response)
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def generate_token(channel_name = nil, uid = nil)
|
87
|
+
self.channel_name = channel_name if channel_name
|
88
|
+
self.uid = uid if uid
|
89
|
+
|
90
|
+
token_expiration_in_seconds = 3600 # 1 hour
|
91
|
+
privilege_expiration_in_seconds = 3600 # 1 hour
|
92
|
+
::AgoraDynamicKey2::RtcTokenBuilder.build_token_with_uid(
|
93
|
+
app_id, app_certificate, self.channel_name, self.uid,
|
94
|
+
::AgoraDynamicKey2::RtcTokenBuilder::ROLE_PUBLISHER, token_expiration_in_seconds, privilege_expiration_in_seconds
|
95
|
+
)
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def handle_response(response)
|
101
|
+
if response.success?
|
102
|
+
JSON.parse(response.body)
|
103
|
+
else
|
104
|
+
raise AgoraRails::Error, "API request failed: #{response.code} - #{response.body}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def default_recording_config(channel_name, uid)
|
109
|
+
{
|
110
|
+
cname: channel_name,
|
111
|
+
uid: uid.to_s,
|
112
|
+
clientRequest: {
|
113
|
+
token: generate_token,
|
114
|
+
recordingConfig: {
|
115
|
+
maxIdleTime: 30,
|
116
|
+
streamTypes: 0, # 0: audio only, 1: audio and video, 2: video only
|
117
|
+
channelType: 0, # 0: communication (audio call / video call), 1: live-broadcast (video live streaming)
|
118
|
+
},
|
119
|
+
storageConfig: {
|
120
|
+
vendor: 1, # 1: AWS, 2: Azure, 3: GCP, 4: Aliyun, 5: Tencent, 6: Qiniu, 7: AWS_S3, 8: Azure_Blob, 9: GCP_Storage, 10: Aliyun_OSS, 11: Tencent_COS, 12: Qiniu_Kodo
|
121
|
+
region: 0, # 0: us-east-1, 1: us-east-2
|
122
|
+
bucket: AgoraRails.configuration.bucket,
|
123
|
+
accessKey: AgoraRails.configuration.access_key,
|
124
|
+
secretKey: AgoraRails.configuration.secret_key,
|
125
|
+
fileNamePrefix: AgoraRails.configuration.file_prefix,
|
126
|
+
},
|
127
|
+
},
|
128
|
+
}
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AgoraRails
|
2
|
+
class Configuration
|
3
|
+
attr_accessor :app_id, :app_certificate, :customer_key, :customer_secret, :bucket, :access_key, :secret_key, :file_prefix
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@app_id = nil
|
7
|
+
@app_certificate = nil
|
8
|
+
@customer_key = nil
|
9
|
+
@customer_secret = nil
|
10
|
+
@bucket = nil
|
11
|
+
@access_key = nil
|
12
|
+
@secret_key = nil
|
13
|
+
@file_prefix = nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module AgoraRails
|
4
|
+
class STT
|
5
|
+
include HTTParty
|
6
|
+
base_uri 'https://api.agora.io/v1/projects'
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@app_id = AgoraRails.configuration.app_id
|
10
|
+
@customer_key = AgoraRails.configuration.customer_key
|
11
|
+
@customer_secret = AgoraRails.configuration.customer_secret
|
12
|
+
@auth = { username: @customer_key, password: @customer_secret }
|
13
|
+
end
|
14
|
+
|
15
|
+
def start_task(channel_name, uid, config)
|
16
|
+
response = self.class.post("/#{@app_id}/rtsc/speech-to-text/tasks",
|
17
|
+
basic_auth: @auth,
|
18
|
+
headers: { 'Content-Type' => 'application/json' },
|
19
|
+
body: {
|
20
|
+
channel_name: channel_name,
|
21
|
+
uid: uid.to_s,
|
22
|
+
config: config
|
23
|
+
}.to_json
|
24
|
+
)
|
25
|
+
handle_response(response)
|
26
|
+
end
|
27
|
+
|
28
|
+
def stop_task(task_id)
|
29
|
+
response = self.class.delete("/#{@app_id}/rtsc/speech-to-text/tasks/#{task_id}",
|
30
|
+
basic_auth: @auth,
|
31
|
+
headers: { 'Content-Type' => 'application/json' }
|
32
|
+
)
|
33
|
+
handle_response(response)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def handle_response(response)
|
39
|
+
if response.success?
|
40
|
+
JSON.parse(response.body)
|
41
|
+
else
|
42
|
+
raise AgoraRails::Error, "API request failed: #{response.code} - #{response.body}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/agora_rails.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative "agora_rails/configuration"
|
2
|
+
require_relative "agora_rails/cloud_recording"
|
3
|
+
require_relative "agora_rails/stt"
|
4
|
+
|
5
|
+
module AgoraRails
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.configure
|
13
|
+
self.configuration ||= Configuration.new
|
14
|
+
yield(configuration)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,220 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'zlib'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module AgoraDynamicKey2
|
6
|
+
class Service
|
7
|
+
attr_accessor :type, :privileges
|
8
|
+
|
9
|
+
def initialize(type)
|
10
|
+
@type = type
|
11
|
+
@privileges = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def add_privilege(privilege, expire)
|
15
|
+
@privileges[privilege] = expire
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch_uid(uid)
|
19
|
+
return '' if uid.eql?(0)
|
20
|
+
|
21
|
+
uid.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def pack
|
25
|
+
Util.pack_uint16(@type) + Util.pack_map_uint32(@privileges)
|
26
|
+
end
|
27
|
+
|
28
|
+
def unpack(data)
|
29
|
+
@privileges, data = Util.unpack_map_uint32(data)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ServiceRtc < Service
|
34
|
+
attr_accessor :channel_name, :uid
|
35
|
+
|
36
|
+
SERVICE_TYPE = 1
|
37
|
+
PRIVILEGE_JOIN_CHANNEL = 1
|
38
|
+
PRIVILEGE_PUBLISH_AUDIO_STREAM = 2
|
39
|
+
PRIVILEGE_PUBLISH_VIDEO_STREAM = 3
|
40
|
+
PRIVILEGE_PUBLISH_DATA_STREAM = 4
|
41
|
+
|
42
|
+
def initialize(channel_name = '', uid = '')
|
43
|
+
super(SERVICE_TYPE)
|
44
|
+
@channel_name = channel_name
|
45
|
+
@uid = fetch_uid(uid)
|
46
|
+
end
|
47
|
+
|
48
|
+
def pack
|
49
|
+
super() + Util.pack_string(@channel_name) + Util.pack_string(@uid)
|
50
|
+
end
|
51
|
+
|
52
|
+
def unpack(data)
|
53
|
+
_, data = super(data)
|
54
|
+
@channel_name, data = Util.unpack_string(data)
|
55
|
+
@uid, data = Util.unpack_string(data)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class ServiceRtm < Service
|
60
|
+
attr_accessor :user_id
|
61
|
+
|
62
|
+
SERVICE_TYPE = 2
|
63
|
+
PRIVILEGE_JOIN_LOGIN = 1
|
64
|
+
|
65
|
+
def initialize(user_id = '')
|
66
|
+
super(SERVICE_TYPE)
|
67
|
+
@user_id = user_id
|
68
|
+
end
|
69
|
+
|
70
|
+
def pack
|
71
|
+
super() + Util.pack_string(@user_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
def unpack(data)
|
75
|
+
_, data = super(data)
|
76
|
+
@user_id, data = Util.unpack_string(data)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
class ServiceFpa < Service
|
81
|
+
SERVICE_TYPE = 4
|
82
|
+
PRIVILEGE_LOGIN = 1
|
83
|
+
|
84
|
+
def initialize
|
85
|
+
super(SERVICE_TYPE)
|
86
|
+
end
|
87
|
+
|
88
|
+
def pack
|
89
|
+
super()
|
90
|
+
end
|
91
|
+
|
92
|
+
def unpack(data)
|
93
|
+
_, data = super(data)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class ServiceChat < Service
|
98
|
+
attr_accessor :uid
|
99
|
+
|
100
|
+
SERVICE_TYPE = 5
|
101
|
+
PRIVILEGE_USER = 1
|
102
|
+
PRIVILEGE_APP = 2
|
103
|
+
|
104
|
+
def initialize(uid = '')
|
105
|
+
super(SERVICE_TYPE)
|
106
|
+
@uid = fetch_uid(uid)
|
107
|
+
end
|
108
|
+
|
109
|
+
def pack
|
110
|
+
super() + Util.pack_string(@uid)
|
111
|
+
end
|
112
|
+
|
113
|
+
def unpack(data)
|
114
|
+
_, data = super(data)
|
115
|
+
@uid, data = Util.unpack_string(data)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class ServiceApaas < Service
|
120
|
+
attr_accessor :room_uuid, :user_uuid, :role
|
121
|
+
|
122
|
+
SERVICE_TYPE = 7
|
123
|
+
PRIVILEGE_ROOM_USER = 1
|
124
|
+
PRIVILEGE_USER = 2
|
125
|
+
PRIVILEGE_APP = 3
|
126
|
+
|
127
|
+
def initialize(room_uuid = '', user_uuid = '', role = -1)
|
128
|
+
super(SERVICE_TYPE)
|
129
|
+
@room_uuid = room_uuid
|
130
|
+
@user_uuid = user_uuid
|
131
|
+
@role = role
|
132
|
+
end
|
133
|
+
|
134
|
+
def pack
|
135
|
+
super() + Util.pack_string(@room_uuid) + Util.pack_string(@user_uuid) + Util.pack_int16(@role)
|
136
|
+
end
|
137
|
+
|
138
|
+
def unpack(data)
|
139
|
+
_, data = super(data)
|
140
|
+
@room_uuid, data = Util.unpack_string(data)
|
141
|
+
@user_uuid, data = Util.unpack_string(data)
|
142
|
+
@role, data = Util.unpack_int16(data)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
class AccessToken
|
147
|
+
attr_accessor :app_cert, :app_id, :expire, :issue_ts, :salt, :services
|
148
|
+
|
149
|
+
VERSION = '007'.freeze
|
150
|
+
VERSION_LENGTH = 3
|
151
|
+
SERVICES = { ServiceRtc::SERVICE_TYPE => ServiceRtc,
|
152
|
+
ServiceRtm::SERVICE_TYPE => ServiceRtm,
|
153
|
+
ServiceFpa::SERVICE_TYPE => ServiceFpa,
|
154
|
+
ServiceChat::SERVICE_TYPE => ServiceChat,
|
155
|
+
ServiceApaas::SERVICE_TYPE => ServiceApaas }.freeze
|
156
|
+
|
157
|
+
def initialize(app_id = '', app_cert = '', expire = 900)
|
158
|
+
@app_id = app_id
|
159
|
+
@app_cert = app_cert
|
160
|
+
@expire = expire
|
161
|
+
@issue_ts = Time.now.to_i
|
162
|
+
@salt = rand(1...99_999_999)
|
163
|
+
@services = {}
|
164
|
+
end
|
165
|
+
|
166
|
+
def add_service(service)
|
167
|
+
@services[service.type] = service
|
168
|
+
end
|
169
|
+
|
170
|
+
def build
|
171
|
+
return '' if !uuid?(@app_id) || !uuid?(@app_cert)
|
172
|
+
|
173
|
+
signing = fetch_sign
|
174
|
+
data = Util.pack_string(@app_id) + Util.pack_uint32(@issue_ts) + Util.pack_uint32(@expire) \
|
175
|
+
+ Util.pack_uint32(@salt) + Util.pack_uint16(@services.size)
|
176
|
+
|
177
|
+
@services.each do |_, service|
|
178
|
+
data += service.pack
|
179
|
+
end
|
180
|
+
|
181
|
+
signature = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), signing, data)
|
182
|
+
fetch_version + Base64.strict_encode64(Zlib::Deflate.deflate(Util.pack_string(signature) + data))
|
183
|
+
end
|
184
|
+
|
185
|
+
def fetch_sign
|
186
|
+
sign = OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), Util.pack_uint32(@issue_ts), @app_cert)
|
187
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new('sha256'), Util.pack_uint32(@salt), sign)
|
188
|
+
end
|
189
|
+
|
190
|
+
def fetch_version
|
191
|
+
VERSION
|
192
|
+
end
|
193
|
+
|
194
|
+
def uuid?(str)
|
195
|
+
return false if str.length != 32
|
196
|
+
|
197
|
+
true
|
198
|
+
end
|
199
|
+
|
200
|
+
def parse(token)
|
201
|
+
return false if token[0..VERSION_LENGTH - 1] != fetch_version
|
202
|
+
|
203
|
+
data = Zlib::Inflate.inflate(Base64.strict_decode64(token[VERSION_LENGTH..-1]))
|
204
|
+
signature, data = Util.unpack_string(data)
|
205
|
+
@app_id, data = Util.unpack_string(data)
|
206
|
+
@issue_ts, data = Util.unpack_uint32(data)
|
207
|
+
@expire, data = Util.unpack_uint32(data)
|
208
|
+
@salt, data = Util.unpack_uint32(data)
|
209
|
+
service_num, data = Util.unpack_uint16(data)
|
210
|
+
|
211
|
+
(1..service_num).each do
|
212
|
+
service_type, data = Util.unpack_uint16(data)
|
213
|
+
service = SERVICES[service_type].new
|
214
|
+
_, data = service.unpack(data)
|
215
|
+
@services[service_type] = service
|
216
|
+
end
|
217
|
+
true
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class ApaasTokenBuilder
|
3
|
+
# Build room user token.
|
4
|
+
#
|
5
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
6
|
+
# from your kit. See Get an App ID.
|
7
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
8
|
+
# See Get an App Certificate.
|
9
|
+
# room_uuid: The room's id, must be unique.
|
10
|
+
# user_uuid: The user's id, must be unique.
|
11
|
+
# role: The user's role.
|
12
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
13
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
14
|
+
# return: The room user token.
|
15
|
+
def self.build_room_user_token(app_id, app_certificate, room_uuid, user_uuid, role, expire)
|
16
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
17
|
+
|
18
|
+
chat_user_id = Digest::MD5.hexdigest user_uuid
|
19
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new(room_uuid, user_uuid, role)
|
20
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_ROOM_USER, expire)
|
21
|
+
access_token.add_service(service_apaas)
|
22
|
+
|
23
|
+
service_rtm = AgoraDynamicKey2::ServiceRtm.new(user_uuid)
|
24
|
+
service_rtm.add_privilege(AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, expire)
|
25
|
+
access_token.add_service(service_rtm)
|
26
|
+
|
27
|
+
service_chat = AgoraDynamicKey2::ServiceChat.new(chat_user_id)
|
28
|
+
service_chat.add_privilege(AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
29
|
+
access_token.add_service(service_chat)
|
30
|
+
|
31
|
+
access_token.build
|
32
|
+
end
|
33
|
+
|
34
|
+
# Build user token.
|
35
|
+
#
|
36
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
37
|
+
# from your kit. See Get an App ID.
|
38
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
39
|
+
# See Get an App Certificate.
|
40
|
+
# user_uuid: The user's id, must be unique.
|
41
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
42
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
43
|
+
# return: The user token.
|
44
|
+
def self.build_user_token(app_id, app_certificate, user_uuid, expire)
|
45
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
46
|
+
|
47
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new('', user_uuid)
|
48
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_USER, expire)
|
49
|
+
access_token.add_service(service_apaas)
|
50
|
+
|
51
|
+
access_token.build
|
52
|
+
end
|
53
|
+
|
54
|
+
# Build app token.
|
55
|
+
#
|
56
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
57
|
+
# from your kit. See Get an App ID.
|
58
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
59
|
+
# See Get an App Certificate.
|
60
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
61
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
62
|
+
# return: The app token.
|
63
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
64
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
65
|
+
|
66
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new
|
67
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_APP, expire)
|
68
|
+
access_token.add_service(service_apaas)
|
69
|
+
|
70
|
+
access_token.build
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class ChatTokenBuilder
|
3
|
+
# Build the Chat user token.
|
4
|
+
#
|
5
|
+
# @param app_id: The App ID issued to you by Agora. Apply for a new App ID from
|
6
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
7
|
+
# @param app_certificate: Certificate of the application that you registered in
|
8
|
+
# the Agora Dashboard. See Get an App Certificate.
|
9
|
+
# @param user_id: The user's account, max length is 64 Bytes.
|
10
|
+
# @param expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
11
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
12
|
+
# @return The Chat User token.
|
13
|
+
def self.build_user_token(app_id, app_certificate, user_id, expire)
|
14
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
15
|
+
|
16
|
+
service_chat = AgoraDynamicKey2::ServiceChat.new(user_id)
|
17
|
+
service_chat.add_privilege(AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
18
|
+
access_token.add_service(service_chat)
|
19
|
+
|
20
|
+
access_token.build
|
21
|
+
end
|
22
|
+
|
23
|
+
# Build the Chat App token.
|
24
|
+
#
|
25
|
+
# @param app_id: The App ID issued to you by Agora. Apply for a new App ID from
|
26
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
27
|
+
# @param app_certificate: Certificate of the application that you registered in
|
28
|
+
# the Agora Dashboard. See Get an App Certificate.
|
29
|
+
# @param expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
30
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
31
|
+
# @return The Chat App token.
|
32
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
33
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
34
|
+
|
35
|
+
service_chat = AgoraDynamicKey2::ServiceChat.new
|
36
|
+
service_chat.add_privilege(AgoraDynamicKey2::ServiceChat::PRIVILEGE_APP, expire)
|
37
|
+
access_token.add_service(service_chat)
|
38
|
+
|
39
|
+
access_token.build
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class EducationTokenBuilder
|
3
|
+
# Build room user token.
|
4
|
+
#
|
5
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
6
|
+
# from your kit. See Get an App ID.
|
7
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
8
|
+
# See Get an App Certificate.
|
9
|
+
# room_uuid: The room's id, must be unique.
|
10
|
+
# user_uuid: The user's id, must be unique.
|
11
|
+
# role: The user's role.
|
12
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
13
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
14
|
+
# return: The room user token.
|
15
|
+
def self.build_room_user_token(app_id, app_certificate, room_uuid, user_uuid, role, expire)
|
16
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
17
|
+
|
18
|
+
chat_user_id = Digest::MD5.hexdigest user_uuid
|
19
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new(room_uuid, user_uuid, role)
|
20
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_ROOM_USER, expire)
|
21
|
+
access_token.add_service(service_apaas)
|
22
|
+
|
23
|
+
service_rtm = AgoraDynamicKey2::ServiceRtm.new(user_uuid)
|
24
|
+
service_rtm.add_privilege(AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, expire)
|
25
|
+
access_token.add_service(service_rtm)
|
26
|
+
|
27
|
+
service_chat = AgoraDynamicKey2::ServiceChat.new(chat_user_id)
|
28
|
+
service_chat.add_privilege(AgoraDynamicKey2::ServiceChat::PRIVILEGE_USER, expire)
|
29
|
+
access_token.add_service(service_chat)
|
30
|
+
|
31
|
+
access_token.build
|
32
|
+
end
|
33
|
+
|
34
|
+
# Build user token.
|
35
|
+
#
|
36
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
37
|
+
# from your kit. See Get an App ID.
|
38
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
39
|
+
# See Get an App Certificate.
|
40
|
+
# user_uuid: The user's id, must be unique.
|
41
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
42
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
43
|
+
# return: The user token.
|
44
|
+
def self.build_user_token(app_id, app_certificate, user_uuid, expire)
|
45
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
46
|
+
|
47
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new('', user_uuid)
|
48
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_USER, expire)
|
49
|
+
access_token.add_service(service_apaas)
|
50
|
+
|
51
|
+
access_token.build
|
52
|
+
end
|
53
|
+
|
54
|
+
# Build app token.
|
55
|
+
#
|
56
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
57
|
+
# from your kit. See Get an App ID.
|
58
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
59
|
+
# See Get an App Certificate.
|
60
|
+
# expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
61
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
62
|
+
# return: The app token.
|
63
|
+
def self.build_app_token(app_id, app_certificate, expire)
|
64
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
65
|
+
|
66
|
+
service_apaas = AgoraDynamicKey2::ServiceApaas.new
|
67
|
+
service_apaas.add_privilege(AgoraDynamicKey2::ServiceApaas::PRIVILEGE_APP, expire)
|
68
|
+
access_token.add_service(service_apaas)
|
69
|
+
|
70
|
+
access_token.build
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class FpaTokenBuilder
|
3
|
+
# Build the FPA token.
|
4
|
+
#
|
5
|
+
# @param app_id The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
6
|
+
# from your kit. See Get an App ID.
|
7
|
+
# @param app_certificate Certificate of the application that you registered in the Agora Dashboard.
|
8
|
+
# See Get an App Certificate.
|
9
|
+
# @return The FPA token.
|
10
|
+
def self.build_token(app_id, app_certificate)
|
11
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, 24 * 3600)
|
12
|
+
|
13
|
+
service_fpa = AgoraDynamicKey2::ServiceFpa.new
|
14
|
+
service_fpa.add_privilege(AgoraDynamicKey2::ServiceFpa::PRIVILEGE_LOGIN, 0)
|
15
|
+
access_token.add_service(service_fpa)
|
16
|
+
|
17
|
+
access_token.build
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class RtcTokenBuilder
|
3
|
+
# RECOMMENDED. Use this role for a voice/video call or a live broadcast, if
|
4
|
+
# your scenario does not require authentication for
|
5
|
+
# [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication).
|
6
|
+
ROLE_PUBLISHER = 1
|
7
|
+
|
8
|
+
# Only use this role if your scenario require authentication for
|
9
|
+
# [Co-host](https://docs.agora.io/en/video-calling/get-started/authentication-workflow?#co-host-token-authentication).
|
10
|
+
# @note In order for this role to take effect, please contact our support team
|
11
|
+
# to enable authentication for Hosting-in for you. Otherwise, Role_Subscriber
|
12
|
+
# still has the same privileges as Role_Publisher.
|
13
|
+
ROLE_SUBSCRIBER = 2
|
14
|
+
|
15
|
+
# Build the RTC token with uid.
|
16
|
+
#
|
17
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
18
|
+
# from your kit. See Get an App ID.
|
19
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
20
|
+
# See Get an App Certificate.
|
21
|
+
# channel_name: Unique channel name for the AgoraRTC session in the string format.
|
22
|
+
# uid: User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
|
23
|
+
# uid must be unique.
|
24
|
+
# role: ROLE_PUBLISHER: A broadcaster/host in a live-broadcast profile.
|
25
|
+
# ROLE_SUBSCRIBER: An audience(default) in a live-broadcast profile.
|
26
|
+
# token_expire: represented by the number of seconds elapsed since now. If, for example,
|
27
|
+
# you want to access the Agora Service within 10 minutes after the token is generated,
|
28
|
+
# set token_expire as 600(seconds).
|
29
|
+
# privilege_expire: represented by the number of seconds elapsed since now. If, for example,
|
30
|
+
# you want to enable your privilege for 10 minutes, set privilege_expire as 600(seconds).
|
31
|
+
# return: The RTC token.
|
32
|
+
def self.build_token_with_uid(app_id, app_certificate, channel_name, uid, role, token_expire, privilege_expire = 0)
|
33
|
+
build_token_with_user_account(app_id, app_certificate, channel_name, uid, role, token_expire, privilege_expire)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Build the RTC token with account.
|
37
|
+
#
|
38
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
39
|
+
# from your kit. See Get an App ID.
|
40
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
41
|
+
# See Get an App Certificate.
|
42
|
+
# channel_name: Unique channel name for the AgoraRTC session in the string format.
|
43
|
+
# uid: User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
|
44
|
+
# uid must be unique.
|
45
|
+
# role: ROLE_PUBLISHER: A broadcaster/host in a live-broadcast profile.
|
46
|
+
# ROLE_SUBSCRIBER: An audience(default) in a live-broadcast profile.
|
47
|
+
# token_expire: represented by the number of seconds elapsed since now. If, for example,
|
48
|
+
# you want to access the Agora Service within 10 minutes after the token is generated,
|
49
|
+
# set token_expire as 600(seconds).
|
50
|
+
# privilege_expire: represented by the number of seconds elapsed since now. If, for example,
|
51
|
+
# you want to enable your privilege for 10 minutes, set privilege_expire as 600(seconds).
|
52
|
+
# return: The RTC token.
|
53
|
+
def self.build_token_with_user_account(app_id, app_certificate, channel_name, account, role, token_expire, privilege_expire = 0)
|
54
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, token_expire)
|
55
|
+
service_rtc = AgoraDynamicKey2::ServiceRtc.new(channel_name, account)
|
56
|
+
|
57
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_JOIN_CHANNEL, privilege_expire)
|
58
|
+
if role == ROLE_PUBLISHER
|
59
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_AUDIO_STREAM, privilege_expire)
|
60
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_VIDEO_STREAM, privilege_expire)
|
61
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_DATA_STREAM, privilege_expire)
|
62
|
+
end
|
63
|
+
access_token.add_service(service_rtc)
|
64
|
+
access_token.build
|
65
|
+
end
|
66
|
+
|
67
|
+
# Generates an RTC token with the specified privilege.
|
68
|
+
#
|
69
|
+
# This method supports generating a token with the following privileges:
|
70
|
+
# - Joining an RTC channel.
|
71
|
+
# - Publishing audio in an RTC channel.
|
72
|
+
# - Publishing video in an RTC channel.
|
73
|
+
# - Publishing data streams in an RTC channel.
|
74
|
+
#
|
75
|
+
# The privileges for publishing audio, video, and data streams in an RTC channel apply only if you have
|
76
|
+
# enabled co-host authentication.
|
77
|
+
#
|
78
|
+
# A user can have multiple privileges. Each privilege is valid for a maximum of 24 hours.
|
79
|
+
# The SDK triggers the onTokenPrivilegeWillExpire and onRequestToken callbacks when the token is about to expire
|
80
|
+
# or has expired. The callbacks do not report the specific privilege affected, and you need to maintain
|
81
|
+
# the respective timestamp for each privilege in your app logic. After receiving the callback, you need
|
82
|
+
# to generate a new token, and then call renewToken to pass the new token to the SDK, or call joinChannel to re-join
|
83
|
+
# the channel.
|
84
|
+
#
|
85
|
+
# @note
|
86
|
+
# Agora recommends setting a reasonable timestamp for each privilege according to your scenario.
|
87
|
+
# Suppose the expiration timestamp for joining the channel is set earlier than that for publishing audio.
|
88
|
+
# When the token for joining the channel expires, the user is immediately kicked off the RTC channel
|
89
|
+
# and cannot publish any audio stream, even though the timestamp for publishing audio has not expired.
|
90
|
+
#
|
91
|
+
# @param app_id The App ID of your Agora project.
|
92
|
+
# @param app_certificate The App Certificate of your Agora project.
|
93
|
+
# @param channel_name The unique channel name for the Agora RTC session in string format. The string length must be less than 64 bytes. The channel name may contain the following characters:
|
94
|
+
# - All lowercase English letters: a to z.
|
95
|
+
# - All uppercase English letters: A to Z.
|
96
|
+
# - All numeric characters: 0 to 9.
|
97
|
+
# - The space character.
|
98
|
+
# - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
|
99
|
+
# @param uid The user ID. A 32-bit unsigned integer with a value range from 1 to (2^32 - 1). It must be unique. Set uid as 0, if you do not want to authenticate the user ID, that is, any uid from the app client can join the channel.
|
100
|
+
# @param token_expire represented by the number of seconds elapsed since now. If, for example, you want to access the
|
101
|
+
# Agora Service within 10 minutes after the token is generated, set token_expire as 600(seconds).
|
102
|
+
# @param join_channel_privilege_expire represented by the number of seconds elapsed since now.
|
103
|
+
# If, for example, you want to join channel and expect stay in the channel for 10 minutes, set join_channel_privilege_expire as 600(seconds).
|
104
|
+
# @param pub_audio_privilege_expire represented by the number of seconds elapsed since now.
|
105
|
+
# If, for example, you want to enable publish audio privilege for 10 minutes, set pub_audio_privilege_expire as 600(seconds).
|
106
|
+
# @param pub_video_privilege_expire represented by the number of seconds elapsed since now.
|
107
|
+
# If, for example, you want to enable publish video privilege for 10 minutes, set pub_video_privilege_expire as 600(seconds).
|
108
|
+
# @param pub_data_stream_privilege_expire represented by the number of seconds elapsed since now.
|
109
|
+
# If, for example, you want to enable publish data stream privilege for 10 minutes, set pub_data_stream_privilege_expire as 600(seconds).
|
110
|
+
# @return The RTC Token
|
111
|
+
def self.build_token_with_uid_and_privilege(app_id, app_certificate, channel_name, uid, token_expire,
|
112
|
+
join_channel_privilege_expire, pub_audio_privilege_expire,
|
113
|
+
pub_video_privilege_expire, pub_data_stream_privilege_expire)
|
114
|
+
build_token_with_user_account_and_privilege(
|
115
|
+
app_id, app_certificate, channel_name, uid, token_expire, join_channel_privilege_expire,
|
116
|
+
pub_audio_privilege_expire, pub_video_privilege_expire, pub_data_stream_privilege_expire
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Generates an RTC token with the specified privilege.
|
121
|
+
#
|
122
|
+
# This method supports generating a token with the following privileges:
|
123
|
+
# - Joining an RTC channel.
|
124
|
+
# - Publishing audio in an RTC channel.
|
125
|
+
# - Publishing video in an RTC channel.
|
126
|
+
# - Publishing data streams in an RTC channel.
|
127
|
+
#
|
128
|
+
# The privileges for publishing audio, video, and data streams in an RTC channel apply only if you have
|
129
|
+
# enabled co-host authentication.
|
130
|
+
#
|
131
|
+
# A user can have multiple privileges. Each privilege is valid for a maximum of 24 hours.
|
132
|
+
# The SDK triggers the onTokenPrivilegeWillExpire and onRequestToken callbacks when the token is about to expire
|
133
|
+
# or has expired. The callbacks do not report the specific privilege affected, and you need to maintain
|
134
|
+
# the respective timestamp for each privilege in your app logic. After receiving the callback, you need
|
135
|
+
# to generate a new token, and then call renewToken to pass the new token to the SDK, or call joinChannel to re-join
|
136
|
+
# the channel.
|
137
|
+
#
|
138
|
+
# @note
|
139
|
+
# Agora recommends setting a reasonable timestamp for each privilege according to your scenario.
|
140
|
+
# Suppose the expiration timestamp for joining the channel is set earlier than that for publishing audio.
|
141
|
+
# When the token for joining the channel expires, the user is immediately kicked off the RTC channel
|
142
|
+
# and cannot publish any audio stream, even though the timestamp for publishing audio has not expired.
|
143
|
+
#
|
144
|
+
# @param app_id The App ID of your Agora project.
|
145
|
+
# @param app_certificate The App Certificate of your Agora project.
|
146
|
+
# @param channel_name The unique channel name for the Agora RTC session in string format. The string length must be less than 64 bytes. The channel name may contain the following characters:
|
147
|
+
# - All lowercase English letters: a to z.
|
148
|
+
# - All uppercase English letters: A to Z.
|
149
|
+
# - All numeric characters: 0 to 9.
|
150
|
+
# - The space character.
|
151
|
+
# - "!", "#", "$", "%", "&", "(", ")", "+", "-", ":", ";", "<", "=", ".", ">", "?", "@", "[", "]", "^", "_", " {", "}", "|", "~", ",".
|
152
|
+
# @param account The user account.
|
153
|
+
# @param token_expire represented by the number of seconds elapsed since now. If, for example, you want to access the
|
154
|
+
# Agora Service within 10 minutes after the token is generated, set token_expire as 600(seconds).
|
155
|
+
# @param join_channel_privilege_expire represented by the number of seconds elapsed since now.
|
156
|
+
# If, for example, you want to join channel and expect stay in the channel for 10 minutes, set join_channel_privilege_expire as 600(seconds).
|
157
|
+
# @param pub_audio_privilege_expire represented by the number of seconds elapsed since now.
|
158
|
+
# If, for example, you want to enable publish audio privilege for 10 minutes, set pub_audio_privilege_expire as 600(seconds).
|
159
|
+
# @param pub_video_privilege_expire represented by the number of seconds elapsed since now.
|
160
|
+
# If, for example, you want to enable publish video privilege for 10 minutes, set pub_video_privilege_expire as 600(seconds).
|
161
|
+
# @param pub_data_stream_privilege_expire represented by the number of seconds elapsed since now.
|
162
|
+
# If, for example, you want to enable publish data stream privilege for 10 minutes, set pub_data_stream_privilege_expire as 600(seconds).
|
163
|
+
# @return The RTC Token
|
164
|
+
def self.build_token_with_user_account_and_privilege(app_id, app_certificate, channel_name, account, token_expire,
|
165
|
+
join_channel_privilege_expire, pub_audio_privilege_expire,
|
166
|
+
pub_video_privilege_expire, pub_data_stream_privilege_expire)
|
167
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, token_expire)
|
168
|
+
service_rtc = AgoraDynamicKey2::ServiceRtc.new(channel_name, account)
|
169
|
+
|
170
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_JOIN_CHANNEL, join_channel_privilege_expire)
|
171
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_AUDIO_STREAM, pub_audio_privilege_expire)
|
172
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_VIDEO_STREAM, pub_video_privilege_expire)
|
173
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_DATA_STREAM, pub_data_stream_privilege_expire)
|
174
|
+
access_token.add_service(service_rtc)
|
175
|
+
access_token.build
|
176
|
+
end
|
177
|
+
|
178
|
+
# Build the RTC and RTM token with account.
|
179
|
+
#
|
180
|
+
# app_id: The App ID issued to you by Agora. Apply for a new App ID from Agora Dashboard if it is missing
|
181
|
+
# from your kit. See Get an App ID.
|
182
|
+
# app_certificate: Certificate of the application that you registered in the Agora Dashboard.
|
183
|
+
# See Get an App Certificate.
|
184
|
+
# channel_name: Unique channel name for the AgoraRTC session in the string format.
|
185
|
+
# uid: User ID. A 32-bit unsigned integer with a value ranging from 1 to (2^32-1).
|
186
|
+
# uid must be unique.
|
187
|
+
# role: ROLE_PUBLISHER: A broadcaster/host in a live-broadcast profile.
|
188
|
+
# ROLE_SUBSCRIBER: An audience(default) in a live-broadcast profile.
|
189
|
+
# token_expire: represented by the number of seconds elapsed since now. If, for example,
|
190
|
+
# you want to access the Agora Service within 10 minutes after the token is generated,
|
191
|
+
# set token_expire as 600(seconds).
|
192
|
+
# privilege_expire: represented by the number of seconds elapsed since now. If, for example,
|
193
|
+
# you want to enable your privilege for 10 minutes, set privilege_expire as 600(seconds).
|
194
|
+
# return: The RTC and RTM token.
|
195
|
+
def self.build_token_with_rtm(app_id, app_certificate, channel_name, account, role, token_expire, privilege_expire = 0)
|
196
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, token_expire)
|
197
|
+
service_rtc = AgoraDynamicKey2::ServiceRtc.new(channel_name, account)
|
198
|
+
|
199
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_JOIN_CHANNEL, privilege_expire)
|
200
|
+
if role == ROLE_PUBLISHER
|
201
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_AUDIO_STREAM, privilege_expire)
|
202
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_VIDEO_STREAM, privilege_expire)
|
203
|
+
service_rtc.add_privilege(AgoraDynamicKey2::ServiceRtc::PRIVILEGE_PUBLISH_DATA_STREAM, privilege_expire)
|
204
|
+
end
|
205
|
+
access_token.add_service(service_rtc)
|
206
|
+
|
207
|
+
service_rtm = AgoraDynamicKey2::ServiceRtm.new(account)
|
208
|
+
|
209
|
+
service_rtm.add_privilege(AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, token_expire)
|
210
|
+
access_token.add_service(service_rtm)
|
211
|
+
|
212
|
+
access_token.build
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module AgoraDynamicKey2
|
2
|
+
class RtmTokenBuilder
|
3
|
+
# Build the RTM token.
|
4
|
+
#
|
5
|
+
# @param app_id: The App ID issued to you by Agora. Apply for a new App ID from
|
6
|
+
# Agora Dashboard if it is missing from your kit. See Get an App ID.
|
7
|
+
# @param app_certificate: Certificate of the application that you registered in
|
8
|
+
# the Agora Dashboard. See Get an App Certificate.
|
9
|
+
# @param user_id: The user's account, max length is 64 Bytes.
|
10
|
+
# @param expire: represented by the number of seconds elapsed since now. If, for example, you want to access the
|
11
|
+
# Agora Service within 10 minutes after the token is generated, set expire as 600(seconds).
|
12
|
+
# @return The RTM token.
|
13
|
+
def self.build_token(app_id, app_certificate, user_id, expire)
|
14
|
+
access_token = AgoraDynamicKey2::AccessToken.new(app_id, app_certificate, expire)
|
15
|
+
service_rtm = AgoraDynamicKey2::ServiceRtm.new(user_id)
|
16
|
+
|
17
|
+
service_rtm.add_privilege(AgoraDynamicKey2::ServiceRtm::PRIVILEGE_JOIN_LOGIN, expire)
|
18
|
+
access_token.add_service(service_rtm)
|
19
|
+
access_token.build
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
3
|
+
module AgoraDynamicKey2
|
4
|
+
class Util
|
5
|
+
def self.pack_int16(int)
|
6
|
+
[int].pack('s')
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.unpack_int16(data)
|
10
|
+
[data[0..2].unpack1('s'), data[2..-1]]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.pack_uint16(int)
|
14
|
+
[int].pack('v')
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.unpack_uint16(data)
|
18
|
+
[data[0..2].unpack1('v'), data[2..-1]]
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.pack_uint32(int)
|
22
|
+
[int].pack('V')
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.unpack_uint32(data)
|
26
|
+
[data[0..4].unpack1('V'), data[4..-1]]
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.pack_string(str)
|
30
|
+
pack_uint16(str.bytesize) + str
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.unpack_string(data)
|
34
|
+
len, data = unpack_uint16(data)
|
35
|
+
if len.zero?
|
36
|
+
return ['', data[len..-1]]
|
37
|
+
end
|
38
|
+
[data[0..len - 1], data[len..-1]]
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.pack_map_uint32(map)
|
42
|
+
kv = ''
|
43
|
+
Hash[map.sort].each do |k, v|
|
44
|
+
kv += pack_uint16(k) + pack_uint32(v)
|
45
|
+
end
|
46
|
+
(pack_uint16(map.size) + kv).force_encoding('utf-8')
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.unpack_map_uint32(data)
|
50
|
+
len, data = unpack_uint16(data)
|
51
|
+
map = {}
|
52
|
+
(1..len).each do
|
53
|
+
k, data = unpack_uint16(data)
|
54
|
+
v, data = unpack_uint32(data)
|
55
|
+
map[k] = v
|
56
|
+
end
|
57
|
+
[map, data]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
data/lib/dynamic_key2.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# code taken from https://github.com/AgoraIO/Tools
|
2
|
+
|
3
|
+
require_relative 'dynamic_key2/access_token'
|
4
|
+
require_relative 'dynamic_key2/apaas_token_builder'
|
5
|
+
require_relative 'dynamic_key2/chat_token_builder'
|
6
|
+
require_relative 'dynamic_key2/education_token_builder'
|
7
|
+
require_relative 'dynamic_key2/fpa_token_builder'
|
8
|
+
require_relative 'dynamic_key2/rtc_token_builder'
|
9
|
+
require_relative 'dynamic_key2/rtm_token_builder'
|
10
|
+
require_relative 'dynamic_key2/util'
|
11
|
+
|
12
|
+
module AgoraDynamicKey2
|
13
|
+
VERSION = '0.2.0'.freeze
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module AgoraRails
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path("templates", __dir__)
|
7
|
+
|
8
|
+
def create_initializer_file
|
9
|
+
template "agora_rails.rb", "config/initializers/agora_rails.rb"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
AgoraRails.configure do |config|
|
2
|
+
config.app_id = "YOUR_APP_ID"
|
3
|
+
config.app_certificate = "YOUR_APP_CERTIFICATE"
|
4
|
+
config.customer_key = "YOUR_CUSTOMER_KEY"
|
5
|
+
config.customer_secret = "YOUR_CUSTOMER_SECRET"
|
6
|
+
|
7
|
+
# the following are optional
|
8
|
+
config.bucket = "YOUR_BUCKET"
|
9
|
+
config.access_key = "YOUR_ACCESS_KEY"
|
10
|
+
config.secret_key = "YOUR_SECRET_KEY"
|
11
|
+
config.file_prefix = "YOUR_FILE_PREFIX"
|
12
|
+
end
|
metadata
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: agora_rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mohammad Forouzani
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-11-08 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
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: httparty
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: openssl
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: webmock
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: Provides functionality for Agora.io token generation and cloud recording
|
84
|
+
email:
|
85
|
+
- mo@usechance.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- README.md
|
91
|
+
- lib/agora_rails.rb
|
92
|
+
- lib/agora_rails/cloud_recording.rb
|
93
|
+
- lib/agora_rails/configuration.rb
|
94
|
+
- lib/agora_rails/stt.rb
|
95
|
+
- lib/dynamic_key2.rb
|
96
|
+
- lib/dynamic_key2/access_token.rb
|
97
|
+
- lib/dynamic_key2/apaas_token_builder.rb
|
98
|
+
- lib/dynamic_key2/chat_token_builder.rb
|
99
|
+
- lib/dynamic_key2/education_token_builder.rb
|
100
|
+
- lib/dynamic_key2/fpa_token_builder.rb
|
101
|
+
- lib/dynamic_key2/rtc_token_builder.rb
|
102
|
+
- lib/dynamic_key2/rtm_token_builder.rb
|
103
|
+
- lib/dynamic_key2/util.rb
|
104
|
+
- lib/generators/agora_rails/install_generator.rb
|
105
|
+
- lib/generators/agora_rails/templates/agora_rails.rb
|
106
|
+
homepage: https://github.com/mamady/agora_rails
|
107
|
+
licenses:
|
108
|
+
- MIT
|
109
|
+
metadata: {}
|
110
|
+
post_install_message:
|
111
|
+
rdoc_options: []
|
112
|
+
require_paths:
|
113
|
+
- lib
|
114
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - ">="
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
requirements: []
|
125
|
+
rubygems_version: 3.5.3
|
126
|
+
signing_key:
|
127
|
+
specification_version: 4
|
128
|
+
summary: Ruby interface for Agora.io APIs
|
129
|
+
test_files: []
|