require 'set'
require 'yaml'
def clear_parameters(spec, path, method, parameters)
found = Set.new
parameters = Set.new(parameters)
spec['paths'][path][method]['parameters'].each do |parameter|
if parameters.include?(parameter['name'])
found.add(parameter['name'])
parameters.delete(parameter['name'])
elsif parameters.include?([parameter['name'], parameter['in']])
found.add([parameter['name'], parameter['in']])
parameters.delete([parameter['name'], parameter['in']])
end
end
raise "Parameter#{parameters.length > 1 ? 's' : ''} not found: #{parameters.to_a.sort.map(&:inspect).join(', ')}" unless parameters.empty?
spec['paths'][path][method]['parameters'].reject! do |parameter|
found.include?(parameter['name']) || found.include?([parameter['name'], parameter['in']])
end
end
def process(spec)
spec['paths'].each do |path, methods|
methods.each do |method, details|
if details['parameters']
details['parameters'].each do |parameter|
if parameter['in'] == 'query' && parameter['required'] == false
parameter.delete('required')
end
end
details['parameters'].reject! { |p| p['in'] == 'path' && !path.include?("{#{p['name']}}") }
path_parameters = details['parameters'].select { |p| p['in'] == 'path' }.map { |p| p['name'] }
details['parameters'].reject! { |p| p['in'] == 'query' && path_parameters.include?(p['name']) }
end
end
end
clear_parameters(spec, '/api2/categories/', 'get', %w[id long_name short_name url])
clear_parameters(spec, '/api2/categories/{bare_id}/', 'get', %w[id long_name short_name url])
clear_parameters(spec, '/api2/user-profiles/', 'get', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as id is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/user-profiles/{id}/', 'get', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/user-profiles/{id}/', 'put', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/user-profiles/{id}/', 'patch', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/', 'get', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as id is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/', 'get', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/', 'put', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/', 'patch', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/collect-tachyons/', 'post', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/purchase-track-record/', 'post', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/{id}/unlock-power/', 'post', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/global-cp-reminder/', 'get', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as id is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
clear_parameters(spec, '/api2/users/global-cp-reminder/', 'post', %w[ask_when_reaffirm_question_modal date_joined default_community_visibility default_mp_visibility email first_name formerly_known_as id is_staff is_superuser last_name last_visited level levelTitle permissions powers purchasable_track_record score show_profile_comments supporter_level supporter_since tachyons url username username_change_cost])
schemas_were_sorted = spec['components']['schemas'].keys == spec['components']['schemas'].keys.sort
if spec['paths']['/api2/about-numbers/']['get']['responses']['200'] == { 'description' => 'No response body' }
spec['paths']['/api2/about-numbers/']['get']['responses']['200'] = {
'content' => {
'application/json' => {
'schema' => {
'$ref' => '#/components/schemas/AboutNumbers'
}
}
},
'description' => ''
}
spec['components']['schemas']['AboutNumbers'] = {
'type' => 'object',
'properties' => {
'predictions' => { 'type' => 'integer' },
'questions' => { 'type' => 'integer' },
'resolved_questions' => { 'type' => 'integer' },
'years_of_predictions' => { 'type' => 'integer' }
},
'required' => ['predictions', 'questions', 'resolved_questions', 'years_of_predictions']
}
check_reminder_schema = false
reminder_schema_lists = [
spec['paths']['/api2/users/global-cp-reminder/']['get']['responses']['200']['content'],
spec['paths']['/api2/users/global-cp-reminder/']['post']['requestBody']['content'],
spec['paths']['/api2/users/global-cp-reminder/']['post']['responses']['200']['content']
]
reminder_schema_lists.each do |list|
list.each do |content_type, content|
if content['schema']['$ref'] == '#/components/schemas/User'
content['schema']['$ref'] = '#/components/schemas/GlobalCPReminder'
check_reminder_schema = true
end
end
end
if check_reminder_schema
spec['components']['schemas']['GlobalCPReminder'] ||= {
'type' => 'object',
'properties' => {
'enabled' => { 'type' => 'boolean' },
'delta' => { 'type' => 'integer' }
},
'required' => ['enabled', 'delta']
}
end
if spec['paths']['/api2/questions/{id}/prediction-history/']['get']['responses']['200'] == { 'description' => 'No response body' }
spec['paths']['/api2/questions/{id}/prediction-history/']['get']['responses']['200'] = {
'content' => {
'application/json' => {
'schema' => {
'$ref' => '#/components/schemas/PredictionHistory'
}
}
},
'description' => ''
}
spec['components']['schemas']['PredictionHistory'] = {
'type' => 'object',
'properties' => {
'question' => { 'type' => 'integer' },
'community_prediction' => { 'type' => 'array', 'items' => { '$ref' => '#/components/schemas/PredictionHistoryTime' } },
'metaculus_prediction' => { 'type' => 'array', 'items' => { '$ref' => '#/components/schemas/PredictionHistoryTime' } },
},
'required' => ['question', 'community_prediction', 'metaculus_prediction']
}
spec['components']['schemas']['PredictionHistoryTime'] = {
'type' => 'object',
'properties' => {
't' => { 'type' => 'number', 'format' => 'double' },
'y' => { 'type' => 'array', 'items' => { 'type' => 'number', 'format' => 'double' } },
'q1' => { 'type' => 'number', 'format' => 'double' },
'q2' => { 'type' => 'number', 'format' => 'double' },
'q3' => { 'type' => 'number', 'format' => 'double' },
'low' => { 'type' => 'number', 'format' => 'double' },
'high' => { 'type' => 'number', 'format' => 'double' },
},
'required' => ['t', 'y', 'q1', 'q2', 'q3', 'low', 'high']
}
end
if spec['paths']['/api2/questions/{id}/predictions/']['get']['responses']['200'] == { 'description' => 'No response body' }
spec['paths']['/api2/questions/{id}/predictions/']['get']['responses']['200'] = {
'content' => {
'application/json' => {
'schema' => {
'type' => 'array',
'items' => {
'$ref' => '#/components/schemas/ExtendedPredictionUsername'
}
}
}
},
'description' => ''
}
end
if schemas_were_sorted
spec['components']['schemas'] = spec['components']['schemas'].sort.to_h
end
end
spec['paths'].each do |path, methods|
methods.each do |method, details|
details.delete('parameters') if details['parameters'] == []
end
end
spec['servers'] = [{ 'url' => 'https://www.metaculus.com' }]
spec
end
spec = open('Metaculus API (1.0).yaml', 'r') { |f| YAML.load(f) }
open('Metaculus API (1.0) Modified.yaml', 'w') { |f| f.write(YAML.dump(process(spec))) }