# frozen_string_literal: true module TimeTree # TimeTree apis client. class Client API_HOST = 'https://timetreeapis.com' # @return [String] attr_reader :token # @return [Integer] attr_reader :ratelimit_limit # @return [Integer] attr_reader :ratelimit_remaining # @return [Time] attr_reader :ratelimit_reset_at # @param token [String] a TimeTree's access token. def initialize(token = nil) @token = token || TimeTree.configuration.token check_token @http_cmd = HttpCommand.new(API_HOST, self) end # # Get current user information. # # @return [TimeTree::User] # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def current_user res = @http_cmd.get '/user' raise ApiError, res if res.status != 200 to_model res.body[:data] end # # Get a single calendar's information. # # @param cal_id [String] calendar's id. # @param include_relationships [Array] # includes association's object in the response. # @return [TimeTree::Calendar] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def calendar(cal_id, include_relationships: nil) check_calendar_id cal_id params = relationships_params(include_relationships, Calendar::RELATIONSHIPS) res = @http_cmd.get "/calendars/#{cal_id}", params raise ApiError, res if res.status != 200 to_model(res.body[:data], included: res.body[:included]) end # # Get calendar list that current user can access. # # @param include_relationships [Array] # includes association's object in the response. # @return [Array] # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def calendars(include_relationships: nil) params = relationships_params(include_relationships, Calendar::RELATIONSHIPS) res = @http_cmd.get '/calendars', params raise ApiError, res if res.status != 200 included = res.body[:included] res.body[:data].map { |item| to_model(item, included: included) } end # # Get a calendar's label information used in event. # # @param cal_id [String] calendar's id. # @return [Array] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def calendar_labels(cal_id) check_calendar_id cal_id res = @http_cmd.get "/calendars/#{cal_id}/labels" raise ApiError, res if res.status != 200 res.body[:data].map { |item| to_model(item) } end # # Get a calendar's member information. # # @param cal_id [String] calendar's id. # @return [Array] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def calendar_members(cal_id) check_calendar_id cal_id res = @http_cmd.get "/calendars/#{cal_id}/members" raise ApiError, res if res.status != 200 res.body[:data].map { |item| to_model item } end # # Get the event's information. # # @param cal_id [String] calendar's id. # @param event_id [String] event's id. # @param include_relationships [Array] # includes association's object in the response. # @return [TimeTree::Event] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::Error] if the event_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def event(cal_id, event_id, include_relationships: nil) check_calendar_id cal_id check_event_id event_id params = relationships_params(include_relationships, Event::RELATIONSHIPS) res = @http_cmd.get "/calendars/#{cal_id}/events/#{event_id}", params raise ApiError, res if res.status != 200 ev = to_model(res.body[:data], included: res.body[:included]) ev.calendar_id = cal_id ev end # # Get the events' information after a request date. # # @param cal_id[String] calendar's id. # @param days [Integer] The number of days to get. # @param timezone [String] Timezone. # @param include_relationships [Array] # includes association's object in the response. # @return [Array] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def upcoming_events(cal_id, days: 7, timezone: 'UTC', include_relationships: nil) check_calendar_id cal_id params = relationships_params(include_relationships, Event::RELATIONSHIPS) params.merge!(days: days, timezone: timezone) res = @http_cmd.get "/calendars/#{cal_id}/upcoming_events", params raise ApiError, res if res.status != 200 included = res.body[:included] res.body[:data].map do |item| ev = to_model(item, included: included) ev.calendar_id = cal_id ev end end # # Creates an event to the calendar. # # @param cal_id [String] calendar's id. # @param params [Hash] TimeTree request body format. # @return [TimeTree::Event] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def create_event(cal_id, params) check_calendar_id cal_id res = @http_cmd.post "/calendars/#{cal_id}/events", params raise ApiError, res if res.status != 201 ev = to_model res.body[:data] ev.calendar_id = cal_id ev end # # Updates an event. # # @param cal_id [String] calendar's id. # @param event_id [String] event's id. # @param params [Hash] # event's information specified in TimeTree request body format. # @return [TimeTree::Event] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::Error] if the event_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def update_event(cal_id, event_id, params) check_calendar_id cal_id check_event_id event_id res = @http_cmd.put "/calendars/#{cal_id}/events/#{event_id}", params raise ApiError, res if res.status != 200 ev = to_model res.body[:data] ev.calendar_id = cal_id ev end # # Deletes an event. # # @param cal_id [String] calendar's id. # @param event_id [String] event's id. # @return [true] if the operation succeeded. # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::Error] if the event_id arg is empty. # @raise [TimeTree::ApiError] if the http response status will not success. # @since 0.0.1 def delete_event(cal_id, event_id) check_calendar_id cal_id check_event_id event_id res = @http_cmd.delete "/calendars/#{cal_id}/events/#{event_id}" raise ApiError, res if res.status != 204 true end # # Creates comment to an event. # # @param cal_id [String] calendar's id. # @param event_id [String] event's id. # @param params [Hash] # comment's information specified in TimeTree request body format. # @return [TimeTree::Activity] # @raise [TimeTree::Error] if the cal_id arg is empty. # @raise [TimeTree::Error] if the event_id arg is empty. # @raise [TimeTree::ApiError] if the http response status is not success. # @since 0.0.1 def create_activity(cal_id, event_id, params) check_calendar_id cal_id check_event_id event_id res = @http_cmd.post "/calendars/#{cal_id}/events/#{event_id}/activities", params raise ApiError, res if res.status != 201 activity = to_model res.body[:data] activity.calendar_id = cal_id activity.event_id = event_id activity end def inspect limit_info = nil if defined?(@ratelimit_limit) && @ratelimit_limit limit_info = " ratelimit:#{@ratelimit_remaining}/#{@ratelimit_limit}" end if defined?(@ratelimit_reset_at) && @ratelimit_reset_at limit_info = "#{limit_info}, reset_at:#{@ratelimit_reset_at.strftime('%m/%d %R')}" end "\#<#{self.class}:#{object_id}#{limit_info}>" end # # update ratelimit properties # # @param res [Faraday::Response] # apis http response. def update_ratelimit(res) limit = res.headers['x-ratelimit-limit'] remaining = res.headers['x-ratelimit-remaining'] reset = res.headers['x-ratelimit-reset'] @ratelimit_limit = limit.to_i if limit @ratelimit_remaining = remaining.to_i if remaining @ratelimit_reset_at = Time.at reset.to_i if reset end private def check_token check_required_property(@token, 'token') end def check_calendar_id(value) check_required_property(value, 'calendar_id') end def check_event_id(value) check_required_property(value, 'event_id') end def check_required_property(value, name) err = Error.new "#{name} is required." raise err if value.nil? raise err if value.to_s.empty? true end def to_model(data, included: nil) TimeTree::BaseModel.to_model data, client: self, included: included end def relationships_params(relationships, default) params = {} relationships ||= default params[:include] = relationships.join ',' if relationships.is_a? Array params end end end