kinescope-rb 0.1.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: 3fb5f95e53be2059c94bbad909351d31f416b85229f4819fe850bbbe78e87071
4
+ data.tar.gz: 3fca2049e2478bd6616ddf6cd947aaa54d9a2df322623009f4db79544b4828ab
5
+ SHA512:
6
+ metadata.gz: af637af6bd71720d97c5107f2c870890bf61e6499f1ac346e45dff6619a6d8b5736c6297cb63fcfdd719c50524cbfa954d490dc57c0c6b13152144618d8d454e
7
+ data.tar.gz: df03cb79f5a3cc44a3d97db6530930682d5ba4636f109987ee1b9490c81550104a0c9e3730f0955ea6ec1bc19699923ab42023647581d91d486d3085d1b2464f
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ .DS_Store
2
+ Gemfile.lock
3
+
4
+ /.bundle/
5
+ /.yardoc
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+
13
+ # rspec failure tracking
14
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format progress
3
+ --require pry
4
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.1
5
+ before_install: gem install bundler -v 1.16.1
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem 'simplecov', '~> 0.17.0'
6
+
7
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 droff
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # Kinescope::Rb
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/kinescope/rb`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'kinescope-rb'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install kinescope-rb
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/kinescope-rb. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
40
+
41
+ ## Code of Conduct
42
+
43
+ Everyone interacting in the Kinescope::Rb project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/[USERNAME]/kinescope-rb/blob/master/CODE_OF_CONDUCT.md).
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
data/bin/console ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'irb'
5
+ require 'kinescope'
6
+
7
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ lib = File.expand_path('../lib', __FILE__)
4
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
+ require 'kinescope/version'
6
+
7
+ Gem::Specification.new do |spec|
8
+ spec.name = 'kinescope-rb'
9
+ spec.version = Kinescope::VERSION
10
+ spec.authors = ['droff']
11
+ spec.email = ['adroff@gmail.com']
12
+ spec.summary = ''
13
+ spec.description = ''
14
+ spec.homepage = 'https://github.com/droff/kinescope-rb'
15
+ spec.license = 'MIT'
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ # if spec.respond_to?(:metadata)
20
+ # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
21
+ # else
22
+ # raise "RubyGems 2.0 or newer is required to protect against " \
23
+ # "public gem pushes."
24
+ # end
25
+
26
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_dependency 'faraday', '~> 0.9'
30
+ spec.add_dependency 'kartograph', '~> 0.2.3'
31
+ spec.add_dependency 'resource_kit', '~> 0.1.5'
32
+ spec.add_dependency 'virtus', '~> 1.0.3'
33
+
34
+ spec.add_development_dependency 'bundler', '~> 1.16'
35
+ spec.add_development_dependency 'pry'
36
+ spec.add_development_dependency 'rake', '~> 10.0'
37
+ spec.add_development_dependency 'rspec', '~> 3.0'
38
+ spec.add_development_dependency 'webmock', '~> 3.8.0'
39
+ end
@@ -0,0 +1,65 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+
5
+ module Kinescope
6
+ class Client
7
+ DEFAULT_API_URL = 'https://api.kinescope.io'.freeze
8
+ DEFAULT_TIMEOUT = 120
9
+ DEFAULT_OPEN_TIMEOUT = 60
10
+
11
+ attr_reader :access_token, :api_url, :open_timeout, :timeout, :user_agent
12
+
13
+ def initialize(options = {})
14
+ @access_token = options[:access_token]
15
+ @api_url = options[:api_url] || DEFAULT_API_URL
16
+ @open_timeout = options[:open_timeout] || DEFAULT_OPEN_TIMEOUT
17
+ @timeout = options[:timeout] || DEFAULT_TIMEOUT
18
+ @user_agent = options[:user_agent]
19
+ end
20
+
21
+ def connection
22
+ @connection ||= Faraday.new(connection_options) do |req|
23
+ req.adapter :net_http
24
+ req.options.timeout = timeout
25
+ req.options.open_timeout = open_timeout
26
+ end
27
+ end
28
+
29
+ def self.resources
30
+ {
31
+ videos: VideoResource,
32
+ }
33
+ end
34
+
35
+ def resources
36
+ @resources ||= {}
37
+ end
38
+
39
+ def method_missing(name, *args, &block)
40
+ if self.class.resources.keys.include?(name)
41
+ resources[name] ||= self.class.resources[name].new(connection: connection)
42
+ resources[name]
43
+ else
44
+ super
45
+ end
46
+ end
47
+
48
+ def default_user_agent
49
+ "kinescope-rb/#{Kinescope::VERSION}"
50
+ end
51
+
52
+ private
53
+
54
+ def connection_options
55
+ {
56
+ url: api_url,
57
+ headers: {
58
+ authorization: "Bearer #{access_token}",
59
+ content_type: 'application/json',
60
+ user_agent: "#{user_agent} #{default_user_agent}".strip
61
+ }
62
+ }
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ class OrderMapping
5
+ include Kartograph::DSL
6
+
7
+ kartograph do
8
+ mapping Order
9
+ root_key plural: 'order', singular: 'order', scopes: [:read]
10
+
11
+ property :created_at, scopes: [:read]
12
+ property :title, scopes: [:read]
13
+ end
14
+ end
15
+
16
+ class PaginationMapping
17
+ include Kartograph::DSL
18
+
19
+ kartograph do
20
+ mapping Pagination
21
+ root_key plural: 'pagination', singular: 'pagination', scopes: [:read]
22
+
23
+ property :page, scopes: [:read]
24
+ property :per_page, scopes: [:read]
25
+ property :total, scopes: [:read]
26
+ end
27
+ end
28
+
29
+ class MetaMapping
30
+ include Kartograph::DSL
31
+
32
+ kartograph do
33
+ mapping Meta
34
+ root_key plural: 'meta', singular: 'meta', scopes: [:read]
35
+
36
+ property :order, include: OrderMapping, scopes: [:read]
37
+ property :pagination, include: PaginationMapping, scopes: [:read]
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ class VideoMapping
5
+ include Kartograph::DSL
6
+
7
+ kartograph do
8
+ mapping Video
9
+ root_key plural: 'data', singular: 'data', scopes: [:read]
10
+
11
+ property :id, scopes: [:read]
12
+ property :project_id, scopes: [:read]
13
+ property :folder_id, scopes: [:read]
14
+ property :version, scopes: [:read]
15
+ property :title, scopes: [:read]
16
+ property :description, scopes: [:read]
17
+ property :status, scopes: [:read]
18
+ property :progress, scopes: [:read]
19
+ property :duration, scopes: [:read]
20
+ property :assets, scopes: [:read]
21
+ property :chapters, scopes: [:read]
22
+ property :privacy_type, scopes: [:read]
23
+ property :privacy_domains, scopes: [:read]
24
+ property :poster, scopes: [:read]
25
+ property :additional_materials, scopes: [:read]
26
+ property :additional_materials_enabled, scopes: [:read]
27
+ property :created_at, scopes: [:read]
28
+ property :updated_at, scopes: [:read]
29
+ property :play_link, scopes: [:read]
30
+ property :embed_link, scopes: [:read]
31
+ property :subtitles, scopes: [:read]
32
+ property :subtitles_enabled, scopes: [:read]
33
+ property :hls_link, scopes: [:read]
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'virtus'
4
+
5
+ module Kinescope
6
+ class BaseModel
7
+ include Virtus.model
8
+ include Virtus::Equalizer.new(name || inspect)
9
+
10
+ def inspect
11
+ variables = instance_variables.map { |name| [name, instance_variable_get(name)] }
12
+ values = Hash[variables]
13
+ "<#{self.class.name} #{values}>"
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ class Meta < BaseModel
5
+ attribute :order
6
+ attribute :pagination
7
+ end
8
+
9
+ class Order < BaseModel
10
+ attribute :created_at
11
+ attribute :title
12
+ end
13
+
14
+ class Pagination < BaseModel
15
+ attribute :page
16
+ attribute :per_page
17
+ attribute :total
18
+ end
19
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ class Video < BaseModel
5
+ attribute :id
6
+ attribute :project_id
7
+ attribute :folder_id
8
+ attribute :version
9
+ attribute :title
10
+ attribute :description
11
+ attribute :status
12
+ attribute :progress
13
+ attribute :duration
14
+ attribute :assets
15
+ attribute :chapters
16
+ attribute :privacy_type
17
+ attribute :privacy_domains
18
+ attribute :poster
19
+ attribute :additional_materials
20
+ attribute :additional_materials_enabled
21
+ attribute :created_at
22
+ attribute :updated_at
23
+ attribute :play_link
24
+ attribute :embed_link
25
+ attribute :subtitles
26
+ attribute :subtitles_enabled
27
+ attribute :hls_link
28
+
29
+ def inspect
30
+ variables = [:@id, :@project_id, :@folder_id, :@title].map { |name| [name, instance_variable_get(name)] }
31
+ values = Hash[variables]
32
+ "<#{self.class.name} #{values}>"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ module Kinescope
2
+ class PaginationResource
3
+ include Enumerable
4
+
5
+ attr_reader :action, :args, :resource
6
+ attr_accessor :page, :per_page, :total
7
+
8
+ def initialize(action, resource, *args)
9
+ @action = action
10
+ @resource = resource
11
+ @args = args
12
+
13
+ @collection = []
14
+ @page = nil
15
+ @per_page = nil
16
+ @total = nil
17
+ end
18
+
19
+ def [](index)
20
+ @collection[index]
21
+ end
22
+
23
+ def each(&block)
24
+ handle_response if total.nil?
25
+ return to_enum(:each) unless block_given?
26
+
27
+ @collection.each { |element| yield(element) }
28
+
29
+ self
30
+ end
31
+
32
+ private
33
+
34
+ def handle_response
35
+ invoker = ResourceKit::ActionInvoker.new(action, resource, *args)
36
+ @collection = invoker.handle_response
37
+
38
+ meta = Kinescope::MetaMapping.extract_single(invoker.response.body, :read)
39
+ self.page = meta.pagination.page
40
+ self.per_page = meta.pagination.per_page
41
+ self.total = meta.pagination.total
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ class VideoResource < ResourceKit::Resource
5
+ # include ErrorHandler
6
+
7
+ resources do
8
+ action :all, 'GET /v1/videos' do
9
+ query_keys :page, :per_page, :project_id, :folder_id
10
+ handler(200) { |response| VideoMapping.extract_collection(response.body, :read) }
11
+ end
12
+ end
13
+
14
+ def all(*args)
15
+ PaginationResource.new(action(:all), self, *args)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kinescope
4
+ VERSION = '0.1.0'.freeze
5
+ end
data/lib/kinescope.rb ADDED
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'kinescope/version'
4
+ require 'resource_kit'
5
+ require 'kartograph'
6
+
7
+ module Kinescope
8
+ autoload :Client, 'kinescope/client'
9
+
10
+ # Models
11
+ autoload :BaseModel, 'kinescope/models/base_model'
12
+ autoload :Video, 'kinescope/models/video'
13
+
14
+ # Mappings
15
+ autoload :VideoMapping, 'kinescope/mappings/video_mapping'
16
+
17
+ # Resources
18
+ autoload :VideoResource, 'kinescope/resources/video_resource'
19
+
20
+ # Meta
21
+ autoload :Meta, 'kinescope/models/meta'
22
+ autoload :Order, 'kinescope/models/meta'
23
+ autoload :Pagination, 'kinescope/models/meta'
24
+ autoload :MetaMapping, 'kinescope/mappings/meta_mapping'
25
+ autoload :PaginationResource, 'kinescope/pagination_resource'
26
+ end
metadata ADDED
@@ -0,0 +1,189 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kinescope-rb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - droff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-03-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: faraday
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: kartograph
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 0.2.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: resource_kit
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.1.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.1.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: virtus
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.3
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.16'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.16'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '10.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '10.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: webmock
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.8.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.8.0
139
+ description: ''
140
+ email:
141
+ - adroff@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - ".rspec"
148
+ - ".travis.yml"
149
+ - Gemfile
150
+ - LICENSE.txt
151
+ - README.md
152
+ - Rakefile
153
+ - bin/console
154
+ - bin/setup
155
+ - kinescope-rb.gemspec
156
+ - lib/kinescope.rb
157
+ - lib/kinescope/client.rb
158
+ - lib/kinescope/mappings/meta_mapping.rb
159
+ - lib/kinescope/mappings/video_mapping.rb
160
+ - lib/kinescope/models/base_model.rb
161
+ - lib/kinescope/models/meta.rb
162
+ - lib/kinescope/models/video.rb
163
+ - lib/kinescope/pagination_resource.rb
164
+ - lib/kinescope/resources/video_resource.rb
165
+ - lib/kinescope/version.rb
166
+ homepage: https://github.com/droff/kinescope-rb
167
+ licenses:
168
+ - MIT
169
+ metadata: {}
170
+ post_install_message:
171
+ rdoc_options: []
172
+ require_paths:
173
+ - lib
174
+ required_ruby_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ required_rubygems_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ">="
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ requirements: []
185
+ rubygems_version: 3.2.3
186
+ signing_key:
187
+ specification_version: 4
188
+ summary: ''
189
+ test_files: []