From 33dfdde9ae03e3218b4796f3595d3b727f626587 Mon Sep 17 00:00:00 2001 From: Amir Rajan Date: Thu, 9 Dec 2021 23:40:11 -0600 Subject: added api.rb to repo --- dragon/api.rb | 634 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 634 insertions(+) create mode 100644 dragon/api.rb diff --git a/dragon/api.rb b/dragon/api.rb new file mode 100644 index 0000000..8ac1bae --- /dev/null +++ b/dragon/api.rb @@ -0,0 +1,634 @@ +# coding: utf-8 +# Copyright 2019 DragonRuby LLC +# MIT License +# api.rb has been released under MIT (*only this file*). + +module GTK + class Api + def initialize + end + + def get_api_autocomplete args, req + html = <<-S + + + + DragonRuby Game Toolkit Documentation + + + + +
+
index
+ +
code
+ +
+ + +
+
+      
+ + #{links} + + +S + + req.respond 200, + html, + { 'Content-Type' => 'text/html' } + end + + def post_api_autocomplete args, req + json = ($gtk.parse_json req.body) + index = json["index"].to_i + text = json["text"] + suggestions = args.gtk.suggest_autocompletion index: index, text: text + list_as_string = suggestions.join("\n") + req.respond 200, list_as_string, { 'Content-Type' => 'text/plain' } + end + + define_method :links do + <<-S + +S + end + + def get_index args, req + req.respond 200, <<-S, { 'Content-Type' => 'text/html' } + + + + DragonRuby Game Toolkit Documentation + + + #{links} + + +S + end + + def source_code_links args + links = args.gtk.reload_list_history.keys.map do |f| + "
  • #{f}
  • " + end + <<-S + +S + end + + def get_api_code args, req + view = <<-S + + + + DragonRuby Game Toolkit Documentation + + + #{source_code_links args} + + #{links} + + +S + req.respond 200, + view, + { 'Content-Type' => 'text/html' } + end + + def code_edit_view args, file + view = <<-S + + + + DragonRuby Game Toolkit Documentation + + + +
    +
    #{file}:
    + +
    + + +
    + #{source_code_links args} + + #{links} + + +S + end + + def get_api_code_edit args, req + file = req.uri.split('?').last.gsub("file=", "") + view = code_edit_view args, file + req.respond 200, + view, + { 'Content-Type' => 'text/html' } + end + + def post_api_code_update args, req + file = req.uri.split('?').last.gsub("file=", "") + code = ($gtk.parse_json req.body)["code"] + args.gtk.write_file file, code + view = code_edit_view args, file + req.respond 200, + view, + { 'Content-Type' => 'text/html' } + end + + def get_api_boot args, req + req.respond 200, + args.gtk.read_file("tmp/src_backup/boot.txt"), + { 'Content-Type' => 'text/plain' } + end + + def get_api_trace args, req + req.respond 200, + args.gtk.read_file("logs/trace.txt"), + { 'Content-Type' => 'text/plain' } + end + + def get_api_log args, req + req.respond 200, + args.gtk.read_file("logs/log.txt"), + { 'Content-Type' => 'text/plain' } + end + + def post_api_log args, req + Log.log req.body + + req.respond 200, + "ok", + { 'Content-Type' => 'text/plain' } + end + + def get_api_puts args, req + req.respond 200, + args.gtk.read_file("logs/puts.txt"), + { 'Content-Type' => 'text/plain' } + end + + def get_api_changes args, req + req.respond 200, + args.gtk.read_file("tmp/src_backup/src_backup_changes.txt"), + { 'Content-Type' => 'text/plain' } + end + + def get_favicon_ico args, req + @favicon ||= args.gtk.read_file('docs/favicon.ico') + req.respond 200, @favicon, { "Content-Type" => 'image/x-icon' } + end + + def get_src_backup args, req + file_name = req.uri.gsub("/dragon/", "") + req.respond 200, + args.gtk.read_file("tmp/src_backup/#{file_name}"), + { 'Content-Type' => 'text/plain' } + end + + def get_not_found args, req + puts("METHOD: #{req.method}"); + puts("URI: #{req.uri}"); + puts("HEADERS:"); + req.headers.each { |k,v| puts(" #{k}: #{v}") } + req.respond 404, "not found: #{req.uri}", { } + end + + def get_docs_html args, req + req.respond 200, + args.gtk.read_file("docs/docs.html"), + { 'Content-Type' => 'text/html' } + end + + def get_docs_css args, req + req.respond 200, + args.gtk.read_file("docs/docs.css"), + { 'Content-Type' => 'text/css' } + end + + def get_docs_search_gif args, req + req.respond 200, + args.gtk.read_file("docs/docs_search.gif"), + { 'Content-Type' => 'image/gif' } + end + + def get_src_backup_index_html args, req + req.respond 200, + args.gtk.read_file("/tmp/src_backup/src_backup_index.html"), + { 'Content-Type' => 'text/html' } + end + + def get_src_backup_index_txt args, req + req.respond 200, + args.gtk.read_file("/tmp/src_backup/src_backup_index.txt"), + { 'Content-Type' => 'text/txt' } + end + + def get_src_backup_css args, req + req.respond 200, + args.gtk.read_file("/tmp/src_backup/src_backup.css"), + { 'Content-Type' => 'text/css' } + end + + def get_src_backup_changes_html args, req + req.respond 200, + args.gtk.read_file("/tmp/src_backup/src_backup_changes.html"), + { 'Content-Type' => 'text/html' } + end + + def get_src_backup_changes_txt args, req + req.respond 200, + args.gtk.read_file("/tmp/src_backup/src_backup_changes.txt"), + { 'Content-Type' => 'text/txt' } + end + + def get_api_eval args, req + eval_view = <<-S + + Eval + + + +
    + +
    + +
    +
    curl -H "Content-Type: application/json" --data '{ "code": "$result = $args.state" }' -X POST http://localhost:9001/dragon/eval/
    +
    Eval Result:
    +
    
    +    #{links}
    +  
    +
    +S
    +      req.respond 200,
    +                  eval_view,
    +                  { 'Content-Type' => 'text/html' }
    +    end
    +
    +    def post_api_eval args, req
    +      if json? req
    +        code = ($gtk.parse_json req.body)["code"]
    +        code = code.gsub("$result", "$eval_result")
    +        Object.new.instance_eval do
    +          begin
    +            Kernel.eval code
    +          rescue Exception => e
    +            $eval_result = e
    +          end
    +        end
    +      end
    +
    +      req.respond 200,
    +                  "#{$eval_result || $eval_results || "nil"}",
    +                  { 'Content-Type' => 'text/plain' }
    +
    +      $eval_result  = nil
    +      $eval_results = nil
    +    end
    +
    +    def api_css_string
    +
    +    end
    +
    +    def get_api_console args, req
    +      html = console_view "# write your code here and set $result.\n$result = $gtk.args.state"
    +      req.respond 200,
    +                  html,
    +                  { 'Content-Type' => 'text/html' }
    +    end
    +
    +    def control_panel_view
    +      <<-S
    +
    +  console
    +  
    +    
    +    
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + #{links} + + +S + end + + def get_api_control_panel args, req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def json? req + req.headers.find { |k, v| k == "Content-Type" && (v.include? "application/json") } + end + + def post_api_reset args, req + $gtk.reset if json? req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def post_api_record args, req + $recording.start 100 if json? req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def post_api_record_stop args, req + $recording.stop 'replay.txt' if json? req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def post_api_replay args, req + $replay.start 'replay.txt' if json? req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def post_api_show_console args, req + $gtk.console.show if json? req + req.respond 200, + control_panel_view, + { 'Content-Type' => 'text/html' } + end + + def tick args + args.inputs.http_requests.each do |req| + match_candidate = { method: req.method.downcase.to_sym, + uri: req.uri, + uri_without_query_string: (req.uri.split '?').first, + query_string: (req.uri.split '?').last, + has_query_string: !!(req.uri.split '?').last, + has_api_prefix: (req.uri.start_with? "/dragon"), + end_with_rb: (req.uri.end_with? ".rb"), + has_file_extension: file_extensions.find { |f| req.uri.include? f }, + has_trailing_slash: (req.uri.split('?').first.end_with? "/") } + + if !match_candidate[:has_file_extension] + if !match_candidate[:has_trailing_slash] + match_candidate[:uri] = match_candidate[:uri_without_query_string] + "/" + if match_candidate[:query_string] + match_candidate[:uri] += "?#{match_candidate[:query_string]}" + end + end + end + + context = { args: args, req: req, match_candidate: match_candidate } + + process! context: context, routes: routes + end + end + + def url_decode args, string + args.fn.gsub string, + '+', " ", + '%27', "'", + '%22', '"', + '%0D%0A', "\n", + '%3D', "=", + '%3B', ";", + '%7C', "|", + '%28', "(", + '%29', ")", + '%7B', "{", + '%7D', "}", + '%2C', ",", + '%3A', ":", + '%5B', "[", + '%5D', "]", + '%23', "#", + '%21', "!", + '%3C', "<", + '%3E', ">", + '%2B', "+", + '%2F', "/", + '%40', "@", + '%3F', "?", + '%26', "&", + '%24', "$", + '%5C', "\\", + '%60', "`", + '%7E', "~", + '%C2%B2', "²", + '%5E', "^", + '%C2%BA', "º", + '%C2%A7', "§", + '%20', " ", + '%0A', "\n", + '%25', "%", + '%2A', "*" + end + + def file_extensions + [".html", ".css", ".gif", ".txt", ".ico", ".rb"] + end + + def routes + [{ match_criteria: { method: :get, uri: "/" }, + handler: :get_index }, + { match_criteria: { method: :get, uri: "/dragon/" }, + handler: :get_index }, + + { match_criteria: { method: :get, uri: "/dragon/boot/" }, + handler: :get_api_boot }, + { match_criteria: { method: :get, uri: "/dragon/trace/" }, + handler: :get_api_trace }, + { match_criteria: { method: :get, uri: "/dragon/puts/" }, + handler: :get_api_puts }, + { match_criteria: { method: :get, uri: "/dragon/log/" }, + handler: :get_api_log }, + { match_criteria: { method: :post, uri: "/dragon/log/" }, + handler: :post_api_log }, + { match_criteria: { method: :get, uri: "/dragon/changes/" }, + handler: :get_api_changes }, + { match_criteria: { method: :get, uri: "/dragon/eval/" }, + handler: :get_api_eval }, + { match_criteria: { method: :post, uri: "/dragon/eval/" }, + handler: :post_api_eval }, + { match_criteria: { method: :get, uri: "/dragon/console/" }, + handler: :get_api_console }, + { match_criteria: { method: :post, uri: "/dragon/console/" }, + handler: :post_api_console }, + { match_criteria: { method: :get, uri: "/dragon/control_panel/" }, + handler: :get_api_control_panel }, + { match_criteria: { method: :post, uri: "/dragon/reset/" }, + handler: :post_api_reset }, + { match_criteria: { method: :post, uri: "/dragon/record/" }, + handler: :post_api_record }, + { match_criteria: { method: :post, uri: "/dragon/record_stop/" }, + handler: :post_api_record_stop }, + { match_criteria: { method: :post, uri: "/dragon/replay/" }, + handler: :post_api_replay }, + { match_criteria: { method: :post, uri: "/dragon/show_console/" }, + handler: :post_api_show_console }, + { match_criteria: { method: :get, uri: "/dragon/code/" }, + handler: :get_api_code }, + { match_criteria: { method: :get, uri: "/dragon/autocomplete/" }, + handler: :get_api_autocomplete }, + { match_criteria: { method: :post, uri: "/dragon/autocomplete/" }, + handler: :post_api_autocomplete }, + { match_criteria: { method: :get, uri_without_query_string: "/dragon/code/edit/", has_query_string: true }, + handler: :get_api_code_edit }, + { match_criteria: { method: :post, uri_without_query_string: "/dragon/code/update/", has_query_string: true }, + handler: :post_api_code_update }, + + + { match_criteria: { method: :get, uri: "/docs.html" }, + handler: :get_docs_html }, + { match_criteria: { method: :get, uri_without_query_string: "/docs.css" }, + handler: :get_docs_css }, + { match_criteria: { method: :get, uri: "/docs_search.gif" }, + handler: :get_docs_search_gif }, + + { match_criteria: { method: :get, uri: "/src_backup_index.html" }, + handler: :get_src_backup_index_html }, + + { match_criteria: { method: :get, uri: "/src_backup_index.txt" }, + handler: :get_src_backup_index_txt }, + + { match_criteria: { method: :get, uri: "/src_backup_changes.html" }, + handler: :get_src_backup_changes_html }, + + { match_criteria: { method: :get, uri: "/src_backup_changes.txt" }, + handler: :get_src_backup_changes_txt }, + + { match_criteria: { method: :get, uri: "/src_backup.css" }, + handler: :get_src_backup_css }, + + { match_criteria: { method: :get, uri: "/favicon.ico" }, + handler: :get_favicon_ico }, + + { match_criteria: { method: :get, end_with_rb: true }, + handler: :get_src_backup }, + + { match_criteria: { method: :get, end_with_rb: true }, + handler: :get_src_backup } + + ] + end + + def process! opts + routes = opts[:routes] + context = opts[:context] + routes.each do |route| + match_found = (process_single! route: route, context: context) + return if match_found + end + end + + def process_single! opts + match_criteria = opts[:route][:match_criteria] + m = opts[:route][:handler] + args = opts[:context][:args] + req = opts[:context][:req] + match_candidate = opts[:context][:match_candidate] + match_criteria.each do |k, v| + return false if match_candidate[k] != v + end + + begin + send m, args, req + rescue Exception => e + req.respond 200, + "#{e}\n#{e.__backtrace_to_org__}", + { 'Content-Type' => 'text/plain' } + end + return true + end + end +end -- cgit v1.2.3