@@ -5,26 +5,26 @@ module SlackApi
55 class MethodsSpider < BaseSpider
66 handle 'https://api.slack.com/methods' , :process_list
77
8+ def downloader
9+ @downloader ||= SlackApi ::Docs ::Downloader . new
10+ end
11+
812 def process_list ( page , _default_data = { } )
9- methods_page = ensure! ( page , '.apiMethodPage' )
10- list = methods_page . search ( '.apiMethodPage__methodList' )
11- ref = list . search ( '[data-automount-component=ApiDocsFilterableReferenceList]' )
12- data = JSON . parse ( ref . attribute ( 'data-automount-props' ) )
13- raise ( ElementNotFound , 'Could not parse methods reference' ) unless data [ 'items' ] . any?
13+ methods = JSON . load_file ( downloader . methods_path )
1414
1515 groups = Set . new
16- data [ 'items' ] . each do |method |
17- next unless method [ 'isPublic' ]
18- next if method [ 'isDeprecated' ]
1916
20- groups += method [ 'groups' ]
17+ methods . each do |method |
18+ groups += method [ 'family' ]
2119 method_name = method [ 'name' ]
22- method_group = method [ 'groups' ] . first . split ( '.' ) . first
20+ method_group = method [ 'family' ] . first . split ( '.' ) . first
21+ downloaded_filename = downloader . method_target_path ( method_name )
2322 file_name = "methods/#{ method_group } /#{ method_name } .json"
24- method_url = resolve_url ( method [ 'link' ] , page )
23+ method_url = resolve_url ( downloader . method_url ( method_name ) , page )
2524 handle method_url ,
2625 :process_method ,
2726 filename : file_name ,
27+ downloaded_filename : downloaded_filename ,
2828 method_name : method_name ,
2929 method_group : method_group ,
3030 method_url : method_url
@@ -37,14 +37,15 @@ def process_list(page, _default_data = {})
3737 end
3838 end
3939
40- def process_method ( page , default_data = { } )
41- method_page = ensure! ( page , '.apiMethodPage' , default_data [ :method_name ] )
42- desc = method_page . search ( '.apiReference__mainDescription' ) . text . gsub ( '’' , "'" )
43- return if desc . downcase . start_with? 'deprecated:'
40+ def process_method ( method_page , default_data = { } )
41+ method_data = JSON . load_file ( default_data [ :downloaded_filename ] )
42+
43+ desc = method_data [ 'desc' ] . gsub ( '’' , "'" )
44+ return if desc . downcase . start_with? 'Deprecated:'
4445
45- args , arg_groups , fields = parse_args ( method_page , default_data )
46- errors = parse_errors ( method_page , default_data )
47- response = parse_response ( method_page , default_data )
46+ args , arg_groups , fields = parse_args ( method_page , method_data )
47+ errors = parse_errors ( method_page , method_data )
48+ response = parse_response ( method_page , method_data )
4849
4950 json_hash = {
5051 'group' => default_data [ :method_group ] ,
@@ -62,24 +63,28 @@ def process_method(page, default_data = {})
6263
6364 private
6465
65- def parse_args ( api_page , default_data = { } )
66- args_wrapper = ensure! ( api_page , '.apiReference__arguments' , default_data [ :method_name ] )
67- rows = args_wrapper . search ( '.apiMethodPage__argumentRow' )
66+ def parse_args ( _api_page , method_data = { } )
6867 args = { }
6968 fields = { }
70- rows . each do |row |
71- name = row . search ( '.apiMethodPage__argument code' ) . text
72- type = massage_type ( name ,
73- row . search ( '.apiMethodPage__argumentType' ) . text ,
74- default_data )
75- required = row . search ( '.apiMethodPage__argumentOptionality--required' ) . any?
76-
77- desc = row . search ( '.apiMethodPage__argumentDesc p' )
78- . text
69+ method_data [ 'args' ] [ 'properties' ] . each_pair do |name , arg |
70+ arg [ 'anyOf' ] &.each do |coll |
71+ all = [ ]
72+ k = coll . first . key
73+ coll . each_pair do |_k , v |
74+ all << v
75+ end
76+ arg [ k ] = all
77+ end
78+ arg . delete ( 'anyOf' )
79+
80+ type = massage_type ( name , arg , method_data )
81+ required = method_data [ 'args' ] [ 'required' ] . include? ( name )
82+
83+ desc = arg [ 'desc' ]
7984 . tap { |t | t . slice! ( "\n " ) }
8085 . tap { |t | t << '.' unless t . end_with? ( '.' ) }
8186 . gsub ( '’' , "'" )
82- example = row . search ( '.apiReference__exampleCode code' ) . first &. text
87+ example = arg [ 'example' ] || arg [ 'default' ]
8388
8489 case name
8590 when 'token'
@@ -98,89 +103,80 @@ def parse_args(api_page, default_data = {})
98103 end
99104 end
100105
101- arg_groups = parse_arg_groups ( args_wrapper )
106+ arg_groups = parse_arg_groups ( _api_page , method_data )
102107
103- [ args , arg_groups , fields ]
108+ [ args . sort . to_h , arg_groups , fields ]
104109 end
105110
106- def parse_arg_groups ( args_wrapper )
107- # Look for groups of args that are interdependent
108- groups = args_wrapper . search ( '.apiMethodPage__argumentGroup' )
109- groups = groups . map do |group |
110- # "At least one of" or "One of"
111- requirement = group . search ( '.apiMethodPage__argument em' ) . text
112- mutually_exclusive = requirement . downcase == 'one of'
113-
114- desc = group . search ( '.apiMethodPage__argumentGroupDesc p' )
115- . text
116- . tap { |t | t . slice! ( "\n " ) }
117- . tap { |t | t << '.' unless t . end_with? ( '.' ) }
118- . gsub ( '’' , "'" )
119-
120- rows = group . search ( '.apiMethodPage__argumentRow' )
121- names = rows . map do |row |
122- row . search ( '.apiMethodPage__argument code' ) . text
123- end
124-
125- {
126- 'args' => names ,
127- 'desc' => desc ,
128- 'mutually_exclusive' => mutually_exclusive
129- }
130- end
111+ def parse_arg_groups ( _api_page , _method_data = { } )
112+ groups = { }
113+
114+ # # Look for groups of args that are interdependent
115+ # groups = args_wrapper.search('.apiMethodPage__argumentGroup')
116+ # groups = groups.map do |group|
117+ # # "At least one of" or "One of"
118+ # requirement = group.search('.apiMethodPage__argument em').text
119+ # mutually_exclusive = requirement.downcase == 'one of'
120+
121+ # desc = group.search('.apiMethodPage__argumentGroupDesc p')
122+ # .text
123+ # .tap { |t| t&.slice!("\n") }
124+ # .tap { |t| t << '.' unless t.end_with?('.') }
125+ # .gsub('’', "'")
126+
127+ # rows = group.search('.apiMethodPage__argumentRow')
128+ # names = rows.map do |row|
129+ # row.search('.apiMethodPage__argument code').text
130+ # end
131+
132+ # {
133+ # 'args' => names,
134+ # 'desc' => desc,
135+ # 'mutually_exclusive' => mutually_exclusive
136+ # }
137+ # end
131138
132139 groups unless groups . empty?
133140 end
134141
135- def massage_type ( name , detected , default_data = { } )
142+ def massage_type ( name , arg , data = { } )
143+ return 'enum' if arg . key? ( 'enum' )
144+
136145 case name
137146 when 'date' then 'date'
138147 when 'latest' , 'oldest' , 'ts' then 'timestamp'
139148 when 'file' then 'file'
140149 when 'bot' , 'user' then 'user'
141150 when 'channel'
142- case default_data [ :method_group ]
151+ case data [ :method_group ]
143152 when 'im' then 'im'
144153 when 'mpim' then 'mpim'
145154 when 'groups' then 'group'
146155 else 'channel'
147156 end
148157 else
149- case detected
158+ case detected = arg [ 'type' ]
150159 when '' , 'null' then nil
151160 else detected
152161 end
153162 end
154163 end
155164
156- def parse_response ( api_page , default_data = { } )
157- response_wrapper = ensure! ( api_page , '.apiReference__response' , default_data [ :method_name ] )
158- responses = response_wrapper . search ( '.apiReference__example' )
165+ def parse_response ( _api_page , data = { } )
159166 examples = [ ]
160- responses . each do |response |
161- response . search ( 'pre' ) . each do |pre |
162- text = pre . text . strip
163- next unless text =~ /^\{ .*}$/m
164-
165- examples . push ( text )
166- end
167+ data [ 'examples' ] &.each_pair do |_example_type , response |
168+ example = JSON . pretty_generate ( response [ 'example' ] , indent : ' ' )
169+ example . gsub! ( /\{ \n \s *\} / , '{}' )
170+ example . gsub! ( /\[ \n \s *\] / , '[]' )
171+ examples . push example
167172 end
168173 { 'examples' => examples }
169174 end
170175
171- def parse_errors ( api_page , default_data = { } )
172- errors_wrapper = ensure! ( api_page , '.apiReference__errors' , default_data [ :method_name ] )
173- rows = errors_wrapper . search ( '.apiDocsTable tr' )
176+ def parse_errors ( _api_page , data = { } )
174177 errors = { }
175- rows . each do |row |
176- next if row . search ( 'th' ) . any?
177-
178- name = row . search ( '[data-label=Error]' ) . text
179- desc = row . search ( '[data-label=Description]' ) . text
180- . tap { |t | t . slice! ( "\n " ) }
181- . tap { |t | t << '.' unless t . end_with? ( '.' ) }
182-
183- errors [ name ] = desc
178+ data [ 'errors' ] &.each_pair do |name , desc |
179+ errors [ name ] = desc [ 'desc' ]
184180 end
185181 errors
186182 end
0 commit comments