summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Okay <cbeok@protonmail.com>2020-04-12 13:33:22 -0500
committerColin Okay <cbeok@protonmail.com>2020-04-12 13:33:22 -0500
commit370fa3f483aae8c932fd42a5ad76c017fcf0c060 (patch)
treec4554bd7e8969b98a88a4dc840be20a6eae65966
initial commit
-rw-r--r--package.lisp4
-rw-r--r--posterbot.asd11
-rw-r--r--posterbot.lisp43
3 files changed, 58 insertions, 0 deletions
diff --git a/package.lisp b/package.lisp
new file mode 100644
index 0000000..53845d9
--- /dev/null
+++ b/package.lisp
@@ -0,0 +1,4 @@
+;;;; package.lisp
+
+(defpackage #:posterbot
+ (:use #:cl #:granolin))
diff --git a/posterbot.asd b/posterbot.asd
new file mode 100644
index 0000000..18f8cc9
--- /dev/null
+++ b/posterbot.asd
@@ -0,0 +1,11 @@
+;;;; posterbot.asd
+
+(asdf:defsystem #:posterbot
+ :description "A Matrix bot to post media links."
+ :author "Colin Okay <cbeok@protonmail.com>"
+ :license "AGPL"
+ :version "0.0.1"
+ :serial t
+ :depends-on (#:granolin #:cl-ppcre #:alexandria #:cl-fad)
+ :components ((:file "package")
+ (:file "posterbot")))
diff --git a/posterbot.lisp b/posterbot.lisp
new file mode 100644
index 0000000..0ff3160
--- /dev/null
+++ b/posterbot.lisp
@@ -0,0 +1,43 @@
+;;;; posterbot.lisp
+
+(in-package #:posterbot)
+
+(defclass posterbot (client auto-joiner) ())
+
+(defvar *posterbot* nil "dynamic variable holding the bot so I dont have to pass it around")
+
+(defparameter +image-link-regex+
+ (ppcre:create-scanner "http.+\.(png|gif|jpeg|bmp|jpg)"
+ :case-insensitive-mode t))
+
+(defun download-link (link)
+ (cl-fad:with-output-to-temporary-file (out :element-type '(unsigned-byte 8))
+ (let ((buffer (make-array 4096 :element-type '(unsigned-byte 8)))
+ (file-stream (drakma:http-request link :want-stream t)))
+ (loop :for bytes = (read-sequence buffer file-stream)
+ :while (plusp bytes) :do (write-sequence buffer out)))))
+
+
+(defun filename-from-link (link)
+ (first (last (ppcre:split "/" link))))
+
+(defun make-mime-type (filename)
+ (format nil "image/~a" (pathname-type filename)))
+
+(defun handle-link-candiate (word)
+ (let ((link (ppcre:scan-to-strings +image-link-regex+ word)))
+ (when link
+ (let* ((file-path (download-link link))
+ (file-name (filename-from-link link))
+ (mxc-uri
+ (upload *posterbot*
+ file-name
+ (alexandria:read-file-into-byte-vector file-path)
+ :content-type (make-mime-type word))))
+ (send-image-message *posterbot* *room-id* file-name mxc-uri
+ :info (list :|mimetype| (make-mime-type word)))))))
+
+;; look for links to images, one word at a time, downloading and
+;; posting any images found to the room at the current *ROOM-ID*
+(defmethod handle-event :after ((*posterbot* posterbot) (event text-message-event))
+ (mapc #'handle-link-candiate (ppcre:split " " (msg-body event))))