vihaya-events 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +18 -0
- data/LICENSE +21 -0
- data/README.md +152 -0
- data/examples/quickstart.rb +58 -0
- data/lib/vihaya/client.rb +208 -0
- data/lib/vihaya/error.rb +26 -0
- data/lib/vihaya/models.rb +324 -0
- data/lib/vihaya/version.rb +5 -0
- data/lib/vihaya.rb +22 -0
- data/vihaya-events.gemspec +38 -0
- metadata +58 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: bc964189032da23b22704e70018dfc84d1e062626c4dd1ce773afaba4746e30d
|
|
4
|
+
data.tar.gz: 9408a9f45ee799454fb04b93d4c0103c26016b478d07d830e232b7f5061c3b8e
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: cc1711f1be3cd370091be2183c39dcda4c43e20d40a29d1a44f35d38237a34b95c8620aa7a5bcf98acd8fad0a6d129063a162a878c38bb59ed2c412904b2df84
|
|
7
|
+
data.tar.gz: e0df7f05daadcc52963abd838db56440ac685ec0326e797b00a85f3f9f20ef92a447fa66335c5a242a988d95b4a299710e9a0a597a1413e95c1d7ceda4f0939b
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 — 2026-04-08
|
|
6
|
+
|
|
7
|
+
First public release on RubyGems.
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- `Vihaya::Client` with `events` and `payments` resource namespaces.
|
|
11
|
+
- `events.list`, `events.get(id)`, `events.register(id, data)` methods.
|
|
12
|
+
- `payments.verify(payment_id:, order_id:, signature:, amount: nil)` method.
|
|
13
|
+
- Plain-Ruby models for `Event`, `CustomField`, `SpecialPrice`, `Contact`,
|
|
14
|
+
`AgendaItem`, `Speaker`, `Sponsor`, `FAQItem`, `PromoCode`, and
|
|
15
|
+
`RegisterData` — feature parity with the JavaScript, Flutter, and Python
|
|
16
|
+
SDKs.
|
|
17
|
+
- `Vihaya::Error` exception class with `#status` and `#data` accessors.
|
|
18
|
+
- Zero runtime dependencies — built on `net/http` and `json` from stdlib.
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vihaya Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
# Vihaya Events — Ruby SDK
|
|
2
|
+
|
|
3
|
+
[](https://rubygems.org/gems/vihaya-events)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
The official Ruby SDK for the [Vihaya Events](https://vihaya.app) platform.
|
|
7
|
+
Built on the Ruby standard library (`net/http` + `json`) with **zero runtime
|
|
8
|
+
dependencies**, and feature parity with the JavaScript, Flutter, and Python
|
|
9
|
+
SDKs.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
gem install vihaya-events
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Or add it to your Gemfile:
|
|
18
|
+
|
|
19
|
+
```ruby
|
|
20
|
+
gem "vihaya-events"
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Requires Ruby 3.0+.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
require "vihaya"
|
|
29
|
+
|
|
30
|
+
vh = Vihaya::Client.new("vh_live_...") # get your key from the developer dashboard
|
|
31
|
+
|
|
32
|
+
vh.events.list.each do |event|
|
|
33
|
+
puts "#{event.title} — #{event.location}"
|
|
34
|
+
end
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Fetch a full event
|
|
38
|
+
|
|
39
|
+
`events.get` returns an `Event` with every piece of metadata the organizer
|
|
40
|
+
has configured — speakers, agenda, sponsors, FAQs, custom fields, pricing
|
|
41
|
+
tiers, and sub-events for mega events.
|
|
42
|
+
|
|
43
|
+
```ruby
|
|
44
|
+
event = vh.events.get("evt_8x42j9")
|
|
45
|
+
|
|
46
|
+
puts event.title
|
|
47
|
+
puts "Mode: #{event.event_mode} Timezone: #{event.timezone}"
|
|
48
|
+
|
|
49
|
+
event.speaker_list.each do |speaker|
|
|
50
|
+
puts "- #{speaker.name} (#{speaker.role})"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
event.agenda_list.each do |item|
|
|
54
|
+
puts "[#{item.time}] #{item.title}"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
event.special_prices.each do |tier|
|
|
58
|
+
puts " #{tier.name}: ₹#{tier.amount}"
|
|
59
|
+
end
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### Mega events
|
|
63
|
+
|
|
64
|
+
If `event.mega_event?` is true, it contains sub-events. Each sub-event has
|
|
65
|
+
its own tiers, custom fields, etc.
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
if event.mega_event?
|
|
69
|
+
event.sub_events.each do |sub|
|
|
70
|
+
price = sub.free? ? "Free" : "₹#{sub.price}"
|
|
71
|
+
puts "- #{sub.title} (#{price})"
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Register an attendee
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
registration = Vihaya::RegisterData.new(
|
|
80
|
+
name: "Anjali Mehta",
|
|
81
|
+
email: "anjali@example.com",
|
|
82
|
+
phone: "+919820012345",
|
|
83
|
+
custom_fields: { "T-Shirt Size" => "L", "College" => "Vihaya Institute" }
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
result = vh.events.register("evt_8x42j9", registration)
|
|
87
|
+
|
|
88
|
+
if result[:isPaid]
|
|
89
|
+
order_id = result[:orderId]
|
|
90
|
+
# Launch Razorpay checkout with this order_id, then verify server-side:
|
|
91
|
+
vh.payments.verify(
|
|
92
|
+
payment_id: "pay_xxx",
|
|
93
|
+
order_id: order_id,
|
|
94
|
+
signature: "sig_xxx"
|
|
95
|
+
)
|
|
96
|
+
else
|
|
97
|
+
puts "Registered! ID: #{result[:registrationId]}"
|
|
98
|
+
end
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
You can also pass a plain `Hash` instead of `RegisterData` if you prefer — the
|
|
102
|
+
SDK will send it as-is, so use camelCase keys for that path.
|
|
103
|
+
|
|
104
|
+
## Error handling
|
|
105
|
+
|
|
106
|
+
All API failures raise `Vihaya::Error` with the HTTP status and raw body:
|
|
107
|
+
|
|
108
|
+
```ruby
|
|
109
|
+
begin
|
|
110
|
+
vh.events.get("evt_does_not_exist")
|
|
111
|
+
rescue Vihaya::Error => e
|
|
112
|
+
puts "#{e.message} (status=#{e.status})"
|
|
113
|
+
puts e.data.inspect
|
|
114
|
+
end
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## API reference
|
|
118
|
+
|
|
119
|
+
### `Vihaya::Client.new(api_key, base_url: ..., headers: {}, timeout: 30)`
|
|
120
|
+
|
|
121
|
+
The main client. `api_key` is required; everything else is keyword.
|
|
122
|
+
|
|
123
|
+
### `vh.events`
|
|
124
|
+
|
|
125
|
+
| Method | Returns | Description |
|
|
126
|
+
| --- | --- | --- |
|
|
127
|
+
| `list` | `Array<Vihaya::Event>` | All events on the authenticated account. |
|
|
128
|
+
| `get(event_id)` | `Vihaya::Event` | Full metadata for one event. |
|
|
129
|
+
| `register(event_id, data)` | `Hash` | Submit a registration. `data` can be `RegisterData` or `Hash`. |
|
|
130
|
+
|
|
131
|
+
### `vh.payments`
|
|
132
|
+
|
|
133
|
+
| Method | Returns | Description |
|
|
134
|
+
| --- | --- | --- |
|
|
135
|
+
| `verify(payment_id:, order_id:, signature:, amount: nil)` | `Hash` | Server-side Razorpay signature verification. |
|
|
136
|
+
|
|
137
|
+
> **Security:** never hard-code a live secret key in client-side code. Use
|
|
138
|
+
> environment variables and perform payment verification from a trusted
|
|
139
|
+
> backend environment only.
|
|
140
|
+
|
|
141
|
+
## Development
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
git clone https://github.com/Vishnu252005/vihaya-sdk-ruby.git
|
|
145
|
+
cd vihaya-sdk-ruby
|
|
146
|
+
ruby test/test_client.rb
|
|
147
|
+
gem build vihaya-events.gemspec
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Quickstart example for the Vihaya Ruby SDK.
|
|
5
|
+
#
|
|
6
|
+
# Run with:
|
|
7
|
+
#
|
|
8
|
+
# VIHAYA_API_KEY=vh_live_... ruby examples/quickstart.rb
|
|
9
|
+
|
|
10
|
+
require "vihaya"
|
|
11
|
+
|
|
12
|
+
api_key = ENV.fetch("VIHAYA_API_KEY", nil)
|
|
13
|
+
if api_key.nil? || api_key.empty?
|
|
14
|
+
warn "Set VIHAYA_API_KEY in your environment first."
|
|
15
|
+
exit 1
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
vh = Vihaya::Client.new(api_key)
|
|
19
|
+
|
|
20
|
+
begin
|
|
21
|
+
puts "Fetching events..."
|
|
22
|
+
events = vh.events.list
|
|
23
|
+
puts "Found #{events.length} event(s)."
|
|
24
|
+
|
|
25
|
+
events.first(5).each do |event|
|
|
26
|
+
price = event.free? ? "Free" : "₹#{event.price}"
|
|
27
|
+
puts " - [#{event.id}] #{event.title} #{price}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
exit 0 if events.empty?
|
|
31
|
+
|
|
32
|
+
first = events.first
|
|
33
|
+
puts "\nFetching details for: #{first.id}"
|
|
34
|
+
detail = vh.events.get(first.id)
|
|
35
|
+
puts " title: #{detail.title}"
|
|
36
|
+
puts " mode: #{detail.event_mode}"
|
|
37
|
+
puts " timezone: #{detail.timezone}"
|
|
38
|
+
puts " speakers: #{detail.speaker_list.length}"
|
|
39
|
+
puts " agenda: #{detail.agenda_list.length} items"
|
|
40
|
+
|
|
41
|
+
puts "\nRegistering a test attendee for: #{first.id}"
|
|
42
|
+
registration = Vihaya::RegisterData.new(
|
|
43
|
+
name: "Quickstart User",
|
|
44
|
+
email: "quickstart@vihaya.app",
|
|
45
|
+
phone: "+919999999999",
|
|
46
|
+
custom_fields: { "College" => "Vihaya Institute" }
|
|
47
|
+
)
|
|
48
|
+
response = vh.events.register(first.id, registration)
|
|
49
|
+
|
|
50
|
+
if response[:isPaid]
|
|
51
|
+
puts " Payment required. Order ID: #{response[:orderId]}"
|
|
52
|
+
else
|
|
53
|
+
puts " Registered. Registration ID: #{response[:registrationId]}"
|
|
54
|
+
end
|
|
55
|
+
rescue Vihaya::Error => e
|
|
56
|
+
warn "API error: #{e.message} (status=#{e.status})"
|
|
57
|
+
exit 2
|
|
58
|
+
end
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "net/http"
|
|
5
|
+
require "uri"
|
|
6
|
+
|
|
7
|
+
require_relative "error"
|
|
8
|
+
require_relative "models"
|
|
9
|
+
require_relative "version"
|
|
10
|
+
|
|
11
|
+
module Vihaya
|
|
12
|
+
# The main Vihaya API client.
|
|
13
|
+
#
|
|
14
|
+
# @example
|
|
15
|
+
# require "vihaya"
|
|
16
|
+
#
|
|
17
|
+
# vh = Vihaya::Client.new("vh_live_...")
|
|
18
|
+
# vh.events.list.each do |event|
|
|
19
|
+
# puts "#{event.title} - #{event.date}"
|
|
20
|
+
# end
|
|
21
|
+
class Client
|
|
22
|
+
DEFAULT_BASE_URL = "https://events.vihaya.app"
|
|
23
|
+
DEFAULT_TIMEOUT = 30
|
|
24
|
+
|
|
25
|
+
attr_reader :events, :payments
|
|
26
|
+
|
|
27
|
+
# @param api_key [String] Your Vihaya API key. Get one from the developer
|
|
28
|
+
# dashboard at https://events.vihaya.app/profile/developer.
|
|
29
|
+
# @param base_url [String] Override the API base URL. Defaults to
|
|
30
|
+
# "https://events.vihaya.app".
|
|
31
|
+
# @param headers [Hash] Extra headers to send with every request.
|
|
32
|
+
# @param timeout [Integer, Float] Per-request timeout in seconds (default 30).
|
|
33
|
+
def initialize(api_key, base_url: DEFAULT_BASE_URL, headers: {}, timeout: DEFAULT_TIMEOUT)
|
|
34
|
+
raise ArgumentError, "api_key is required" if api_key.nil? || api_key.to_s.empty?
|
|
35
|
+
|
|
36
|
+
@api_key = api_key
|
|
37
|
+
@base_url = base_url.to_s.sub(%r{/\z}, "")
|
|
38
|
+
@extra_headers = headers || {}
|
|
39
|
+
@timeout = timeout
|
|
40
|
+
|
|
41
|
+
@events = EventsAPI.new(self)
|
|
42
|
+
@payments = PaymentsAPI.new(self)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Internal: perform a JSON request. Raises {Vihaya::Error} on any
|
|
46
|
+
# non-2xx response or transport error.
|
|
47
|
+
#
|
|
48
|
+
# @api private
|
|
49
|
+
def request(method, path, body: nil, query: nil)
|
|
50
|
+
uri = URI.parse(@base_url + path)
|
|
51
|
+
uri.query = URI.encode_www_form(query) if query && !query.empty?
|
|
52
|
+
|
|
53
|
+
req = build_request(method, uri, body)
|
|
54
|
+
|
|
55
|
+
response = perform(uri, req)
|
|
56
|
+
parse_response(response)
|
|
57
|
+
rescue Vihaya::Error
|
|
58
|
+
raise
|
|
59
|
+
rescue StandardError => e
|
|
60
|
+
raise Vihaya::Error, "Network error: #{e.message}"
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def build_request(method, uri, body)
|
|
66
|
+
klass = {
|
|
67
|
+
"GET" => Net::HTTP::Get,
|
|
68
|
+
"POST" => Net::HTTP::Post,
|
|
69
|
+
"PUT" => Net::HTTP::Put,
|
|
70
|
+
"PATCH" => Net::HTTP::Patch,
|
|
71
|
+
"DELETE" => Net::HTTP::Delete
|
|
72
|
+
}.fetch(method.to_s.upcase) { raise ArgumentError, "Unsupported HTTP method: #{method}" }
|
|
73
|
+
|
|
74
|
+
req = klass.new(uri.request_uri)
|
|
75
|
+
default_headers.each { |k, v| req[k] = v }
|
|
76
|
+
@extra_headers.each { |k, v| req[k.to_s] = v.to_s }
|
|
77
|
+
req.body = JSON.generate(body) if body
|
|
78
|
+
req
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def default_headers
|
|
82
|
+
{
|
|
83
|
+
"x-api-key" => @api_key,
|
|
84
|
+
"Content-Type" => "application/json",
|
|
85
|
+
"Accept" => "application/json",
|
|
86
|
+
"User-Agent" => "vihaya-ruby/#{Vihaya::VERSION}"
|
|
87
|
+
}
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def perform(uri, req)
|
|
91
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
92
|
+
http.use_ssl = (uri.scheme == "https")
|
|
93
|
+
http.open_timeout = @timeout
|
|
94
|
+
http.read_timeout = @timeout
|
|
95
|
+
http.request(req)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def parse_response(response)
|
|
99
|
+
body = response.body.to_s
|
|
100
|
+
data =
|
|
101
|
+
if body.empty?
|
|
102
|
+
nil
|
|
103
|
+
else
|
|
104
|
+
begin
|
|
105
|
+
JSON.parse(body, symbolize_names: true)
|
|
106
|
+
rescue JSON::ParserError
|
|
107
|
+
nil
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
code = response.code.to_i
|
|
112
|
+
return data if code.between?(200, 299)
|
|
113
|
+
|
|
114
|
+
message =
|
|
115
|
+
(data.is_a?(Hash) && (data[:error] || data[:message])) ||
|
|
116
|
+
"Vihaya API error (#{code})"
|
|
117
|
+
raise Vihaya::Error.new(message, status: code, data: data)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# ------------------------------------------------------------------
|
|
121
|
+
# Resource namespaces
|
|
122
|
+
# ------------------------------------------------------------------
|
|
123
|
+
|
|
124
|
+
# Event-related API methods. Access via {Vihaya::Client#events}.
|
|
125
|
+
class EventsAPI
|
|
126
|
+
def initialize(client)
|
|
127
|
+
@client = client
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# List all events on the authenticated account.
|
|
131
|
+
# @return [Array<Vihaya::Event>]
|
|
132
|
+
def list
|
|
133
|
+
result = @client.request("GET", "/api/v1/events")
|
|
134
|
+
data = Client.unwrap(result, default: [])
|
|
135
|
+
Event.from_list(data)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Fetch comprehensive metadata for a single event by ID.
|
|
139
|
+
# @param event_id [String]
|
|
140
|
+
# @return [Vihaya::Event]
|
|
141
|
+
def get(event_id)
|
|
142
|
+
result = @client.request("GET", "/api/v1/events/#{event_id}")
|
|
143
|
+
Event.new(Client.unwrap(result, default: result) || {})
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
# Register an attendee for an event.
|
|
147
|
+
#
|
|
148
|
+
# For paid events the response will include an `orderId` you should
|
|
149
|
+
# use to launch Razorpay checkout. For free events the response
|
|
150
|
+
# confirms the registration directly.
|
|
151
|
+
#
|
|
152
|
+
# @param event_id [String]
|
|
153
|
+
# @param data [Vihaya::RegisterData, Hash] payload
|
|
154
|
+
# @return [Hash] raw API response (symbol keys)
|
|
155
|
+
def register(event_id, data)
|
|
156
|
+
payload =
|
|
157
|
+
case data
|
|
158
|
+
when RegisterData then data.to_payload
|
|
159
|
+
when Hash then data
|
|
160
|
+
else
|
|
161
|
+
raise ArgumentError, "data must be a Vihaya::RegisterData or Hash"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
result = @client.request("POST", "/api/v1/events/#{event_id}/register", body: payload)
|
|
165
|
+
result.is_a?(Hash) ? result : { data: result }
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Payment-related API methods. Access via {Vihaya::Client#payments}.
|
|
170
|
+
class PaymentsAPI
|
|
171
|
+
def initialize(client)
|
|
172
|
+
@client = client
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Server-side verification of a Razorpay payment signature.
|
|
176
|
+
#
|
|
177
|
+
# Call this from a trusted environment (backend, cron job, CLI) after
|
|
178
|
+
# the frontend Razorpay checkout succeeds.
|
|
179
|
+
#
|
|
180
|
+
# @param payment_id [String] Razorpay payment ID (e.g. "pay_O8K2...")
|
|
181
|
+
# @param order_id [String] Razorpay order ID from the registration response
|
|
182
|
+
# @param signature [String] The signature Razorpay returned to the frontend
|
|
183
|
+
# @param amount [Numeric, nil] Optional expected amount
|
|
184
|
+
# @return [Hash] raw API response (symbol keys)
|
|
185
|
+
def verify(payment_id:, order_id:, signature:, amount: nil)
|
|
186
|
+
payload = {
|
|
187
|
+
paymentId: payment_id,
|
|
188
|
+
orderId: order_id,
|
|
189
|
+
signature: signature
|
|
190
|
+
}
|
|
191
|
+
payload[:amount] = amount unless amount.nil?
|
|
192
|
+
|
|
193
|
+
result = @client.request("POST", "/api/v1/payments/verify", body: payload)
|
|
194
|
+
result.is_a?(Hash) ? result : { data: result }
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# Unwraps the `{"success": true, "data": ...}` envelope used by the Vihaya
|
|
199
|
+
# API. Older endpoints returned the data directly, so we fall back.
|
|
200
|
+
#
|
|
201
|
+
# @api private
|
|
202
|
+
def self.unwrap(result, default:)
|
|
203
|
+
return result[:data] if result.is_a?(Hash) && result.key?(:data)
|
|
204
|
+
|
|
205
|
+
result.nil? ? default : result
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
data/lib/vihaya/error.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vihaya
|
|
4
|
+
# Raised when the Vihaya API returns an error response, or when the SDK
|
|
5
|
+
# cannot reach the API at all.
|
|
6
|
+
#
|
|
7
|
+
# @!attribute [r] message
|
|
8
|
+
# @return [String] human-readable error message from the server
|
|
9
|
+
# @!attribute [r] status
|
|
10
|
+
# @return [Integer, nil] HTTP status code, or nil for transport errors
|
|
11
|
+
# @!attribute [r] data
|
|
12
|
+
# @return [Hash, nil] raw parsed JSON response body, or nil
|
|
13
|
+
class Error < StandardError
|
|
14
|
+
attr_reader :status, :data
|
|
15
|
+
|
|
16
|
+
def initialize(message, status: nil, data: nil)
|
|
17
|
+
super(message)
|
|
18
|
+
@status = status
|
|
19
|
+
@data = data
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def inspect
|
|
23
|
+
"#<Vihaya::Error message=#{message.inspect} status=#{status.inspect}>"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Vihaya
|
|
4
|
+
# Lightweight base model for Vihaya API responses.
|
|
5
|
+
#
|
|
6
|
+
# Instead of pulling in an ORM or Dry::Struct, each model is a plain Ruby
|
|
7
|
+
# object with explicit snake_case accessors. Unknown fields are preserved
|
|
8
|
+
# in {#raw} so forward-compatible API additions don't break clients.
|
|
9
|
+
#
|
|
10
|
+
# Every model also responds to Hash-like access (`event[:title]`,
|
|
11
|
+
# `event["title"]`) and has `to_h` for serialization back out.
|
|
12
|
+
class Model
|
|
13
|
+
attr_reader :raw
|
|
14
|
+
|
|
15
|
+
# Override in subclasses: map of snake_case Ruby name to camelCase API key.
|
|
16
|
+
FIELDS = {}.freeze
|
|
17
|
+
|
|
18
|
+
def initialize(data = {})
|
|
19
|
+
@raw = symbolize(data)
|
|
20
|
+
self.class::FIELDS.each do |ruby_name, api_key|
|
|
21
|
+
instance_variable_set(:"@#{ruby_name}", @raw[api_key.to_sym])
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def [](key)
|
|
26
|
+
@raw[key.to_sym]
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_h
|
|
30
|
+
@raw.dup
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def ==(other)
|
|
34
|
+
other.is_a?(self.class) && other.raw == @raw
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.from(data)
|
|
38
|
+
return nil if data.nil?
|
|
39
|
+
|
|
40
|
+
new(data)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def self.from_list(list)
|
|
44
|
+
return [] if list.nil?
|
|
45
|
+
|
|
46
|
+
Array(list).map { |item| new(item) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def symbolize(obj)
|
|
52
|
+
case obj
|
|
53
|
+
when Hash
|
|
54
|
+
obj.each_with_object({}) { |(k, v), memo| memo[k.to_sym] = symbolize(v) }
|
|
55
|
+
when Array
|
|
56
|
+
obj.map { |item| symbolize(item) }
|
|
57
|
+
else
|
|
58
|
+
obj
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# A custom input field on an event registration form.
|
|
64
|
+
class CustomField < Model
|
|
65
|
+
FIELDS = {
|
|
66
|
+
id: :id,
|
|
67
|
+
name: :name,
|
|
68
|
+
type: :type,
|
|
69
|
+
required: :required,
|
|
70
|
+
options: :options,
|
|
71
|
+
replaces_default: :replacesDefault
|
|
72
|
+
}.freeze
|
|
73
|
+
|
|
74
|
+
attr_reader :id, :name, :type, :required, :options, :replaces_default
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# A pricing tier (VIP, Early Bird, Student, etc.).
|
|
78
|
+
class SpecialPrice < Model
|
|
79
|
+
FIELDS = {
|
|
80
|
+
name: :name,
|
|
81
|
+
amount: :amount,
|
|
82
|
+
early_bird_amount: :earlyBirdAmount,
|
|
83
|
+
requires_valid_id: :requiresValidId,
|
|
84
|
+
valid_ids: :validIds,
|
|
85
|
+
custom_fields: :customFields
|
|
86
|
+
}.freeze
|
|
87
|
+
|
|
88
|
+
attr_reader :name, :amount, :early_bird_amount, :requires_valid_id, :valid_ids
|
|
89
|
+
|
|
90
|
+
def custom_fields
|
|
91
|
+
CustomField.from_list(@raw[:customFields])
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# A contact person for an event.
|
|
96
|
+
class Contact < Model
|
|
97
|
+
FIELDS = { id: :id, name: :name, phone: :phone, email: :email }.freeze
|
|
98
|
+
attr_reader :id, :name, :phone, :email
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# A session / slot in the event schedule.
|
|
102
|
+
class AgendaItem < Model
|
|
103
|
+
FIELDS = {
|
|
104
|
+
id: :id,
|
|
105
|
+
title: :title,
|
|
106
|
+
time: :time,
|
|
107
|
+
description: :description,
|
|
108
|
+
speaker_id: :speakerId
|
|
109
|
+
}.freeze
|
|
110
|
+
|
|
111
|
+
attr_reader :id, :title, :time, :description, :speaker_id
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# A speaker appearing at an event.
|
|
115
|
+
class Speaker < Model
|
|
116
|
+
FIELDS = {
|
|
117
|
+
id: :id,
|
|
118
|
+
name: :name,
|
|
119
|
+
role: :role,
|
|
120
|
+
bio: :bio,
|
|
121
|
+
image_url: :imageUrl,
|
|
122
|
+
linkedin_url: :linkedinUrl,
|
|
123
|
+
twitter_url: :twitterUrl,
|
|
124
|
+
website_url: :websiteUrl
|
|
125
|
+
}.freeze
|
|
126
|
+
|
|
127
|
+
attr_reader :id, :name, :role, :bio,
|
|
128
|
+
:image_url, :linkedin_url, :twitter_url, :website_url
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# An event sponsor.
|
|
132
|
+
class Sponsor < Model
|
|
133
|
+
FIELDS = {
|
|
134
|
+
id: :id,
|
|
135
|
+
name: :name,
|
|
136
|
+
logo_url: :logoUrl,
|
|
137
|
+
category: :category,
|
|
138
|
+
website_url: :websiteUrl
|
|
139
|
+
}.freeze
|
|
140
|
+
|
|
141
|
+
attr_reader :id, :name, :logo_url, :category, :website_url
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# A frequently-asked question entry for an event.
|
|
145
|
+
class FAQItem < Model
|
|
146
|
+
FIELDS = { id: :id, question: :question, answer: :answer }.freeze
|
|
147
|
+
attr_reader :id, :question, :answer
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
# A promo / discount code applied at registration time.
|
|
151
|
+
class PromoCode < Model
|
|
152
|
+
FIELDS = {
|
|
153
|
+
code: :code,
|
|
154
|
+
type: :type,
|
|
155
|
+
value: :value,
|
|
156
|
+
usage_limit: :usageLimit,
|
|
157
|
+
used_count: :usedCount,
|
|
158
|
+
is_active: :isActive
|
|
159
|
+
}.freeze
|
|
160
|
+
|
|
161
|
+
attr_reader :code, :type, :value, :usage_limit, :used_count, :is_active
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# A Vihaya event with full metadata.
|
|
165
|
+
#
|
|
166
|
+
# Mirrors the `VihayaEvent` shape exposed by the JavaScript, Flutter, and
|
|
167
|
+
# Python SDKs. Every non-identifier field may be nil because the API
|
|
168
|
+
# only returns what the organizer has configured for that event.
|
|
169
|
+
class Event < Model
|
|
170
|
+
FIELDS = {
|
|
171
|
+
id: :id,
|
|
172
|
+
title: :title,
|
|
173
|
+
event_type: :eventType,
|
|
174
|
+
description: :description,
|
|
175
|
+
date: :date,
|
|
176
|
+
end_date: :endDate,
|
|
177
|
+
location: :location,
|
|
178
|
+
price: :price,
|
|
179
|
+
is_free: :isFree,
|
|
180
|
+
creator_id: :creatorId,
|
|
181
|
+
created_at: :createdAt,
|
|
182
|
+
has_special_prices: :hasSpecialPrices,
|
|
183
|
+
has_platform_fee: :hasPlatformFee,
|
|
184
|
+
platform_fee: :platformFee,
|
|
185
|
+
platform_fee_type: :platformFeeType,
|
|
186
|
+
pass_platform_fee_to_user: :passPlatformFeeToUser,
|
|
187
|
+
collect_dietary_preferences: :collectDietaryPreferences,
|
|
188
|
+
collect_accessibility_needs: :collectAccessibilityNeeds,
|
|
189
|
+
collect_emergency_contact: :collectEmergencyContact,
|
|
190
|
+
collect_affiliation: :collectAffiliation,
|
|
191
|
+
collect_research_interests: :collectResearchInterests,
|
|
192
|
+
collect_t_shirt_size: :collectTShirtSize,
|
|
193
|
+
enable_food_scanning: :enableFoodScanning,
|
|
194
|
+
food_scan_limit: :foodScanLimit,
|
|
195
|
+
is_team_event: :isTeamEvent,
|
|
196
|
+
min_team_size: :minTeamSize,
|
|
197
|
+
max_team_size: :maxTeamSize,
|
|
198
|
+
venue_name: :venueName,
|
|
199
|
+
full_address: :fullAddress,
|
|
200
|
+
city: :city,
|
|
201
|
+
country: :country,
|
|
202
|
+
google_map_link: :googleMapLink,
|
|
203
|
+
contact_phone: :contactPhone,
|
|
204
|
+
contact_email: :contactEmail,
|
|
205
|
+
contact_person_name: :contactPersonName,
|
|
206
|
+
event_mode: :eventMode,
|
|
207
|
+
timezone: :timezone,
|
|
208
|
+
currency: :currency,
|
|
209
|
+
registration_deadline: :registrationDeadline,
|
|
210
|
+
requires_approval: :requiresApproval,
|
|
211
|
+
waitlist_available: :waitlistAvailable
|
|
212
|
+
}.freeze
|
|
213
|
+
|
|
214
|
+
attr_reader :id, :title, :event_type, :description, :date, :end_date,
|
|
215
|
+
:location, :price, :is_free, :creator_id, :created_at,
|
|
216
|
+
:has_special_prices, :has_platform_fee, :platform_fee,
|
|
217
|
+
:platform_fee_type, :pass_platform_fee_to_user,
|
|
218
|
+
:collect_dietary_preferences, :collect_accessibility_needs,
|
|
219
|
+
:collect_emergency_contact, :collect_affiliation,
|
|
220
|
+
:collect_research_interests, :collect_t_shirt_size,
|
|
221
|
+
:enable_food_scanning, :food_scan_limit,
|
|
222
|
+
:is_team_event, :min_team_size, :max_team_size,
|
|
223
|
+
:venue_name, :full_address, :city, :country, :google_map_link,
|
|
224
|
+
:contact_phone, :contact_email, :contact_person_name,
|
|
225
|
+
:event_mode, :timezone, :currency,
|
|
226
|
+
:registration_deadline, :requires_approval, :waitlist_available
|
|
227
|
+
|
|
228
|
+
def free?
|
|
229
|
+
is_free == true
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
def mega_event?
|
|
233
|
+
event_type == "megaEvent"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def agenda_list
|
|
237
|
+
AgendaItem.from_list(@raw[:agendaList])
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def speaker_list
|
|
241
|
+
Speaker.from_list(@raw[:speakerList])
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def sponsor_list
|
|
245
|
+
Sponsor.from_list(@raw[:sponsorList])
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def faq_list
|
|
249
|
+
FAQItem.from_list(@raw[:faqList])
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def contact_list
|
|
253
|
+
Contact.from_list(@raw[:contactList])
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
def custom_fields
|
|
257
|
+
CustomField.from_list(@raw[:customFields])
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def special_prices
|
|
261
|
+
SpecialPrice.from_list(@raw[:specialPrices])
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def promo_codes
|
|
265
|
+
PromoCode.from_list(@raw[:promoCodes])
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
def sub_events
|
|
269
|
+
Event.from_list(@raw[:subEvents])
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# Payload for {Vihaya::Client#events}.register.
|
|
274
|
+
#
|
|
275
|
+
# Only `name`, `email`, and `phone` are required. Everything else is
|
|
276
|
+
# optional and mirrors the JS/Flutter/Python SDK shapes.
|
|
277
|
+
class RegisterData
|
|
278
|
+
# Map of Ruby kwarg name -> wire (camelCase) key.
|
|
279
|
+
FIELDS = {
|
|
280
|
+
name: :name,
|
|
281
|
+
email: :email,
|
|
282
|
+
phone: :phone,
|
|
283
|
+
payment_id: :paymentId,
|
|
284
|
+
order_id: :orderId,
|
|
285
|
+
registration_id: :registrationId,
|
|
286
|
+
special_price: :specialPrice,
|
|
287
|
+
promo_code: :promoCode,
|
|
288
|
+
is_early_bird_applied: :isEarlyBirdApplied,
|
|
289
|
+
team_name: :teamName,
|
|
290
|
+
team_members: :teamMembers,
|
|
291
|
+
accommodation: :accommodation,
|
|
292
|
+
dietary_preference: :dietaryPreference,
|
|
293
|
+
preferences: :preferences,
|
|
294
|
+
custom_fields: :customFields,
|
|
295
|
+
user_id: :userId,
|
|
296
|
+
source: :source
|
|
297
|
+
}.freeze
|
|
298
|
+
|
|
299
|
+
attr_accessor(*FIELDS.keys)
|
|
300
|
+
|
|
301
|
+
def initialize(name:, email:, phone:, **extras)
|
|
302
|
+
@name = name
|
|
303
|
+
@email = email
|
|
304
|
+
@phone = phone
|
|
305
|
+
extras.each do |key, value|
|
|
306
|
+
unless FIELDS.key?(key)
|
|
307
|
+
raise ArgumentError, "Unknown RegisterData field: #{key.inspect}"
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
public_send("#{key}=", value)
|
|
311
|
+
end
|
|
312
|
+
end
|
|
313
|
+
|
|
314
|
+
# Serializes to the wire format (camelCase keys, nils dropped).
|
|
315
|
+
def to_payload
|
|
316
|
+
FIELDS.each_with_object({}) do |(ruby_name, wire_key), memo|
|
|
317
|
+
value = public_send(ruby_name)
|
|
318
|
+
memo[wire_key] = value unless value.nil?
|
|
319
|
+
end
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
alias to_h to_payload
|
|
323
|
+
end
|
|
324
|
+
end
|
data/lib/vihaya.rb
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Official Ruby SDK for the Vihaya Events platform.
|
|
4
|
+
#
|
|
5
|
+
# Quick start:
|
|
6
|
+
#
|
|
7
|
+
# require "vihaya"
|
|
8
|
+
#
|
|
9
|
+
# vh = Vihaya::Client.new("vh_live_...")
|
|
10
|
+
# vh.events.list.each do |event|
|
|
11
|
+
# puts "#{event.title} - #{event.date}"
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# See https://events.vihaya.app/profile/developer/docs for the full API
|
|
15
|
+
# reference.
|
|
16
|
+
module Vihaya
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
require_relative "vihaya/version"
|
|
20
|
+
require_relative "vihaya/error"
|
|
21
|
+
require_relative "vihaya/models"
|
|
22
|
+
require_relative "vihaya/client"
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/vihaya/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "vihaya-events"
|
|
7
|
+
spec.version = Vihaya::VERSION
|
|
8
|
+
spec.authors = ["Vihaya Team"]
|
|
9
|
+
spec.email = ["vihaya.app@gmail.com"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Official Ruby SDK for the Vihaya Events platform."
|
|
12
|
+
spec.description = "Fetch events, register attendees, and verify Razorpay " \
|
|
13
|
+
"payments on the Vihaya Events platform with a fully-typed " \
|
|
14
|
+
"Ruby client. Feature parity with the JavaScript, Flutter, " \
|
|
15
|
+
"and Python SDKs."
|
|
16
|
+
spec.homepage = "https://github.com/Vishnu252005/vihaya-sdk-ruby"
|
|
17
|
+
spec.license = "MIT"
|
|
18
|
+
spec.required_ruby_version = ">= 3.0.0"
|
|
19
|
+
|
|
20
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
21
|
+
spec.metadata["source_code_uri"] = "https://github.com/Vishnu252005/vihaya-sdk-ruby"
|
|
22
|
+
spec.metadata["changelog_uri"] = "https://github.com/Vishnu252005/vihaya-sdk-ruby/blob/main/CHANGELOG.md"
|
|
23
|
+
spec.metadata["documentation_uri"] = "https://events.vihaya.app/profile/developer/docs"
|
|
24
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/Vishnu252005/vihaya-sdk-ruby/issues"
|
|
25
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
26
|
+
|
|
27
|
+
spec.files = Dir[
|
|
28
|
+
"lib/**/*.rb",
|
|
29
|
+
"examples/**/*.rb",
|
|
30
|
+
"README.md",
|
|
31
|
+
"CHANGELOG.md",
|
|
32
|
+
"LICENSE",
|
|
33
|
+
"vihaya-events.gemspec"
|
|
34
|
+
]
|
|
35
|
+
spec.require_paths = ["lib"]
|
|
36
|
+
|
|
37
|
+
# Zero runtime dependencies — built on Ruby stdlib (net/http + json).
|
|
38
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: vihaya-events
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Vihaya Team
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: Fetch events, register attendees, and verify Razorpay payments on the
|
|
13
|
+
Vihaya Events platform with a fully-typed Ruby client. Feature parity with the JavaScript,
|
|
14
|
+
Flutter, and Python SDKs.
|
|
15
|
+
email:
|
|
16
|
+
- vihaya.app@gmail.com
|
|
17
|
+
executables: []
|
|
18
|
+
extensions: []
|
|
19
|
+
extra_rdoc_files: []
|
|
20
|
+
files:
|
|
21
|
+
- CHANGELOG.md
|
|
22
|
+
- LICENSE
|
|
23
|
+
- README.md
|
|
24
|
+
- examples/quickstart.rb
|
|
25
|
+
- lib/vihaya.rb
|
|
26
|
+
- lib/vihaya/client.rb
|
|
27
|
+
- lib/vihaya/error.rb
|
|
28
|
+
- lib/vihaya/models.rb
|
|
29
|
+
- lib/vihaya/version.rb
|
|
30
|
+
- vihaya-events.gemspec
|
|
31
|
+
homepage: https://github.com/Vishnu252005/vihaya-sdk-ruby
|
|
32
|
+
licenses:
|
|
33
|
+
- MIT
|
|
34
|
+
metadata:
|
|
35
|
+
homepage_uri: https://github.com/Vishnu252005/vihaya-sdk-ruby
|
|
36
|
+
source_code_uri: https://github.com/Vishnu252005/vihaya-sdk-ruby
|
|
37
|
+
changelog_uri: https://github.com/Vishnu252005/vihaya-sdk-ruby/blob/main/CHANGELOG.md
|
|
38
|
+
documentation_uri: https://events.vihaya.app/profile/developer/docs
|
|
39
|
+
bug_tracker_uri: https://github.com/Vishnu252005/vihaya-sdk-ruby/issues
|
|
40
|
+
rubygems_mfa_required: 'true'
|
|
41
|
+
rdoc_options: []
|
|
42
|
+
require_paths:
|
|
43
|
+
- lib
|
|
44
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
45
|
+
requirements:
|
|
46
|
+
- - ">="
|
|
47
|
+
- !ruby/object:Gem::Version
|
|
48
|
+
version: 3.0.0
|
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - ">="
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '0'
|
|
54
|
+
requirements: []
|
|
55
|
+
rubygems_version: 4.0.3
|
|
56
|
+
specification_version: 4
|
|
57
|
+
summary: Official Ruby SDK for the Vihaya Events platform.
|
|
58
|
+
test_files: []
|