<commit_before>;;; Copyright 2012 <NAME> All Rights Reserved.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;;     http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

(in-package #:orcabot)

(defvar *orcabot-data-root-pathname* nil)
(defparameter *orcabot-static-root-pathname*
  (merge-pathnames #p"data/"
                   (asdf:component-pathname (asdf:find-system "orcabot"))))

(define-condition keepalive-failed () ())
(define-condition orcabot-exiting () ())
(define-condition no-such-module (error) ())

(defvar *command-funcs* (make-hash-table :test 'equalp))

(defun static-path (filename)
  "Returns a pathname referring to the static data directory in the
project root."
  (merge-pathnames filename *orcabot-static-root-pathname*))

(defun data-path (filename)
  "Returns a pathname within the data directory specified at startup."
  (merge-pathnames filename *orcabot-data-root-pathname*))

(defun write-to-file (path object)
  (with-open-file (ouf (data-path path)
                       :direction :output
                       :if-exists :supersede
                       :if-does-not-exist :create)
    (write object :stream ouf)
    (terpri ouf)))

(defun http-to-file (url path)
  (let ((inf (drakma:http-request url :want-stream t)))
    (when inf
      (let ((byte-stream (flexi-streams:flexi-stream-stream inf)))
        (with-open-file (ouf path
                             :element-type '(unsigned-byte 8)
                             :direction :output
                             :if-exists :supersede
                             :if-does-not-exist :create)
          (loop
             with buf = (make-array #x2000 :element-type '(unsigned-byte 8))
             for read-bytes = (read-sequence buf byte-stream)
             while (= read-bytes #x2000)
             do (write-sequence buf ouf)
             finally (write-sequence buf ouf :end read-bytes))))
      t)))

(defun join-to-string (delimiter seq)
  "Returns a string with the printed elements of SEQ seperated by the
printed elements of DELIMITER."
  (with-output-to-string (result)
    (cond
      ((consp seq)
        (loop for el on seq do
             (write (car el) :stream result :escape nil)
             (when (cdr el)
               (write delimiter :stream result :escape nil))))
      ((plusp (length seq))
        (loop 
           for idx from 0 upto (- (length seq) 2)
           do
             (write (elt seq idx) :stream result :escape nil)
             (write delimiter :stream result :escape nil)
           finally (write (elt seq (1- (length seq))) :stream result :escape nil))))))

(defun string-limit (str max-len)
  (string-trim '(#\space)
               (if (< (length str) max-len)
                   str
                   (let ((pivot (position-if-not #'alphanumericp
                                                 str
                                                 :from-end t
                                                 :end max-len)))
                     (concatenate 'string
                                  (subseq str 0 (or pivot max-len))
                                  "...")))))

(defun action-to (message fmt &rest args)
  (let* ((raw-response (format nil "~?" fmt args))
         (raw-response-lines (ppcre:split "\\n" raw-response))
         (responses (mapcar (lambda (line)
                              (string-limit line 500))
                            raw-response-lines)))
    (cond
      ((char= #\# (char (first (arguments message)) 0))
       (dolist (line responses)
         (when (string/= line "")
           (irc::action (connection message) (first (arguments message)) line))))
      (t
       (dolist (line responses)
         (when (string/= line "")
           (irc::action (connection message) (source message) line)))))))

(defun reply-to (message fmt &rest args)
  (let* ((raw-response (format nil "~?" fmt args))
         (raw-response-lines (ppcre:split "\\n" raw-response))
         (responses (mapcar (lambda (line)
                              (string-limit line 500))
                            raw-response-lines)))
    (cond
      ((char= #\# (char (first (arguments message)) 0))
       (dolist (line responses)
         (when (string/= line "")<commit_msg>Wrap long output lines instead of truncating them<commit_after>;;; Copyright 2012 <NAME> All Rights Reserved.
;;;
;;; Licensed under the Apache License, Version 2.0 (the "License");
;;; you may not use this file except in compliance with the License.
;;; You may obtain a copy of the License at
;;;
;;;     http://www.apache.org/licenses/LICENSE-2.0
;;;
;;; Unless required by applicable law or agreed to in writing, software
;;; distributed under the License is distributed on an "AS IS" BASIS,
;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
;;; See the License for the specific language governing permissions and
;;; limitations under the License.

(in-package #:orcabot)

(defvar *orcabot-data-root-pathname* nil)
(defparameter *orcabot-static-root-pathname*
  (merge-pathnames #p"data/"
                   (asdf:component-pathname (asdf:find-system "orcabot"))))

(define-condition keepalive-failed () ())
(define-condition orcabot-exiting () ())
(define-condition no-such-module (error) ())

(defvar *command-funcs* (make-hash-table :test 'equalp))

(defun static-path (filename)
  "Returns a pathname referring to the static data directory in the
project root."
  (merge-pathnames filename *orcabot-static-root-pathname*))

(defun data-path (filename)
  "Returns a pathname within the data directory specified at startup."
  (merge-pathnames filename *orcabot-data-root-pathname*))

(defun write-to-file (path object)
  (with-open-file (ouf (data-path path)
                       :direction :output
                       :if-exists :supersede
                       :if-does-not-exist :create)
    (write object :stream ouf)
    (terpri ouf)))

(defun http-to-file (url path)
  (let ((inf (drakma:http-request url :want-stream t)))
    (when inf
      (let ((byte-stream (flexi-streams:flexi-stream-stream inf)))
        (with-open-file (ouf path
                             :element-type '(unsigned-byte 8)
                             :direction :output
                             :if-exists :supersede
                             :if-does-not-exist :create)
          (loop
             with buf = (make-array #x2000 :element-type '(unsigned-byte 8))
             for read-bytes = (read-sequence buf byte-stream)
             while (= read-bytes #x2000)
             do (write-sequence buf ouf)
             finally (write-sequence buf ouf :end read-bytes))))
      t)))

(defun join-to-string (delimiter seq)
  "Returns a string with the printed elements of SEQ seperated by the
printed elements of DELIMITER."
  (with-output-to-string (result)
    (cond
      ((consp seq)
        (loop for el on seq do
             (write (car el) :stream result :escape nil)
             (when (cdr el)
               (write delimiter :stream result :escape nil))))
      ((plusp (length seq))
        (loop 
           for idx from 0 upto (- (length seq) 2)
           do
             (write (elt seq idx) :stream result :escape nil)
             (write delimiter :stream result :escape nil)
           finally (write (elt seq (1- (length seq))) :stream result :escape nil))))))

(defun string-limit (str max-len)
  (string-trim '(#\space)
               (if (< (length str) max-len)
                   str
                   (let ((pivot (position-if-not #'alphanumericp
                                                 str
                                                 :from-end t
                                                 :end max-len)))
                     (concatenate 'string
                                  (subseq str 0 (or pivot max-len))
                                  "...")))))

(defun wrap-string (string width)
  "Given an initial string, returns the string broken up into lines breaking on word boundaries."
  (loop
     for raw-wrap-pos = width then (+ wrap-pos width)
     until (> raw-wrap-pos (length string))
     for wrap-pos = (or (position-if-not #'alpha-char-p string :end raw-wrap-pos :from-end t)
                        raw-wrap-pos)
     for start-pos = 0 then (1+ wrap-pos)
     collect (string-trim " " (subseq string start-pos wrap-pos))
     into result
     finally (return (nconc result
                            (list (string-trim " "
                                               (subseq string (or wrap-pos 0))))))))


(defun action-to (message fmt &rest args)
  (let* ((raw-response (format nil "~?" fmt args))
         (raw-response-lines (ppcre:split "\\n" raw-response))
         (responses (mapcan (lambda (line)
                              (wrap-string line 405))
                            raw-response-lines)))
    (cond
      ((char= #\# (char (first (arguments message)) 0))
       (dolist (line responses)
         (when (string/= line "")
           (irc::action (connection message) (first (arguments message)) line))))
      (t
       (dolist (line responses)
         (when (string/= line "")
           (irc::action (connection message) (source message) line)))))))

(defun reply-to (message fmt &rest args)
  (let* ((raw-response (format nil "~?" fmt args))
         (raw-response-lines (ppcre:split "\\n" raw-response))
         (responses (mapcan (lambda (line)
                              (wrap-string line 405))
                            raw-response-lines)))
    (cond
      ((char= #\# (char (first (arguments message)) 0))
       (dolist (line responses)
         (when (string/= line "")
{'fraction_non_alphanumeric': 0.12307236061684461, 'fraction_numerical': 0.006227758007117438, 'mean_word_length': 1.9299160150593686, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 6, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 18, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5954233', 'n_tokens_mistral': 2908, 'n_tokens_neox': 2800, 'n_words': 925}