mirror of
https://codeberg.org/cage/tinmop/
synced 2025-02-10 07:20:35 +01:00
- added a directory to store gempub, the software will sync the directory's contents with its internal metadata database.
This commit is contained in:
parent
ff5f8f0cd7
commit
a8dca176f3
@ -41,6 +41,10 @@ editor = "nano --locking"
|
||||
# (default 'no', change to 'yes' if desired)
|
||||
start.update.gemlog = yes
|
||||
|
||||
# directory to scan for gempub files
|
||||
|
||||
gempub.directory.library = /home/cage/lisp/tinmop/
|
||||
|
||||
# close links window when opening the selected link
|
||||
|
||||
open-message-link-window.close-after-select = yes
|
||||
|
@ -331,7 +331,6 @@ example
|
||||
example
|
||||
|
||||
(make-delete :table-name
|
||||
(:col-a :col-b)
|
||||
(:and (:= col-a 1)
|
||||
(:= col-b 2)))
|
||||
"
|
||||
@ -343,7 +342,7 @@ example
|
||||
|
||||
example
|
||||
|
||||
(make-delete :table-name
|
||||
(make-update :table-name
|
||||
(:col-a :col-b)
|
||||
(1 2)
|
||||
(:and (:= col-a 1)
|
||||
|
100
src/db.lisp
100
src/db.lisp
@ -591,15 +591,15 @@
|
||||
" \"local-uri\" TEXT, "
|
||||
" \"original-uri\" TEXT, "
|
||||
" title TEXT, "
|
||||
" gpubVersion TEXT, "
|
||||
" \"index\" TEXT, "
|
||||
" \"gpub-version\" TEXT, "
|
||||
" \"index-file\" TEXT, "
|
||||
" author TEXT, "
|
||||
" language TEXT, "
|
||||
" charset TEXT, "
|
||||
" description TEXT, "
|
||||
" published TEXT, "
|
||||
" publishDate TEXT, "
|
||||
" revisionDate TEXT, "
|
||||
" \"publish-date\" TEXT, "
|
||||
" \"revision-date\" TEXT, "
|
||||
" copyright TEXT, "
|
||||
" license TEXT, "
|
||||
" version TEXT, "
|
||||
@ -1861,6 +1861,34 @@ row."
|
||||
|
||||
(gen-access-message-row section :section)
|
||||
|
||||
(gen-access-message-row local-uri :local-uri)
|
||||
|
||||
(gen-access-message-row original-uri :original-uri)
|
||||
|
||||
(gen-access-message-row gpub-version :gpub-version)
|
||||
|
||||
(gen-access-message-row index-file :index-file)
|
||||
|
||||
(gen-access-message-row author :author)
|
||||
|
||||
(gen-access-message-row language :language)
|
||||
|
||||
(gen-access-message-row charset :charset)
|
||||
|
||||
(gen-access-message-row publishedp :published)
|
||||
|
||||
(gen-access-message-row publish-date :publish-date)
|
||||
|
||||
(gen-access-message-row revision-date :revision-date)
|
||||
|
||||
(gen-access-message-row copyright :copyright)
|
||||
|
||||
(gen-access-message-row license :license)
|
||||
|
||||
(gen-access-message-row version :version)
|
||||
|
||||
(gen-access-message-row cover :cover)
|
||||
|
||||
(defun row-votes-count (row)
|
||||
(and row (db-getf row :votes-count :default 0)))
|
||||
|
||||
@ -3170,3 +3198,67 @@ days in the past"
|
||||
|
||||
(defun bookmark-delete (id)
|
||||
(delete-by-id +table-bookmark+ id))
|
||||
|
||||
(defun gempub-metadata-add (local-uri
|
||||
&optional
|
||||
original-uri
|
||||
title
|
||||
gpub-version
|
||||
index-file
|
||||
author
|
||||
language
|
||||
charset
|
||||
description
|
||||
published
|
||||
publish-date
|
||||
revision-date
|
||||
copyright
|
||||
license
|
||||
version
|
||||
cover)
|
||||
(assert (stringp local-uri))
|
||||
(with-db-current-timestamp (now)
|
||||
(query (make-insert +table-gempub-metadata+
|
||||
(:local-uri
|
||||
:original-uri
|
||||
:title
|
||||
:gpub-version
|
||||
:index-file
|
||||
:author
|
||||
:language
|
||||
:charset
|
||||
:description
|
||||
:published
|
||||
:publish-date
|
||||
:revision-date
|
||||
:copyright
|
||||
:license
|
||||
:version
|
||||
:cover
|
||||
:created-at)
|
||||
(local-uri
|
||||
original-uri
|
||||
title
|
||||
gpub-version
|
||||
index-file
|
||||
author
|
||||
language
|
||||
charset
|
||||
description
|
||||
published
|
||||
publish-date
|
||||
revision-date
|
||||
copyright
|
||||
license
|
||||
version
|
||||
cover
|
||||
now)))))
|
||||
|
||||
(defun all-gempub-metadata ()
|
||||
(query (select :* (from +table-gempub-metadata+))))
|
||||
|
||||
(defun gempub-metadata-delete (local-uri)
|
||||
(query (delete-from +table-gempub-metadata+ (where (:= :local-uri local-uri)))))
|
||||
|
||||
(defun gempub-metadata-find (local-uri)
|
||||
(query (select :* (from +table-gempub-metadata+) (where (:= :local-uri local-uri)))))
|
||||
|
@ -133,6 +133,26 @@
|
||||
(setf all-paths (sort all-paths #'string<))
|
||||
all-paths))
|
||||
|
||||
(defun collect-files/dirs (root)
|
||||
(let ((all-files '())
|
||||
(all-dirs '()))
|
||||
(labels ((collect (dir)
|
||||
(when (not (member dir all-files :test #'string=))
|
||||
(let* ((all-children (collect-children dir))
|
||||
(files (remove-if #'directory-exists-p all-children))
|
||||
(directories (remove-if (lambda (a)
|
||||
(or (file-exists-p a)
|
||||
(string= (path-last-element a) ".")
|
||||
(string= (path-last-element a) "..")))
|
||||
all-children)))
|
||||
(setf all-files (append all-files files))
|
||||
(setf all-dirs (append all-dirs directories))
|
||||
(loop for new-dir in directories do
|
||||
(collect new-dir))))))
|
||||
(collect root)
|
||||
(values all-files
|
||||
all-dirs))))
|
||||
|
||||
(defgeneric prepend-pwd (object))
|
||||
|
||||
(defmethod prepend-pwd ((object string))
|
||||
|
@ -70,10 +70,51 @@
|
||||
|
||||
(define-constant +metadata-entry-name "metadata.txt" :test #'string=)
|
||||
|
||||
(defmethod extract-metadata (zip-file)
|
||||
(defun extract-metadata (zip-file)
|
||||
(when (zip-info:zip-file-p zip-file)
|
||||
(let ((entries (zip-info:list-entries zip-file)))
|
||||
(when (find +metadata-entry-name entries :test #'String=)
|
||||
(when-let ((metadata-raw (os-utils:unzip-single-file zip-file
|
||||
+metadata-entry-name)))
|
||||
(parse 'metadata metadata-raw))))))
|
||||
|
||||
(defun save-metadata (zip-file)
|
||||
(when-let ((metadata (extract-metadata zip-file)))
|
||||
(db:gempub-metadata-add zip-file
|
||||
nil
|
||||
(getf metadata :title)
|
||||
(getf metadata :gpubVersion)
|
||||
(getf metadata :index)
|
||||
(getf metadata :author)
|
||||
(getf metadata :language)
|
||||
(getf metadata :charset)
|
||||
(getf metadata :description)
|
||||
(getf metadata :published)
|
||||
(getf metadata :publishDate)
|
||||
(getf metadata :revisionDate)
|
||||
(getf metadata :copyright)
|
||||
(getf metadata :license)
|
||||
(getf metadata :version)
|
||||
(getf metadata :cover))))
|
||||
|
||||
(defun sync-library (&key (notify nil))
|
||||
(let ((all-known (db:all-gempub-metadata))
|
||||
(all-gempub-files (remove-if-not (lambda (a) (ignore-errors (zip-info:zip-file-p a)))
|
||||
(fs:collect-files/dirs (swconf:gempub-library-directory))))
|
||||
(removed-known '())
|
||||
(added-file '()))
|
||||
(loop for known in all-known do
|
||||
(let ((local-uri (db:row-local-uri known)))
|
||||
(when (not (and (fs:file-exists-p local-uri)
|
||||
(zip-info:zip-file-p local-uri)))
|
||||
(push local-uri removed-known)
|
||||
(db:gempub-metadata-delete local-uri))))
|
||||
(loop for gempub-file in all-gempub-files do
|
||||
(when (not (db:gempub-metadata-find gempub-file))
|
||||
(push gempub-file added-file)
|
||||
(save-metadata gempub-file)))
|
||||
(when notify
|
||||
(loop for removed in removed-known do
|
||||
(ui:notify (format nil (_ "Removed gempub ~s from library, missing file") removed)))
|
||||
(loop for added in added-file do
|
||||
(ui:notify (format nil (_ "Added gempub ~s into the library") added))))))
|
||||
|
@ -282,6 +282,7 @@
|
||||
:add-extension
|
||||
:do-directory
|
||||
:collect-children
|
||||
:collect-files/dirs
|
||||
:prepend-pwd
|
||||
:search-matching-file
|
||||
:regular-file-p
|
||||
@ -909,6 +910,20 @@
|
||||
:row-seenp
|
||||
:row-description
|
||||
:row-value
|
||||
:row-local-uri
|
||||
:row-original-uri
|
||||
:row-gpub-version
|
||||
:row-index-file
|
||||
:row-author
|
||||
:row-language
|
||||
:row-charset
|
||||
:row-publishedp
|
||||
:row-publish-date
|
||||
:row-revision-date
|
||||
:row-copyright
|
||||
:row-license
|
||||
:row-version
|
||||
:row-cover
|
||||
:next-status-tree
|
||||
:previous-status-tree
|
||||
:message-tree-root-equal
|
||||
@ -1036,12 +1051,15 @@
|
||||
:delete-gemlog-entry
|
||||
:purge-seen-gemlog-entries
|
||||
:bookmark-add
|
||||
:bookmark-delete
|
||||
:bookmark-complete->id
|
||||
:bookmark-description-for-complete
|
||||
:bookmark-all-sections
|
||||
:bookmark-all-grouped-by-section
|
||||
:bookmark-delete))
|
||||
:bookmark-delete
|
||||
:gempub-metadata-add
|
||||
:all-gempub-metadata
|
||||
:gempub-metadata-delete
|
||||
:gempub-metadata-find))
|
||||
|
||||
(defpackage :date-formatter
|
||||
(:use
|
||||
@ -1176,6 +1194,7 @@
|
||||
:max-report-comment-length
|
||||
:quote-char
|
||||
:max-attachments-allowed
|
||||
:gempub-library-directory
|
||||
:color-regexps
|
||||
:ignore-users-regexps
|
||||
:win-bg
|
||||
@ -2425,7 +2444,8 @@
|
||||
(:shadowing-import-from :text-utils :split-lines)
|
||||
(:shadowing-import-from :misc :random-elt :shuffle)
|
||||
(:export
|
||||
:extract-metadata))
|
||||
:extract-metadata
|
||||
:sync-library))
|
||||
|
||||
(defpackage :main-window
|
||||
(:use
|
||||
|
@ -70,10 +70,14 @@
|
||||
(when (swconf:gemini-update-gemlog-at-start-p)
|
||||
(ui:gemlog-refresh-all)))
|
||||
|
||||
(gen-at-boot-function sync-gempub-library
|
||||
(gempub:sync-library :notify t))
|
||||
|
||||
(defun run-scheduled-events (ticks)
|
||||
(refresh-all-chats-messages ticks)
|
||||
(refresh-all-chats-data ticks)
|
||||
(refresh-gemlog-subscriptions ticks)
|
||||
(purge-gemlog-entries ticks)
|
||||
(purge-history)
|
||||
(refresh-gemlog-posts))
|
||||
(refresh-gemlog-posts)
|
||||
(sync-gempub-library))
|
||||
|
@ -504,6 +504,9 @@
|
||||
command-separator
|
||||
gemini
|
||||
gemlog
|
||||
gempub
|
||||
library
|
||||
sync
|
||||
favicon
|
||||
tree
|
||||
branch
|
||||
@ -525,6 +528,7 @@
|
||||
read
|
||||
unread
|
||||
directory-symbol
|
||||
directory
|
||||
fetch
|
||||
update
|
||||
close-after-select
|
||||
@ -834,6 +838,14 @@
|
||||
+key-max-numbers-allowed-attachments+)
|
||||
4))
|
||||
|
||||
(defun gempub-library-directory ()
|
||||
(or (access:accesses *software-configuration*
|
||||
+key-gempub+
|
||||
+key-directory+
|
||||
+key-library+)
|
||||
(res:home-datadir)))
|
||||
|
||||
|
||||
(defun external-editor ()
|
||||
(access:access *software-configuration*
|
||||
+key-editor+))
|
||||
|
@ -130,30 +130,40 @@
|
||||
(defun make-zip-error (reason)
|
||||
(error 'zip-error :text reason))
|
||||
|
||||
(alexandria:define-constant +max-eocd-total-size+ 65536 :test #'=)
|
||||
|
||||
(defun zip-file-p (path)
|
||||
(let ((file-size (file-size path))
|
||||
(eocd-start nil))
|
||||
(if (>= file-size +eocd-fixed-size+)
|
||||
(with-open-zip-file (stream path)
|
||||
(loop named signature-finder for position
|
||||
from (- file-size +eocd-signature-size+)
|
||||
downto 0 do
|
||||
(file-position stream position)
|
||||
(let ((maybe-signature (read-bytes->int stream +eocd-signature-size+)))
|
||||
(when (= maybe-signature +eocd-signature-value+)
|
||||
(setf eocd-start position)
|
||||
(return-from signature-finder t))))
|
||||
(if eocd-start
|
||||
(let* ((eocd-fixed-part-offset (+ eocd-start +eocd-fixed-size+))
|
||||
(eocd-offset-minus-zip-comment (- eocd-fixed-part-offset
|
||||
+eocd-zip-file-comment-length+)))
|
||||
(file-position stream eocd-offset-minus-zip-comment)
|
||||
(let ((comment-size (read-bytes->int stream +eocd-zip-file-comment-length+)))
|
||||
(values (= (+ eocd-fixed-part-offset comment-size)
|
||||
file-size)
|
||||
eocd-start)))
|
||||
(make-zip-error (format nil "File ~s contains no zip signature" path))))
|
||||
(make-zip-error (format nil "File ~s is too short to be a zip file" path)))))
|
||||
(with-open-zip-file (stream path)
|
||||
(let ((buffer (make-array +max-eocd-total-size+ :element-type +byte-type+)))
|
||||
(file-position stream (- file-size +max-eocd-total-size+))
|
||||
(read-sequence buffer stream)
|
||||
(loop named signature-finder
|
||||
for eocd-position
|
||||
from (- file-size +eocd-signature-size+) downto 0
|
||||
for position
|
||||
from (- +max-eocd-total-size+ +eocd-signature-size+) downto 0
|
||||
do
|
||||
(let* ((maybe-signature (misc:byte->int (subseq buffer
|
||||
position
|
||||
(+ position
|
||||
+eocd-signature-size+)))))
|
||||
(when (= maybe-signature +eocd-signature-value+)
|
||||
(setf eocd-start eocd-position)
|
||||
(return-from signature-finder t)))))
|
||||
(if eocd-start
|
||||
(let* ((eocd-fixed-part-offset (+ eocd-start +eocd-fixed-size+))
|
||||
(eocd-offset-minus-zip-comment (- eocd-fixed-part-offset
|
||||
+eocd-zip-file-comment-length+)))
|
||||
(file-position stream eocd-offset-minus-zip-comment)
|
||||
(let ((comment-size (read-bytes->int stream +eocd-zip-file-comment-length+)))
|
||||
(values (= (+ eocd-fixed-part-offset comment-size)
|
||||
file-size)
|
||||
eocd-start)))
|
||||
(make-zip-error (format nil "File ~s contains no zip signature" path))))
|
||||
(make-zip-error (format nil "File ~s is too short to be a zip file" path)))))
|
||||
|
||||
(defun start-of-central-directory (path)
|
||||
(multiple-value-bind (zipp eocd-start)
|
||||
|
Loading…
x
Reference in New Issue
Block a user