# frozen_string_literal: true module Qismo module Api # @!parse include Qismo::Client # List customer rooms # # @see https://s.id/list-customer-rooms # @param options [Hash] # @return [Qismo::CollectionObject] def rooms(options = {}) body = post("/api/v2/customer_rooms", options) CollectionObject.new( body.data.customer_rooms, prev_page: body.meta&.cursor_before, next_page: body.meta&.cursor_after, prev_func: -> { rooms(options.merge(cursor_before: body.meta&.cursor_before)) }, next_func: -> { rooms(options.merge(cursor_after: body.meta&.cursor_after)) } ) end # Get room by id # # @see https://s.id/get-room-by-room-id # @param room_id [Integer] # @return [Qismo::SingleObject] def room(room_id) body = get("/api/v2/customer_rooms/#{room_id}") if body.data.customer_room.nil? raise Qismo::NotFoundError.new("Room not found", status_code: 404, response_body: body.to_json) end body.data.customer_room end # List tags inside room # # @see https://s.id/list-room-tags # @param room_id [Integer] # @return [Qismo::CollectionObject] def room_tags(room_id) CollectionObject.new(get("/api/v2/room_tags/#{room_id}").data) end # Add room tag # # @see https://s.id/add-room-tag # @param room_id [Integer] # @param tag_name [String] # @return [Qismo::SingleObject] def add_room_tag(room_id, tag_name) post("/api/v2/room_tags/#{room_id}", tag: tag_name).data end # Delete room tag # # @see https://s.id/delete-room-tag # @param room_id [Integer] # @param tag_id [Integer] # @return [TrueClass] def delete_room_tag(room_id, tag_id) delete("/api/v2/room_tags/#{room_id}/#{tag_id}") true end # List room additional info # # @see https://s.id/list-room-info # @param room_id [Integer] # @return [Qismo::CollectionObject] def room_additional_info(room_id) CollectionObject.new( get( "/api/v1/qiscus/room/#{room_id}/user_info" ).data&.extras&.user_properties ) || CollectionObject.new end alias_method :room_info, :room_additional_info # Set room additional info # # @see https://s.id/set-room-info # @note This will replace your current room additional info # @param room_id [Integer] # @param additional_info [Array] # @return [Qismo::CollectionObject] def set_room_additional_info(room_id, additional_info) CollectionObject.new( post( "/api/v1/qiscus/room/#{room_id}/user_info", user_properties: additional_info ).data&.extras&.user_properties ) || CollectionObject.new end alias_method :set_room_info, :set_room_additional_info alias_method :create_room_info, :set_room_additional_info alias_method :create_room_additional_info, :set_room_additional_info # Update room additional info # # @param room_id [Integer] # @param additional_info [Array] # @return [Qismo::CollectionObject] def update_room_additional_info(room_id, additional_info) old_additional_info = room_additional_info(room_id) new_additional_info = (additional_info + old_additional_info).uniq { |h| h.values_at("key") } set_room_additional_info(room_id, new_additional_info) end alias_method :update_room_info, :update_room_additional_info # List Whatsapp broadcast history inside room # # @see https://s.id/list-room-broadcast-history # @param room_id [Integer] # @param options [Hash] # @return [Qismo::CollectionObject] def room_broadcast_history(room_id, options = {}) body = get("/api/v2/customer_rooms/#{room_id}/broadcast_history", options) next_page = (body.meta.page < body.meta.total_page) ? (body.meta.page + 1) : nil prev_page = (body.meta.page > 1) ? (body.meta.page - 1) : nil CollectionObject.new( body.data.broadcast_logs, next_page: next_page, prev_page: prev_page, next_func: -> { room_broadcast_history(options.merge(page: next_page)) }, prev_func: -> { room_broadcast_history(options.merge(page: prev_page)) } ) end # Assign agent to room # # @see https://s.id/assign-agent # @param room_id [Integer] # @param agent_id [Integer] # @param options [Hash] # @return [Qismo::SingleObject] def assign_agent(room_id, agent_id, options = {}) body = post("/api/v1/admin/service/assign_agent", options.merge(room_id: room_id.to_s, agent_id: agent_id)) body.data.added_agent end # Remove agent from room # # @see https://s.id/remove-agent # @param room_id [Integer] # @param agent_id [Integer] # @return [TrueClass] def remove_agent(room_id, agent_id) post("/api/v1/admin/service/remove_agent", room_id: room_id.to_s, agent_id: agent_id) true end # Resolve room # # @see https://s.id/resolve-room # @param room_id [Integer] # @param last_comment_id [Integer] # @param options [Hash] # @return [Qismo::SingleObject] def resolve_room(room_id, last_comment_id, options = {}) body = post("/api/v1/admin/service/mark_as_resolved", options.merge(room_id: room_id.to_s, last_comment_id: last_comment_id)) body.data.service end alias_method :resolve, :resolve_room # Get agent that can be assigned to room # # @see https://s.id/allocate-agent # @param source [String] # @param options [Hash] # @return [Qismo::SingleObject] def allocate_agent(source, options = {}) body = post("/api/v1/admin/service/allocate_agent", options.merge(source: source)) body.data.agent end # Get agent that can be allocated to room and automatically assign them # # @see https://s.id/allocate-and-assign-agent # @param room_id [Integer] # @param options [Hash] # @return [Qismo::SingleObject] def allocate_and_assign_agent(room_id, options = {}) body = post("/api/v1/admin/service/allocate_assign_agent", options.merge(room_id: room_id)) body.data.agent end # List agents that are not in room and can be assigned to room # # @see https://s.id/list-other-agents # @param room_id [Integer] # @param options [Hash] # @return [Qismo::CollectionObject] def other_agents(room_id, options = {}) body = get("/api/v2/admin/service/other_agents", options.merge(room_id: room_id)) CollectionObject.new( body.data.agents, prev_page: body.meta&.cursor_before, next_page: body.meta&.cursor_after, prev_func: -> { other_agents(options.merge(cursor_before: body.meta&.cursor_before)) }, next_func: -> { other_agents(options.merge(cursor_after: body.meta&.cursor_after)) } ) end # List available agents in room # # @see https://s.id/list-available-agents # @param room_id [Integer] # @param options [Hash] # @return [Qismo::CollectionObject] def available_agents(room_id, options = {}) body = get("/api/v2/admin/service/available_agents", options.merge(room_id: room_id)) CollectionObject.new( body.data.agents, prev_page: body.meta&.cursor_before, next_page: body.meta&.cursor_after, prev_func: -> { available_agents(options.merge(cursor_before: body.meta&.cursor_before)) }, next_func: -> { available_agents(options.merge(cursor_after: body.meta&.cursor_after)) } ) end # Get new session webhook config # # @return [Qismo::SingleObject] def new_session_webhook get("/api/v2/app/config/new_session_webhook").data.configs end # Set new session webhook # # @param url [String] # @param options [Hash] # @return [Qismo::SingleObject] def set_new_session_webhook(url, options = {}) post("/api/v2/app/config/new_session_webhook", options.merge(url: url)).data.configs end # Get auth webhook config # # @return [Qismo::SingleObject] def auth_webhook get("/api/v2/app/config/auth_webhook").data.configs end # Set auth webhook # # @param url [String] # @param enabled [TrueClass, FalseClass] # @param options [Hash] # @return [Qismo::SingleObject] def set_auth_webhook(url, enabled = true, options = {}) post("/api/v2/app/config/auth_webhook", options.merge(url: url, enabled: enabled)).data.configs end # Get resolve webhook config # # @return [Qismo::SingleObject] def resolve_webhook get("/api/v1/app/webhook/mark_as_resolved").data end # Set resolve webhook # # @param url [String] # @param options [Hash] # @return [Qismo::SingleObject] def set_resolve_webhook(url, options = {}) post("/api/v1/app/webhook/mark_as_resolved", options.merge(url: url)).data end # List agents # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#849205ca-00d9-4356-9fdd-f05bff777b4e # @param options [Hash] # @return [Qismo::CollectionObject] def agents(options = {}) if options[:page].nil? || options[:page].empty? options[:page] = 1 end body = get("/api/v2/admin/agents", options) total_page = (body.meta.total_count.to_f / body.meta.per_page.to_f).ceil next_page = (options[:page] < total_page) ? (options[:page] + 1) : nil prev_page = (options[:page] > 1) ? (options[:page] - 1) : nil CollectionObject.new( body.data.agents, next_page: next_page, prev_page: prev_page, next_func: -> { agents(options.merge(page: next_page)) }, prev_func: -> { agents(options.merge(page: prev_page)) } ) end # List agents by id # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#3db6c8c8-8ffe-4a88-b630-41f9d5b62298 # @param ids [Array] # @return [Qismo::CollectionObject] def agents_by_ids(ids) CollectionObject.new(get("/api/v1/admin/agents/get_by_ids", {"ids[]": ids}).data) || CollectionObject.new end # List agents by divisions # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#94eeb9cb-dd70-4baf-9f63-361e7922299a # @param division_ids [Array] # @param options [Hash] # @return [Qismo::CollectionObject] def agents_by_divisions(division_ids, options = {}) body = get("/api/v2/admin/agents/by_division", options.merge({"division_ids[]": division_ids})) next_page = (body.meta.page < body.meta.total_page) ? (body.meta.page + 1) : nil prev_page = (body.meta.page > 1) ? (body.meta.page - 1) : nil CollectionObject.new( body.data, next_page: next_page, prev_page: prev_page, next_func: -> { agents_by_divisions(options.merge(page: next_page)) }, prev_func: -> { agents_by_divisions(options.merge(page: prev_page)) } ) end # Get agent by id # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#c6184a6b-ba4d-4f3e-a4da-c6d0fa4597af # @param agent_id [Integer] # @return [Qismo::SingleObject] def agent(agent_id) get("/api/v2/admin/agent/#{agent_id}").data.agent end # Get office hour config # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#6f3f0cb0-a391-4945-b01a-95ce81138913 # @return [Qismo::SingleObject] def office_hours data = get("/api/v1/admin/office_hours").data data_hash = data.as_json data_hash["is_in_office_hour"] = Util.in_office_hour?(data) SingleObject.new(data_hash) end # List WA broadcast templates # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#e38d2244-9559-4015-99d5-8c707f6c01bd # @param options [Hash] # @return [Qismo::CollectionObject] def wa_broadcast_templates(options = {}) body = get("/api/v3/admin/hsm", options) meta = body.meta next_page = (meta.page < meta.total_page) ? (meta.page + 1) : nil prev_page = (meta.page > 1) ? (meta.page - 1) : nil CollectionObject.new( body.data.hsm_templates, next_page: next_page, prev_page: prev_page, next_func: -> { wa_broadcast_templates(options.merge(page: next_page)) }, prev_func: -> { wa_broadcast_templates(options.merge(page: prev_page)) } ) end alias_method :wa_message_templates, :wa_broadcast_templates alias_method :wa_outbound_templates, :wa_broadcast_templates # Send WA outbound message # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#d0183cf6-deca-439b-aff3-2e2f007c15a9 # @param options [Hash] # @return [Qismo::SingleObject] def send_wa_outbound(options = {}) post("/api/v3/admin/broadcast/client", options).data end # Upload wa broadcast file that want to be sent in broadcast # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#030acde2-21cf-4373-8d11-075206053c1d # @param file [HTTP::FormData] # @param template_detail_id [Integer] # @return [Qismo::SingleObject] def upload_wa_broadcast_csv(file, template_detail_id) raise ArgumentError, "Invalid file" unless file.is_a?(HTTP::FormData::File) post_upload("/api/v3/admin/broadcast/upload_csv", file: file, template_detail_id: template_detail_id) end # Send wa broadcast # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#717c1a12-facb-4945-aed5-04557696b873 # @param options [Hash] # @return [Qismo::SingleObject] def send_wa_broadcast(options = {}) post("/api/v3/admin/broadcast/send_broadcast", options).data.broadcast_job end alias_method :create_wa_broadcast, :send_wa_broadcast # List wa broadcast jobs # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#3a4caa8b-eef4-427f-adcb-d065989899c9 # @param options [Hash] # @return [Qismo::CollectionObject] def wa_broadcast_jobs(options = {}) body = get("/api/v2/admin/broadcast_jobs", options) prev_page = (body.meta.page > 1) ? (body.meta.meta - 1) : nil next_page = (body.meta.page < body.meta.total_page) ? (body.meta.page + 1) : nil CollectionObject.new( body.data.broadcast_jobs, next_page: next_page, prev_page: prev_page, next_func: -> { wa_broadcast_jobs(options.merge(page: next_page)) }, prev_func: -> { wa_broadcast_jobs(options.merge(page: prev_page)) } ) end # Get wa broadcast job by id # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#ed0806c8-2e4a-4ea4-8acb-45c84c63c2da # @param broadcast_job_id [Integer] # @return [Qismo::SingleObject] def wa_broadcast_job(broadcast_job_id) get("/api/v2/admin/broadcast_jobs/#{broadcast_job_id}").data.broadcast_job end # List wa broadcast logs # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#3f2d8ba8-ab14-43b2-af82-74c8b766216f # @param broadcast_job_id [Integer] # @param options [Hash] # @return [Qismo::CollectionObject] def wa_broadcast_logs(broadcast_job_id, options = {}) body = get("/api/v2/admin/broadcast_logs/#{broadcast_job_id}", options) prev_page = (body.meta.page > 1) ? (body.meta.meta - 1) : nil next_page = (body.meta.page < body.meta.total_page) ? (body.meta.page + 1) : nil CollectionObject.new( body.data.broadcast_logs, next_page: next_page, prev_page: prev_page, next_func: -> { wa_broadcast_logs(options.merge(page: next_page)) }, prev_func: -> { wa_broadcast_jobs(options.merge(page: prev_page)) } ) end # Send message as bot # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#bb77c653-5daa-4e1c-a866-43bca7c494fc # @param options [Hash] # @return [TrueClass] def send_bot_message(options = {}) post("#{app_id}/bot", options) true end # Enable chabot in room # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#494d825f-a49c-4b18-954e-eaaccb738bcd # @param room_id [Integer] # @return [TrueClass] def enable_bot_in_room(room_id) post("/bot/#{room_id}/activate", is_active: true) true end # Disable chatbot in room # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#494d825f-a49c-4b18-954e-eaaccb738bcd # @param room_id [Integer] # @return [TrueClass] def disable_bot_in_room(room_id) post("/bot/#{room_id}/activate", is_active: false) true end # Handover room from chatbot to human agent # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#40867e85-7412-4e0d-84bd-e2506df23df8 # @param room_id [Integer] # @return [TrueClass] def handover_room_from_bot(room_id) post("/#{app_id}/bot/#{room_id}/hand_over") true end # Handover room from chatbot to human agent in specific divisions # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#8218db08-9753-4d74-ae5f-0ee62f8579b9 # @param room_id [Integer] # @param roles [Array] # @param options [Hash] # @return [TrueClass] def handover_room_from_bot_to_division(room_id, roles, options = {}) post("/#{app_id}/bot/#{room_id}/hand_over_to_role", options.merge(roles: roles)) true end # Initiate chat using Qiscus widget channel # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#d5a555de-59e0-4705-9582-c216d79e9390 # @param user_id [String] # @param name [String] # @param options [Hash] # @return [Qismo::SingleObject] def initiate_widget_chat(user_id, name, options = {}) options = options.merge(app_id: app_id, user_id: user_id, name: name) post("/api/v2/qiscus/initiate_chat", options).data.customer_room end alias_method :initiate_chat, :initiate_widget_chat # Send message to custom channel # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#aee54b21-68f1-4d31-9d81-d3c73b3e125b # @param identifier_key [String] # @param user_id [String] # @param name [String] # @param options [Hash] # @return [Qismo::SingleObject] def send_message_to_custom_channel(identifier_key, user_id, name, options = {}) post("/#{app_id}/api/v2/custom_channel/send", options.merge(identifier_key: identifier_key, user_id: user_id, name: name)).data end # List integrated channels # # @see https://documenter.getpostman.com/view/8259884/TVsuCSeT#aee54b21-68f1-4d31-9d81-d3c73b3e125b # @return [Qismo::SingleObject] def channels get("/api/v2/channels").data end # Create customchannel # # @param identifier_key [String] # @param name [String] # @param webhook_url [String] # @param options [Hash] # @return [Qismo::SingleObject] def create_custom_channel(identifier_key, name, webhook_url, options = {}) options = options.merge( identifier_key: identifier_key, name: name, webhook_url: webhook_url ) options[:is_active] = true unless options[:is_active].nil? post("/api/v1/custom_channel/connect", options.merge).data end # Update custom channel # # @param id [Integer] # @param options [Hash] # @return [Qismo::SingleObject] def update_custom_channel(id, options = {}) channel = channels.custom_channels.find { |cc| cc.id == id } if channel.nil? raise Qismo::NotFoundError.new("Channel not found", status_code: 404, response_body: nil) end channel_hash = JSON.parse(channel.to_json, symbolize_names: true) new_channel_config = channel_hash.merge(options) post("/api/v1/custom_channel/connect/update", new_channel_config).data end # Activate custom channel # # @param id [Integer] # @return [Qismo::SingleObject] def activate_custom_channel(id) update_custom_channel(id, is_active: true) end # Deactivate custom channel # # @param id [Integer] # @return [Qismo::SingleObject] def deactivate_custom_channel(id) update_custom_channel(id, is_active: false) end # Delete custom channel # # @param id [Integer] # @return [TrueClass] def delete_custom_channel(id) post("/api/v2/custom_channel/connect/#{id}/delete") true end end end