Moved hunchentoot utils to seperate package. Update readme

ご主人様
not manx 4 years ago
parent 4214c213e3
commit a31d24c28d
Signed by: C-xC-c
GPG Key ID: F52ED472284EF2F4

1
.gitignore vendored

@ -1 +1,2 @@
src/config.lisp
\#*#

@ -1,117 +1,83 @@
* BantFlags
A user script and backend enabling user created flags on [[https://boards.4chan.org/bant][/bant/]],
originally based on [[https://github.com/flaghunters/Extra-Flags-for-4chan][extraflags]].
A user script and backend enabling user created flags on [[https://boards.4chan.org/bant][/bant/]],
originally based on [[https://github.com/flaghunters/Extra-Flags-for-4chan][extraflags]].
[[https://flags.plum.moe/bantflags.user.js][Install bantflags]]
[[https://flags.plum.moe/bantflags.user.js][Install bantflags]]
** Userscript
The userscript uses of ~GM_xmlhttpRequest~ to get and post flags with
the backend . A user's flags are stored between pages using
~GM_setValue~ and ~GM_getValue~.
The userscript uses of ~GM_xmlhttpRequest~ to get and post flags with
the backend . A user's flags are stored between pages using
~GM_setValue~ and ~GM_getValue~.
Old versions of GreaseMonkey will be able to recieve updates to the
script through the ~@updateURL~ and ~@downloadURL~ directives, though
these were depricated sometime in GreaseMonkey 3.x and updates are
only checked from the location the script was downloaded from so be
careful where you upload links.
Old versions of GreaseMonkey will be able to recieve updates to the
script through the ~@updateURL~ and ~@downloadURL~ directives, though
these were depricated sometime in GreaseMonkey 3.x and updates are
only checked from the location the script was downloaded from so be
careful where you upload links.
On self hosting, changing ~back_end~ to your domain /should/ be all
you need to do, but don't take this as fact. I haven't tested the
example nginx config.
On self hosting, changing ~back_end~ to your domain /should/ be all
you need to do, but don't take this as fact. I haven't tested the
example nginx config.
The userscript has been designed specifically to target ECMAScript
2015 (ES6), making liberal use of arrow functions, and const/let
declarations. Update your hecking browser.
The userscript has been designed specifically to target ECMAScript
2015 (ES6), making liberal use of arrow functions, and const/let
declarations. Update your hecking browser.
** Backend
*** Prerequisites
- .NET Core 3.1
- MariaDB / MySQL
*** .NET dependancies
- Nito.AsyncEX
- Newtonsoft.Json
- MySql.Data
- Microsoft.AspNetCore.Mvc.NewtonsoftJson
- Microsoft.AspNetCore.StaticFiles
- Microsoft.AspNetCore.Razor
- Microsoft.EntityFrameworkCore.SqlServer
- Microsoft.EntityFrameworkCore.Tools
- Magick.NET-Q8-AnyCPU
- I use SBCL
*** Dependancies
- hunchentoot
- [[https://github.com/C-xC-c/hunchenhelpers][hunchenhelpers]], my hunchentoot helper library
- clsql
- jonathan, the JSON encoder/decoder
- cl-ppcre
*** Setup
1) [[https://dotnet.microsoft.com/download/dotnet-core][Install .NET Core]]
2) Clone and build the BantFlags solution.
3) Create the database using [[https://github.com/C-xC-c/BantFlags/blob/master/Environment/database.sql][database.sql]].
- *Change the password*.
4) configure ~BantFlags/appsettings.example.json~ with your connection
string and webroot (where you'll serve the flags from *without a
trailing slash*) and rename it to ~appsettings.json~
- [[./BantFlags/appsettings.example.json][example appsettings.json]]
- ASP.NET Core applications look for a folder called ~wwwroot~ in
the same directory as the application for static files. However
you can choose to logically seperate these by providing a vaild
directory to ~webroot~.
- That is to say, if the bantflags application is in
~/var/www/bantflags/BantFlags.dll~, the program will look for
the folder ~/var/www/bantflags/wwwroot/~ to host static content,
or whatever directory is provided to ~wwwroot~.
5) If you're hosting on your GNU/Linux distribution of choice, Create a
folder called ~keys~ in the same directory as the bantflags
executable.
- E.G. ~/var/www/bantflags/keys/~
- This is because ASP.NET Core uses some cryptic bullshit anti
forgery token when processing HTML forms, and it's unable to
persistantly store the decryption keys in memory on
GNU/Linux. This directory will store said keys when you or
users upload flags to /upload. The path uses
~AppDomain.CurrentDomain.BaseDirectory~ internally,
I.E. wherever the program is.
6) Add flags to the backend by uploading them to the flag console (/Upload).
- Flags must be 16x11 pixels and under 15kb. Their names must not
exceed 100 characters and cannot contain either "||" or ",".
7) Configure your webserver of choice to forward requests to kestral
- [[https://github.com/C-xC-c/BantFlags/blob/master/Environment/nginx.conf][Example nginx config.]]
8) Run with ~dotnet BantFlags.dll~ or create a service to run it as a
daemon.
- [[https://github.com/C-xC-c/BantFlags/blob/master/Environment/bantflags.service][Example systemd service.]]
9) ???
10) profit.
1. clone the project
2. Symlink src/ to your ~/quicklisp/local-projects
3. Move ~src/config.example.org~ to ~src/config.org~ and change it
to whatever your settings are.
4. Type the following into your repl:
#+BEGIN_SRC lisp
(ql:quickload :bantflags)
(bantflags:main)
#+END_SRC
You will almost certainly have several issues building clsql, the
database connector used. I've [[https://plum.moe/words/bludgeoning-clsql-and-mariadb.html][written a blog post]] on some of the
issues I've encountered personally, but there's no guarantee it'll
work. Piece of shit.
*** Database
Tables look like this:
Tables look like this:
*posts*
| id | post_nr | board |
| 1 | 12345 | bant |
| 2 | 56789 | bant |
*flags*
| id | flag |
| 1 | patchouli |
| 2 | chen |
*postflags*
| id | post_nr | flag |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 2 | 2 | 2 |
where ~post_nr~ and ~flag~ in *postflags* are the id fields in their
respective tables.
*posts*
| id | post_nr | board |
| 1 | 12345 | bant |
| 2 | 56789 | bant |
*flags*
| id | flag |
| 1 | patchouli |
| 2 | chen |
*postflags*
| id | post_nr | flag |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 2 | 2 | 2 |
where ~post_nr~ and ~flag~ in *postflags* are the id fields in their
respective tables.
*** API
The backend exposes three endpoints for the userscript to get and post
flags. Flags themselves are hosted from the ~flags/~ directory. This
will be whatever value you gave to ~webroot~ (or
~/path/to/bantflags/wwwroot/~ if no value is provided) + ~flags/~.
| route | purpse |
|------------+--------------------------------------------|
| /api/get | Get flags using post numbers in the thread |
| /api/post | Add flags to the database |
| /api/flags | List the flags we support |
| /flags/* | The flag images |
The backend exposes three endpoints for the userscript to get and
post flags. Flags themselves are hosted from ~flags/~ which is
~www-root/flags/~ from ~config.lisp~ on the filesystem
** Backwards Compatibility
The API is 1:1 compatable with all previous versions of
bantflags. Further improvements are achieved by encoding a ~version~
variable when poking endpoints which allows for breaking changes in
the script and backend while guaranteeing data can be parsed on both
ends. See [[https://github.com/C-xC-c/BantFlags/tree/master/Docs/][Docs/{endpoint}]] for changes and compatibility.
| route | purpse |
|------------+--------------------------------------------|
| /api/get | Get flags using post numbers in the thread |
| /api/post | Add flags to the database |
| /api/flags | List the flags we support |
| /flags/* | The flag images |
** Notes
You will get an error like =Recursive lock attempt #<SB-THREAD:MUTEX
"global-message-log-lock" owner: #<SB-THREAD:THREAD
"hunchentoot-worker-127.0.0.1:54454" RUNNING {1001DED5E3}>>.= if you
try and log to a file that doesn't exist / you don't have permissions
to read/write.

@ -182,15 +182,14 @@ function makeFlagSelect() {
flagSelect.addEventListener('click', function (e) {
// So it works if we click the flag image
const node = e.target.nodeName === 'LI' ? e.target : e.target.parentNode;
if (node.nodeName === 'LI') {
if (node.nodeName === 'LI')
flagInput.value = node.querySelector('span').innerHTML;
}
flagList.classList.toggle('hide');
});
document.getElementById('flagLoad').style.display = 'none';
document.querySelector('.flagsForm').style.marginRight = "200px"; // Element has position: absolute and is ~200px long.
document.querySelector('.flagsForm').style.marginRight = "200px"; // flagsForm has position: absolute and is ~200px long.
flagSelect.style.display = 'inline-block';
flagsLoaded = true;
});
@ -219,7 +218,8 @@ function resolveFlags() {
function (resp) {
if (resp.status !== 200) {
console.log('[bantflags] Couldn\'t load flags. Refresh the page.');
console.log('[bantflags] Couldn\'t load flags. Refresh the page');
debug(resp.responseText);
return;
}

@ -11,11 +11,13 @@
:version "0.0.1"
:serial t
:depends-on (:hunchentoot
:hunchenhelpers
:cl-ppcre
:clsql
:jonathan)
:Components
((:file "utils")
((:file "package")
(:file "utils")
(:file "db")
(:file "config")
(:file "main")))

@ -1,3 +1,5 @@
(in-package #:bantflags)
(defvar config
'((boards "bant")
(staging-password "not implemented")
@ -6,5 +8,7 @@
(www-root #p"/path/to/files/")
(port 4242)
;; These can be a file or stream, make them nil to disable logging
;; If the file can't be accessed, throws a weird error. See
;; README.org
(access-log *standard-output*)
(error-log #p"/path/to/error/log/")))

@ -2,6 +2,7 @@
;; This file is part of bantflags.
;; bantflags is licensed under the GNU AGPL Version 3.0 or later.
;; see the LICENSE file or <https://www.gnu.org/licenses/>
(in-package #:bantflags)
;; Databases in common lisp are the fucking worst.
;; Don't even bother.

@ -2,6 +2,7 @@
;; This file is part of bantflags.
;; bantflags is licensed under the GNU AGPL Version 3.0 or later.
;; see the LICENSE file or <https://www.gnu.org/licenses/>
(in-package :bantflags)
(defun init ()
(setf conn (conf 'db-conn))
@ -13,20 +14,23 @@
:port (cconf 'port)
:document-root (cconf 'www-root)
:access-log-destination (cconf 'access-log)
:message-log-destination (cconf 'error-log)))
(hunchentoot:start +serb+))
:message-log-destination (cconf 'error-log))))
(defun main ()
(handler-case (init)
(error (c)
(format t "Init fucked up, exiting ~a" c)
(return-from main)))
(handler-case (hunchentoot:start +serb+)
(error (c)
(format t "couldn't start serb: ~a" c)
(return-from main)))
(loop (sleep 43200) (gc :full t)))
(defmethod hunchentoot:acceptor-status-message (acceptor (http-status-code (eql 404)) &key)
(format nil "")) ;; Empty 404 page
(handle :post (api-post :uri "/api/post") @json
(henh:handle :post (api-post :uri "/api/post") @json
(post_nr regions board version)
(multiple-value-bind (result msg) (insert-post-p post_nr (cl-ppcre:split "," regions) board)
(cond
@ -35,12 +39,12 @@
(format nil "{\"~a\": [~{\"~a\"~^,~}]}~%" post_nr msg)) ;; This makes JSON
(t (format nil "{\"Error\": \"~a\"}~%" msg)))))
(handle :post (api-get :uri "/api/get") @json
(henh:handle :post (api-get :uri "/api/get") @json
(post_nrs board version)
(if (get-posts-p (cl-ppcre:split "," post_nrs) board)
(format nil "~a~%" (get-posts post_nrs board))
(t (format nil "{[\"~a\"]}~%" "bad"))))
(handle :get (api-flags :uri "/api/flags") @plain
(henh:handle :get (api-flags :uri "/api/flags") @plain
()
(format nil "~a~%" *flags-txt*))

@ -0,0 +1,3 @@
(defpackage #:bantflags
(:use #:cl)
(:export :init))

@ -2,6 +2,7 @@
;; This file is part of bantflags.
;; bantflags is licensed under the GNU AGPL Version 3.0 or later.
;; see the LICENSE file or <https://www.gnu.org/licenses/>
(in-package #:bantflags)
(defvar empty-flag '("empty, or there were errors. Re-set your flags."))
@ -26,7 +27,7 @@
do (setf (gethash (car flag) *flags*) id))
;; We don't want users to select `empty-flag`
(setf *flags-txt*
(cl-ppcre:regex-replace (concatenate 'string empty-flag "\\n") ;; newline
(cl-ppcre:regex-replace (concatenate 'string (car empty-flag) "\\n") ;; newline
(format nil "~{~a~^~%~}" (mapcan (lambda (x) (cdr x)) flags))
""))))
@ -59,20 +60,6 @@
(every #'post-number-p post_nrs)
(boardp board)))
;; hunchentoot
(defmacro handle (method uri content-type params &body body)
"Creates an easy handles for a specific HTTP request method. If the
method provided sent from the client isn't correct, return 404 and
stop processing the request.
(handle :get (uri-fun :uri \"/path/to/page\"/) @content-type (args) (body))"
`(hunchentoot:define-easy-handler ,uri ,params
(unless (eq ,method (hunchentoot:request-method*))
(setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
(hunchentoot:abort-request-handler))
(setf (tbnl:content-type* tbnl:*reply*) ,content-type)
,@body))
;; Content types
(defvar @json "application/json")
(defvar @plain "text/plain")

Loading…
Cancel
Save