agora_rails 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 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
@@ -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
+
@@ -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: []