summaryrefslogtreecommitdiff
path: root/src/utils.scm
blob: ddcfb3fb436a987357151902293c679651b3953a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
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))))