require 'sinatra' require 'json' require 'yaml' # Configure Sinatra set :port, ENV['PORT'] || 4567 set :bind, '0.0.0.0' set :public_folder, 'public' set :views, 'views' # Load responses from YAML file RESPONSES = YAML.load_file('responses.yml') DEFAULT_LANGUAGE = 'en' # Helper method to get a random "no" response def get_no_response(lang = DEFAULT_LANGUAGE) language = RESPONSES[lang] || RESPONSES[DEFAULT_LANGUAGE] language['responses'].sample end # Helper method to get language name def get_language_name(lang) language = RESPONSES[lang] || RESPONSES[DEFAULT_LANGUAGE] language['name'] end # Helper method to get available languages def get_available_languages RESPONSES.map { |code, data| { code: code, name: data['name'] } } end # Helper method to determine language from request def determine_language(params, headers) # Priority: URL parameter > Accept-Language header > default return params[:lang] if params[:lang] && RESPONSES[params[:lang]] # Parse Accept-Language header if headers['HTTP_ACCEPT_LANGUAGE'] accepted_langs = headers['HTTP_ACCEPT_LANGUAGE'] .split(',') .map { |lang| lang.split(';').first.downcase.strip } # Check for exact matches first accepted_langs.each do |lang| return lang if RESPONSES[lang] end # Check for language family matches (e.g., 'nb' or 'nn' -> 'no') accepted_langs.each do |lang| case lang when /^zh/ # Chinese variants return 'zh' when /^es/ # Spanish variants return 'es' when /^hi/ # Hindi variants return 'hi' when /^ar/ # Arabic variants return 'ar' when /^bn/ # Bengali variants return 'bn' when /^pt/ # Portuguese variants return 'pt' when /^ru/ # Russian variants return 'ru' when /^ja/ # Japanese variants return 'ja' when /^tr/ # Turkish variants return 'tr' when /^ko/ # Korean variants return 'ko' when /^fr/ # French variants return 'fr' when /^de/ # German variants return 'de' when /^vi/ # Vietnamese variants return 'vi' when /^it/ # Italian variants return 'it' when /^th/ # Thai variants return 'th' when /^pl/ # Polish variants return 'pl' when /^nl/ # Dutch variants return 'nl' when /^ur/ # Urdu variants return 'ur' when /^ms/ # Malay variants return 'ms' when /^nb|nn/ # Norwegian Bokmål/Nynorsk return 'no' when /^sv/ # Swedish variants return 'sv' when /^da/ # Danish variants return 'da' when /^is/ # Icelandic variants return 'is' when /^fi/ # Finnish variants return 'fi' when /^fo/ # Faroese variants return 'fo' when /^se|smi/ # Sami variants return 'smi' end end end DEFAULT_LANGUAGE end # Root endpoint - returns HTML by default get '/' do lang = determine_language(params, request.env) no_response = get_no_response(lang) case request.accept.first&.to_s when /application\/json/ content_type :json { answer: no_response, language: lang, language_name: get_language_name(lang), timestamp: Time.now.iso8601 }.to_json else content_type :html erb :index, locals: { no_response: no_response, language: lang, language_name: get_language_name(lang), available_languages: get_available_languages } end end # Languages endpoint - list available languages get '/languages' do content_type :json { languages: get_available_languages, default: DEFAULT_LANGUAGE, timestamp: Time.now.iso8601 }.to_json end # Explicit JSON endpoint with language support get '/api/no' do lang = determine_language(params, request.env) content_type :json { answer: get_no_response(lang), language: lang, language_name: get_language_name(lang), timestamp: Time.now.iso8601, service: "No as a Service", version: "2.0.0" }.to_json end # Language-specific endpoint get '/api/no/:lang' do lang = params[:lang] unless RESPONSES[lang] content_type :json status 404 return { error: "Language not supported", requested: lang, available: get_available_languages.map { |l| l[:code] }, timestamp: Time.now.iso8601 }.to_json end content_type :json { answer: get_no_response(lang), language: lang, language_name: get_language_name(lang), timestamp: Time.now.iso8601, service: "No as a Service", version: "2.0.0" }.to_json end # Health check endpoint get '/health' do content_type :json { status: "healthy", languages_loaded: RESPONSES.keys.size, timestamp: Time.now.iso8601 }.to_json end # Catch-all route for any other endpoint get '/*' do lang = determine_language(params, request.env) no_response = get_no_response(lang) case request.accept.first&.to_s when /application\/json/ content_type :json { answer: no_response, language: lang, language_name: get_language_name(lang), timestamp: Time.now.iso8601 }.to_json else content_type :html erb :index, locals: { no_response: no_response, language: lang, language_name: get_language_name(lang), available_languages: get_available_languages } end end