@@ -17,151 +17,135 @@ module Api
1717 module V1
1818 # RESTful API v1 for feeds
1919 module Feeds
20- module_function
20+ class << self
21+ def show ( request , token )
22+ ensure_auto_source_enabled!
2123
22- def show ( request , token )
23- handle_token_based_feed ( request , token )
24- end
24+ feed_token = validated_token_for ( token )
25+ account = account_for ( feed_token )
26+ ensure_access! ( account , feed_token . url )
2527
26- def create ( request )
27- raise ForbiddenError , 'Auto source feature is disabled' unless AutoSource . enabled?
28+ render_generated_feed ( request , feed_token . url )
29+ end
2830
29- account = authenticate_request ( request )
30- params = extract_create_params ( request )
31- validate_create_params ( params , account )
31+ def create ( request )
32+ ensure_auto_source_enabled!
3233
33- feed_data = AutoSource . create_stable_feed ( params [ :name ] , params [ :url ] , account , params [ :strategy ] )
34- raise InternalServerError , 'Failed to create feed' unless feed_data
34+ account = require_account ( request )
35+ params = build_create_params ( request , account )
3536
36- build_create_response ( request , feed_data )
37- end
37+ feed_data = AutoSource . create_stable_feed ( params [ :name ] , params [ :url ] , account , params [ :strategy ] )
38+ raise InternalServerError , 'Failed to create feed' unless feed_data
3839
39- def handle_token_based_feed ( request , token )
40- raise ForbiddenError , 'Auto source feature is disabled' unless AutoSource . enabled?
40+ json_response ( request , feed_response_payload ( feed_data ) , status : 201 )
41+ end
4142
42- feed_token = validate_feed_token ( token )
43- account = get_account_for_token ( feed_token )
44- validate_account_access ( account , feed_token . url )
43+ private
4544
46- generate_feed_response ( request , feed_token . url )
47- end
45+ def ensure_auto_source_enabled!
46+ raise ForbiddenError , 'Auto source feature is disabled' unless AutoSource . enabled?
47+ end
4848
49- def validate_feed_token ( token )
50- feed_token = FeedToken . decode ( token )
51- raise UnauthorizedError , 'Invalid token' unless feed_token
49+ def json_response ( request , payload , status : 200 )
50+ request . response [ 'Content-Type' ] = 'application/json'
51+ request . response . status = status
52+ payload
53+ end
5254
53- validated_token = FeedToken . validate_and_decode ( token , feed_token . url , Auth . secret_key )
54- raise UnauthorizedError , 'Invalid token' unless validated_token
55+ def build_create_params ( request , account )
56+ url = request . params [ 'url' ] . to_s . strip
57+ raise BadRequestError , 'URL parameter is required' if url . empty?
58+ raise BadRequestError , 'Invalid URL format' unless UrlValidator . valid_url? ( url )
59+ raise ForbiddenError , 'URL not allowed for this account' unless UrlValidator . url_allowed? ( account , url )
5560
56- validated_token
57- end
61+ {
62+ url : url ,
63+ name : extract_site_title ( url ) ,
64+ strategy : normalize_strategy ( request . params [ 'strategy' ] )
65+ }
66+ end
5867
59- def get_account_for_token ( feed_token )
60- account = AccountManager . get_account_by_username ( feed_token . username )
61- raise UnauthorizedError , 'Account not found' unless account
68+ def normalize_strategy ( raw_strategy )
69+ strategy = raw_strategy . to_s . strip
70+ strategy = default_strategy if strategy . empty?
6271
63- account
64- end
72+ raise BadRequestError , 'Unsupported strategy' unless supported_strategies . include? ( strategy )
6573
66- def validate_account_access ( account , url )
67- raise ForbiddenError , 'Access Denied' unless UrlValidator . url_allowed? ( account , url )
68- end
69-
70- def generate_feed_response ( request , url )
71- strategy = select_strategy ( request . params [ 'strategy' ] )
72- rss_content = AutoSource . generate_feed_content ( url , strategy )
74+ strategy
75+ end
7376
74- request . response [ 'Content-Type' ] = 'application/xml'
77+ def validated_token_for ( token )
78+ feed_token = Auth . validate_and_decode_feed_token ( token )
79+ raise UnauthorizedError , 'Invalid token' unless feed_token
7580
76- # TODO: get ttl from feed
77- HttpCache . expires ( request . response , 600 , cache_control : 'public' )
81+ feed_token
82+ end
7883
79- rss_content . to_s
80- end
84+ def account_for ( feed_token )
85+ account = AccountManager . get_account_by_username ( feed_token . username )
86+ raise UnauthorizedError , 'Account not found' unless account
8187
82- def authenticate_request ( request )
83- account = Auth . authenticate ( request )
84- raise UnauthorizedError , 'Authentication required' unless account
88+ account
89+ end
8590
86- account
87- end
91+ def ensure_access! ( account , url )
92+ raise ForbiddenError , 'Access Denied' unless UrlValidator . url_allowed? ( account , url )
93+ end
8894
89- private
95+ def render_generated_feed ( request , url )
96+ rss_content = AutoSource . generate_feed_content ( url , normalize_strategy ( request . params [ 'strategy' ] ) )
9097
91- def extract_create_params ( request )
92- url = request . params [ 'url' ]
93- strategy = select_strategy ( request . params [ 'strategy' ] )
94- {
95- url : url ,
96- name : extract_site_title ( url ) ,
97- strategy : strategy
98- }
99- end
98+ request . response [ 'Content-Type' ] = 'application/xml'
10099
101- def validate_create_params ( params , account )
102- raise BadRequestError , 'URL parameter is required' if params [ :url ] . nil? || params [ :url ] . empty?
103- raise BadRequestError , 'Invalid URL format' unless UrlValidator . valid_url? ( params [ :url ] )
104- raise ForbiddenError , 'URL not allowed for this account' unless UrlValidator . url_allowed? ( account ,
105- params [ :url ] )
106- end
100+ # TODO: get ttl from feed
101+ HttpCache . expires ( request . response , 600 , cache_control : 'public' )
107102
108- def build_create_response ( request , feed_data )
109- request . response [ 'Content-Type' ] = 'application/json'
110- request . response . status = 201
111- feed_response_payload ( feed_data )
112- end
103+ rss_content . to_s
104+ end
113105
114- def select_strategy ( raw_strategy )
115- strategy = raw_strategy . to_s . strip
116- strategy = default_strategy if strategy . empty?
106+ def require_account ( request )
107+ account = Auth . authenticate ( request )
108+ raise UnauthorizedError , 'Authentication required' unless account
117109
118- raise BadRequestError , 'Unsupported strategy' unless supported_strategies . include? ( strategy )
110+ account
111+ end
119112
120- strategy
121- end
113+ def supported_strategies
114+ Html2rss ::RequestService . strategy_names . map ( &:to_s )
115+ end
122116
123- def supported_strategies
124- Html2rss ::RequestService . strategy_names . map ( & : to_s)
125- end
117+ def default_strategy
118+ Html2rss ::RequestService . default_strategy_name . to_s
119+ end
126120
127- def default_strategy
128- Html2rss ::RequestService . default_strategy_name . to_s
129- end
121+ def feed_response_payload ( feed_data )
122+ {
123+ success : true ,
124+ data : { feed : feed_attributes ( feed_data ) } ,
125+ meta : { created : true }
126+ }
127+ end
130128
131- def feed_response_payload ( feed_data )
132- {
133- success : true ,
134- data : { feed : feed_attributes ( feed_data ) } ,
135- meta : { created : true }
136- }
137- end
129+ def feed_attributes ( feed_data )
130+ timestamp = Time . now . iso8601
138131
139- def feed_attributes ( feed_data )
140- timestamp = Time . now . iso8601
141-
142- {
143- id : feed_data [ :id ] ,
144- name : feed_data [ :name ] ,
145- url : feed_data [ :url ] ,
146- strategy : feed_data [ :strategy ] ,
147- public_url : feed_data [ :public_url ] ,
148- created_at : timestamp ,
149- updated_at : timestamp
150- }
151- end
132+ {
133+ id : feed_data [ :id ] ,
134+ name : feed_data [ :name ] ,
135+ url : feed_data [ :url ] ,
136+ strategy : feed_data [ :strategy ] ,
137+ public_url : feed_data [ :public_url ] ,
138+ created_at : timestamp ,
139+ updated_at : timestamp
140+ }
141+ end
152142
153- def extract_site_title ( url )
154- Html2rss ::Url . for_channel ( url ) . channel_titleized
155- rescue StandardError
156- nil
143+ def extract_site_title ( url )
144+ Html2rss ::Url . for_channel ( url ) . channel_titleized
145+ rescue StandardError
146+ nil
147+ end
157148 end
158-
159- module_function :extract_create_params , :validate_create_params , :build_create_response ,
160- :authenticate_request , :select_strategy , :supported_strategies , :default_strategy ,
161- :feed_response_payload , :feed_attributes , :extract_site_title
162- private_class_method :extract_create_params , :validate_create_params , :build_create_response ,
163- :authenticate_request , :select_strategy , :supported_strategies , :default_strategy ,
164- :feed_response_payload , :feed_attributes , :extract_site_title
165149 end
166150 end
167151 end
0 commit comments