diff options
Diffstat (limited to 'src/utils.scm')
| -rw-r--r-- | src/utils.scm | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/src/utils.scm b/src/utils.scm new file mode 100644 index 0000000..ddcfb3f --- /dev/null +++ b/src/utils.scm @@ -0,0 +1,137 @@ +;; kenku --- crawl and reproduce github actions +;; Copyright © 2026 bdunahu <bdunahu@operationnull.com> +;; +;; This program is free software: you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <https://www.gnu.org/licenses/>. + +(define-module (src utils) + #:use-module (srfi srfi-1) + #:use-module (ice-9 match) + #:use-module (web client) + #:use-module (web response) + #:use-module (rnrs bytevectors) + #:use-module (json) + #:use-module (ice-9 receive) + #:use-module (ice-9 textual-ports) + #:use-module (ice-9 pretty-print) + #:use-module (ice-9 regex) + #:use-module (ice-9 popen) + #:export (default-headers + url-exists? + url->scm + shell->str + normalize-file + append-to-values + mkdir-p + filter-actions-on-regex)) + +(define default-headers + `((Accept . "application/vnd.github+json") + (Authorization . ,(string-append + "Bearer " + (getenv "TOKEN"))) + (User-Agent . "curl 8.6.0"))) ;i lied + +(define (url-exists? url) + (receive (status body) + (http-request url #:headers default-headers) + (equal? 200 (response-code status)))) + +(define* (url->scm url #:key (headers default-headers)) + (receive (status body) + (http-request url #:headers headers) + (json-string->scm (utf8->string body)))) + +(define (shell->str . args) + (let* ((port (apply open-pipe* + (cons OPEN_READ + args))) + (contents (get-string-all port))) + (close-pipe port) + contents)) + +(define (normalize-file file) + (let* ((str (call-with-input-file file get-string-all)) + (str (string-filter (lambda (c) + (not (member c (list #\, #\" #\' #\return)))) + str)) + (str (string-join + (delete-duplicates (string-split str #\newline)) + "\n")) + (output (open-file file "w"))) + (display str output) + (close output))) + +(define (append-to-values hashtable k v) + (let ((existing (hash-ref hashtable k '()))) + (hash-set! hashtable k (cons v existing)) + hashtable)) + +(define (mkdir-p dir) + "Yoinked from https://codeberg.org/guix/guix." + (define absolute? + (string-prefix? "/" dir)) + (define not-slash + (char-set-complement (char-set #\/))) + (let loop ((components (string-tokenize dir not-slash)) + (root (if absolute? + "" + "."))) + (match components + ((head tail ...) + (let ((path (string-append root "/" head))) + (catch 'system-error + (lambda () + (mkdir path) + (loop tail path)) + (lambda args + (if (= EEXIST (system-error-errno args)) + (loop tail path) + (apply throw args)))))) + (() #t)))) + +(define (filter-actions-on-regex file file->regex parse-f) + "This procedure is for the bash drop-ins only, which do not filter their +outputs into files, but rather output lines which need to be filtered based on +regex. + +FILE: the file to be filtered +FILE->REGEX: an alist mapping file names to the regex each item (usually a line +in FILE, should match) would need to match for inclusion to said file name. +PARSE-F: A function describing how the contents of FILE should be parsed into +items." + (let ((ht (make-hash-table))) + (define (hash-actions-to-regex actions) + (for-each + (lambda (s) + (for-each + (lambda (pair) + (let ((file (car pair)) + (regex (cdr pair))) + (when (string-match regex s) + (append-to-values ht file s)))) + file->regex)) + actions) + ht) + (define (hash->files) + (hash-for-each (lambda (file actions) + (mkdir-p (dirname file)) + (let ((output (open-file file "w"))) + (map (lambda (a) (format output "~a~%" a)) + actions) + (close output))) + ht)) + (let* ((str (call-with-input-file file get-string-all)) + (actions (parse-f str))) + (hash-actions-to-regex actions) + (hash->files)))) |
