|
|
@@ -75,6 +75,7 @@
|
|
|
(:checkins (handle-cmd-checkins chat-id id args))
|
|
|
(:rss (handle-cmd-rss chat-id id args))
|
|
|
(:feeds (handle-cmd-feeds chat-id id args))
|
|
|
+ (:lastrss (handle-cmd-last-rss chat-id id args))
|
|
|
(otherwise (handle-admin-cmd chat-id text cmd args))))
|
|
|
(send-dont-understand chat-id (preprocess-input text))))
|
|
|
(when location
|
|
|
@@ -336,8 +337,19 @@
|
|
|
|
|
|
|
|
|
;; RSS
|
|
|
-(defvar *rss-feeds* nil "All aggragated RSS feeds")
|
|
|
-(defvar *rss-chat-feeds* (make-hash-table) "Chat->Feeds mapping")
|
|
|
+(defun handle-cmd-feeds (chat-id message-id args)
|
|
|
+ (log:info "handle-cmd-feeds" chat-id message-id args)
|
|
|
+ (handler-case
|
|
|
+ (telegram-send-message
|
|
|
+ chat-id
|
|
|
+ (if (null args)
|
|
|
+ "URL давай"
|
|
|
+ (format nil "~:[Не нашел RSS там~;~:*~{~{~A - ~A~}~^~%~}~]"
|
|
|
+ (find-rss-links (car args))))
|
|
|
+ :disable-web-preview 1)
|
|
|
+ (error (e)
|
|
|
+ (log:error e)
|
|
|
+ (telegram-send-message chat-id "Ошибочка вышла"))))
|
|
|
|
|
|
(defun %send-feeds (chat-id feeds)
|
|
|
(telegram-send-message
|
|
|
@@ -350,42 +362,26 @@
|
|
|
append (list index (feed-title feed) (feed-url feed)))))
|
|
|
:disable-web-preview 1))
|
|
|
|
|
|
+(defun %fetch-new-items (feed)
|
|
|
+ (prog1
|
|
|
+ (loop for item in (refresh-feed feed #'db-rss-item-exists)
|
|
|
+ do (db-rss-add-item item)
|
|
|
+ collect item)
|
|
|
+ (db-rss-update-feed feed)))
|
|
|
+
|
|
|
(defun %get-feed (url)
|
|
|
(when url
|
|
|
- (or (find url *rss-feeds* :key #'feed-url :test #'equal)
|
|
|
+ (or (db-rss-get-feed-by-url url)
|
|
|
(alexandria:when-let (feed (build-feed url))
|
|
|
(log:info "Added feed" feed)
|
|
|
- (fetch-new-items feed)
|
|
|
- (push feed *rss-feeds*)
|
|
|
+ (db-rss-add-feed feed)
|
|
|
+ (%fetch-new-items feed)
|
|
|
feed))))
|
|
|
|
|
|
-(defun %used-feed-p (feed)
|
|
|
- (loop for feeds being the hash-values in *rss-chat-feeds*
|
|
|
- when (member feed feeds)
|
|
|
- do (return t)))
|
|
|
-
|
|
|
-(defun %refresh-feeds ()
|
|
|
- (setf *rss-feeds*
|
|
|
- (remove-if-not #'%used-feed-p *rss-feeds*)))
|
|
|
-
|
|
|
-(defun handle-cmd-feeds (chat-id message-id args)
|
|
|
- (log:info "handle-cmd-feeds" chat-id message-id args)
|
|
|
- (handler-case
|
|
|
- (telegram-send-message
|
|
|
- chat-id
|
|
|
- (if (null args)
|
|
|
- "URL давай"
|
|
|
- (format nil "~:[Не нашел RSS там~;~:*~{~{~A - ~A~}~^~%~}~]"
|
|
|
- (find-rss-links (car args))))
|
|
|
- :disable-web-preview 1)
|
|
|
- (error (e)
|
|
|
- (log:error e)
|
|
|
- (telegram-send-message chat-id "Ошибочка вышла"))))
|
|
|
-
|
|
|
(defun handle-cmd-rss (chat-id message-id args)
|
|
|
(log:info "handle-cmd-rss" chat-id message-id args)
|
|
|
(handler-case
|
|
|
- (let ((feeds (gethash chat-id *rss-chat-feeds*)))
|
|
|
+ (let ((feeds (db-rss-get-chat-feeds chat-id)))
|
|
|
(if (null args)
|
|
|
(%send-feeds chat-id feeds)
|
|
|
(progn
|
|
|
@@ -398,43 +394,46 @@
|
|
|
(alexandria:when-let (feed (%get-feed
|
|
|
(or (cadar (find-rss-links url))
|
|
|
url)))
|
|
|
- (if (member feed feeds)
|
|
|
- (setf feeds (remove feed feeds))
|
|
|
- (push feed feeds))))
|
|
|
- (error (e) (log:error e))))
|
|
|
- (setf (gethash chat-id *rss-chat-feeds*) feeds)
|
|
|
- (%refresh-feeds)
|
|
|
- (save-settings)
|
|
|
+ (let ((existing (find (feed-url feed) feeds :key #'feed-url :test #'equal)))
|
|
|
+ (if existing
|
|
|
+ (setf feeds (remove existing feeds))
|
|
|
+ (push feed feeds)))))
|
|
|
+ (error (e) (log:error e))))
|
|
|
+ (log:info feeds)
|
|
|
+ (db-rss-set-chat-feeds chat-id feeds)
|
|
|
(%send-feeds chat-id feeds))))
|
|
|
(error (e)
|
|
|
(log:error e)
|
|
|
(telegram-send-message chat-id "Ошибочка вышла"))))
|
|
|
|
|
|
-(defun %feed-send-to (feed)
|
|
|
- (loop for chat-id being the hash-keys in *rss-chat-feeds* using (hash-value feeds)
|
|
|
- when (member feed feeds)
|
|
|
- collect chat-id))
|
|
|
+(defun handle-cmd-last-rss (chat-id message-id args)
|
|
|
+ (log:info "handle-cmd-last-rss" chat-id message-id args)
|
|
|
+ (handler-case
|
|
|
+ (let ((feeds (db-rss-get-chat-feeds chat-id)))
|
|
|
+ (if (null args)
|
|
|
+ (%send-feeds chat-id feeds)
|
|
|
+ (let* ((idx (1- (parse-integer (car args))))
|
|
|
+ (limit (if (> (length args) 1) (parse-integer (second args)) 10))
|
|
|
+ (items (db-rss-last-feed-items (nth idx feeds) limit)))
|
|
|
+ (telegram-send-message chat-id
|
|
|
+ (format nil "~{~A~^~%~%~}"
|
|
|
+ (mapcar #'format-feed-item items))
|
|
|
+ :disable-web-preview 1))))
|
|
|
+ (error (e)
|
|
|
+ (log:error e)
|
|
|
+ (telegram-send-message chat-id "Ошибочка вышла"))))
|
|
|
|
|
|
(defun process-feeds ()
|
|
|
(handler-case
|
|
|
- (dolist (feed (remove-if-not #'need-fetch-p *rss-feeds*))
|
|
|
+ (dolist (feed (remove-if-not #'need-fetch-p (db-rss-get-active-feeds)))
|
|
|
(log:info "Fetching new items" (feed-url feed))
|
|
|
- (dolist (item (fetch-new-items feed))
|
|
|
- (dolist (chat-id (%feed-send-to feed))
|
|
|
+ (dolist (item (%fetch-new-items feed))
|
|
|
+ (dolist (chat-id (db-rss-get-feed-chats feed))
|
|
|
(telegram-send-message chat-id
|
|
|
- (format-feed-item feed item)
|
|
|
+ (format-feed-item item)
|
|
|
:disable-web-preview 1))))
|
|
|
(error (e) (log:error e))))
|
|
|
|
|
|
-(defun %load-rss-feeds (alist)
|
|
|
- (alexandria:alist-hash-table
|
|
|
- (loop for (chat-id . urls) in alist
|
|
|
- collect (cons chat-id (mapcar #'%get-feed urls)))))
|
|
|
-
|
|
|
-(defun %save-rss-feeds ()
|
|
|
- (loop for chat-id being the hash-keys in *rss-chat-feeds* using (hash-value feeds)
|
|
|
- collect (cons chat-id (mapcar #'feed-url feeds))))
|
|
|
-
|
|
|
|
|
|
(defvar *save-settings-lock* (bordeaux-threads:make-lock "save-settings-lock")
|
|
|
"Lock for multithreading access to write settings file")
|
|
|
@@ -450,11 +449,15 @@
|
|
|
(write
|
|
|
`(setf *chat-locations* ',*chat-locations*
|
|
|
*akb-send-to* ',*akb-send-to*
|
|
|
- *akb-last-id* ,*akb-last-id*
|
|
|
- *rss-chat-feeds* (%load-rss-feeds ',(%save-rss-feeds)))
|
|
|
+ *akb-last-id* ,*akb-last-id*)
|
|
|
:stream s)
|
|
|
(values))))
|
|
|
|
|
|
+(defvar *schedules* '(process-latest-akb
|
|
|
+ process-latest-checkins
|
|
|
+ process-rates
|
|
|
+ process-feeds) "Enabled schedules")
|
|
|
+
|
|
|
(defun start ()
|
|
|
;; Clear prev threads
|
|
|
(mapc #'trivial-timers:unschedule-timer (trivial-timers:list-all-timers))
|
|
|
@@ -471,34 +474,13 @@
|
|
|
(asdf:find-system '#:chatikbot)))))
|
|
|
(load file))
|
|
|
;; Start timers
|
|
|
- (clon:schedule-function
|
|
|
- (lambda () (process-latest-akb))
|
|
|
- (clon:make-scheduler
|
|
|
- (clon:make-typed-cron-schedule :minute '* :hour '*)
|
|
|
- :allow-now-p t)
|
|
|
- :name 'process-latest-akb
|
|
|
- :thread t)
|
|
|
- (clon:schedule-function
|
|
|
- (lambda () (process-latest-checkins))
|
|
|
- (clon:make-scheduler
|
|
|
- (clon:make-typed-cron-schedule :minute '* :hour '*)
|
|
|
- :allow-now-p t)
|
|
|
- :name 'process-latest-checkins
|
|
|
- :thread t)
|
|
|
- (clon:schedule-function
|
|
|
- (lambda () (process-rates))
|
|
|
- (clon:make-scheduler
|
|
|
- (clon:make-typed-cron-schedule :minute '* :hour '*)
|
|
|
- :allow-now-p t)
|
|
|
- :name 'process-rates
|
|
|
- :thread t)
|
|
|
- (clon:schedule-function
|
|
|
- (lambda () (process-feeds))
|
|
|
- (clon:make-scheduler
|
|
|
- (clon:make-typed-cron-schedule :minute '* :hour '*)
|
|
|
- :allow-now-p t)
|
|
|
- :name 'process-feeds
|
|
|
- :thread t)
|
|
|
+ (dolist (func *schedules*)
|
|
|
+ (clon:schedule-function func
|
|
|
+ (clon:make-scheduler
|
|
|
+ (clon:make-typed-cron-schedule :minute '* :hour '*)
|
|
|
+ :allow-now-p t)
|
|
|
+ :name func
|
|
|
+ :thread t))
|
|
|
;; Start getUpdates thread
|
|
|
(bordeaux-threads:make-thread
|
|
|
(lambda ()
|