modules

package
v0.1.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2025 License: GPL-3.0 Imports: 7 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var HttpModule = map[string]*object.Builtin{
	"httpGet": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 1 || len(args) > 2 {
				return &object.Error{Message: "httpGet expects 1 or 2 arguments: httpGet(url, [headers])"}
			}

			urlObj, ok := args[0].(*object.String)
			if !ok {
				if instance, ok := args[0].(*object.Instance); ok {
					if value, ok := instance.Env.Get("value"); ok {
						if str, ok := value.(*object.String); ok {
							urlObj = str
						} else {
							return &object.Error{Message: "httpGet expects URL as string"}
						}
					} else {
						return &object.Error{Message: "httpGet expects URL as string"}
					}
				} else {
					return &object.Error{Message: "httpGet expects URL as string"}
				}
			}

			client := &http.Client{
				Timeout: 30 * time.Second,
			}

			req, err := http.NewRequest("GET", urlObj.Value, nil)
			if err != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", err)}
			}

			if len(args) == 2 {
				if err := setHeaders(req, args[1]); err != nil {
					return err
				}
			}

			resp, err := client.Do(req)
			if err != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", err)}
			}
			defer resp.Body.Close()

			body, err := io.ReadAll(resp.Body)
			if err != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to read response: %v", err)}
			}

			result := &object.Hash{
				Pairs: make(map[object.HashKey]object.HashPair),
			}

			statusKey := &object.String{Value: "status"}
			result.Pairs[statusKey.HashKey()] = object.HashPair{
				Key:   statusKey,
				Value: &object.Integer{Value: int64(resp.StatusCode)},
			}

			bodyKey := &object.String{Value: "body"}
			result.Pairs[bodyKey.HashKey()] = object.HashPair{
				Key:   bodyKey,
				Value: &object.String{Value: string(body)},
			}

			headersKey := &object.String{Value: "headers"}
			result.Pairs[headersKey.HashKey()] = object.HashPair{
				Key:   headersKey,
				Value: headersToHash(resp.Header),
			}

			return result
		},
	},
	"httpPost": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 2 || len(args) > 3 {
				return &object.Error{Message: "httpPost expects 2 or 3 arguments: httpPost(url, body, [headers])"}
			}

			urlObj, err := extractString(args[0], "URL")
			if err != nil {
				return err
			}

			bodyStr, err := extractString(args[1], "body")
			if err != nil {
				return err
			}

			client := &http.Client{
				Timeout: 30 * time.Second,
			}

			req, reqErr := http.NewRequest("POST", urlObj, strings.NewReader(bodyStr))
			if reqErr != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", reqErr)}
			}

			req.Header.Set("Content-Type", "application/json")

			if len(args) == 3 {
				if err := setHeaders(req, args[2]); err != nil {
					return err
				}
			}

			resp, respErr := client.Do(req)
			if respErr != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", respErr)}
			}
			defer resp.Body.Close()

			return buildResponse(resp)
		},
	},
	"httpPut": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 2 || len(args) > 3 {
				return &object.Error{Message: "httpPut expects 2 or 3 arguments: httpPut(url, body, [headers])"}
			}

			urlObj, err := extractString(args[0], "URL")
			if err != nil {
				return err
			}

			bodyStr, err := extractString(args[1], "body")
			if err != nil {
				return err
			}

			client := &http.Client{
				Timeout: 30 * time.Second,
			}

			req, reqErr := http.NewRequest("PUT", urlObj, strings.NewReader(bodyStr))
			if reqErr != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", reqErr)}
			}

			req.Header.Set("Content-Type", "application/json")

			if len(args) == 3 {
				if err := setHeaders(req, args[2]); err != nil {
					return err
				}
			}

			resp, respErr := client.Do(req)
			if respErr != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", respErr)}
			}
			defer resp.Body.Close()

			return buildResponse(resp)
		},
	},
	"httpDelete": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 1 || len(args) > 2 {
				return &object.Error{Message: "httpDelete expects 1 or 2 arguments: httpDelete(url, [headers])"}
			}

			urlObj, err := extractString(args[0], "URL")
			if err != nil {
				return err
			}

			client := &http.Client{
				Timeout: 30 * time.Second,
			}

			req, reqErr := http.NewRequest("DELETE", urlObj, nil)
			if reqErr != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", reqErr)}
			}

			if len(args) == 2 {
				if err := setHeaders(req, args[1]); err != nil {
					return err
				}
			}

			resp, respErr := client.Do(req)
			if respErr != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", respErr)}
			}
			defer resp.Body.Close()

			return buildResponse(resp)
		},
	},
	"httpHead": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 1 || len(args) > 2 {
				return &object.Error{Message: "httpHead expects 1 or 2 arguments: httpHead(url, [headers])"}
			}

			urlObj, err := extractString(args[0], "URL")
			if err != nil {
				return err
			}

			client := &http.Client{
				Timeout: 30 * time.Second,
			}

			req, reqErr := http.NewRequest("HEAD", urlObj, nil)
			if reqErr != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", reqErr)}
			}

			if len(args) == 2 {
				if err := setHeaders(req, args[1]); err != nil {
					return err
				}
			}

			resp, respErr := client.Do(req)
			if respErr != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", respErr)}
			}
			defer resp.Body.Close()

			result := &object.Hash{
				Pairs: make(map[object.HashKey]object.HashPair),
			}

			statusKey := &object.String{Value: "status"}
			result.Pairs[statusKey.HashKey()] = object.HashPair{
				Key:   statusKey,
				Value: &object.Integer{Value: int64(resp.StatusCode)},
			}

			headersKey := &object.String{Value: "headers"}
			result.Pairs[headersKey.HashKey()] = object.HashPair{
				Key:   headersKey,
				Value: headersToHash(resp.Header),
			}

			return result
		},
	},
	"httpRequest": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return &object.Error{Message: "httpRequest expects 1 argument: httpRequest(options)"}
			}

			options, ok := args[0].(*object.Hash)
			if !ok {
				return &object.Error{Message: "httpRequest expects options as hash"}
			}

			method, err := getHashString(options, "method")
			if err != nil {
				method = "GET"
			}

			url, err := getHashString(options, "url")
			if err != nil {
				return &object.Error{Message: "httpRequest requires 'url' in options"}
			}

			var bodyReader io.Reader
			if body, err := getHashString(options, "body"); err == nil {
				bodyReader = strings.NewReader(body)
			}

			timeout := 30
			if timeoutVal, err := getHashInt(options, "timeout"); err == nil {
				timeout = int(timeoutVal)
			}

			client := &http.Client{
				Timeout: time.Duration(timeout) * time.Second,
			}

			req, reqErr := http.NewRequest(method, url, bodyReader)
			if reqErr != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to create request: %v", reqErr)}
			}

			if headers, err := getHashValue(options, "headers"); err == nil {
				if err := setHeaders(req, headers); err != nil {
					return err
				}
			}

			resp, respErr := client.Do(req)
			if respErr != nil {
				return &object.Error{Message: fmt.Sprintf("Request failed: %v", respErr)}
			}
			defer resp.Body.Close()

			return buildResponse(resp)
		},
	},
	"httpParseJSON": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return &object.Error{Message: "httpParseJSON expects 1 argument: httpParseJSON(jsonString)"}
			}

			jsonStr, err := extractString(args[0], "JSON string")
			if err != nil {
				return err
			}

			var result interface{}
			if err := json.Unmarshal([]byte(jsonStr), &result); err != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to parse JSON: %v", err)}
			}

			return jsonToObject(result)
		},
	},
	"httpStringifyJSON": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return &object.Error{Message: "httpStringifyJSON expects 1 argument: httpStringifyJSON(object)"}
			}

			data := objectToInterface(args[0])
			jsonBytes, err := json.Marshal(data)
			if err != nil {
				return &object.Error{Message: fmt.Sprintf("Failed to stringify JSON: %v", err)}
			}

			return &object.String{Value: string(jsonBytes)}
		},
	},
	"httpBuildQuery": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return &object.Error{Message: "httpBuildQuery expects 1 argument: httpBuildQuery(params)"}
			}

			params, ok := args[0].(*object.Hash)
			if !ok {
				return &object.Error{Message: "httpBuildQuery expects params as hash"}
			}

			var queryParts []string
			for _, pair := range params.Pairs {
				key := pair.Key.Inspect()
				value := pair.Value.Inspect()
				queryParts = append(queryParts, fmt.Sprintf("%s=%s", key, value))
			}

			return &object.String{Value: strings.Join(queryParts, "&")}
		},
	},
}
View Source
var TimeModule = map[string]*object.Builtin{
	"timeNow": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 0 {
				return &object.Error{Message: "timeNow takes no arguments"}
			}
			return &object.Integer{Value: time.Now().Unix()}
		},
	},
	"timeNowNano": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 0 {
				return &object.Error{Message: "timeNowNano takes no arguments"}
			}
			return &object.Integer{Value: time.Now().UnixNano()}
		},
	},
	"timeSleep": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 1 {
				return &object.Error{Message: "timeSleep requires 1 argument: seconds (INT or FLOAT)"}
			}

			switch val := args[0].(type) {
			case *object.Integer:
				if val.Value < 0 {
					return &object.Error{Message: "timeSleep duration cannot be negative"}
				}
				time.Sleep(time.Duration(val.Value) * time.Second)
			case *object.Float:
				if val.Value < 0 {
					return &object.Error{Message: "timeSleep duration cannot be negative"}
				}
				nanos := int64(val.Value * 1_000_000_000)
				time.Sleep(time.Duration(nanos))
			case *object.Instance:

				if value, exists := val.Env.Get("value"); exists {
					switch innerVal := value.(type) {
					case *object.Integer:
						if innerVal.Value < 0 {
							return &object.Error{Message: "timeSleep duration cannot be negative"}
						}
						time.Sleep(time.Duration(innerVal.Value) * time.Second)
					case *object.Float:
						if innerVal.Value < 0 {
							return &object.Error{Message: "timeSleep duration cannot be negative"}
						}
						nanos := int64(innerVal.Value * 1_000_000_000)
						time.Sleep(time.Duration(nanos))
					default:
						return &object.Error{Message: "timeSleep instance value must be INTEGER or FLOAT, got " + string(innerVal.Type())}
					}
				} else {
					return &object.Error{Message: "timeSleep instance missing value"}
				}
			default:
				return &object.Error{Message: "timeSleep argument must be INTEGER or FLOAT, got " + string(args[0].Type())}
			}

			return &object.None{}
		},
	},
	"timeFormat": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) < 1 || len(args) > 2 {
				return &object.Error{Message: "timeFormat requires 1 or 2 arguments: timestamp, [format]"}
			}

			timestamp, ok := args[0].(*object.Integer)
			if !ok {
				return &object.Error{Message: "timeFormat first argument must be INTEGER timestamp"}
			}

			format := "2006-01-02 15:04:05"
			if len(args) == 2 {
				formatArg, ok := args[1].(*object.String)
				if !ok {
					return &object.Error{Message: "timeFormat second argument must be STRING format"}
				}
				format = formatArg.Value
			}

			t := time.Unix(timestamp.Value, 0)
			formatted := t.Format(format)
			return &object.String{Value: formatted}
		},
	},
	"timeParse": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 2 {
				return &object.Error{Message: "timeParse requires 2 arguments: format, timeString"}
			}

			format, ok1 := args[0].(*object.String)
			timeStr, ok2 := args[1].(*object.String)
			if !ok1 || !ok2 {
				return &object.Error{Message: "timeParse arguments must be STRINGs"}
			}

			t, err := time.Parse(format.Value, timeStr.Value)
			if err != nil {
				return &object.Error{Message: "timeParse failed: " + err.Error()}
			}

			return &object.Integer{Value: t.Unix()}
		},
	},
	"timeDate": {
		Fn: func(args ...object.Object) object.Object {
			var t time.Time
			if len(args) == 0 {
				t = time.Now()
			} else if len(args) == 1 {
				timestamp, ok := args[0].(*object.Integer)
				if !ok {
					return &object.Error{Message: "timeDate argument must be INTEGER timestamp"}
				}
				t = time.Unix(timestamp.Value, 0)
			} else {
				return &object.Error{Message: "timeDate requires 0 or 1 arguments"}
			}

			year, month, day := t.Date()
			elements := []object.Object{
				&object.Integer{Value: int64(year)},
				&object.Integer{Value: int64(month)},
				&object.Integer{Value: int64(day)},
			}
			return &object.Array{Elements: elements}
		},
	},
	"timeAddDuration": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 2 {
				return &object.Error{Message: "timeAddDuration requires 2 arguments: timestamp, seconds"}
			}

			timestamp, ok1 := args[0].(*object.Integer)
			duration, ok2 := args[1].(*object.Integer)
			if !ok1 || !ok2 {
				return &object.Error{Message: "timeAddDuration arguments must be INTEGERs"}
			}

			t := time.Unix(timestamp.Value, 0)
			newTime := t.Add(time.Duration(duration.Value) * time.Second)
			return &object.Integer{Value: newTime.Unix()}
		},
	},
	"timeDiff": {
		Fn: func(args ...object.Object) object.Object {
			if len(args) != 2 {
				return &object.Error{Message: "timeDiff requires 2 arguments: timestamp1, timestamp2"}
			}

			ts1, ok1 := args[0].(*object.Integer)
			ts2, ok2 := args[1].(*object.Integer)
			if !ok1 || !ok2 {
				return &object.Error{Message: "timeDiff arguments must be INTEGERs"}
			}

			diff := ts1.Value - ts2.Value
			return &object.Integer{Value: diff}
		},
	},
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL