package Managers import ( "AnP/Drivers" "AnP/Interfaces" "AnP/Models" "AnP/Modules" "AnP/Utils" "maps" "slices" "time" ) type RoutesManager struct { anp Models.AnPModel domains []string routes []Models.RoutesModel indexes []string wmarkdown_html_file string alternative_domains map[string]string } var default_indexes []string = []string{"index.w.md", "index.md", "index.html", "index.htm"} var default_wmarkdown_html string = "/HTML/AnP.wmarkdown.html" func GetDefaultHTTPResponse() map[string]any { return map[string]any{ "ok": false, "code": 502, } } func NewRoutesManager(anp Models.AnPModel, inputs any) RoutesManager { var options map[string]map[string]any = nil var alternative_domains map[string]any = Utils.Get[map[string]any](anp.Settings.Get("alternative_domains", inputs, nil), nil) var manager RoutesManager = RoutesManager{ anp: anp, domains: Utils.GetStrings(anp.Settings.Get([]string{ "default_routes_domains", "default_routes_domain", "default_domains", "default_domain", "domains", "domain", }, inputs, nil)), routes: []Models.RoutesModel{}, indexes: Utils.GetStrings(anp.Settings.Get([]string{}, inputs, Utils.GetPointer[any](default_indexes))), wmarkdown_html_file: Utils.Get(anp.Settings.Get("wmarkdown_html", inputs, Utils.GetPointer[any](default_wmarkdown_html)), &default_wmarkdown_html), alternative_domains: nil, } if alternative_domains != nil { manager.alternative_domains = map[string]string{} for domain, pattern := range alternative_domains { manager.alternative_domains[domain] = Utils.Get[string](pattern, nil) } } switch value := anp.Settings.Get([]string{"options", "route_options", "routes_options"}, inputs, nil).(type) { case map[string]any: for key, value := range value { switch subvalue := value.(type) { case map[string]any: if options == nil { options = map[string]map[string]any{ key: {}, } } for header_key, header_value := range subvalue { options[key][header_key] = header_value } } } } for _, key := range []string{"default_routes_files", "default_routes", "routes_files", "routes"} { manager.Add(anp.Settings.Get(key, inputs, nil), true, options) } return manager } func (_self *RoutesManager) Add(inputs any, overwrite bool, options map[string]map[string]any) { switch group := inputs.(type) { case string: var route Models.RoutesModel = Models.NewRoutesModel(group, options) if route.Ok { var i int = -1 var exists bool = false for _, current := range _self.routes { if current.IsSame(route) { i = current.I exists = true break } } if overwrite || !exists { if exists { _self.routes[i] = route route.I = i } else { route.I = len(_self.routes) _self.routes = append(_self.routes, route) } } } else { _self.anp.Request.LoadJSON(group, func(data any) { _self.Add(data, overwrite, options) }, false) } case []any: for _, subinputs := range group { _self.Add(subinputs, overwrite, options) } } } func (_self RoutesManager) StringVariables(_string string, inputs any) string { var dictionary map[string]any = Utils.GetDictionary(inputs, false) return Utils.Patterns.Replace(_string, Utils.Patterns.RE_VIEWS_STRING_VARIABLES, func(matches Utils.PatternMatch) string { if matches.Groups[1] != "" { if value, exists := dictionary[matches.Groups[1]]; exists { return Utils.ToString(value) } } else if matches.Groups[2] != "" { return _self.anp.I18N.Get(Utils.StringVariables(matches.Groups[2], inputs, nil), inputs, matches.Groups[0]) } return matches.Groups[0] }) } func (_self RoutesManager) GetOwnFullPath(subpath string, roots []string) (string, bool) { var full_path string = subpath var exists bool = Drivers.FileExists(full_path) if !exists && roots != nil { full_path = _self.anp.Request.GetAbsolutePath(subpath, roots) exists = Drivers.FileExists(full_path) } return full_path, exists } func (_self RoutesManager) Go(request_interface Interfaces.RequestModelInterface, settings map[string]any, paths []string) (map[string]any, bool) { var response map[string]any = GetDefaultHTTPResponse() var done bool = false var request Models.RequestModel = request_interface.(Models.RequestModel) if slices.Contains(_self.domains, request.Domain) || slices.Contains(_self.domains, "") { var code int = 404 done = true for _, route := range _self.routes { var matches Utils.PatternMatch = Utils.Patterns.Match(request.URL, route.URL) if matches.Ok { var variables map[string]any = route.GetVariables(matches) if route.Type == Models.RouteTypePath { switch subpath := variables["path"].(type) { case string: var slash string = _self.anp.Request.GetSlash() var full_path string var exists bool subpath = route.Path + slash + subpath if full_path, exists = _self.GetOwnFullPath(subpath, paths); !exists { for _, index := range _self.indexes { if full_path, exists = _self.GetOwnFullPath(subpath+slash+index, paths); exists { break } } } if exists { if full_path[len(full_path)-3:] == ".md" { html, subvariables := _self.anp.WMarkDown.Process(_self.anp.Request.LoadFile(full_path), Modules.WMD.HTML, full_path) var last_date_modified time.Time = *Drivers.LastDateModified(full_path) var html_file string var request_domain string = "k3y.pw" if html_file, exists = _self.GetOwnFullPath(_self.wmarkdown_html_file, paths); !exists { html_file, exists = _self.GetOwnFullPath(default_wmarkdown_html, paths) } if _self.alternative_domains != nil { for domain, pattern := range _self.alternative_domains { if request.Domain[len(request.Domain)-len(pattern):] == pattern { request_domain = domain break } } } variables["contents"] = html variables["version"] = last_date_modified.Format("20060102") variables["request_domain"] = request_domain maps.Copy(variables, settings) for key, value := range subvariables { variables[key] = value } response["ok"] = true code = 200 response["mime"] = "text/html;charset=" + variables["charset"].(string) response["response"] = _self.StringVariables(_self.anp.Request.LoadFile(html_file), variables) } else { var mime_type string = Drivers.GetMime(full_path) var data []byte = _self.anp.Request.LoadBinaryFile(full_path) response["ok"] = true code = 200 response["mime"] = mime_type if mime_type[:5] == "text/" { response["response"] = string(data) } else { response["response"] = data } } } default: code = 501 } } else if route.Type == Models.RouteTypeView { code = 503 } else if route.Type == Models.RouteTypeController { code = 503 } else { code = 500 } response["code"] = code if route.Options != nil && (code >= 200 && code < 300) || slices.Contains([]int{301, 302, 304}, code) { response["options"] = route.Options } } } } return response, done }