# frozen_string_literal: true module PlausibleApi module Stats class Base def initialize(options = {}) @options = { compare: nil, date: nil, filters: nil, interval: nil, limit: nil, metrics: nil, page: nil, period: nil, property: nil }.merge(options) @options[:period] = 'custom' if @options[:date] end def request_url_base raise NotImplementedError end def request_class Net::HTTP::Get end def request_body? false end def request_body nil end def request_url params = @options.select{ |_,v| !v.to_s.empty? } [request_url_base, URI.encode_www_form(params)].reject{|e| e.empty?}.join('&') end def request_headers {} end def request_auth? true end def parse_response(body) raise NotImplementedError end def valid? errors.empty? end def errors allowed_period = %w(12mo 6mo month 30d 7d day custom) allowed_metrics = %w(visitors visits pageviews views_per_visit bounce_rate visit_duration events) allowed_compare = %w(previous_period) allowed_interval = %w(date month) allowed_property = %w(event:page visit:entry_page visit:exit_page visit:source visit:referrer visit:utm_medium visit:utm_source visit:utm_campaign visit:device visit:browser visit:browser_version visit:os visit:os_version visit:country) e = 'Not a valid parameter. Allowed parameters are: ' errors = [] if @options[:period] errors.push({ period: "#{e}#{allowed_period.join(', ')}" }) unless allowed_period.include? @options[:period] end if @options[:metrics] metrics_array = @options[:metrics].split(',') errors.push({ metrics: "#{e}#{allowed_metrics.join(', ')}" }) unless metrics_array & allowed_metrics == metrics_array end if @options[:compare] errors.push({ compare: "#{e}#{allowed_compare.join(', ')}" }) unless allowed_compare.include? @options[:compare] end if @options[:interval] errors.push({ interval: "#{e}#{allowed_interval.join(', ')}" }) unless allowed_interval.include? @options[:interval] end if @options[:property] errors.push({ property: "#{e}#{allowed_property.join(', ')}" }) unless allowed_property.include? @options[:property] end if @options[:filters] filters_array = @options[:filters].to_s.split(';') filters_array.each do |f| parts = f.split("==") errors.push({ filters: "Unrecognized filter: #{f}" }) unless parts.length == 2 errors.push({ filters: "Unknown metric for filter: #{parts[0]}" }) unless allowed_property.include? parts[0] end end if @options[:limit] errors.push({ limit: "Limit param must be a positive number" }) unless @options[:limit].is_a? Integer and @options[:limit] > 0 end if @options[:page] errors.push({ page: "Page param must be a positive number" }) unless @options[:page].is_a? Integer and @options[:page] > 0 end if @options[:date] errors.push({ date: 'You must define the period parameter as custom' }) unless @options[:period] == 'custom' date_array = @options[:date].split(",") errors.push({ date: 'You must define start and end dates divided by comma' }) unless date_array.length == 2 regex = /\d{4}\-\d{2}\-\d{2}/ errors.push({ date: 'Wrong format for the start date' }) unless date_array[0] =~ regex errors.push({ date: 'Wrong format for the end date' }) unless date_array[1] =~ regex end errors end end end end