diff --git a/idec-answers.el b/idec-answers.el index fe22b46..fcfb16d 100644 --- a/idec-answers.el +++ b/idec-answers.el @@ -29,6 +29,37 @@ (require 'idec-mode) (require 'web) +(defun replace-in-string (what with str) + "Replace WHAT WITH in STR." + (replace-regexp-in-string (regexp-quote what) with str nil 'literal)) + +(defun base64-to-base64url (str) + "Make url safe base64 string STR." + (when (string-match (regexp-quote "=") str) + (and (base64-to-base64url (replace-regexp-in-string "=+$" "" str)))) + (when (string-match (regexp-quote "+") str) + (and (base64-to-base64url (replace-in-string "+" "-" str)))) + (when (string-match (regexp-quote "/") str) + (and (base64-to-base64url (replace-in-string "/" "_" str)))) + str) + +(defun base64url-to-base64 (str) + "Make base64 from urlsafe STR." + (when (string-match (regexp-quote "-") str) + (and (base64url-to-base64 (replace-in-string "-" "+" str)))) + (when (string-match (regexp-quote "_") str) + (and (base64url-to-base64 (replace-in-string "_" "/" str)))) + str) + +(defun base64url-encode-string (str) + "Decode base64 urlsafe string STR." + (message (concat "Base64url: " (base64-to-base64url (base64-encode-string str t)))) + (base64-to-base64url (base64-encode-string str t))) + +(defun base64url-decode-string (str) + "Encode base64 urlsafe string STR." + (base64-decode-string (base64url-to-base64 str))) + (defun point-url () "Return url with `idec-primary-node' to send messages." (concat idec-primary-node "u/point")) @@ -37,23 +68,65 @@ "Show message with RESULT code." (message "IDEC: Sended. Result: %S" result)) -(defun do-post-request (url data) - "Make POST request to URL with DATA." +(defun do-post-request (url msg) + "Make POST request to URL with data MSG." + (message (gethash 'tmsg msg)) (web-http-post (lambda (con header data) (request-is-done data)) :url url - :data data)) + :data msg + ) + ;; (request + ;; url + ;; :type "POST" + ;; :data '(("pauth" . (gethash "path" msg)) ("tmsg" . (gethash "tmsg" msg))) + ;; ;; :headers '(("Content-Type" . "application/json")) + ;; ;; :parser 'json-read + ;; :success (function* + ;; (lambda (&key data &allow-other-keys) + ;; (message "I sent: %S" (assoc-default 'json data))))) + ) (defun post-message (encoded-message) "Do POST request to `idec-primary-node' with Base64 ENCODED-MESSAGE." + (message (base64url-decode-string encoded-message)) (let (json) (setq json (make-hash-table :test 'equal)) - (puthash "pauth" idec-account-auth json) - (puthash "tmsg" encoded-message json) + (puthash 'pauth idec-account-auth json) + (puthash 'tmsg encoded-message json) (do-post-request (point-url) json)) + ;; (message (base64url-decode-string encoded-message)) (message "Message sended")) +(defun send-new-message (echo) + "Send new message to ECHO." + (switch-to-buffer (concat "*IDEC: New message to echo " echo "*")) + (let ((msg (make-hash-table :test 'equal))) + (puthash "body" + (encode-coding-string (s-join "\n" (-drop-last 1 (-drop 4 (split-string (buffer-string) "\n")))) + 'utf-8) + msg) + (puthash "subj" + (encode-coding-string (nth 1 (split-string (nth 2 (split-string (buffer-string) "\n")) "bj: ")) + 'utf-8) + msg) + (puthash "echo" echo msg) + + (do-send-new-post-request msg))) + +(defun do-send-new-post-request (msg) + "Make IDEC compatible point message MSG and send it to `idec-primary-node'." + (let (point-message) + (setq point-message (list + (gethash "echo" msg) + "All" + (gethash "subj" msg) + "" + (gethash "body" msg))) + ;; Encode message in Base64 + (post-message (base64url-encode-string (s-join "\n" point-message))))) + (defun do-send-reply-post-request (message) "Make IDEC compatible point MESSAGE and send it to `idec-primary-node'." (message (gethash "body" message)) @@ -66,9 +139,10 @@ (concat "@repto:" (gethash "id" message)) (gethash "body" message))) ;; Encode message in Base64 - (post-message (base64-encode-string (encode-coding-string (s-join "\n" point-message) 'utf-8))))) + (post-message (base64url-encode-string (encode-coding-string (s-join "\n" point-message) 'utf-8))) + (kill-buffer (concat "*IDEC: answer to " (gethash "id" message) "*")))) -(defun send-message (msg) +(defun send-reply-message (msg) "Send message MSG to `idec-primary-node'." (switch-to-buffer (concat "*IDEC: answer to " (gethash "id" msg) "*")) (puthash "body" @@ -121,13 +195,38 @@ (insert "\n") (insert-text-button "[Send]" - 'action (lambda (x) (send-message (button-get x 'msg))) + 'action (lambda (x) (send-reply-message (button-get x 'msg))) 'msg answer-hash) (goto-char p) (idec-mode))) ;; END OF ANSWERS +;; NEW MESSAGE +(defun make-new-message-header (echo) + "Return header for new message with filled ECHO field." + (concat + (concat "New message to echo " echo "\n") + "\n" + "Subj: \n" + "------- YOU MESSAGE BELLOW -------\n") + ) + +(defun edit-new-message (echo) + "Edit new message to ECHO." + (switch-to-buffer (get-buffer-create (concat "*IDEC: New message to echo " echo "*"))) + (insert (make-new-message-header echo)) + (forward-line) + + (let (p) + (setq p (point)) + (insert "\n") + (insert-text-button "[Send]" + 'action (lambda (x) (send-new-message (button-get x 'msg-echo))) + 'msg-echo echo) + (goto-char p)) + (idec-mode)) + (provide 'idec-answers) ;;; idec-answers.el ends here diff --git a/idec-db.el b/idec-db.el new file mode 100644 index 0000000..ac16d67 --- /dev/null +++ b/idec-db.el @@ -0,0 +1,75 @@ +;;; idec-db.el --- This file is a part of GNU Emacs client for IDEC network + +;; Copyright (c) 2017 Denis Zheleztsov + +;; Author: Denis Zheleztsov +;; Keywords: lisp,network,IDEC +;; Version: 0.1 + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; In active developent. +;; Fetched node must be support modern IDEC extensions like /list.txt, /x/c, etc. + +;;; Code: +(require 'emacsql) +(require 'idec-parser) + +(defun create-echo-mail-dir (echo) + "Create ECHO directory inside `idec-mail-dir'." + (if (file-exists-p idec-mail-dir) + (message idec-mail-dir) + (mkdir idec-mail-dir)) + (if (file-exists-p (concat idec-mail-dir "/" echo)) + (message (concat idec-mail-dir "/" echo)) + (mkdir (concat idec-mail-dir "/" echo)))) + +(defun get-echo-dir (echo) + "Get ECHO dir from `idec-mail-dir'." + (concat idec-mail-dir (concat "/" echo))) + +(defun filename-to-store (content id) + "Make filename from CONTENT unixtime and ID." + (concat (nth 2 (split-string content)) "-" id)) + +(defun get-message-file (echo id) + "Get ECHO message filename by ID." + (concat (get-echo-dir echo) "/" id)) + +(defun get-counter-file (echo) + "Get ECHO counter filename." + (concat (get-echo-dir echo) "/counter")) + +(defun store-message (content echo id) + "Store CONTENT from ECHO message in `idec-mail-dir' with it ID." + (create-echo-mail-dir echo) + (write-region content nil (get-message-file echo id))) + +(defun store-echo-counter (echo) + "Store count messages in ECHO." + (create-echo-mail-dir echo) + (write-region (echo-messages-count echo) nil (get-counter-file echo))) + +(defun check-message-in-echo (msg echo) + "Check if exists message MSG in ECHO `idec-mail-dir'." + (not (f-file? (get-message-file echo msg)))) + +(defun open-echo-db (echo) + "Create or open sqlite database inside ECHO `idec-mail-dir'.") + +(provide 'idec-db) + +;;; idec-db.el ends here diff --git a/idec-mode.el b/idec-mode.el index 1345b5f..0cfce60 100644 --- a/idec-mode.el +++ b/idec-mode.el @@ -58,7 +58,10 @@ "Default highlighting expressions for IDEC mode.") (defvar idec-mode-syntax-table - (make-syntax-table text-mode-syntax-table)) + (let ((st (make-syntax-table))) + (modify-syntax-entry ?_ "w" st) + (modify-syntax-entry ?/ ". 2b" st) + st)) ;; Mode function (defun idec-mode () @@ -66,7 +69,7 @@ (interactive) (kill-all-local-variables) ;; Mode definition - ;; (set-syntax-table idec-mode-syntax-table) + (set-syntax-table idec-mode-syntax-table) (use-local-map idec-mode-map) ;; (font-lock-add-keywords 'idec-mode '(idec-font-lock-keywords)) ;; (set (make-local-variable 'font-lock-defaults) '(idec-font-lock-keywords)) diff --git a/idec.el b/idec.el index a91bedf..8f9510c 100644 --- a/idec.el +++ b/idec.el @@ -30,6 +30,7 @@ ;; (require 'idec-answers) (require 'idec-parser) (require 'idec-online) +(require 'idec-db) (defgroup idec nil "IDEC configuration." @@ -159,45 +160,6 @@ Default to `idec-download-offset'" ;; FUNCTIONS ;; ;;;;;;;;; -(defun create-echo-mail-dir (echo) - "Create ECHO directory inside `idec-mail-dir'." - (if (file-exists-p idec-mail-dir) - (message idec-mail-dir) - (mkdir idec-mail-dir)) - (if (file-exists-p (concat idec-mail-dir "/" echo)) - (message (concat idec-mail-dir "/" echo)) - (mkdir (concat idec-mail-dir "/" echo)))) - -(defun get-echo-dir (echo) - "Get ECHO dir from `idec-mail-dir'." - (concat idec-mail-dir (concat "/" echo))) - -(defun filename-to-store (content id) - "Make filename from CONTENT unixtime and ID." - (concat (nth 2 (split-string content)) "-" id)) - -(defun get-message-file (echo id) - "Get ECHO message filename by ID." - (concat (get-echo-dir echo) "/" id)) - -(defun get-counter-file (echo) - "Get ECHO counter filename." - (concat (get-echo-dir echo) "/counter")) - -(defun store-message (content echo id) - "Store CONTENT from ECHO message in `idec-mail-dir' with it ID." - (create-echo-mail-dir echo) - (write-region content nil (get-message-file echo id))) - -(defun store-echo-counter (echo) - "Store count messages in ECHO." - (create-echo-mail-dir echo) - (write-region (echo-messages-count echo) nil (get-counter-file echo))) - -(defun check-message-in-echo (msg echo) - "Check if exists message MSG in ECHO `idec-mail-dir'." - (not (f-file? (get-message-file echo msg)))) - (defun get-url-content (url) "Get URL content and return it without headers." @@ -268,11 +230,16 @@ Default to `idec-download-offset'" (s-join "\n" (get-message-field (gethash "msg" msg) "body")))) (princ "\n__________________________________\n") (princ "[") - (insert-button "Answer" - 'action (lambda (x) (message "OK"))) + (let (answer-hash) + (setq answer-hash (make-hash-table :test 'equal)) + (puthash "content" (gethash "msg" msg) answer-hash) + (insert-button "Answer" + 'action (lambda (x) (edit-answer-without-quote (button-get x 'id) (button-get x 'msg-hash))) + 'id (gethash "id" msg) + 'msg-hash answer-hash)) (princ "]") (princ "\t [") - (insert-button "Answer with quote") + (insert-button "Quote answer") (princ "]") (add-text-properties (point-min) (point-max) 'read-only)) (point-max) @@ -402,6 +369,11 @@ If ONLINE is t uses `idec-online-download-limit' and `idec-online-download-offse ;; END OF ECHOES FUNCTIONS ;; ;;;;;;;;;;;;;;;;;;;;;;; +(defun idec-new-message () + "Make new message." + (interactive) + (edit-new-message (read-string "Echo: "))) + ;; END OF FUNCTIONS ;; ;;;;;;;;;;;;;;;;