module Kaltura class ClientBase attr_accessor :config attr_accessor :ks attr_reader :is_multirequest def initialize(config) @should_log = false @config = config @calls_queue = [] if @config.logger != nil @should_log = true end end def queue_service_action_call(service, action, params = {}) # in start session partner id is optional (default -1). if partner id was not set, use the one in the config if (!params.key?('partnerId') || params['partnerId'] == -1) params['partnerId'] = config.partner_id; end add_param(params, 'ks', @ks); call = ServiceActionCall.new(service, action, params); @calls_queue.push(call); end def do_queue() start_time = Time.now if @calls_queue.length == 0 @is_multirequest = false return nil end log('service url: [' + @config.service_url + ']') # append the basic params params = {} add_param(params, "format", @config.format) add_param(params, "clientTag", @config.client_tag) url = @config.service_url+"/api_v3/index.php?service=" if (@is_multirequest) url += "multirequest" i = 1 @calls_queue.each_value do |call| call_params = call.get_params_for_multirequest(i.next) params.merge!(call_params) end else call = @calls_queue[0] url += call.service + "&action=" + call.action params.merge!(call.params) end # reset @calls_queue = [] @is_multirequest = false signature = signature(params) add_param(params, "kalsig", signature) log("url: " + url) log("params: " + params.to_yaml) result = do_http_request(url, params) result_object = parse_to_objects(result.body) log("result (object yaml dump): " + result_object.to_yaml) end_time = Time.now log("execution time for [#{url}]: [#{end_time - start_time}]") return result_object end def do_http_request(url, params) res = RestClient.post url , params return res end def parse_to_objects(data) parse_xml_to_objects(data) end def parse_xml_to_objects(xml) doc = REXML::Document.new(xml) raise_exception_if_error(doc) doc.elements.each('xml/result') do | element | return ClassFactory.object_from_xml(element) end end def raise_exception_if_error(doc) if is_error(doc) code = doc.elements["xml/result/error/code"].text message = doc.elements["xml/result/error/message"].text raise APIError.new(code,message) end end def is_error(doc) doc.elements["xml/result/error/message"] && doc.elements["xml/result/error/code"] end def start_multirequest() @is_multirequest = true end def do_multirequest() return do_queue() end def signature(params) str = params.keys.map {|key| key.to_s }.sort.map {|key| "#{escape(key)}#{escape(params[key])}" }.join("") Digest::MD5.hexdigest(str) end def add_param(params, name, value) if value == nil return elsif value.is_a? Hash value.each do |sub_name, sub_value| add_param(params, "#{name}:#{sub_name}", sub_value); end elsif value.is_a? ObjectBase add_param(params, name, value.to_params) else params[name] = value end end # Escapes a query parameter. Stolen from RFuzz def escape(s) s.to_s.gsub(/([^ a-zA-Z0-9_.-]+)/n) { '%' + $1.unpack('H2'*$1.size).join('%').upcase }.tr(' ', '+') end def log(msg) if @should_log config.logger.log(msg) end end end class ServiceActionCall attr_accessor :service attr_accessor :action attr_accessor :params def initialize(service, action, params = array()) @service = service @action = action @params = parse_params(params) end def parse_params(params) new_params = {} params.each do |key, val| if val.kind_of? Hash new_params[key] = parse_params(val) else new_params[key] = val end end return new_params end def get_params_for_multirequest(multirequest_index) multirequest_params = {} multirequest_params[multirequest_index+":service"] = @service multirequest_params[multirequest_index+":action"] = @action @params.each do |key| multirequest_params[multirequest_index+":"+key] = @params[key] end return multirequest_params end end class ObjectBase attr_accessor :object_type def to_params params = {}; params["objectType"] = self.class.name.split('::').last instance_variables.each do |var| value = instance_variable_get(var) var = var.to_s.sub('@', '') kvar = camelcase(var) if (value != nil) if (value.is_a? ObjectBase) params[kvar] = value.to_params; else params[kvar] = value; end end end return params; end def to_b(val) return [true, 'true', 1, '1'].include?(val.is_a?(String) ? val.downcase : val) end def camelcase(val) val = val.split('_').map { |e| e.capitalize }.join() val[0,1].downcase + val[1,val.length] end end class Configuration attr_accessor :logger attr_accessor :service_url attr_accessor :format attr_accessor :client_tag attr_accessor :timeout attr_accessor :partner_id def initialize(partner_id = -1) @service_url = "http://www.kaltura.com" @format = 2 # xml @client_tag = "ruby" @timeout = 10 @partner_id = partner_id end def service_url=(url) @service_url = url.chomp('/') end end class ClassFactory def self.object_from_xml(xml_element) instance = nil if xml_element.elements.size > 0 if xml_element.elements[1].name == 'item' # array instance = [] xml_element.elements.each('item') do | element | instance.push(ClassFactory.object_from_xml(element)) end else # object object_type_element = xml_element.get_text('objectType') if (object_type_element != nil) object_class = xml_element.get_text('objectType').value instance = ClassFactory.set_instance(object_class) xml_element.elements.each do | element | value = ClassFactory.object_from_xml(element) instance.send(self.underscore(element.name) + "=", value); end end end else # simple type return xml_element.text end return instance; end def self.underscore(val) val.gsub(/(.)([A-Z])/,'\1_\2').downcase end def self.set_instance(object_request_class) string_object_class = object_request_class.to_s instance = nil stripped_request = ClassFactory.strip_kaltura_from_request(string_object_class) instance = Module.const_get("Kaltura") unless ClassFactory.request_is_response?(string_object_class) instance = instance.const_get("Response").const_get(stripped_request).new else instance = instance.const_get(stripped_request).new end instance end def self.strip_kaltura_from_request(request) request.gsub("Kaltura","") end def self.request_is_response?(request) request_array = [] request_array << request request_array == request.split("Response",0) end end class APIError < RuntimeError attr_reader :code attr_reader :message def initialize(code,message) @code = code @message = message end end end