11# frozen_string_literal: true
22
3- require 'time'
43require 'json'
4+ require 'time'
55
66module Html2rss
77 module Web
88 module Api
99 module V1
1010 ##
1111 # Creates stable feed records from authenticated API requests.
12- module CreateFeed # rubocop:disable Metrics/ModuleLength
12+ module CreateFeed
1313 FEED_ATTRIBUTE_KEYS =
1414 %i[ id name url feed_token public_url json_public_url created_at updated_at ] . freeze
15- class << self # rubocop:disable Metrics/ClassLength
15+
16+ class << self
1617 # Creates a feed and returns a normalized API success payload.
1718 #
1819 # @param request [Rack::Request] HTTP request with auth context.
1920 # @return [Hash{Symbol=>Object}] API response payload.
20- def call ( request ) # rubocop:disable Metrics/MethodLength
21- params , feed_data = build_feed_from_request ( request )
21+ # rubocop:disable Metrics/MethodLength
22+ def call ( request )
23+ account = require_account ( request )
24+ params = build_create_params ( request , account )
25+ feed_data = create_feed ( params , account )
26+
2227 emit_create_success ( params )
2328 Response . success ( response : request . response ,
2429 status : 201 ,
@@ -30,14 +35,10 @@ def call(request) # rubocop:disable Metrics/MethodLength
3035 emit_create_failure ( error )
3136 raise
3237 end
38+ # rubocop:enable Metrics/MethodLength
3339
3440 private
3541
36- # @return [void]
37- def ensure_auto_source_enabled!
38- raise Html2rss ::Web ::AutoSourceDisabledError unless AutoSource . enabled?
39- end
40-
4142 # @param request [Rack::Request]
4243 # @return [Hash]
4344 def require_account ( request )
@@ -47,15 +48,41 @@ def require_account(request)
4748 account
4849 end
4950
50- # @param params [Hash ]
51+ # @param request [Rack::Request ]
5152 # @param account [Hash]
5253 # @return [Html2rss::Web::Api::V1::FeedMetadata::CreateParams]
53- def build_create_params ( params , account )
54- url = validated_url ( params [ 'url' ] , account )
55- FeedMetadata ::CreateParams . new (
56- url : url ,
57- name : FeedMetadata . site_title_for ( url )
58- )
54+ def build_create_params ( request , account )
55+ url = validated_url ( request_params ( request ) [ 'url' ] , account )
56+ FeedMetadata ::CreateParams . new ( url :, name : FeedMetadata . site_title_for ( url ) )
57+ end
58+
59+ # @param request [Rack::Request]
60+ # @return [Hash]
61+ def request_params ( request )
62+ return request . params unless json_request? ( request )
63+
64+ request . GET . merge ( parsed_json_body ( request ) )
65+ end
66+
67+ # @param request [Rack::Request]
68+ # @return [Hash]
69+ def parsed_json_body ( request )
70+ raw_body = request . body . read
71+ request . body . rewind
72+ return { } if raw_body . strip . empty?
73+
74+ parsed = JSON . parse ( raw_body )
75+ raise Html2rss ::Web ::BadRequestError , 'Invalid JSON payload' unless parsed . is_a? ( Hash )
76+
77+ parsed
78+ rescue JSON ::ParserError
79+ raise Html2rss ::Web ::BadRequestError , 'Invalid JSON payload'
80+ end
81+
82+ # @param request [Rack::Request]
83+ # @return [Boolean]
84+ def json_request? ( request )
85+ request . env [ 'CONTENT_TYPE' ] . to_s . include? ( 'application/json' )
5986 end
6087
6188 # @param raw_url [String, nil]
@@ -102,49 +129,23 @@ def hostname_input?(url)
102129 }ix . match? ( url )
103130 end
104131
105- # @param feed_data [Hash, Html2rss::Web::Api::V1::FeedMetadata::Metadata]
106- # @return [Hash{Symbol=>Object}]
107- def feed_attributes ( feed_data )
108- timestamp = Time . now . iso8601
109- typed_feed = feed_metadata ( feed_data )
110- typed_feed_attributes ( typed_feed , timestamp ) . slice ( *FEED_ATTRIBUTE_KEYS )
111- end
112-
113- # @param request [Rack::Request]
114- # @return [Hash]
115- def request_params ( request )
116- return request . params unless json_request? ( request )
117-
118- raw_body = request . body . read
119- request . body . rewind
120- return request . params if raw_body . strip . empty?
121-
122- parsed = JSON . parse ( raw_body )
123- raise Html2rss ::Web ::BadRequestError , 'Invalid JSON payload' unless parsed . is_a? ( Hash )
124-
125- request . params . merge ( parsed )
126- rescue JSON ::ParserError
127- raise Html2rss ::Web ::BadRequestError , 'Invalid JSON payload'
128- end
129-
130- # @param request [Rack::Request]
131- # @return [Boolean]
132- def json_request? ( request )
133- content_type = request . env [ 'CONTENT_TYPE' ] . to_s
134- content_type . include? ( 'application/json' )
135- end
136-
137- # @param request [Rack::Request]
138- # @return [Array<(Html2rss::Web::Api::V1::FeedMetadata::CreateParams, Object)>]
139- def build_feed_from_request ( request )
140- account = require_account ( request )
141- ensure_auto_source_enabled!
142- params = build_create_params ( request_params ( request ) , account )
132+ # @param params [Html2rss::Web::Api::V1::FeedMetadata::CreateParams]
133+ # @param account [Hash]
134+ # @return [Html2rss::Web::Api::V1::FeedMetadata::Metadata]
135+ def create_feed ( params , account )
136+ raise Html2rss ::Web ::AutoSourceDisabledError unless AutoSource . enabled?
143137
144138 feed_data = AutoSource . create_stable_feed ( params . name , params . url , account )
145139 raise Html2rss ::Web ::InternalServerError , 'Failed to create feed' unless feed_data
146140
147- [ params , feed_data ]
141+ feed_data . is_a? ( FeedMetadata ::Metadata ) ? feed_data : FeedMetadata ::Metadata . new ( **feed_data )
142+ end
143+
144+ # @param feed_data [Html2rss::Web::Api::V1::FeedMetadata::Metadata]
145+ # @return [Hash{Symbol=>Object}]
146+ def feed_attributes ( feed_data )
147+ timestamp = Time . now . iso8601
148+ feed_data . to_h . merge ( created_at : timestamp , updated_at : timestamp ) . slice ( *FEED_ATTRIBUTE_KEYS )
148149 end
149150
150151 # @param params [Html2rss::Web::Api::V1::FeedMetadata::CreateParams]
@@ -168,21 +169,6 @@ def emit_create_failure(error)
168169 level : :warn
169170 )
170171 end
171-
172- # @param feed_data [Hash, Html2rss::Web::Api::V1::FeedMetadata::Metadata]
173- # @return [Html2rss::Web::Api::V1::FeedMetadata::Metadata]
174- def feed_metadata ( feed_data )
175- return feed_data if feed_data . is_a? ( FeedMetadata ::Metadata )
176-
177- FeedMetadata ::Metadata . new ( **feed_data )
178- end
179-
180- # @param typed_feed [Html2rss::Web::Api::V1::FeedMetadata::Metadata]
181- # @param timestamp [String]
182- # @return [Hash{Symbol=>Object}]
183- def typed_feed_attributes ( typed_feed , timestamp )
184- typed_feed . to_h . merge ( created_at : timestamp , updated_at : timestamp )
185- end
186172 end
187173 end
188174 end
0 commit comments