diff --git a/custom_connectors/oauth2/ringcentral_video_connector.rb b/custom_connectors/oauth2/ringcentral_video_connector.rb new file mode 100644 index 00000000..1e144899 --- /dev/null +++ b/custom_connectors/oauth2/ringcentral_video_connector.rb @@ -0,0 +1,4745 @@ +{ + title: 'RingCentral Video', + + connection: { + fields: [ + { + name: 'client_id', + control_type: 'string', + optional: false, + hint: <<-HELP + Create an app in your Developer portal account + to obtain your Client ID and Client secret. + Click here to learn more. + HELP + }, + { + name: 'client_secret', + hint: 'The client secret provided by RingCentral after creating your app in the Developer portal.', + control_type: 'password', + optional: false + } + ], + authorization: { + type: 'oauth2', + authorization_url: lambda do |connection| + params = { + response_type: 'code', + client_id: connection['client_id'], + redirect_uri: 'https://www.workato.com/oauth/callback' + }.to_param + 'https://platform.ringcentral.com/restapi/oauth/authorize?' + + params + end, + + acquire: lambda do |connection, auth_code, redirect_uri| + post('https://platform.ringcentral.com/restapi/oauth/token'). + payload(grant_type: 'authorization_code', + client_id: connection['client_id'], + client_secret: connection['client_secret'], + code: auth_code, + redirect_uri: redirect_uri). + request_format_www_form_urlencoded + end, + refresh_on: [401, 403], + refresh: lambda do |connection, refresh_token| + encode = "#{connection['client_id']}:#{connection['client_secret']}".encode_base64 + post('https://platform.ringcentral.com/restapi/oauth/token'). + payload(grant_type: 'refresh_token', + refresh_token: refresh_token). + headers('Authorization': "Basic #{encode}").request_format_www_form_urlencoded + end, + apply: lambda do |_connection, access_token| + headers('Authorization' => "Bearer #{access_token}") + end + }, + base_uri: lambda do |_connection| + 'https://platform.ringcentral.com' + end + }, + + test: -> { get('/scim/v2/Users') }, + + methods: { + ### UTILITIES ### + custom_input_parser: lambda do |input| + input.each_with_object({}) do |(key, value), hash| + if key.include?('_2_0_') + key = "urn:ietf:params:scim:schemas:#{key.gsub('_2_0_', ':2.0:').gsub('_', ':')}" + end + hash[key] = value + end + end, + custom_output_parser: lambda do |output| + if output.is_a?(Array) + output.map do |arr_value| + call('custom_output_parser', arr_value) + end + else + if output['schemas'].present? + output['schemas'] = output['schemas']&.map do |schema| + { 'value' => schema } + end + end + if output['audioOptions'].present? + output['audioOptions'] = output['audioOptions']&.map do |audio| + { 'value' => audio } + end + end + if output['addedPersonIds'].present? + output['addedPersonIds'] = output['addedPersonIds']&.map do |person| + { 'value' => person } + end + end + if output['chatIds'].present? + output['chatIds'] = output['chatIds']&.map do |chat| + { 'value' => chat } + end + end + output.each_with_object({}) do |(key, value), hash| + if key.include?('urn:ietf:params:scim:schemas:') + key = key.gsub('urn:ietf:params:scim:schemas:', '').gsub(/:|\./, '_') + end + if value.is_a?(Array) || value.is_a?(Hash) + value = call('custom_output_parser', value) + end + hash[key] = value + end + end + end, + make_schema_builder_fields_sticky: lambda do |schema| + schema.map do |field| + if field['properties'].present? + field['properties'] = call('make_schema_builder_fields_sticky', + field['properties']) + end + field['sticky'] = true + + field + end + end, + format_schema: lambda do |input| + input&.map do |field| + if (props = field[:properties]) + field[:properties] = call('format_schema', props) + elsif (props = field['properties']) + field['properties'] = call('format_schema', props) + end + if (name = field[:name]) + field[:label] = field[:label].presence || name.labelize + field[:name] = name.gsub(/\W/) { |spl_chr| "__#{spl_chr.encode_hex}__" } + elsif (name = field['name']) + field['label'] = field['label'].presence || name.labelize + field['name'] = name.gsub(/\W/) { |spl_chr| "__#{spl_chr.encode_hex}__" } + end + + field + end + end, + format_payload: lambda do |payload| + if payload.is_a?(Array) + payload.map do |array_value| + call('format_payload', array_value) + end + elsif payload.is_a?(Hash) + payload.each_with_object({}) do |(key, value), hash| + key = key.gsub(/__\w+__/) do |string| + string.gsub(/__/, '').decode_hex.as_utf8 + end + if value.is_a?(Array) || value.is_a?(Hash) + value = call('format_payload', value) + end + hash[key] = value + end + end + end, + format_response: lambda do |response| + response = response&.compact unless response.is_a?(String) || response + if response.is_a?(Array) + response.map do |array_value| + call('format_response', array_value) + end + elsif response.is_a?(Hash) + response.each_with_object({}) do |(key, value), hash| + key = key.gsub(/\W/) { |spl_chr| "__#{spl_chr.encode_hex}__" } + if value.is_a?(Array) || value.is_a?(Hash) + value = call('format_response', value) + end + hash[key] = value + end + else + response + end + end, + + ### SAMPLE OUTPUTS ### + search_sample_output: lambda do |input| + input['accountId'] = '~' + input['extensionId'] = '~' + case input['object'] + when 'posts' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + call('search_posts_execute', 'chatId' => chat_id) + when 'notes' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + call('search_notes_execute', 'chatId' => chat_id) + when 'tasks' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + get("/restapi/v1.0/glip/chats/#{chat_id}/tasks?recordCount=1") + when 'account_meeting_recordings', 'user_meeting_recordings' + params = { + meetingStartTimeFrom: '2020-01-01T00:00:00.000Z', + meetingStartTimeTo: Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ'), + perPage: 100 + } + get("/restapi/v1.0/account/#{input.delete('accountId')}/meeting-recordings", params) + else + call("search_#{input['object']}_execute", input) + end + end, + get_sample_output: lambda do |input| + input['accountId'] = '~' + input['extensionId'] = '~' + case input['object'] + when 'users', 'user' + call('search_users_execute', input)&.[]('Resources')&.first + when 'post' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + call('search_posts_execute', 'chatId' => chat_id)&.[]('records')&.first + when 'note' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + call('search_notes_execute', 'chatId' => chat_id)&.[]('records')&.first + when 'team' + call('search_teams_execute', 'recordCount' => 1)&.[]('records')&.first + when 'team_members' + { result: 'Successfully added.' } + when 'calendar_event' + call('search_calendar_events_execute', 'recordCount' => 1)&.[]('records')&.first + when 'task' + chat_id = get('/restapi/v1.0/glip/chats?recordCount=1')&.dig('records', 0, 'id') + get("/restapi/v1.0/glip/chats/#{chat_id}/tasks?recordCount=1")&.[]('records')&.first + when 'everyone_chat' + { + id: '52342', + creationTime: '2015-03-31T16:00:00.000Z', + lastModifiedTime: '2018-07-31T18:00:00.000Z', + type: 'Everyone', + name: 'Chat name', + description: 'Chat description' + } + when 'user_call_record' + call('search_user_call_log_records_execute', input)&.[]('records')&.first + when 'ringout_call' + call('ringout_call_sample_output', '') + when 'call_recording' + { + id: '401786818008', + contentUri: 'https://platform.ringcentral.com/restapi/v1.0/account/401452676008/recording/401786818008/content', + contentType: 'audio/x-wav', + duration: 30 + } + when 'callout_session_status' + call('callout_sample_output', '') + else + object = input['object'].pluralize + call("search_#{object}_execute", input)&.[]('records')&.first + end + end, + ringout_call_sample_output: lambda do |_input| + { + 'uri': 'https://platform.ringcentral.com/restapi/v1.0/account/123/extension/123/ring-out/s-123', + 'id': 's-123', + 'status': { + 'callStatus': 'InProgress', + 'callerStatus': 'InProgress', + 'calleeStatus': 'InProgress' + } + } + end, + send_sms_sample_output: lambda do |_input| + { + uri: 'https://platform.ringcentral.com/restapi/v1.0/account/1933605021/extension/1933605021/message-store/1150778182020', + id: '1150778182020', + to: [ + { + phoneNumber: '+16504590478', + location: 'Half Moon Bay, CA' + } + ], + from: { + phoneNumber: '+16503766229', + name: 'Dev partner 8', + location: 'San Mateo, CA' + }, + type: 'SMS', + creationTime: '2020-04-29T11:46:22.000Z', + readStatus: 'Read', + priority: 'Normal', + attachments: [ + { + id: '1150778182020', + uri: 'https://platform.ringcentral.com/restapi/v1.0/account/1933605021/extension/1933605021/message-store/1150778182020/content/1150778182020', + type: 'Text', + contentType: 'text/plain' + } + ], + direction: 'Outbound', + availability: 'Alive', + subject: 'TEST SMS', + messageStatus: 'Queued', + smsSendingAttemptsCount: 1, + conversationId: '6537012962707654000', + conversation: { + id: '6537012962707653893', + uri: 'https://platform.ringcentral.com/restapi/v1.0/conversation/6537012962707653893' + }, + lastModifiedTime: '2020-04-29T11:46:22.241Z' + } + end, + callout_sample_output: lambda do |_input| + { + session: { + creationTime: '2019-08-19T11:42:21Z', + id: 's-54a38392c79849dab4a25fe8040edd53', + origin: { + type: 'Call' + }, + parties: [ + { + direction: 'Outbound', + from: { + deviceId: '803469127021', + extensionId: '297277020', + name: 'John Smith', + phoneNumber: '+18885287464' + }, + id: 'p-54a38392c79849dab4a25fe8040edd53-1', + muted: false, + owner: { + accountId: '37439510', + extensionId: '297277020' + }, + standAlone: false, + status: { + "code": 'Setup' + }, + to: { + phoneNumber: '+79817891689' + } + } + ] + } + } + end, + reply_with_text_sample_output: lambda do |_input| + { + accountId: '1933605021', + direction: 'Inbound', + extensionId: '1933605021', + from: { + deviceId: '804543271020', + extensionId: '3342526020', + name: 'Joshua Aaron Navarro', + phoneNumber: '120' + }, + id: 'p-15640f2ae96045cbb03e3bae04a6a874-2', + muted: false, + owner: { + accountId: '1933605021', + extensionId: '1933605021' + }, + standAlone: false, + status: { + code: 'Setup', + reason: 'CallReplied' + }, + to: { + extensionId: '1933605021', + name: 'Dev partner 8', + phoneNumber: '101' + } + } + end, + + ### CREATE METHODS ### + create_meeting_schema: lambda do |_input| + timezone_id = get('/restapi/v1.0/dictionary/timezone?page=1&perPage=100')['records'].pluck('name', 'id') || [] + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'topic', sticky: true }, + { + name: 'meetingType', + control_type: 'select', + pick_list: 'meetingType', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'meetingType', + label: 'Meeting type', + type: 'string', + control_type: 'text', + optional: true, + toggle_hint: 'Use custom value', + hint: 'Allowed values are: Scheduled, Instant, Recurring' + } + }, + { name: 'schedule', type: 'object', sticky: true, + properties: [ + { name: 'startTime', type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'durationInMinutes', type: 'integer', + sticky: true, control_type: 'integer', render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'timeZone', type: 'object', sticky: true, + properties: [ + { name: 'id', label: 'Timezone', sticky: true, control_type: 'select', + hint: 'Please select the timezone.', + pick_list: timezone_id, + toggle_hint: 'Select from options', + toggle_field: { + name: 'id', label: 'Timezone ID', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the internal identifier of a timezone.
' \ + 'You can use the Search timezone action to retrieve the Timezone ID.' + } } + ] } + ] }, + { name: 'password', sticky: true }, + { name: 'host', type: 'object', sticky: true, + properties: [ + { name: 'uri', label: 'URI', sticky: true, hint: 'Link to the meeting host resource' }, + { name: 'id', sticky: true, hint: 'Internal identifier of an extension which is assigned to be a meeting host' } + ] }, + { + name: 'allowJoinBeforeHost', + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'allowJoinBeforeHost', + type: 'boolean', + control_type: 'text', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + label: 'Allow join before host', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { + name: 'startHostVideo', + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'startHostVideo', + type: 'boolean', + control_type: 'text', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + label: 'Start host video', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { + name: 'startParticipantsVideo', + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'startParticipantsVideo', + type: 'boolean', + control_type: 'text', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + label: 'Start participants video', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { + name: 'usePersonalMeetingId', + control_type: 'checkbox', + type: 'boolean', + sticky: true, + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'usePersonalMeetingId', + type: 'boolean', + control_type: 'text', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + label: 'Use personal meeting ID', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'audioOptions', control_type: 'multiselect', delimiter: ',', + pick_list: 'audioOptions', toggle_hint: 'Select from options', + toggle_field: { + name: 'audioOptions', + toggle_hint: 'Use custom value', + label: 'Audio options', + type: 'text', + control_type: 'text', + optional: false, + hint: 'Allowed values: Phone, ComputerAudio. Please enter values separated by commas, without spaces.' + } }, + { name: 'recurrence', type: 'object', + properties: [ + { + name: 'frequency', + control_type: 'select', + sticky: true, + hint: 'Recurrence time frame', + pick_list: [ + %w[Daily Daily], + %w[Weekly Weekly], + %w[Monthly Monthly] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'frequency', + type: 'string', + control_type: 'text', + label: 'Frequency', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Daily, Weekly, Monthly' + } + }, + { name: 'interval', type: 'integer', label: 'Interval', + render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'Reccurence interval. ' \ + 'The supported ranges are: 1-90 for Daily; 1-12 for Weekly; 1-3 for Monthly' }, + { + name: 'monthlyByWeek', + control_type: 'select', + sticky: true, + hint: 'Supported together with Weekly by day', + pick_list: [ + %w[Last Last], + %w[First First], + %w[Second Second], + %w[Third Third], + %w[Fourth Fourth] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'monthlyByWeek', + type: 'string', + control_type: 'text', + label: 'Monthly by week', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Last, First, Second, Third, Fourth' + } + }, + { + name: 'weeklyByDays', + control_type: 'multiselect', + delimiter: ',', + optional: true, + sticky: true, + pick_list: [ + %w[Sunday Sunday], + %w[Monday Monday], + %w[Tuesday Tuesday], + %w[Wednesday Wednesday], + %w[Thursday Thursday], + %w[Friday Friday], + %w[Saturday Saturday] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'weeklyByDays', + type: 'string', + control_type: 'text', + label: 'Weekly by days', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Sunday, Monday, Tuesday, Wednesday, + Thursday, Friday, Saturday' + } + }, + { name: 'monthlyByDay', type: 'integer', sticky: true, + render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'The supported range is 1-31' }, + { name: 'count', type: 'integer', sticky: true, + render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'Number of occurences' }, + { name: 'until', hint: 'Meeting expiration datetime', + type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' } + ] }, + { + name: 'autoRecordType', + control_type: 'select', + sticky: true, + pick_list: [ + %w[Local Local], + %w[Cloud Cloud], + %w[None None] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'autoRecordType', + type: 'string', + control_type: 'text', + label: 'Auto record type', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Local, Cloud, None' + } + } + ] + end, + create_meeting_output_schema: lambda do |_input| + [ + { name: 'uri', label: 'URI' }, + { name: 'uuid', label: 'UUID' }, + { name: 'id' }, + { name: 'topic' }, + { name: 'meetingType' }, + { name: 'password' }, + { name: 'h323Password', label: 'H323 password' }, + { name: 'status' }, + { name: 'links', type: 'object', + properties: [ + { name: 'startUri', label: 'Start URI' }, + { name: 'joinUri', label: 'Join URI' } + ] }, + { name: 'schedule', type: 'object', + properties: [ + { name: 'startTime', type: 'date_time', control_type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'durationInMinutes', type: 'integer', render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'timeZone', type: 'object', + properties: [ + { name: 'uri', label: 'URI' }, + { name: 'id' }, + { name: 'name' }, + { name: 'description' } + ] } + ] }, + { name: 'host', type: 'object', + properties: [ + { name: 'uri', label: 'URI' }, + { name: 'id' } + ] }, + { name: 'allowJoinBeforeHost', type: 'boolean', render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'startHostVideo', type: 'boolean', render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'startParticipantsVideo', type: 'boolean', render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'usePersonalMeetingId', type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'audioOptions', type: 'array', of: 'object', + properties: [ + { name: 'value' } + ] }, + { name: 'occurrences', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'durationInMinutes', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'status' } + ] } + ] + end, + create_meeting_execute: lambda do |input| + input['audioOptions'] = input['audioOptions']&.split(',') || nil + input['recurrence']['weeklyByDays'] = input['recurrence']['weeklyByDays']&.split(',') || nil + post("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/meeting", input.compact.except('object')) + end, + + create_user_schema: lambda do |_input| + country = get('/restapi/v1.0/dictionary/country?page=1&perPage=300')['records'].pluck('name', 'name') || [] + state = get('/restapi/v1.0/dictionary/state?allCountries=true&countryId=1&page=1&perPage=500&withPhoneNumbers=false')['records']. + pluck('name', 'name') || [] + [ + { name: 'externalId', hint: 'External unique resource ID defined by provisioning client', sticky: true }, + { name: 'userName', label: 'User name', hint: 'Must be same as work type email address', + optional: false }, + { + name: 'active', + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'active', + type: 'boolean', + control_type: 'text', + label: 'Active', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'addresses', type: 'array', of: 'object', list_mode: 'static', + item_label: 'Address', add_item_label: 'Add addresses tag', + empty_list_title: 'Specify addresses', + properties: [ + { + name: 'type', + control_type: 'select', + pick_list: [ + %w[Work work] + ], + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + optional: true, + toggle_hint: 'Use custom value', + hint: 'Allowed values are work' + } + }, + { name: 'streetAddress', sticky: true }, + { name: 'locality', sticky: true }, + { name: 'region', sticky: true, control_type: 'select', + hint: 'Please select the region or state.', + pick_list: state, + toggle_hint: 'Select from options', + toggle_field: { + name: 'region', label: 'Region', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the region or state name.' + } }, + { name: 'country', sticky: true, control_type: 'select', + pick_list: country, + extends_schema: true, + toggle_hint: 'Select from options', + toggle_field: { + name: 'country', label: 'Country', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the country name. ' \ + "Click here to learn more." + } }, + { name: 'postalCode', sticky: true } + ] }, + { name: 'emails', type: 'array', of: 'object', optional: false, + item_label: 'Email', add_item_label: 'Add emails tag', + empty_list_title: 'Specify emails', + properties: [ + { + name: 'type', + control_type: 'select', + pick_list: [ + %w[Work work] + ], + optional: false, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + toggle_hint: 'Use custom value', + optional: false, + hint: 'Allowed values are work' + } + }, + { name: 'value', optional: false, + hint: 'Value should be a valid email, e.g. example@example.com' } + ] }, + { name: 'name', type: 'object', optional: false, + properties: [ + { name: 'familyName', optional: false }, + { name: 'givenName', optional: false } + ] }, + { name: 'phoneNumbers', type: 'array', of: 'object', list_mode: 'static', + item_label: 'Phone number', add_item_label: 'Add phone numbers tag', + empty_list_title: 'Specify phone numbers', sticky: true, + properties: [ + { + name: 'type', + sticky: true, + control_type: 'select', + pick_list: 'phoneType', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + optional: true, + toggle_hint: 'Use custom value', + hint: 'Allowed values are work, mobile, or other' + } + }, + { name: 'value', sticky: true, + hint: 'Value should be a valid phone number, e.g. +16504356474' } + ] }, + { name: 'photos', type: 'array', of: 'object', list_mode: 'static', + item_label: 'Photo', add_item_label: 'Add photos tag', + empty_list_title: 'Specify photos', + sticky: true, + properties: [ + { + name: 'type', + control_type: 'select', + pick_list: 'photoType', + sticky: true, + toggle_hint: 'Select from list', + toggle_field: + { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + optional: true, + toggle_hint: 'Use custom value', + hint: 'Allowed value is Photo' + } + }, + { name: 'value', sticky: true, + hint: 'Value should be a valid URL, e.g. https//:wwww.example.com/test.jpg' } + ] }, + { name: 'schemas', + control_type: 'multiselect', + delimiter: '|', + pick_list: 'schemasType', + optional: false, + hint: 'Select one or more schemas to assign', + toggle_hint: 'Select from schemas', + toggle_field: { + name: 'schemas', + toggle_hint: 'Use custom value', + change_on_blur: true, + label: 'Schemas', + type: 'text', + control_type: 'text', + optional: false, + hint: 'Allowed values are urn:ietf:params:scim:schemas:core:2.0:User, + urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' + } }, + { name: 'extension_enterprise_2_0_User', label: 'Schemas extension enterprise 2.0 User', type: 'object', + properties: [ + { name: 'department' } + ] } + ] + end, + create_user_output_schema: lambda do |_input| + [ + { name: 'schemas', type: 'array', of: 'object', + properties: [ + { name: 'value' } + ] }, + { name: 'id' }, + { name: 'externalId' }, + { name: 'meta', type: 'object', + properties: [ + { name: 'resourceType' }, + { name: 'created', type: 'date_time', control_type: 'date_time', + render_input: 'render_iso8601_timestamp', parse_output: 'date_time_conversion' }, + { name: 'lastModified', type: 'date_time', control_type: 'date_time', + render_input: 'render_iso8601_timestamp', parse_output: 'date_time_conversion' }, + { name: 'location' } + ] }, + { name: 'userName' }, + { name: 'name', type: 'object', + properties: [ + { name: 'formatted' }, + { name: 'familyName' }, + { name: 'givenName' } + ] }, + { name: 'active', type: 'boolean', render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'emails', type: 'array', of: 'object', + properties: [ + { name: 'primary' }, + { name: 'value' }, + { name: 'type' } + ] }, + { name: 'phoneNumbers', type: 'array', of: 'object', + properties: [ + { name: 'value' }, + { name: 'type' } + ] }, + { name: 'photos', type: 'array', of: 'object', + properties: [ + { name: 'value' }, + { name: 'type' } + ] }, + { name: 'addresses', type: 'array', of: 'object', + properties: [ + { name: 'type' }, + { name: 'streetAddress' }, + { name: 'locality' }, + { name: 'region' }, + { name: 'country' }, + { name: 'postalCode' } + ] }, + { name: 'extension_enterprise_2_0_User', type: 'object', + properties: [ + { name: 'department' } + ] } + ] + end, + create_user_execute: lambda do |input| + input['schemas'] = input['schemas']&.split('|') || nil + post('/scim/v2/Users', input.compact.except('object')) + end, + + create_contact_schema: lambda do |_input| + state = get('/restapi/v1.0/dictionary/state?allCountries=true&countryId=1&page=1&perPage=500&withPhoneNumbers=false')['records']. + pluck('name', 'name') || [] + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to ' \ + 'indicate the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'firstName', hint: 'First name of the contact', sticky: true }, + { name: 'lastName', hint: 'Last name of the contact', sticky: true }, + { name: 'middleName', hint: 'Middle name of the contact', sticky: true }, + { name: 'nickName', label: 'Nickname', hint: 'Nick name of the contact', sticky: true }, + { name: 'company', hint: 'Company name of the contact', sticky: true }, + { name: 'jobTitle', hint: 'Job Title of the contact', sticky: true }, + { name: 'email', hint: 'Email of the contact', sticky: true }, + { name: 'email2', label: 'Email 2', hint: 'Second email of the contact', sticky: true }, + { name: 'email3', label: 'Email 3', hint: 'Third email of the contact', sticky: true }, + { name: 'birthday', type: 'date', hint: 'Date of birth of the contact', sticky: true }, + { name: 'webPage', hint: 'The contact home page URL', sticky: true }, + { name: 'notes', hint: 'Notes for the contact' }, + { name: 'homePhone', hint: 'Home phone number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'homePhone2', label: 'Home Phone 2', hint: '2nd home phone number of the contact ' \ + 'in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'businessPhone', hint: 'Business phone of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'businessPhone2', label: 'Business phone 2', + hint: '2nd business phone of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'mobilePhone', hint: 'Mobile phone of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'businessFax', hint: 'Business fax number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'companyPhone', hint: 'Company number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'assistantPhone', hint: 'Phone number of the contact assistant in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'carPhone', hint: 'Car phone number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'otherPhone', hint: 'Other phone number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'otherFax', hint: 'Other fax number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'callbackPhone', hint: 'Callback phone number of the contact in e.164 (with "+") format. e.g. +15551234567' }, + { name: 'homeAddress', type: 'object', + properties: [ + { name: 'street', hint: 'Street address' }, + { name: 'city', hint: 'City name' }, + { name: 'state', sticky: true, control_type: 'select', + hint: 'Please select the province or state.', + pick_list: state, + toggle_hint: 'Select from options', + toggle_field: { + name: 'state', label: 'State name', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the province or state name.' + } }, + { name: 'zip', hint: 'Zip/Postal code' } + ] }, + { name: 'businessAddress', type: 'object', + properties: [ + { name: 'street', hint: 'Street address' }, + { name: 'city', hint: 'City name' }, + { name: 'state', sticky: true, control_type: 'select', + hint: 'Please select the province or state.', + pick_list: state, + toggle_hint: 'Select from options', + toggle_field: { + name: 'state', label: 'State name', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the province or state name.' + } }, + { name: 'zip', hint: 'Zip/Postal code' } + ] }, + { name: 'otherAddress', type: 'object', label: 'Other address', + properties: [ + { name: 'street', hint: 'Street address' }, + { name: 'city', hint: 'City name' }, + { name: 'state', sticky: true, control_type: 'select', + hint: 'Please select the province or state.', + pick_list: state, + toggle_hint: 'Select from options', + toggle_field: { + name: 'state', label: 'State name', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the province or state name.' + } }, + { name: 'zip', hint: 'Zip/Postal code' } + ] } + ] + end, + create_contact_output_schema: lambda do |_input| + [ + { name: 'uri' }, + { name: 'availability' }, + { name: 'id', type: 'integer', render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'firstName' }, + { name: 'lastName' }, + { name: 'middleName' }, + { name: 'nickName' }, + { name: 'company' }, + { name: 'jobTitle' }, + { name: 'email' }, + { name: 'email2', label: 'Email 2' }, + { name: 'email3', label: 'Email 3' }, + { name: 'birthday', type: 'date_time', control_type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'webPage' }, + { name: 'notes' }, + { name: 'homePhone' }, + { name: 'homePhone2' }, + { name: 'businessPhone' }, + { name: 'businessPhone2' }, + { name: 'mobilePhone' }, + { name: 'businessFax' }, + { name: 'companyPhone' }, + { name: 'assistantPhone' }, + { name: 'carPhone' }, + { name: 'otherPhone' }, + { name: 'otherFax' }, + { name: 'callbackPhone' }, + { name: 'homeAddress', type: 'object', + properties: [ + { name: 'street' }, + { name: 'city' }, + { name: 'state' }, + { name: 'zip' } + ] }, + { name: 'businessAddress', type: 'object', + properties: [ + { name: 'street' }, + { name: 'city' }, + { name: 'state' }, + { name: 'zip' } + ] }, + { name: 'otherAddress', type: 'object', + properties: [ + { name: 'street' }, + { name: 'city' }, + { name: 'state' }, + { name: 'zip' } + ] } + ] + end, + create_contact_execute: lambda do |input| + post("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/address-book/contact", input.except('object')) + end, + + create_ringout_call_schema: lambda do |_input| + calling_code = get('/restapi/v1.0/dictionary/country?page=1&perPage=300')['records']. + pluck('name', 'callingCode').group_by { |(_country, code)| code }. + map { |code, match| [match.map { |items| items[0] }.join('/'), code] }. + map do |countries| + if countries.first.include?('Canada') + ['Canada/United States', countries.last] + elsif countries.first.include?('Bonaire') + ['Bonaire/Curacao', countries.last] + elsif countries.first.include?('United Kingdom') + ['United Kingdom', countries.last] + else + [countries.first, countries.last] + end + end || [] + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to ' \ + 'indicate the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate ' \ + 'the extension assigned to the account logged-in within the current session' }, + { name: 'from', type: 'object', optional: false, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g. +14155552671', optional: false }, + { name: 'forwardingNumberId', hint: 'Internal identifier of a forwarding number', sticky: true } + ] }, + { name: 'to', type: 'object', optional: false, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g.+14155552671', optional: false } + ] }, + { name: 'callerId', type: 'object', label: 'Caller ID', sticky: true, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g.+14155552671', sticky: true } + ] }, + { + name: 'playPrompt', + control_type: 'checkbox', + sticky: true, + type: :boolean, + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + hint: 'The audio prompt that the calling party hears when the call is connected', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'playPrompt', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + control_type: 'text', + label: 'Play prompt', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'country', type: 'object', label: 'Country', sticky: true, + properties: [ + { name: 'id', label: 'Country name', sticky: true, control_type: 'select', + pick_list: calling_code, + toggle_hint: 'Select from options', + toggle_field: { + name: 'id', label: 'Country code', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the dialing plan country identifier. ' \ + "Click here to learn more." + } } + ] } + ] + end, + create_ringout_call_output_schema: lambda do |_input| + [ + { name: 'uri', label: 'URI' }, + { name: 'id' }, + { name: 'status', type: 'object', + properties: [ + { name: 'callStatus' }, + { name: 'callerStatus' }, + { name: 'calleeStatus' } + ] } + ] + end, + create_ringout_call_execute: lambda do |input| + post("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/ring-out", input.except('object')) + end, + + create_reply_with_text_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate ' \ + 'the extension assigned to the account logged-in within the current session' }, + { name: 'telephonySessionId', optional: false, hint: 'Internal identifier of a call session' }, + { name: 'partyId', optional: false, hint: 'Internal identifier of a call party ID' }, + { name: 'replyWithText', hint: 'Text to reply', sticky: true }, + { name: 'replyWithPattern', type: 'object', + properties: [ + { + name: 'pattern', + control_type: 'select', + sticky: true, + hint: 'Predefined reply pattern name', + pick_list: [ + %w[Will\ call\ you\ back WillCallYouBack], + %w[Call\ me\ back CallMeBack], + %w[On\ my\ way OnMyWay], + %w[On\ the\ other\ line OnTheOtherLine], + %w[Will\ call\ you\ back\ later WillCallYouBackLater], + %w[Call\ me\ back\ later CallMeBackLater], + %w[In\ a\ meeting InAMeeting], + %w[On\ the\ other\ line\ no\ call OnTheOtherLineNoCall] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'pattern', + control_type: 'text', + type: 'string', + label: 'Pattern', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: WillCallYouBack, CallMeBack, OnMyWay, OnTheOtherLine, + WillCallYouBackLater' + } + }, + { name: 'time', type: 'integer', render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'Number of time units. Applicable only ' \ + 'to Will call you back, Call me back patterns.', sticky: true }, + { + name: 'timeUnit', + control_type: 'select', + sticky: true, + hint: 'Time unit name', + pick_list: [ + %w[Minute Minute], + %w[Hour Hour], + %w[Day Day] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'timeUnit', + control_type: 'text', + type: 'string', + label: 'Time unit', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Minute, Hour, Day' + } + } + ] } + ] + end, + create_reply_with_text_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'status', type: 'object', + properties: [ + { name: 'code' }, + { name: 'peerId', type: 'object', + properties: [ + { name: 'sessionId' }, + { name: 'telephonySessionId' }, + { name: 'partyId' } + ] }, + { name: 'reason' }, + { name: 'description' } + ] }, + { name: 'muted' }, + { name: 'standAlone' }, + { name: 'park', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'from', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'name' }, + { name: 'deviceId' }, + { name: 'extensionId' } + ] }, + { name: 'to', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'name' }, + { name: 'deviceId' }, + { name: 'extensionId' } + ] }, + { name: 'owner', type: 'object', + properties: [ + { name: 'accountId' }, + { name: 'extensionId' } + ] }, + { name: 'direction' } + ] + end, + create_reply_with_text_execute: lambda do |input| + post("/restapi/v1.0/account/#{input.delete('accountId')}/telephony/sessions/" \ + "#{input.delete('telephonySessionId')}/parties/#{input.delete('partyId')}/reply", input.except('object')) + end, + + create_send_sms_schema: lambda do |_input| + country_id = get('/restapi/v1.0/dictionary/country?page=1&perPage=300')['records'].pluck('name', 'id') || [] + [ + { name: 'accountId', label: 'Account ID', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionId', label: 'Extension ID', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'from', type: 'object', label: 'From', optional: false, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g. +14155552671', + sticky: true } + ] }, + { name: 'to', type: 'array', of: 'object', label: 'To', optional: false, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g. +14155552671', + sticky: true } + ] }, + { name: 'text', optional: false, hint: 'Text of a message. Max length is 1000 symbols ' \ + '(2-byte UTF-16 encoded). If a character is encoded in 4 bytes in UTF-16 it is treated ' \ + 'as 2 characters, thus restricting the maximum message length to 500 symbols.' }, + { name: 'country', type: 'object', + properties: [ + { name: 'id', label: 'Country name', sticky: true, control_type: 'select', + hint: 'Please select the country name.', + pick_list: country_id, + toggle_hint: 'Select from options', + toggle_field: { + name: 'id', label: 'Country ID', type: 'string', optional: true, + control_type: 'text', toggle_hint: 'Use custom value', + hint: 'Please enter the internal identifier of a country.
' \ + 'You can use the Search countries action to retrieve the country ID.' + } } + ] } + ] + end, + create_send_sms_output_schema: lambda do |_input| + [ + { name: 'uri' }, + { name: 'id' }, + { name: 'attachments', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'uri' }, + { name: 'contentType' }, + { name: 'type' }, + { name: 'vmDuration', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'fileName' }, + { name: 'size', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'height', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'width', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion } + ] }, + { name: 'availability' }, + { name: 'conversationId', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'conversation', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'deliveryErrorCode' }, + { name: 'direction' }, + { name: 'faxPageCount', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'faxResolution' }, + { name: 'from', type: 'object', + properties: [ + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'name' }, + { name: 'phoneNumber' } + ] }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'messageStatus' }, + { name: 'pgToDepartment', type: 'boolean', render_input: 'boolean_conversion', + parse_output: 'boolean_conversion' }, + { name: 'priority' }, + { name: 'readStatus' }, + { name: 'smsDeliveryTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'smsSendingAttemptsCount', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion }, + { name: 'subject' }, + { name: 'to', type: 'array', of: 'object', + properties: [ + { name: 'target' }, + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'messageStatus' }, + { name: 'faxErrorCode' }, + { name: 'name' }, + { name: 'phoneNumber' } + ] }, + { name: 'type' }, + { name: 'vmTranscriptionStatus' }, + { name: 'coverIndex' }, + { name: 'convercoverPageTextsationId' } + + ] + end, + create_send_sms_execute: lambda do |input| + post("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/sms", input.except('object')) + end, + + create_post_schema: lambda do |_input| + [ + { name: 'chatId', optional: false, hint: 'Internal identifier of a chat' }, + { name: 'text', optional: false }, + { name: 'attachments', type: 'array', of: 'object', + properties: [ + { name: 'id', hint: 'Internal identifier of an attachment', + sticky: true }, + { name: 'type', hint: 'Attachment type', sticky: true } + ] } + ] + end, + create_post_output_schema: lambda do |_input| + [ + { name: 'groupId' }, + { name: 'id' }, + { name: 'addedPersonIds', type: 'array', of: 'object', label: 'Added person IDs', + properties: [ + { name: 'value', label: 'Added person IDs' } + ] }, + { name: 'type' }, + { name: 'text' }, + { name: 'creatorId' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'attachments', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'type' }, + { name: 'fallback' }, + { name: 'intro' }, + { name: 'author', type: 'object', + properties: [ + { name: 'name' }, + { name: 'uri', label: 'URI' }, + { name: 'iconUri', label: 'Icon URI' } + ] }, + { name: 'title' }, + { name: 'text' }, + { name: 'imageUri', label: 'Image URI' }, + { name: 'thumbnailUri', label: 'Thumbnail URI' }, + { name: 'fields', type: 'array', of: 'object', + properties: [ + { name: 'title' }, + { name: 'value' }, + { name: 'style' } + ] }, + { name: 'footnote', type: 'object', + properties: [ + { name: 'text' }, + { name: 'time', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'iconUri', label: 'Icon URI' } + ] }, + { name: 'creatorId' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'endTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'allDay' }, + { name: 'recurrence ' }, + { name: 'endingCondition' }, + { name: 'endingAfter' }, + { name: 'endingOn' }, + { name: 'color' }, + { name: 'location ' }, + { name: 'description' } + ] }, + { name: 'mentions', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'name' }, + { name: 'type' } + ] }, + { name: 'iconEmoji' }, + { name: 'iconUri', label: 'Icon URI' }, + { name: 'title' }, + { name: 'activity' } + ] + end, + create_post_execute: lambda do |input| + post("/restapi/v1.0/glip/chats/#{input.delete('chatId')}/posts", input.except('object')) + end, + + create_conversation_schema: lambda do |_input| + [ + { name: 'members', type: 'array', of: 'object', optional: false, + properties: [ + { name: 'id', hint: 'Internal identifier of a user', sticky: true }, + { name: 'email', hint: 'Email of a user', sticky: true } + ] } + ] + end, + create_conversation_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'members', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'email' } + ] }, + { name: 'type' }, + { name: 'text' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' } + ] + end, + create_conversation_execute: lambda do |input| + post('/restapi/v1.0/glip/conversations', input.except('object')) + end, + + create_note_schema: lambda do |_input| + [ + { name: 'chatId', hint: 'Internal identifier of a chat to create a note', optional: false }, + { name: 'title', hint: 'Title of a note', optional: false }, + { name: 'body', hint: 'Contents of a note', sticky: true } + ] + end, + create_note_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'creator', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'lastModifiedBy', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'lockedBy', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'type' }, + { name: 'status' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'title ' }, + { name: 'preview' }, + { name: 'chatIds', type: 'array', of: 'object', + properties: [ + { name: 'value', label: 'Chat ID' } + ] } + ] + end, + create_note_execute: lambda do |input| + post("/restapi/v1.0/glip/chats/#{input.delete('chatId')}/notes", input.except('object')) + end, + + create_publish_note_schema: lambda do |_input| + [ + { name: 'noteId', hint: 'Internal identifier of a note to be published', optional: false } + ] + end, + create_publish_note_output_schema: lambda do |_input| + [] + end, + create_publish_note_execute: lambda do |input| + post("/restapi/v1.0/glip/notes/#{input.delete('noteId')}/publish", input.except('object')) + end, + + create_join_team_schema: lambda do |_input| + [].concat(call('get_conversation_schema', '')) + end, + create_join_team_output_schema: lambda do |_input| + [] + end, + create_join_team_execute: lambda do |input| + post("/restapi/v1.0/glip/teams/#{input.delete('chatId')}/join", input.except('object')) + end, + + create_leave_team_schema: lambda do |_input| + [].concat(call('get_conversation_schema', '')) + end, + create_leave_team_output_schema: lambda do |_input| + [] + end, + create_leave_team_execute: lambda do |input| + post("/restapi/v1.0/glip/teams/#{input.delete('chatId')}/leave", input.except('object')) + end, + + create_calendar_event_schema: lambda do |_input| + [ + { name: 'id', hint: 'Internal identifier of an event' }, + { name: 'creatorId', hint: 'Internal identifier of a person created an event' }, + { name: 'title', hint: 'Event title', optional: false }, + { name: 'startTime', hint: 'Datetime of starting an event', optional: false, type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', control_type: 'date_time' }, + { name: 'endTime', hint: 'Datetime of starting an event', optional: false, type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', control_type: 'date_time' }, + { + name: 'allDay', + control_type: 'checkbox', + sticky: true, + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + hint: 'Indicates whether event has some specific time slot or lasts for whole day', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'allDay', + control_type: 'text', + type: 'boolean', + label: 'All day', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { + name: 'recurrence', + control_type: 'select', + sticky: true, + hint: 'Event recurrence settings. For non-periodic events, the value is ' \ + 'None. Must be greater or equal to event duration: 1- Day/Weekday; ' \ + '7 - Week; 28 - Month; 365 - Year', + pick_list: [ + %w[None None], + %w[Day Day], + %w[Weekday All], + %w[Week Week], + %w[Month Month], + %w[Year Year] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'recurrence', + type: 'string', + control_type: 'text', + label: 'Recurrence', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: None, Day, Weekday, Week, Month and Year' + } + }, + { name: 'endingOn', hint: 'Iterations end datetime for periodic events. Must be specified if Ending condition is Date.', + type: 'date_time', parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', control_type: 'date_time' }, + { name: 'endingAfter', type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'Count of iterations. ' \ + 'For periodic events only. Value range is 1 - 10. ' \ + 'Must be specified if Ending condition is Count' }, + { name: 'location', hint: 'Event location' }, + { name: 'description', hint: 'Event details' }, + { + name: 'endingCondition', + control_type: 'select', + sticky: true, + hint: 'Condition of ending', + pick_list: [ + %w[None None], + %w[Count Count], + %w[Date Date] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'endingCondition', + type: 'string', + control_type: 'text', + label: 'Ending condition', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: None, Count, Day' + } + }, + { + name: 'color', + control_type: 'select', + sticky: true, + hint: 'Color of Event title (including its presentation in Calendar)', + pick_list: [ + %w[Black Black], + %w[Red Red], + %w[Orange Orange], + %w[Yellow Yellow], + %w[Green Green], + %w[Blue Blue], + %w[Purple Purple], + %w[Magenta Magenta] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'color', + type: 'string', + control_type: 'text', + label: 'Color', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Black, Red, Orange, Yellow, Green, Blue, Purple, Magenta' + } + } + ] + end, + create_calendar_event_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'type' }, + { name: 'creatorId' }, + { name: 'title' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'endTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'endingAfter', type: 'integer' }, + { name: 'endingOn' }, + { name: 'recurrence' }, + { name: 'endingCondition' }, + { name: 'color' }, + { name: 'location' }, + { name: 'description' }, + { name: 'allDay', type: 'boolean' } + ] + end, + create_calendar_event_execute: lambda do |input| + post('/restapi/v1.0/glip/events', input.except('object')) + end, + + create_task_schema: lambda do |_input| + [ + { name: 'chatId', hint: 'Internal identifier of a chat', optional: false }, + { name: 'assignees', label: 'Assignees', type: 'array', of: 'object', optional: false, + properties: [ + { name: 'id', optional: false, hint: 'Assignee ID' } + ] } + ].concat(call('update_task_schema', '').ignored('taskId', 'assignees').required('subject')) + end, + create_task_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'type' }, + { name: 'creator', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'chatIds', type: 'array', label: 'Chat IDs', + properties: [ + { name: 'value', label: 'Chat ID' } + ] }, + { name: 'status' }, + { name: 'subject ' }, + { name: 'assignees', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'status' } + ] }, + { name: 'completenessCondition' }, + { name: 'completenessPercentage' }, + { name: 'endingCondition' }, + { name: 'startDate', type: 'date', control_type: 'date' }, + { name: 'dueDate', type: 'date', control_type: 'date' }, + { name: 'color ' }, + { name: 'section' }, + { name: 'description' }, + { name: 'recurrence', type: 'object', + properties: [ + { name: 'schedule' }, + { name: 'endingCondition' }, + { name: 'endingAfter' }, + { name: 'endingOn' } + ] }, + { name: 'attachments', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'type' }, + { name: 'name' }, + { name: 'contentUri', label: 'Content URI' } + ] } + ] + end, + create_task_execute: lambda do |input| + post("/restapi/v1.0/glip/chats/#{input.delete('chatId')}/tasks", input.except('object')) + end, + + create_callout_schema: lambda do |_input| + [ + { name: 'accountId', label: 'Account ID', hint: 'Internal identifier of ' \ + 'a RingCentral account or tilde (~) to indicate the account logged-in within the current session', + optional: false }, + { name: 'from', type: 'object', optional: false, + properties: [ + { name: 'deviceId', hint: 'Internal identifier of a device', sticky: true } + ] }, + { name: 'to', type: 'object', optional: false, + properties: [ + { name: 'phoneNumber', hint: 'Phone number in E.164 format, e.g. +10000000000', sticky: true }, + { name: 'extensionNumber', hint: 'Extension number, e.g. 101', sticky: true } + ] } + ] + end, + create_callout_output_schema: lambda do |_input| + [ + { name: 'session', type: 'object', + properties: call('get_callout_session_status_output_schema', '') } + ] + end, + create_callout_execute: lambda do |input| + post("/restapi/v1.0/account/#{input.delete('accountId')}/telephony/call-out", input.except('object')) + end, + + create_team_schema: lambda do |_input| + [ + { + name: 'public', + control_type: 'checkbox', + sticky: true, + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + hint: 'Team access level', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'public', + control_type: 'text', + type: 'boolean', + label: 'Public', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'name', optional: false, hint: 'Team name' }, + { name: 'description', sticky: true, hint: 'Team description' }, + { name: 'members', sticky: true, type: 'array', of: 'object', properties: [ + { name: 'id', hint: 'Internal identifier of a user', sticky: true }, + { name: 'email', hint: 'Email address of the user', sticky: true } + ] } + ] + end, + create_team_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'type' }, + { name: 'public', type: 'boolean' }, + { name: 'name' }, + { name: 'description' }, + { name: 'status' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' } + ] + end, + create_team_execute: lambda do |input| + post('/restapi/v1.0/glip/teams', input.except('object')) + end, + + create_team_members_schema: lambda do |_input| + [ + { name: 'chatId', label: 'Chat ID', hint: 'Internal identifier of a team to add members to.', optional: false }, + { name: 'members', sticky: true, type: 'array', of: 'object', properties: [ + { name: 'id', hint: 'Internal identifier of a user', sticky: true }, + { name: 'email', hint: 'Email address of the user', sticky: true } + ] } + ] + end, + create_team_members_output_schema: lambda do |_input| + [ + { name: 'result' } + ] + end, + create_team_members_execute: lambda do |input| + post("/restapi/v1.0/glip/teams/#{input.delete('chatId')}/add", input.except('object')) + end, + + ### SEARCH METHODS ### + search_meetings_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' } + ] + end, + search_meetings_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Meetings', type: 'array', of: 'object', + properties: call('create_meeting_output_schema', '') } + ] + end, + search_meetings_execute: lambda do |input| + get("/restapi/v1.0/account/#{input['accountId']}/extension/" \ + "#{input['extensionId']}/meeting", input.except('object')) + end, + + search_users_schema: lambda do |_input| + [ + { name: 'filter', label: 'Filter', + hint: 'Only userName and email fields are supported for filter expressions
Example: userName eq "partners@workato.com"', + sticky: true }, + { name: 'startIndex', type: 'integer', render_input: 'integer_conversion', + parse_output: 'integer_conversion', hint: 'Start index, default is 1.', + sticky: true }, + { name: 'count', label: 'Page size', type: 'integer', render_input: 'integer_conversion', + parse_output: 'integer_conversion', sticky: true } + ] + end, + search_users_output_schema: lambda do |_input| + [ + { name: 'Resources', label: 'Users', type: 'array', of: 'object', + properties: call('create_user_output_schema', '') } + ] + end, + search_users_execute: lambda do |input| + get('/scim/Users', input.except('object')) + end, + + search_contacts_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'startsWith', sticky: true, + hint: 'If specified, only contacts whose First + name or Last name start with the mentioned substring are returned. Case-insensitive' }, + { + name: 'sortBy', + control_type: 'select', + sticky: true, + hint: 'Sorts results by the specified property', + pick_list: [ + %w[First\ name FirstName], + %w[Last\ name LastName], + %w[Company Company] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'Sortby', + control_type: 'text', + type: 'string', + label: 'Sort by', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: FirstName, LastName, Company' + } + }, + { name: 'page', type: 'integer', render_input: 'integer_conversion', + parse_output: 'integer_conversion', sticky: true, + hint: 'Indicates the page number to retrieve. Only positive number values are accepted' }, + { name: 'perPage', type: 'integer', label: 'Perpage', sticky: true, + render_input: 'integer_conversion', parse_output: 'integer_conversion', hint: 'Indicates the page size' }, + { name: 'phoneNumber', hint: 'Please enter phone numbers to filter separated by commas, without spaces.' } + ] + end, + search_contacts_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Contacts', type: 'array', of: 'object', + properties: call('create_contact_output_schema', '') } + ] + end, + search_contacts_execute: lambda do |input| + input['phoneNumber'] = input['phoneNumber']&.split(',') unless input['phoneNumber'].blank? + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/address-book/contact", input.except('object')) + end, + + search_user_call_log_records_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' }, + { name: 'extensionNumber', hint: 'Extension number of a user. ' \ + 'If specified, returns call log for a particular extension only', sticky: true }, + { + name: 'showBlocked', + control_type: 'checkbox', + type: :boolean, + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + sticky: true, + hint: 'If Yes, then calls from/to blocked numbers are returned', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'showBlocked', + control_type: 'text', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + label: 'Show blocked', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'phoneNumber', label: 'Phone number', hint: 'Phone number of a caller/callee. ' \ + 'If specified, returns all calls (both incoming and outcoming) with the phone number specified', sticky: true }, + { name: 'direction', + control_type: 'multiselect', + delimiter: '|', + pick_list: [ + %w[Inbound Inbound], + %w[Outbound Outbound] + ], + optional: true, + sticky: true, + hint: 'The direction for the resulting records. If not specified, both inbound and ' \ + 'outbound records are returned. Multiple values are accepted.', + toggle_hint: 'Select from list', + toggle_field: { + name: 'direction', + type: 'string', + control_type: 'text', + label: 'Direction', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Inbound, Outbound' + } }, + { name: 'sessionId', hint: 'Internal identifier of a session', sticky: true }, + { name: 'type', + control_type: 'multiselect', + delimiter: '|', + hint: 'Call type of a record. It is allowed to specify more than one type. If not specified, ' \ + 'all call types are returned. Multiple values are accepted.', + pick_list: [ + %w[Voice Voice], + %w[Fax Fax] + ], + optional: true, + sticky: true, + toggle_hint: 'Select from list', + toggle_field: { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Voice, Fax' + } }, + { name: 'transport', + control_type: 'multiselect', + delimiter: '|', + hint: 'Call transport type. PSTN specifies that a call leg is initiated from the PSTN ' \ + 'network provider; VoIP - from an RC phone. By default this filter is disabled.', + pick_list: [ + %w[PSTN PSTN], + %w[VoIP VoIP] + ], + optional: true, + sticky: true, + toggle_hint: 'Select from list', + toggle_field: { + name: 'transport', + type: 'string', + control_type: 'text', + label: 'Transport', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: PSTN, VoIP' + } }, + { + name: 'view', + control_type: 'select', + sticky: true, + optional: true, + hint: 'View of call records. The same view parameter specified for FSync will be applied for + ISync, the view cannot be changed for ISync', + pick_list: [ + %w[Simple Simple], + %w[Detailed Detailed] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'view', + type: 'string', + control_type: 'text', + label: 'View', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Simple, Detailed' + } + }, + { + name: 'recordingType', + control_type: 'select', + sticky: true, + optional: true, + hint: 'Type of a call recording. If not specified, then calls without recordings are also returned.', + pick_list: [ + %w[Automatic Automatic], + %w[On\ demand OnDemand], + %w[All All] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'recordingType', + type: 'string', + control_type: 'text', + label: 'Recording type', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Automatic, OnDemand, All' + } + }, + { name: 'dateTo', type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'The end datetime for resulting records. The default value is current time.' }, + { name: 'dateFrom', type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'The start datetime for resulting records. The default value is Date to minus 24 hours.' }, + { name: 'page', type: 'integer', render_input: 'integer_conversion', sticky: true, + parse_output: 'integer_conversion', hint: 'Indicates the page ' \ + 'number to retrieve. Only positive number values are allowed' }, + { name: 'perPage', type: 'integer', render_input: 'integer_conversion', sticky: true, + parse_output: 'integer_conversion', hint: 'Indicates the page size (number of items)' }, + { + name: 'showDeleted', + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + optional: true, + sticky: true, + hint: 'If Yes, then deleted calls are returned.', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'showDeleted', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + control_type: 'text', + label: 'Show deleted', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + } + ] + end, + search_user_call_log_records_output_schema: lambda do |_input| + [ + { name: 'records', label: 'User call logs', type: 'array', of: 'object', + properties: call('get_user_call_record_output_schema', '') } + ] + end, + search_user_call_log_records_execute: lambda do |input| + if input['direction'] + url = '' + input.delete('direction')&.split('|')&.each do |name| + url = url + "&direction=#{name}" + end + end + + if input['type'] + urltype = '' + input.delete('type')&.split('|')&.each do |name| + urltype = urltype + "&type=#{name}" + end + end + + if input['transport'] + urltransport = '' + input.delete('transport')&.split('|')&.each do |name| + urltransport = urltransport + "&transport=#{name}" + end + end + + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/call-log?#{url}#{urltype}" \ + "#{urltransport}", input.except('object')) + end, + + search_user_active_calls_schema: lambda do |_input| + call('search_user_call_log_records_schema', ''). + only('accountId', 'extensionId', 'direction', 'view', 'type', 'page', 'perPage') + end, + search_user_active_calls_output_schema: lambda do |_input| + [ + { name: 'records', label: 'User active calls', type: 'array', of: 'object', + properties: call('get_user_call_record_output_schema', '') } + ] + end, + search_user_active_calls_execute: lambda do |input| + if input['direction'] + url = '' + input.delete('direction')&.split('|')&.each do |name| + url = url + "&direction=#{name}" + end + end + + if input['type'] + urltype = '' + input.delete('type')&.split('|')&.each do |name| + urltype = urltype + "&type=#{name}" + end + end + + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/active-calls?#{url}#{urltype}", input.except('object')) + end, + + search_company_active_calls_schema: lambda do |_input| + call('search_user_call_log_records_schema', ''). + only('accountId', 'transport', 'direction', 'view', 'type', 'page', 'perPage') + end, + search_company_active_calls_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Company active calls', type: 'array', of: 'object', + properties: call('get_user_call_record_output_schema', '') } + ] + end, + search_company_active_calls_execute: lambda do |input| + if input['direction'] + url = '' + input.delete('direction')&.split('|')&.each do |name| + url = url + "&direction=#{name}" + end + end + + if input['type'] + urltype = '' + input.delete('type')&.split('|')&.each do |name| + urltype = urltype + "&type=#{name}" + end + end + + if input['transport'] + urltransport = '' + input.delete('transport')&.split('|')&.each do |name| + urltransport = urltransport + "&transport=#{name}" + end + end + + get("/restapi/v1.0/account/#{input.delete('accountId')}/active-calls?#{url}#{urltype}#{urltransport}", input.except('object')) + end, + + search_company_call_log_records_schema: lambda do |_input| + call('search_user_call_log_records_schema', ''). + only('accountId', 'extensionNumber', 'phoneNumber', 'direction', 'view', 'type', 'page', 'perPage', + 'withRecording', 'recordingType', 'dateFrom', 'dateTo', 'sessionId') + end, + search_company_call_log_records_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Company call logs', type: 'array', of: 'object', + properties: call('get_user_call_record_output_schema', '') } + ] + end, + search_company_call_log_records_execute: lambda do |input| + if input['direction'] + url = '' + input.delete('direction')&.split('|')&.each do |name| + url = url + "&direction=#{name}" + end + end + + if input['type'] + urltype = '' + input.delete('type')&.split('|')&.each do |name| + urltype = urltype + "&type=#{name}" + end + end + + get("/restapi/v1.0/account/#{input.delete('accountId')}/call-log?#{url}#{urltype}", input.except('object')) + end, + + search_conversations_schema: lambda do |_input| + [ + { name: 'recordCount', type: 'integer', control_type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion', + hint: 'Number of items to be fetched. The maximum value is 250, default is 30.', sticky: true } + ] + end, + search_conversations_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Conversations', type: 'array', of: 'object', + properties: [ + { name: 'id ' }, + { name: 'type' }, + { name: 'members', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'email' } + ] }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' } + ] } + ] + end, + search_conversations_execute: lambda do |input| + get('/restapi/v1.0/glip/conversations', input.except('object')) + end, + + search_teams_schema: lambda do |_input| + call('search_conversations_schema', '') + end, + search_teams_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Teams', type: 'array', of: 'object', + properties: [ + { name: 'id ' }, + { name: 'name' }, + { name: 'type' }, + { name: 'status' }, + { name: 'description' }, + { name: 'public' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' } + ] } + ] + end, + search_teams_execute: lambda do |input| + get('/restapi/v1.0/glip/teams', input.except('object')) + end, + + search_calendar_events_schema: lambda do |_input| + call('search_conversations_schema', '') + end, + search_calendar_events_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Calendar events', type: 'array', of: 'object', + properties: [ + { name: 'id ' }, + { name: 'type' }, + { name: 'creatorId' }, + { name: 'title' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'endTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'recurrence' }, + { name: 'endingCondition' }, + { name: 'endingAfter', type: 'integer', control_type: 'integer', parse_output: 'integer_conversion' }, + { name: 'endingOn' }, + { name: 'color' }, + { name: 'location' }, + { name: 'description' }, + { name: 'allDay', type: 'boolean', parse_output: 'boolean_conversion' } + ] } + ] + end, + search_calendar_events_execute: lambda do |input| + get('/restapi/v1.0/glip/events', input.except('object')) + end, + + search_chats_schema: lambda do |_input| + [ + { name: 'type', + control_type: 'multiselect', + delimiter: '|', + pick_list: [ + %w[Everyone Everyone], + %w[Group Group], + %w[Personal Personal], + %w[Direct Direct], + %w[Team Team] + ], + optional: true, + sticky: true, + toggle_hint: 'Select from list', + toggle_field: { + name: 'type', + type: 'string', + control_type: 'text', + label: 'Type', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Everyone, Group, Personal, Direct, Team' + } }, + { name: 'recordCount', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion', + hint: 'Number of chats to be fetched. The maximum value is 250, default is 30.', sticky: true } + ] + end, + search_chats_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Chats', type: 'array', of: 'object', + properties: [ + { name: 'id ' }, + { name: 'type' }, + { name: 'public' }, + { name: 'name' }, + { name: 'description' }, + { name: 'status' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'members', type: 'array', of: 'object', + properties: [ + { name: 'id' } + ] } + ] } + ] + end, + search_chats_execute: lambda do |input| + if input['type'] + url = '' + input.delete('type')&.split('|')&.each do |name| + url = url + "&type=#{name}" + end + end + + get("/restapi/v1.0/glip/chats?#{url}", input.except('object')) + end, + + search_tasks_schema: lambda do |_input| + [ + { name: 'chatId', hint: 'Internal identifier of a chat', optional: false }, + { name: 'creationTimeTo', type: 'date_time', parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', sticky: true }, + { name: 'creationTimeFrom', type: 'date_time', parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', sticky: true }, + { name: 'creatorId', label: 'Creator IDs', type: 'array', of: 'object', sticky: true, + properties: [ + { name: 'creatorId', sticky: true } + ] }, + { name: 'status', + control_type: 'multiselect', + delimiter: ',', + sticky: true, + hint: 'Task execution status', + pick_list: [ + %w[Pending Pending], + %w[In\ progress InProgress], + %w[Completed Completed] + ], + optional: true, + toggle_hint: 'Select from list', + toggle_field: { + name: 'status', + type: 'string', + control_type: 'text', + label: 'Status', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Pending, InProgress , Completed' + } }, + { + name: 'assignmentStatus', + control_type: 'select', + hint: 'Task assignment status', + sticky: true, + pick_list: [ + %w[Unassigned Unassigned], + %w[Assigned Assigned] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'assignmentStatus', + type: 'string', + control_type: 'text', + label: 'Assignment status', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Unassigned, Assigned' + } + }, + { name: 'assigneeId', label: 'Assignee IDs', type: 'array', of: 'object', sticky: true, + properties: [ + { name: 'assigneeId', sticky: true } + ] }, + { + name: 'assigneeStatus', + control_type: 'select', + hint: 'Task assignment status', + sticky: true, + pick_list: [ + %w[Pending Pending], + %w[Completed Completed] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'assigneeStatus', + type: 'string', + control_type: 'text', + label: 'Assignee status', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Pending, Completed' + } + }, + { name: 'recordCount', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion', + hint: 'Number of records to be returned', sticky: true } + ] + end, + search_tasks_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Tasks', type: 'array', of: 'object', + properties: call('create_task_output_schema', '') } + ] + end, + search_tasks_execute: lambda do |input| + input['creatorId'] = input['creatorId']&.pluck('creatorId')&.join(',') unless input['creatorId'].blank? + input['assigneeId'] = input['assigneeId']&.pluck('assigneeId')&.join(',') unless input['assigneeId'].blank? + input['creationTimeTo'] = input['creationTimeTo']&.to_time&.utc&.strftime('%Y-%m-%dT%H:%M:%S.%LZ') unless input['creationTimeTo'].blank? + input['creationTimeFrom'] = input['creationTimeFrom']&.to_time&.utc&.strftime('%Y-%m-%dT%H:%M:%S.%LZ') unless input['creationTimeFrom'].blank? + + get("restapi/v1.0/glip/chats/#{input.delete('chatId')}/tasks", input.compact.except('object')) + end, + + search_notes_schema: lambda do |_input| + [ + { name: 'chatId', hint: 'Internal identifier of a chat', optional: false }, + { name: 'creationTimeTo', label: 'Creation time to', type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'The end datetime for resulting records. The default value is the current time', sticky: true }, + { name: 'creationTimeFrom', label: 'Creation time from', type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'The start datetime for resulting records.', sticky: true }, + { name: 'creatorId', hint: 'Internal identifier of the user that created the note', sticky: true }, + { name: 'status', + control_type: 'select', + sticky: true, + hint: 'Status of notes to be fetched. If not specified, all notes are fetched by default.', + pick_list: [ + %w[Active Active], + %w[Draft Draft] + ], + optional: true, + toggle_hint: 'Select from list', + toggle_field: { + name: 'status', + type: 'string', + control_type: 'text', + label: 'Status', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Active, Draft' + } }, + { name: 'recordCount', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion', + hint: 'Number of records to be returned', sticky: true } + ] + end, + search_notes_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Notes', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'creator', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'lastModifiedBy', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'type' }, + { name: 'status' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'title ' }, + { name: 'preview' }, + { name: 'chatIds', label: 'Chat IDs', type: 'array', of: 'object', + properties: [ + { name: 'value', label: 'Chat ID' } + ] } + ] } + ] + end, + search_notes_execute: lambda do |input| + input['creationTimeTo'] = input['creationTimeTo']&.to_time&.utc&.strftime('%Y-%m-%dT%H:%M:%S.%LZ') unless input['creationTimeTo'].blank? + input['creationTimeFrom'] = input['creationTimeFrom']&.to_time&.utc&.strftime('%Y-%m-%dT%H:%M:%S.%LZ') unless input['creationTimeFrom'].blank? + + get("restapi/v1.0/glip/chats/#{input.delete('chatId')}/notes", input.except('object')) + end, + + search_posts_schema: lambda do |_input| + [ + { name: 'chatId', hint: 'Internal identifier of a chat', optional: false } + ].concat(call('search_conversations_schema', '')) + end, + search_posts_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Posts', type: 'array', of: 'object', + properties: [ + { name: 'groupId' }, + { name: 'id' }, + { name: 'addedPersonIds', label: 'Added person IDs', type: 'array', of: 'object', + properties: [ + { name: 'value', label: 'Added person ID' } + ] }, + { name: 'type' }, + { name: 'text' }, + { name: 'creatorId' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'attachments', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'type' }, + { name: 'fallback' }, + { name: 'intro' }, + { name: 'author', type: 'object', + properties: [ + { name: 'name' }, + { name: 'uri', label: 'URI' }, + { name: 'iconUri', label: 'Icon URI' } + ] }, + { name: 'title' }, + { name: 'text' }, + { name: 'imageUri', label: 'Image URI' }, + { name: 'thumbnailUri', label: 'Thumbnail URI' }, + { name: 'fields', type: 'array', of: 'object', + properties: [ + { name: 'title' }, + { name: 'value' }, + { name: 'style' } + ] }, + { name: 'footnote', type: 'object', + properties: [ + { name: 'text' }, + { name: 'time' }, + { name: 'iconUri', label: 'Icon URI' } + ] }, + { name: 'creatorId' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'endTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'allDay' }, + { name: 'recurrence' }, + { name: 'endingCondition' }, + { name: 'endingAfter' }, + { name: 'endingOn' }, + { name: 'color' }, + { name: 'location' }, + { name: 'description' } + ] }, + { name: 'mentions', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'name' }, + { name: 'type' } + ] }, + { name: 'iconEmoji' }, + { name: 'iconUri', label: 'Icon URI' }, + { name: 'title' }, + { name: 'activity' } + ] } + ] + end, + search_posts_execute: lambda do |input| + get("restapi/v1.0/glip/chats/#{input.delete('chatId')}/posts", input.except('object')) + end, + + search_account_meeting_recordings_schema: lambda do |_input| + [ + { name: 'meetingId', sticky: true, hint: 'Internal identifier of a meeting. ' \ + 'Either Meeting ID or Meeting start time from and to must be specified.' }, + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned ' \ + 'to the account logged-in within the current session' }, + { name: 'meetingStartTimeFrom', type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'Recordings of meetings started after the time specified will be returned. ' \ + 'Either Meeting ID or Meeting start time from and to must be specified.' }, + { name: 'meetingStartTimeTo', type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp', + hint: 'Recordings of meetings started before the time specified will be returned. ' \ + 'Either Meeting ID or Meeting start time from and to must be specified.' }, + { name: 'page', type: 'integer', sticky: true, render_input: 'integer_conversion', + parse_output: 'integer_conversion', hint: 'Page number' }, + { name: 'perPage', type: 'integer', sticky: true, render_input: 'integer_conversion', + parse_output: 'integer_conversion', hint: 'Number of items per page. Maximum value is 300.' } + ] + end, + search_account_meeting_recordings_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Meeting recordings', type: 'array', of: 'object', + properties: [ + { name: 'meeting', type: 'object', + properties: [ + { name: 'id' }, + { name: 'topic' }, + { name: 'startTime', type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' } + ] }, + { name: 'recording', type: 'array', of: 'object', + properties: [ + { name: 'contentDownloadUri', label: 'Content download URI' }, + { name: 'contentType' }, + { name: 'size' }, + { name: 'status' }, + { name: 'startTime', type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'endTime', type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' } + ] } + ] } + ] + end, + search_account_meeting_recordings_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/meeting-recordings", input.except('object')) + end, + + search_user_meeting_recordings_schema: lambda do |_input| + [ + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned + to the account logged-in within the current session' } + ].concat(call('search_account_meeting_recordings_schema', '')) + end, + search_user_meeting_recordings_output_schema: lambda do |_input| + call('search_account_meeting_recordings_output_schema', '') + end, + search_user_meeting_recordings_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/meeting-recordings", input.except('object')) + end, + + search_states_schema: lambda do |_input| + [ + { name: 'allCountries', hint: 'If set to Yes, then states for all countries are ' \ + 'returned and Country ID is ignored, even if specified. If the value is empty ' \ + 'then the parameter is ignored', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'allCountries', + control_type: 'text', + type: 'boolean', + label: 'All countries', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } }, + { name: 'countryId', sticky: true, hint: 'Internal identifier of a country' }, + { name: 'page', sticky: true, hint: 'Indicates the page number to retrieve. Only positive number values are accepted.' }, + { name: 'perPage', hint: 'Indicates the page size (number of items)', sticky: true }, + { name: 'withPhoneNumbers', hint: 'If Yes, the list of states with phone numbers available for buying is returned.', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'withPhoneNumbers', + control_type: 'text', + type: 'boolean', + label: 'With phone numbers', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } } + ] + end, + search_states_output_schema: lambda do |_input| + [ + { name: 'records', label: 'States', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'country', type: 'object', properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] }, + { name: 'isoCode', label: 'ISO code' }, + { name: 'name' } + ] } + ] + end, + search_states_execute: lambda do |input| + get('/restapi/v1.0/dictionary/state', input.except('object')) + end, + + search_countries_schema: lambda do |_input| + [ + { name: 'loginAllowed', hint: 'Specifies whether login with the phone numbers of this country is enabled or not.', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'loginAllowed', + control_type: 'text', + type: 'boolean', + label: 'Login allowed', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } }, + { name: 'signupAllowed', hint: 'Indicates whether signup/billing is allowed for a country. If not specified all countries are returned.', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'signupAllowed', + control_type: 'text', + type: 'boolean', + label: 'Signup allowed', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } }, + { name: 'numberSelling', hint: 'Specifies if RingCentral sells phone numbers of this country.', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'numberSelling', + control_type: 'text', + type: 'boolean', + label: 'Number selling', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } }, + { name: 'freeSoftphoneLine', hint: 'Specifies if free phone line for softphone is available for a country or not.', + sticky: true, + control_type: 'checkbox', + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'freeSoftphoneLine', + control_type: 'text', + type: 'boolean', + label: 'Free softphone line', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } }, + { name: 'page', sticky: true, hint: 'Indicates the page number to retrieve. Only positive number values are accepted.' }, + { name: 'perPage', hint: 'Indicates the page size (number of items)', sticky: true } + ] + end, + search_countries_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Countries', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'callingCode' }, + { name: 'emergencyCalling', type: 'boolean' }, + { name: 'isoCode', label: 'ISO code' }, + { name: 'name' } + ].concat(call('search_countries_schema', '').ignored('page', 'perPage')) } + ] + end, + search_countries_execute: lambda do |input| + get('/restapi/v1.0/dictionary/country', input.except('object')) + end, + + search_timezones_schema: lambda do |_input| + [ + { name: 'page', sticky: true, hint: 'Indicates the page number to retrieve. Only positive number values are accepted.' }, + { name: 'perPage', hint: 'Indicates the page size (number of items)', sticky: true } + ] + end, + search_timezones_output_schema: lambda do |_input| + [ + { name: 'records', label: 'Timezones', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'description' }, + { name: 'name' }, + { name: 'bias' } + ] } + ] + end, + search_timezones_execute: lambda do |input| + get('/restapi/v1.0/dictionary/timezone', input.except('object')) + end, + + ### GET METHODS ### + get_meeting_schema: lambda do |_input| + [ + { name: 'meetingId', optional: false } + ].concat(call('search_meetings_schema', '')) + end, + get_meeting_output_schema: lambda do |_input| + call('create_meeting_output_schema', '') + end, + get_meeting_execute: lambda do |input| + get("/restapi/v1.0/account/#{input['accountId']}/extension/#{input['extensionId']}/meeting/#{input['meetingId']}") + end, + + get_user_schema: lambda do |_input| + [ + { name: 'id', optional: false, label: 'User ID' } + ] + end, + get_user_output_schema: lambda do |_input| + call('create_user_output_schema', '') + end, + get_user_execute: lambda do |input| + get("/scim/v2/Users/#{input['id']}") + end, + + get_contact_schema: lambda do |_input| + [ + { name: 'contactId', type: 'integer', optional: false, + render_input: 'integer_conversion', parse_output: 'integer_conversion' }, + { name: 'accountId', label: 'Account ID', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to indicate the extension assigned ' \ + 'to the account logged-in within the current session' }, + { name: 'extensionId', label: 'Extension ID', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate the extension assigned ' \ + 'to the account logged-in within the current session' } + ] + end, + get_contact_output_schema: lambda do |_input| + call('create_contact_output_schema', '') + end, + get_contact_execute: lambda do |input| + get("/restapi/v1.0/account/#{input['accountId']}/extension/#{input['extensionId']}/address-book/contact/#{input['contactId']}") + end, + + get_user_call_record_schema: lambda do |_input| + [ + { name: 'callRecordId', optional: false, hint: 'Internal identifier of a call record' } + ].concat(call('search_user_call_log_records_schema', '').only('extensionId', 'accountId', 'view')) + end, + get_user_call_record_output_schema: lambda do |_input| + [ + { name: 'uri', label: 'URI' }, + { name: 'id' }, + { name: 'sessionId' }, + { name: 'telephonySessionId' }, + { name: 'type' }, + { name: 'direction' }, + { name: 'action' }, + { name: 'result' }, + { name: 'to', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'name' }, + { name: 'device', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] } + ] }, + { name: 'from', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'name' }, + { name: 'device', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] } + ] }, + { name: 'extension', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] }, + { name: 'transport' }, + { name: 'legs', type: 'array', of: 'object', + properties: [ + { name: 'action' }, + { name: 'direction' }, + { name: 'billing', type: 'object', + properties: [ + { name: 'costIncluded' }, + { name: 'costPurchased' } + ] }, + { name: 'delegate', type: 'object', + properties: [ + { name: 'id' }, + { name: 'name' } + ] }, + { name: 'extensionId' }, + { name: 'duration', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion' }, + { name: 'extension', type: 'object', + properties: [ + { name: 'id' }, + { name: 'name' } + ] }, + { name: 'legType' }, + { name: 'startTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'type' }, + { name: 'result' }, + { name: 'reason' }, + { name: 'reasonDescription' }, + { name: 'from', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'name' }, + { name: 'device', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] } + ] }, + { name: 'to', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'extensionNumber' }, + { name: 'extensionId' }, + { name: 'location' }, + { name: 'name' }, + { name: 'device', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' } + ] } + ] }, + { name: 'transport' }, + { name: 'recording', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'type' }, + { name: 'contentUri', label: 'Content URI' } + ] }, + { name: 'shortRecording', type: 'boolean', render_input: 'boolean_conversion', parse_output: 'boolean_conversion' }, + { name: 'master', type: 'boolean', render_input: 'boolean_conversion', parse_output: 'boolean_conversion' }, + { name: 'message', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'type' } + ] } + ] }, + { name: 'billing', type: 'object', + properties: [ + { name: 'costIncluded', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion' }, + { name: 'costPurchased', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion' } + ] }, + { name: 'startTime', type: 'date_time', parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'deleted', type: 'boolean', render_input: 'boolean_conversion', parse_output: 'boolean_conversion' }, + { name: 'duration', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'recording', type: 'object', + properties: [ + { name: 'id' }, + { name: 'uri', label: 'URI' }, + { name: 'type' }, + { name: 'contentUri', label: 'Content URI' } + ] }, + { name: 'shortRecording', type: 'boolean', render_input: 'boolean_conversion', parse_output: 'boolean_conversion' }, + { name: 'action' }, + { name: 'result' }, + { name: 'reason' }, + { name: 'reasonDescription' } + ] + end, + get_user_call_record_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/#{input.delete('extensionId')}/call-log/#{input.delete('callRecordId')}", + input.except('object')) + end, + + get_company_call_log_record_schema: lambda do |_input| + [ + { name: 'callRecordId', optional: false, hint: 'Internal identifier of a call record' } + ].concat(call('search_user_call_log_records_schema', '').only('accountId', 'view')) + end, + get_company_call_log_record_output_schema: lambda do |_input| + call('get_user_call_record_output_schema', '') + end, + get_company_call_log_record_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/call-log/#{input.delete('callRecordId')}", input.except('object')) + end, + + get_call_recording_schema: lambda do |_input| + [ + { name: 'recordingId', optional: false } + ].concat(call('search_user_call_log_records_schema', '').only('accountId')) + end, + get_call_recording_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'contentUri', label: 'Content URI' }, + { name: 'contentType' }, + { name: 'duration', type: 'integer', render_input: 'integer_conversion', parse_output: 'integer_conversion' } + ] + end, + get_call_recording_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/recording/#{input.delete('recordingId')}") + end, + + get_call_recordings_data_schema: lambda do |_input| + [ + { name: 'recordingId', optional: false } + ].concat(call('search_user_call_log_records_schema', '').only('accountId')) + end, + get_call_recordings_data_output_schema: lambda do |_input| + [ + { name: 'file_contents' } + ] + end, + get_call_recordings_data_execute: lambda do |input| + response = get("/restapi/v1.0/account/#{input['accountId']}/recording/#{input['recordingId']}/content"). + response_format_raw + { file_contents: response } + end, + + get_post_schema: lambda do |_input| + call('update_post_schema', '').only('chatId', 'postId') + end, + get_post_output_schema: lambda do |_input| + call('update_post_output_schema', '') + end, + get_post_execute: lambda do |input| + get("/restapi/v1.0/glip/chats/#{input.delete('chatId')}/posts/#{input.delete('postId')}") + end, + + get_conversation_schema: lambda do |_input| + [ + { name: 'chatId', optional: false, hint: 'Internal identifier of a conversation.' } + ] + end, + get_conversation_output_schema: lambda do |_input| + call('create_conversation_output_schema', '') + end, + get_conversation_execute: lambda do |input| + get("/restapi/v1.0/glip/conversations/#{input.delete('chatId')}") + end, + + get_note_schema: lambda do |_input| + [ + { name: 'noteId', optional: false, hint: 'Internal identifier of a conversation' } + ] + end, + get_note_output_schema: lambda do |_input| + [ + { name: 'body' } + ].concat(call('create_note_output_schema', '')) + end, + get_note_execute: lambda do |input| + get("/restapi/v1.0/glip/notes/#{input.delete('noteId')}") + end, + + get_chat_schema: lambda do |_input| + [ + { name: 'chatId', optional: false, hint: 'Internal identifier of a chat' } + ] + end, + get_chat_output_schema: lambda do |_input| + [ + { name: 'members', type: 'array', of: 'object', + properties: [ + { name: 'id' } + ] } + ].concat(call('create_team_output_schema', '')) + end, + get_chat_execute: lambda do |input| + get("/restapi/v1.0/glip/chats/#{input.delete('chatId')}") + end, + + get_task_schema: lambda do |_input| + [ + { name: 'taskId', optional: false, hint: 'Internal identifier of a task' } + ] + end, + get_task_output_schema: lambda do |_input| + call('create_task_output_schema', '') + end, + get_task_execute: lambda do |input| + get("/restapi/v1.0/glip/tasks/#{input.delete('taskId')}") + end, + + get_ringout_call_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to ' \ + 'indicate the account logged-in within the current session' }, + { name: 'extensionId', optional: false, + hint: 'Internal identifier of an extension or tilde (~) to indicate ' \ + 'the extension assigned to the account logged-in within the current session' }, + { name: 'ringoutId', optional: false, hint: 'Internal identifier of a RingOut call' } + ] + end, + get_ringout_call_output_schema: lambda do |_input| + call('create_ringout_call_output_schema', '') + end, + get_ringout_call_execute: lambda do |input| + get("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/ring-out/#{input.delete('ringoutId')}") + end, + + get_team_schema: lambda do |_input| + [ + { name: 'chatId', optional: false, hint: 'Internal identifier of a team to be returned' } + ] + end, + get_team_output_schema: lambda do |_input| + call('create_team_output_schema', '') + end, + get_team_execute: lambda do |input| + get("/restapi/v1.0/glip/teams/#{input['chatId']}") + end, + + get_calendar_event_schema: lambda do |_input| + [ + { name: 'eventId', optional: false, hint: 'Internal identifier of an event' } + ] + end, + get_calendar_event_output_schema: lambda do |_input| + call('create_calendar_event_output_schema', '') + end, + get_calendar_event_execute: lambda do |input| + get("/restapi/v1.0/glip/events/#{input['eventId']}") + end, + + get_callout_session_status_schema: lambda do |_input| + [ + { name: 'accountId', optional: false, + hint: 'Internal identifier of a RingCentral account or tilde (~) to ' \ + 'indicate the account logged-in within the current session' }, + { name: 'telephonySessionId', optional: false, hint: 'Internal identifier of a call session' } + ] + end, + get_callout_session_status_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'origin', type: 'object', + properties: [ + { name: 'type' } + ] }, + { name: 'voiceCallToken' }, + { name: 'parties', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'status', type: 'object', + properties: [ + { name: 'code' }, + { name: 'peerId', type: 'object', + properties: [ + { name: 'sessionId' }, + { name: 'telephonySessionId ' }, + { name: 'partyId' } + ] }, + { name: 'reason' }, + { name: 'description' } + ] }, + { name: 'muted' }, + { name: 'standAlone' }, + { name: 'park', type: 'object', + properties: [ + { name: 'id' } + ] }, + { name: 'from', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'name' }, + { name: 'deviceId' }, + { name: 'extensionId' } + ] }, + { name: 'to', type: 'object', + properties: [ + { name: 'phoneNumber' }, + { name: 'name' }, + { name: 'deviceId' }, + { name: 'extensionId' } + ] }, + { name: 'owner', type: 'object', + properties: [ + { name: 'accountId' }, + { name: 'extensionId' } + ] }, + { name: 'direction' }, + { name: 'conferenceRole' }, + { name: 'ringOutRole' }, + { name: 'ringMeRole' }, + { name: 'recordings', type: 'array', of: 'object', + properties: [ + { name: 'id' }, + { name: 'active' } + ] } + ] }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' } + ] + end, + get_callout_session_status_execute: lambda do |input| + get("/restapi/v1.0/account/#{input['accountId']}/telephony/sessions/#{input['telephonySessionId']}") + end, + + ### UPDATE METHODS ### + update_meeting_schema: lambda do |_input| + [ + { name: 'meetingId', label: 'Meeting ID', optional: false, hint: 'Internal identifier of a RingCentral meeting' } + ].concat(call('create_meeting_schema', '')) + end, + update_meeting_output_schema: lambda do |_input| + call('create_meeting_output_schema', '') + end, + update_meeting_execute: lambda do |input| + input['audioOptions'] = input['audioOptions']&.pluck('audioOptions') || nil + input['recurrence']['weeklyByDays'] = input['recurrence']['weeklyByDays']&.split(',') || nil + put("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/meeting/" \ + "#{input.delete('meetingId')}", input.compact.except('object')) + end, + + update_user_schema: lambda do |_input| + [ + { name: 'userID', optional: false, hint: 'User ID to update' }, + { name: 'id', hint: 'Unique resource ID defined by RingCentral' } + ].concat(call('create_user_schema', '')) + end, + update_user_output_schema: lambda do |_input| + call('create_user_output_schema', '') + end, + update_user_execute: lambda do |input| + input['schemas'] = input['schemas']&.split('|') || nil + put("/scim/v2/Users/#{input.delete('userID')}", input.except('object')) + end, + + update_contact_schema: lambda do |_input| + [ + { name: 'contactId', type: 'integer', optional: false, control_type: 'integer', + hint: 'Internal identifier of a contact record in the RingCentral to update' } + ].concat(call('create_contact_schema', '')) + end, + update_contact_output_schema: lambda do |_input| + call('create_contact_output_schema', '') + end, + update_contact_execute: lambda do |input| + put("/restapi/v1.0/account/#{input.delete('accountId')}/extension/" \ + "#{input.delete('extensionId')}/address-book/contact/" \ + "#{input.delete('contactId')}", input.except('object')) + end, + + update_post_schema: lambda do |_input| + [ + { name: 'chatId', label: 'Chat ID', + optional: false, hint: 'Internal identifier of a chat' }, + { name: 'postId', label: 'Post ID', optional: false, + hint: 'Internal identifier of a post to be updated' }, + { name: 'text', hint: 'Post text', sticky: true } + ] + end, + update_post_output_schema: lambda do |_input| + call('create_post_output_schema', '') + end, + update_post_execute: lambda do |input| + patch("/restapi/v1.0/glip/chats/#{input.delete('chatId')}/posts/#{input.delete('postId')}", input.except('object')) + end, + + update_everyone_chat_schema: lambda do |_input| + [ + { name: 'name', hint: 'Everyone chat name. Maximum number of characters supported is 250', sticky: true }, + { name: 'description', hint: 'Everyone chat description. Maximum number of characters supported is 1000', sticky: true } + ] + end, + update_everyone_chat_output_schema: lambda do |_input| + [ + { name: 'id' }, + { name: 'creationTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'lastModifiedTime', type: 'date_time', control_type: 'date_time', parse_output: 'date_time_conversion' }, + { name: 'type' }, + { name: 'name' }, + { name: 'description' } + ] + end, + update_everyone_chat_execute: lambda do |input| + patch('/restapi/v1.0/glip/everyone', input.except('object')) + end, + + update_calendar_event_schema: lambda do |_input| + [ + { name: 'eventId', optional: false, hint: 'Internal identifier of an event to update' } + ].concat(call('create_calendar_event_schema', '')) + end, + update_calendar_event_output_schema: lambda do |_input| + call('create_calendar_event_output_schema', '') + end, + update_calendar_event_execute: lambda do |input| + put("/restapi/v1.0/glip/events/#{input.delete('eventId')}", input.except('object')) + end, + + update_task_schema: lambda do |_input| + [ + { name: 'taskId', label: 'Task ID', optional: false, + hint: 'Internal identifier of a task to update' }, + { name: 'subject', label: 'Subject', hint: 'Task name/subject', sticky: true }, + { name: 'assignees', label: 'Assignees', type: 'array', of: 'object', sticky: true, + properties: [ + { name: 'id', hint: 'Assignee ID' } + ] }, + { + name: 'completenessCondition', + control_type: 'select', + sticky: true, + pick_list: [ + %w[Simple Simple], + %w[AllAssignees AllAssignees], + %w[Percentage Percentage] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'completenessCondition', + control_type: 'text', + type: 'string', + label: 'Completeness condition', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Simple, AllAssignees, Percentage' + } + }, + { name: 'startTime', hint: 'Task start date in UTC time zone.', + type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { name: 'dueDate', hint: 'Task due date/time in UTC time zone', + type: 'date_time', sticky: true, + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' }, + { + name: 'color', + control_type: 'select', + sticky: true, + hint: 'Color of Event title (including its presentation in Calendar)', + pick_list: [ + %w[Black Black], + %w[Red Red], + %w[Orange Orange], + %w[Yellow Yellow], + %w[Green Green], + %w[Blue Blue], + %w[Purple Purple], + %w[Magenta Magenta] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'color', + type: 'string', + control_type: 'text', + label: 'Color', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: Black, Red, Orange, Yellow, Green, Blue, Purple, Magenta' + } + }, + { name: 'section', hint: 'Task section to group', sticky: true }, + { name: 'description', hint: 'Task details', sticky: true }, + { name: 'recurrence', type: 'object', sticky: true, + properties: [ + { + name: 'schedule', + control_type: 'select', + sticky: true, + hint: 'Task recurrence settings. For non-periodic tasks the value is None', + pick_list: [ + %w[None None], + %w[Day Day], + %w[Weekday All], + %w[Week Week], + %w[Month Month], + %w[Year Year] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'schedule', + type: 'string', + control_type: 'text', + label: 'Schedule', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: None, Day, Weekday, Week, Month, Year' + } + }, + { + name: 'endingCondition', + control_type: 'select', + sticky: true, + hint: 'Task ending condition', + pick_list: [ + %w[None None], + %w[Count Count], + %w[Day Day] + ], + toggle_hint: 'Select from list', + toggle_field: + { + name: 'endingCondition', + type: 'string', + control_type: 'text', + label: 'EndingCondition', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: None, Count, Day' + } + }, + { name: 'endingAfter', sticky: true, type: 'integer', + render_input: :integer_conversion, + parse_output: :integer_conversion, hint: 'Count of iterations of periodic tasks' }, + { name: 'endingOn', sticky: true, hint: 'End date of periodic task', + type: 'date_time', + parse_output: 'date_time_conversion', render_input: 'render_iso8601_timestamp' } + ] }, + { name: 'attachments', label: 'Attachments', type: 'array', of: 'object', sticky: true, + properties: [ + { name: 'id', hint: 'Internal identifier of a file' } + ] } + ] + end, + update_task_output_schema: lambda do |_input| + call('create_task_output_schema', '') + end, + update_task_execute: lambda do |input| + patch("/restapi/v1.0/glip/tasks/#{input.delete('taskId')}", input.except('object')) + end, + + update_team_schema: lambda do |_input| + [ + { + name: 'public', + control_type: 'checkbox', + sticky: true, + type: 'boolean', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + hint: 'Team access level', + toggle_hint: 'Select from list', + toggle_field: + { + name: 'public', + control_type: 'text', + type: 'boolean', + label: 'Public', + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + toggle_hint: 'Use custom value', + optional: true, + hint: 'Allowed values are: true, false' + } + }, + { name: 'name', sticky: true, hint: 'Team name' }, + { name: 'description', sticky: true, hint: 'Team description' }, + { name: 'chatId', optional: false, label: 'Chat ID', hint: 'Internal identifier of a team to be updated' } + ] + end, + update_team_output_schema: lambda do |_input| + call('create_team_output_schema', '') + end, + update_team_execute: lambda do |input| + patch("/restapi/v1.0/glip/teams/#{input.delete('chatId')}", input.except('object')) + end, + + update_note_schema: lambda do |_input| + [ + { name: 'noteId', optional: false, hint: 'Internal identifier of a note' }, + { name: 'title', optional: false, hint: 'Title of a note' }, + { name: 'body', hint: 'Contents of a note', control_type: 'text-area', sticky: true } + ] + end, + update_note_output_schema: lambda do |_input| + call('get_note_output_schema', '') + end, + update_note_execute: lambda do |input| + patch("/restapi/v1.0/glip/notes/#{input.delete('noteId')}", input.except('object')) + end, + + ### DELETE METHODS ### + delete_meeting_schema: lambda do |_input| + call('get_meeting_schema', '') + end, + delete_meeting_execute: lambda do |input| + delete("/restapi/v1.0/account/#{input['accountId']}/extension/#{input['extensionId']}/" \ + "meeting/#{input['meetingId']}") + end, + + delete_user_schema: lambda do |_input| + call('get_user_schema', '') + end, + delete_user_execute: lambda do |input| + delete("/scim/v2/Users/#{input['id']}") + end, + + delete_contact_schema: lambda do |_input| + call('get_contact_schema', '') + end, + delete_contact_execute: lambda do |input| + delete("/restapi/v1.0/account/#{input['accountId']}/extension/" \ + "#{input['extensionId']}/address-book/contact/#{input['contactId']}") + end, + + delete_calendar_event_schema: lambda do |_input| + call('get_calendar_event_schema', '') + end, + delete_calendar_event_execute: lambda do |input| + delete("/restapi/v1.0/glip/events/#{input['eventId']}") + end, + + delete_task_schema: lambda do |_input| + call('get_task_schema', '') + end, + delete_task_execute: lambda do |input| + delete("/restapi/v1.0/glip/tasks/#{input['taskId']}") + end, + + delete_note_schema: lambda do |_input| + call('get_note_schema', '') + end, + delete_note_execute: lambda do |input| + delete("/restapi/v1.0/glip/notes/#{input['noteId']}") + end, + + delete_post_schema: lambda do |_input| + call('update_post_schema', '').only('chatId', 'postId') + end, + delete_post_execute: lambda do |input| + delete("/restapi/v1.0/glip/chats/#{input['chatId']}/posts/#{input['postId']}") + end, + + delete_team_members_schema: lambda do |_input| + [ + { name: 'members', optional: false, type: 'array', of: 'object', + properties: [ + { name: 'id', optional: false } + ] }, + { name: 'chatId', optional: false, hint: 'Internal identifier of a chat' } + ] + end, + delete_team_members_execute: lambda do |input| + post("/restapi/v1.0/glip/teams/#{input.delete('chatId')}/remove", input.except('object')) + end + + }, + + object_definitions: { + custom_action_input: { + fields: lambda do |_connection, config_fields| + verb = config_fields['verb'] + input_schema = parse_json(config_fields.dig('input', 'schema') || '[]') + data_props = + input_schema.map do |field| + if config_fields['request_type'] == 'multipart' && + field['binary_content'] == 'true' + field['type'] = 'object' + field['properties'] = [ + { name: 'file_content', optional: false }, + { + name: 'content_type', + default: 'text/plain', + sticky: true + }, + { name: 'original_filename', sticky: true } + ] + end + field + end + data_props = call('make_schema_builder_fields_sticky', data_props) + input_data = + if input_schema.present? + if input_schema.dig(0, 'type') == 'array' && + input_schema.dig(0, 'details', 'fake_array') + { + name: 'data', + type: 'array', + of: 'object', + properties: data_props.dig(0, 'properties') + } + else + { name: 'data', type: 'object', properties: data_props } + end + end + + [ + { + name: 'path', + hint: 'Base URI is ' \ + 'https://platform.ringcentral.com' \ + ' - path will be appended to this URI. Use absolute URI to ' \ + 'override this base URI.', + optional: false + }, + if %w[post put patch].include?(verb) + { + name: 'request_type', + default: 'json', + sticky: true, + extends_schema: true, + control_type: 'select', + pick_list: [ + ['JSON request body', 'json'], + ['URL encoded form', 'url_encoded_form'], + ['Mutipart form', 'multipart'], + ['Raw request body', 'raw'] + ] + } + end, + { + name: 'response_type', + default: 'json', + sticky: false, + extends_schema: true, + control_type: 'select', + pick_list: [['JSON response', 'json'], ['Raw response', 'raw']] + }, + if %w[get options delete].include?(verb) + { + name: 'input', + label: 'Request URL parameters', + sticky: true, + add_field_label: 'Add URL parameter', + control_type: 'form-schema-builder', + type: 'object', + properties: [ + { + name: 'schema', + sticky: input_schema.blank?, + extends_schema: true + }, + input_data + ].compact + } + else + { + name: 'input', + label: 'Request body parameters', + sticky: true, + type: 'object', + properties: + if config_fields['request_type'] == 'raw' + [{ + name: 'data', + sticky: true, + control_type: 'text-area', + type: 'string' + }] + else + [ + { + name: 'schema', + sticky: input_schema.blank?, + extends_schema: true, + schema_neutral: true, + control_type: 'schema-designer', + sample_data_type: 'json_input', + custom_properties: + if config_fields['request_type'] == 'multipart' + [{ + name: 'binary_content', + label: 'File attachment', + default: false, + optional: true, + sticky: true, + render_input: 'boolean_conversion', + parse_output: 'boolean_conversion', + control_type: 'checkbox', + type: 'boolean' + }] + end + }, + input_data + ].compact + end + } + end, + { + name: 'request_headers', + sticky: false, + extends_schema: true, + control_type: 'key_value', + empty_list_title: 'Does this HTTP request require headers?', + empty_list_text: 'Refer to the API documentation and add ' \ + 'required headers to this HTTP request', + item_label: 'Header', + type: 'array', + of: 'object', + properties: [{ name: 'key' }, { name: 'value' }] + }, + unless config_fields['response_type'] == 'raw' + { + name: 'output', + label: 'Response body', + sticky: true, + extends_schema: true, + schema_neutral: true, + control_type: 'schema-designer', + sample_data_type: 'json_input' + } + end, + { + name: 'response_headers', + sticky: false, + extends_schema: true, + schema_neutral: true, + control_type: 'schema-designer', + sample_data_type: 'json_input' + } + ].compact + end + }, + custom_action_output: { + fields: lambda do |_connection, config_fields| + response_body = { name: 'body' } + + [ + if config_fields['response_type'] == 'raw' + response_body + elsif (output = config_fields['output']) + output_schema = call('format_schema', parse_json(output)) + if output_schema.dig(0, 'type') == 'array' && + output_schema.dig(0, 'details', 'fake_array') + response_body[:type] = 'array' + response_body[:properties] = output_schema.dig(0, 'properties') + else + response_body[:type] = 'object' + response_body[:properties] = output_schema + end + + response_body + end, + if (headers = config_fields['response_headers']) + header_props = parse_json(headers)&.map do |field| + if field[:name].present? + field[:name] = field[:name].gsub(/\W/, '_').downcase + elsif field['name'].present? + field['name'] = field['name'].gsub(/\W/, '_').downcase + end + field + end + + { name: 'headers', type: 'object', properties: header_props } + end + ].compact + end + }, + + create_object_input: { + fields: lambda do |_connection, config_fields| + call("create_#{config_fields['object']}_schema", config_fields) || [] + end + }, + create_object_output: { + fields: lambda do |_connection, config_fields| + call("create_#{config_fields['object']}_output_schema", config_fields) || [] + end + }, + + search_object_input: { + fields: lambda do |_connection, config_fields| + call("search_#{config_fields['object']}_schema", config_fields) || [] + end + }, + search_object_output: { + fields: lambda do |_connection, config_fields| + call("search_#{config_fields['object']}_output_schema", config_fields) || [] + end + }, + + get_object_input: { + fields: lambda do |_connection, config_fields| + call("get_#{config_fields['object']}_schema", config_fields) || [] + end + }, + get_object_output: { + fields: lambda do |_connection, config_fields| + call("get_#{config_fields['object']}_output_schema", config_fields) || [] + end + }, + + update_object_input: { + fields: lambda do |_connection, config_fields| + call("update_#{config_fields['object']}_schema", config_fields) || [] + end + }, + update_object_output: { + fields: lambda do |_connection, config_fields| + call("update_#{config_fields['object']}_output_schema", config_fields) || [] + end + }, + + delete_object_input: { + fields: lambda do |_connection, config_fields| + call("delete_#{config_fields['object']}_schema", config_fields) || [] + end + }, + publish_note_input: { + fields: lambda do |_connection, _config_fields| + [{ name: 'noteId', hint: 'Internal identifier of a note to be published', optional: false }] + end + }, + join_team_input: { + fields: lambda do |_connection, _config_fields| + [{ name: 'chatId', hint: 'Internal identifier of a team', optional: false }] + end + }, + + send_sms_object_input: { + fields: lambda do |_connection| + call('create_send_sms_schema', '') + end + }, + send_sms_object_output: { + fields: lambda do |_connection| + call('create_send_sms_output_schema', '') + end + }, + + make_ringout_call_object_input: { + fields: lambda do |_connection| + call('create_ringout_call_schema', '') + end + }, + make_ringout_call_object_output: { + fields: lambda do |_connection| + call('create_ringout_call_output_schema', '') + end + }, + + cancel_ringout_call_object_input: { + fields: lambda do |_connection| + call('get_ringout_call_schema', '') + end + }, + + callout_object_input: { + fields: lambda do |_connection| + call('create_callout_schema', '') + end + }, + callout_object_output: { + fields: lambda do |_connection| + call('create_callout_output_schema', '') + end + }, + + reply_with_text_object_input: { + fields: lambda do |_connection| + call('create_reply_with_text_schema', '') + end + }, + reply_with_text_object_output: { + fields: lambda do |_connection| + call('create_reply_with_text_output_schema', '') + end + } + }, + + actions: { + create_object: { + title: 'Create object', + subtitle: 'Create an object in RingCentral Video', + description: lambda do |_connection, create_object_list| + "Create #{create_object_list[:object]&.downcase || 'an object'}" \ + " in RingCentral Video" + end, + help: lambda do |_input, pick_lists| + help = { + 'Meeting' => 'Creates a new meeting.', + 'User' => 'Creates a new user.', + 'Contact' => 'Creates a personal user contact.', + 'Post' => 'Creates a post within the specified chat.', + 'Conversation' => 'Creates a new conversation or opens the existing one. ' \ + 'If the conversation already exists, then its ID will be returned in response. ' \ + 'A conversation is an adhoc discussion between a particular set of users, not featuring ' \ + 'any specific name or description. If you add a person to the existing conversation, ' \ + 'it creates a whole new conversation.', + 'Note' => 'Creates a new note in the specified chat.', + 'Team' => 'Creates a team, and adds a list of people to the team.', + 'Team members' => 'Adds members to the specified team.', + 'Calendar event' => 'Creates a new calendar event.', + 'Task' => 'Creates a task in the specified chat.' + }[pick_lists['object']] || 'Create an object' + + { body: help.present? ? help : '' } + end, + config_fields: [ + { + name: 'object', + sticky: true, + optional: false, + type: 'string', + extends_schema: true, + control_type: 'select', + pick_list: 'create_object_list', + toggle_hint: 'Select object type to create', + hint: 'Please select an item from the list.' + } + ], + input_fields: lambda do |object_definition| + object_definition['create_object_input'] + end, + execute: lambda do |_connection, input| + input = call('custom_input_parser', input) + object_name = input['object'] + response = if object_name == 'team_members' + call("create_#{object_name}_execute", input). + after_response do |code, body, _headers| + if code == 204 + { 'result' => 'Successfully added.' } + else + error(body) + end + end + else + call("create_#{object_name}_execute", input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end + call('custom_output_parser', response) + end, + output_fields: lambda do |object_definition| + object_definition['create_object_output'] + end, + sample_output: lambda do |_connection, input| + call('get_sample_output', input) + end + }, + search_object: { + title: 'Search object', + subtitle: 'Search an object in RingCentral Video', + description: lambda do |_connection, search_object_list| + "Search for #{search_object_list[:object]&.downcase || 'an object'}" \ + " in RingCentral Video" + end, + help: lambda do |_input, pick_lists| + help = { + 'Meetings' => 'Returns a list of meetings for a particular extension. ' \ + 'The list of meetings does not include meetings of Instant type.', + 'Users' => 'Returns a list of users. Filters are supported.', + 'Contacts' => 'Returns user personal contacts.', + 'Company call log records' => 'Returns call log records filtered by parameters specified.', + 'User call log records' => 'Returns call log records filtered by parameters specified.', + 'User active calls' => 'Returns records of all extension calls that are in progress, ' \ + 'ordered by start time in descending order.', + 'Company active calls' => 'Returns records of all calls that are in progress, ' \ + 'ordered by start time in descending order.', + 'Posts' => 'Returns a list of posts from the specified chat.', + 'Conversations' => 'Returns the list of conversations where the user is a member. ' \ + 'All records in response are sorted by creation time of a chat in ascending order.', + 'Notes' => 'Returns the list of notes created in the specified chat.', + 'Teams' => 'Returns the list of teams where the user is a member (both archived and active) ' \ + 'combined with a list of public teams that can be joined by the current user. ' \ + 'All records in response are sorted by creation time of a chat in ascending order.', + 'Calendar events' => 'Returns all calendar events created by the current user.', + 'Tasks' => 'Returns the list of tasks of the specified chat.', + 'Chats' => 'Returns the list of chats where the user is a member and also public teams that can be joined. ' \ + 'All records in response are sorted by creation time of a chat in ascending order.', + 'Company meeting recordings' => 'Returns the list of meeting recordings for the current account.', + 'User meeting recordings' => 'Returns the list of meetings recordings for the current user.' + }[pick_lists['object']] || '' + + { body: help.present? ? help : 'Search an object' } + end, + config_fields: [ + { + name: 'object', + sticky: true, + type: 'string', + optional: false, + extends_schema: true, + control_type: 'select', + pick_list: 'search_object_list', + toggle_hint: 'Select object type to search', + hint: 'Please select an object from the list' + } + ], + input_fields: lambda do |object_definition| + object_definition['search_object_input'] + end, + execute: lambda do |_connection, input| + object_name = input['object'] + response = call("search_#{object_name}_execute", input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + call('custom_output_parser', response) + end, + output_fields: lambda do |object_definition| + object_definition['search_object_output'] + end, + sample_output: lambda do |_connection, input| + call('search_sample_output', input) + end + }, + get_object: { + title: 'Get object', + subtitle: 'Get an object in RingCentral Video', + description: lambda do |_connection, get_object_list| + "Get #{get_object_list[:object]&.downcase || 'an object'}" \ + " in RingCentral Video" + end, + help: lambda do |_input, pick_lists| + help = { + 'Meeting' => 'Returns a particular meetings details by ID.', + 'User' => 'Retrieve details of a specific user.', + 'Contact' => 'Retrieve contact details by ID.', + 'Company call log record' => 'Returns individual call log record by ID.', + 'Call recordings data' => 'Returns media content of a call recording.', + 'Call recording' => 'Returns call recordings by ID.', + 'User call record' => 'Returns call log records by ID.', + 'Ringout call' => 'Returns the status of a 2-leg RingOut call.', + 'Post' => 'Returns information about the specified post.', + 'Conversation' => 'Returns information about the specified conversation, ' \ + 'including the list of conversation participants. A conversation is an adhoc discussion ' \ + 'between a particular set of users, not featuring any specific name or description. ' \ + 'If you add a person to the existing conversation, it creates a whole new conversation.', + 'Note' => 'Returns the details of the specified note.', + 'Team' => 'Returns information about the specified team.', + 'Calendar event' => 'Returns the specified calendar event by ID.', + 'Chat' => 'Returns information about a chat by ID.', + 'Task' => 'Returns information about the specified task by ID.', + 'Callout session status' => 'Returns the status of a call session by ID.' + }[pick_lists['object']] || '' + + { body: help.present? ? help : 'Retrieve an object' } + end, + config_fields: [ + { + name: 'object', + sticky: true, + type: 'string', + optional: false, + extends_schema: true, + control_type: 'select', + pick_list: 'get_object_list', + toggle_hint: 'Select object type to get', + hint: 'Please select an object from the list' + } + ], + input_fields: lambda do |object_definition| + object_definition['get_object_input'] + end, + execute: lambda do |_connection, input| + object_name = input['object'] + if object_name == 'call_recordings_data' + call("get_#{object_name}_execute", input) + else + response = call("get_#{object_name}_execute", input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + call('custom_output_parser', response) + end + end, + output_fields: lambda do |object_definition| + object_definition['get_object_output'] + end, + sample_output: lambda do |_connection, input| + call('get_sample_output', input) + end + }, + update_object: { + title: 'Update object', + subtitle: 'Update an object in RingCentral Video', + description: lambda do |_connection, update_object_list| + "Update #{update_object_list[:object]&.downcase || 'an object'}" \ + " in RingCentral Video" + end, + help: lambda do |_input, pick_lists| + help = { + 'Meeting' => 'Modifies a particular meeting.', + 'User' => 'Update specific user details.', + 'Contact' => 'Updates personal contact information by contact ID.', + 'Post' => 'Updates a specific post within a chat.', + 'Note' => 'Edits a note. Notes can be edited by any user if posted to a chat the user belongs to.', + 'Team' => 'Updates the name and description of the specified team.', + 'Task' => 'Updates the specified task by ID.', + 'Everyone chat' => 'Updates Everyone chat information.', + 'Calendar event' => 'Updates the specified calendar event' + }[pick_lists['object']] || '' + + { body: help.present? ? help : 'Update an object' } + end, + config_fields: [ + { + name: 'object', + sticky: true, + type: 'string', + optional: false, + extends_schema: true, + control_type: 'select', + pick_list: 'update_object_list', + toggle_hint: 'Select object type to update', + hint: 'Please select an object from the list' + } + ], + input_fields: lambda do |object_definition| + object_definition['update_object_input'] + end, + execute: lambda do |_connection, input| + object_name = input['object'] + response = call("update_#{object_name}_execute", input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + call('custom_output_parser', response) + end, + output_fields: lambda do |object_definition| + object_definition['update_object_output'] + end, + sample_output: lambda do |_connection, input| + call('get_sample_output', input) + end + }, + delete_object: { + title: 'Delete object', + subtitle: 'Delete an object in RingCentral Video', + description: lambda do |_connection, delete_object_list| + "Delete #{delete_object_list[:object]&.downcase || 'an object'}" \ + " in RingCentral Video" + end, + help: lambda do |_input, pick_lists| + help = { + 'Meeting' => 'Deletes a scheduled meeting.', + 'User' => 'Deletes a specific user by ID.', + 'Contact' => 'Deletes a contact by ID.', + 'Post' => 'Deletes the specified post from the chat.', + 'Note' => 'Deletes the specified note.', + 'Team members' => 'Removes members from the specified team.', + 'Calendar event' => 'Deletes the specified calendar event.' + }[pick_lists['object']] || '' + + { body: help.present? ? help : 'Delete an object' } + end, + config_fields: [ + { + name: 'object', + sticky: true, + type: 'string', + optional: false, + extends_schema: true, + control_type: 'select', + pick_list: 'delete_object_list', + toggle_hint: 'Select object type to Delete', + hint: 'Please select an object from the list' + } + ], + input_fields: lambda do |object_definition| + object_definition['delete_object_input'] + end, + execute: lambda do |_connection, input| + call("delete_#{input['object']}_execute", input). + after_response do |code, _body, _headers| + if code == 204 + { result: 'Success' } + end + end. + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |_object_definitions| + [{ name: 'result' }] + end, + sample_output: lambda do |_input| + { result: 'Success' } + end + }, + publish_note_object: { + title: 'Publish note', + subtitle: 'Publish a note in RingCentral Video', + description: lambda do |_connection| + "Publish a note" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Publishes a note making it visible to other users.' } + end, + input_fields: lambda do |object_definition| + object_definition['publish_note_input'] + end, + execute: lambda do |_connection, input| + post("/restapi/v1.0/glip/notes/#{input['noteId']}/publish"). + after_response do |code, _body, _headers| + if code == 204 + { result: 'Success' } + end + end. + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |_object_definitions| + [{ name: 'result' }] + end, + sample_output: lambda do |_input| + { result: 'Success' } + end + }, + send_message_object: { + title: 'Send SMS', + subtitle: 'Send SMS in RingCentral Video', + description: lambda do |_connection| + "Send SMS" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Creates and sends a new text message. You can send SMS messages simultaneously ' \ + 'to different recipients up to 40 requests per minute; this limitation is relevant for ' \ + 'all client applications. Sending and receiving SMS is available for Toll-Free Numbers within the USA. ' } + end, + input_fields: lambda do |object_definition| + object_definition['send_sms_object_input'] + end, + execute: lambda do |_connection, input| + call('create_send_sms_execute', input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |object_definition| + object_definition['send_sms_object_output'] + end, + sample_output: lambda do |_connection, input| + call('send_sms_sample_output', input) + end + }, + make_ringout_call_object: { + title: 'Make ringout call', + subtitle: 'Make ringout call in RingCentral Video', + description: lambda do |_connection| + "Make ringout call" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Makes a 2-leg RingOut call.' } + end, + input_fields: lambda do |object_definition| + object_definition['make_ringout_call_object_input'] + end, + execute: lambda do |_connection, input| + call('create_ringout_call_execute', input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |object_definition| + object_definition['make_ringout_call_object_output'] + end, + sample_output: lambda do |_connection, input| + call('ringout_call_sample_output', input) + end + }, + cancel_ringout_call_object: { + title: 'Cancel ringout call', + subtitle: 'Cancel ringout call in RingCentral Video', + description: lambda do |_connection| + "Cancel ringout call" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Cancels a 2-leg RingOut call.' } + end, + input_fields: lambda do |object_definition| + object_definition['cancel_ringout_call_object_input'] + end, + execute: lambda do |_connection, input| + delete("/restapi/v1.0/account/#{input['accountId']}/extension/#{input['extensionId']}/ring-out/#{input['ringoutId']}"). + after_response do |code, _body, _headers| + if code == 204 + { result: 'Success' } + end + end. + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |_object_definitions| + [{ name: 'result' }] + end, + sample_output: lambda do |_input| + { result: 'Success' } + end + }, + callout_object: { + title: 'Make callout', + subtitle: 'Make callout in RingCentral Video', + description: lambda do |_connection| + "Make callout" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Creates a new outbound call out session.' } + end, + input_fields: lambda do |object_definition| + object_definition['callout_object_input'] + end, + execute: lambda do |_connection, input| + call('create_callout_execute', input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |object_definition| + object_definition['callout_object_output'] + end, + sample_output: lambda do |_connection, input| + call('callout_sample_output', input) + end + }, + reply_with_text_object: { + title: 'Reply with text', + subtitle: 'Reply with text in RingCentral Video', + description: lambda do |_connection| + "Reply with text" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Replies with text/pattern without picking up a call.' } + end, + input_fields: lambda do |object_definition| + object_definition['reply_with_text_object_input'] + end, + execute: lambda do |_connection, input| + call('create_reply_with_text_execute', input). + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |object_definition| + object_definition['reply_with_text_object_output'] + end, + sample_output: lambda do |_connection, input| + call('reply_with_text_sample_output', input) + end + }, + join_team_object: { + title: 'Join team', + subtitle: 'Join a team in RingCentral Video', + description: lambda do |_connection| + "Join a team" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Adds the current user to the specified team.' } + end, + input_fields: lambda do |object_definition| + object_definition['join_team_input'] + end, + execute: lambda do |_connection, input| + post("/restapi/v1.0/glip/teams/#{input['chatId']}/join"). + after_response do |code, _body, _headers| + if code == 204 + { result: 'Success' } + end + end. + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |_object_definitions| + [{ name: 'result' }] + end, + sample_output: lambda do |_input| + { result: 'Success' } + end + }, + leave_team_object: { + title: 'Leave team', + subtitle: 'Leave a team in RingCentral Video', + description: lambda do |_connection| + "Leave a team" \ + " in RingCentral Video" + end, + help: lambda do |_input, _pick_lists| + { body: 'Removes the current user from the specified team.' } + end, + input_fields: lambda do |object_definition| + object_definition['join_team_input'] + end, + execute: lambda do |_connection, input| + post("/restapi/v1.0/glip/teams/#{input['chatId']}/leave"). + after_response do |code, _body, _headers| + if code == 204 + { result: 'Success' } + end + end. + after_error_response(/.*/) do |_code, body, _header, message| + error("#{message}: #{body}") + end + end, + output_fields: lambda do |_object_definitions| + [{ name: 'result' }] + end, + sample_output: lambda do |_input| + { result: 'Success' } + end + }, + custom_action: { + subtitle: 'Build your own RingCentral Video action with a HTTP request', + + description: lambda do |object_value, _object_label| + "" \ + "#{object_value[:action_name] || 'Custom action'} in " \ + "RingCentral Video" + end, + + help: { + body: 'Build your own RingCentral Video action with a HTTP request. ' \ + 'The request will be authorized with your RingCentral Video connection.', + learn_more_url: 'https://developers.ringcentral.com/api-reference/', + learn_more_text: 'RingCentral Video API documentation' + }, + + config_fields: [ + { + name: 'action_name', + hint: "Give this action you're building a descriptive name, e.g. " \ + 'create record, get record', + default: 'Custom action', + optional: false, + schema_neutral: true + }, + { + name: 'verb', + label: 'Method', + hint: 'Select HTTP method of the request', + optional: false, + control_type: 'select', + pick_list: %w[get post put patch options delete].map { |verb| [verb.upcase, verb] } + } + ], + + input_fields: lambda do |object_definition| + object_definition['custom_action_input'] + end, + + execute: lambda do |_connection, input| + verb = input['verb'] + if %w[get post put patch options delete].exclude?(verb) + error("#{verb.upcase} not supported") + end + path = input['path'] + data = input.dig('input', 'data') || {} + if input['request_type'] == 'multipart' + data = data.each_with_object({}) do |(key, val), hash| + hash[key] = if val.is_a?(Hash) + [val[:file_content], + val[:content_type], + val[:original_filename]] + else + val + end + end + end + request_headers = input['request_headers']&.each_with_object({}) do |item, hash| + hash[item['key']] = item['value'] + end || {} + request = case verb + when 'get' + get(path, data) + when 'post' + if input['request_type'] == 'raw' + post(path).request_body(data) + else + post(path, data) + end + when 'put' + if input['request_type'] == 'raw' + put(path).request_body(data) + else + put(path, data) + end + when 'patch' + if input['request_type'] == 'raw' + patch(path).request_body(data) + else + patch(path, data) + end + when 'options' + options(path, data) + when 'delete' + delete(path, data) + end.headers(request_headers) + request = case input['request_type'] + when 'url_encoded_form' + request.request_format_www_form_urlencoded + when 'multipart' + request.request_format_multipart_form + else + request + end + response = + if input['response_type'] == 'raw' + request.response_format_raw + else + request + end.after_error_response(/.*/) do |code, body, headers, message| + error({ code: code, message: message, body: body, headers: headers }.to_json) + end + + response.after_response do |_code, res_body, res_headers| + { + body: res_body ? call('format_response', res_body) : nil, + headers: res_headers + } + end + end, + + output_fields: lambda do |object_definition| + object_definition['custom_action_output'] + end + } + }, + + pick_lists: { + trigger_objects: lambda do + [ + %w[Group group] + ] + end, + phoneType: lambda do + [ + %w[Work work], + %w[Mobile mobile], + %w[Other other] + ] + end, + photoType: lambda do + [ + %w[Photo photo] + ] + end, + emailType: lambda do + [ + %w[Work work] + ] + end, + audioOptions: lambda do + [ + %w[Phone Phone], + %w[ComputerAudio ComputerAudio] + ] + end, + meetingType: lambda do + [ + %w[Scheduled Scheduled], + %w[Instant Instant], + %w[Recurring Recurring] + ] + end, + delete_object_list: lambda do + [ + %w[Meeting meeting], + %w[User user], + %w[Contact contact], + %w[Post post], + %w[Note note], + %w[Team\ members team_members], + %w[Calendar\ event calendar_event] + ] + end, + update_object_list: lambda do + [ + %w[Meeting meeting], + %w[User user], + %w[Contact contact], + %w[Post post], + %w[Note note], + %w[Team team], + %w[Task task], + %w[Everyone\ chat everyone_chat], + %w[Calendar\ event calendar_event] + ] + end, + search_object_list: lambda do + [ + %w[Meetings meetings], + %w[Users users], + %w[Contacts contacts], + %w[Posts posts], + %w[Conversations conversations], + %w[Notes notes], + %w[Teams teams], + %w[Calendar\ events calendar_events], + %w[Tasks tasks], + %w[Chats chats], + %w[User\ call\ log\ records user_call_log_records], + %w[User\ active\ calls user_active_calls], + %w[Company\ active\ calls company_active_calls], + %w[Company\ call\ log\ records company_call_log_records], + %w[Company\ meeting\ recordings account_meeting_recordings], + %w[User\ meeting\ recordings user_meeting_recordings], + %w[States states], + %w[Countries countries], + %w[Timezones timezones] + ] + end, + create_object_list: lambda do + [ + %w[Meeting meeting], + %w[Contact contact], + %w[User user], + %w[Post post], + %w[Conversation conversation], + %w[Note note], + %w[Team team], + %w[Team\ members team_members], + %w[Calendar\ event calendar_event], + %w[Task task] + ] + end, + get_object_list: lambda do + [ + %w[Meeting meeting], + %w[User user], + %w[Contact contact], + %w[Company\ call\ log\ record company_call_log_record], + %w[Call\ recordings\ data call_recordings_data], + %w[Call\ recording call_recording], + %w[User\ call\ record user_call_record], + %w[Ringout\ call ringout_call], + %w[Post post], + %w[Conversation conversation], + %w[Note note], + %w[Team team], + %w[Calendar\ event calendar_event], + %w[Chat chat], + %w[Task task], + %w[Callout\ session\ status callout_session_status] + ] + end, + schemasType: lambda do + [ + %w[urn:ietf:params:scim:schemas:core:2.0:User urn:ietf:params:scim:schemas:core:2.0:User], + %w[urn:ietf:params:scim:schemas:extension:enterprise:2.0:User urn:ietf:params:scim:schemas:extension:enterprise:2.0:User] + ] + end + } +}