too many things and I suck at git
This commit is contained in:
		
							parent
							
								
									4bb3340d43
								
							
						
					
					
						commit
						1ddf492249
					
				
							
								
								
									
										147
									
								
								apidoc
									
									
									
									
									
								
							
							
						
						
									
										147
									
								
								apidoc
									
									
									
									
									
								
							| @ -4,7 +4,7 @@ Text Entities | ||||
| The `entities` attribute is an array of objects that represent blocks | ||||
| of text within a post that have special properties. Clients may safely | ||||
| ignore these things without losing too much meaning, but in a rich | ||||
| application like an Emacs or GUI implementation, they can provide | ||||
| implementation like an Emacs or GUI, they can provide | ||||
| some highlighting and navigation perks. The array object may be | ||||
| empty. If its not, its populated with arrays representing the | ||||
| modifications to be made. | ||||
| @ -19,31 +19,35 @@ property in the body string. The way clients are to access these | ||||
| indices is beyond the scope of this document; accessing a subsequence | ||||
| varies a lot between programming languages. | ||||
| 
 | ||||
| Some objects will provide further arguments beyond those 3. | ||||
| 
 | ||||
| |--------------|----------------------------------------------------------| | ||||
| | Name         | Description                                              | | ||||
| |--------------|----------------------------------------------------------| | ||||
| | `quote`      | This is a string that refers to a previous post number.  | | ||||
| |              | These are formatted like >>5, which means it is a        | | ||||
| |              | reference to `post_id` 5. These are not processed in     | | ||||
| |              | thread OPs. >>0 may be used to refer to the OP.          | | ||||
| |--------------|----------------------------------------------------------| | ||||
| | `blockquote` | This is a block of text, denoted by a newline during     | | ||||
| |              | composure, representing text that is assumed to be       | | ||||
| |              | a quote of someone else.                                 | | ||||
| |--------------|----------------------------------------------------------| | ||||
| | `color`      | This is a block of text, denoted by [[color: body]]      | | ||||
| |              | during composure. The body may span across newlines.     | | ||||
| |              | A fourth item is provided in the array: it is one of the | | ||||
| |              | following strings representing the color.                | | ||||
| |              | `red`, `green`, `yellow`, `blue`, `magenta`, or `cyan`.  | | ||||
| |--------------|----------------------------------------------------------| | ||||
| | `bold`       | Like color, except that no additional attribute is       | | ||||
| |              | provided. it is denoted as [[bold: body]] during         | | ||||
| |              | composure.                                                 | | ||||
| |--------------|----------------------------------------------------------| | ||||
| Some objects will provide further arguments beyond those 3. They will | ||||
| always be at the end of the array. | ||||
| 
 | ||||
| |-------------|----------------------------------------------------------| | ||||
| | Name        | Description                                              | | ||||
| |-------------|----------------------------------------------------------| | ||||
| | `quote`     | This is a string that refers to a previous post number.  | | ||||
| |             | These are formatted like >>5, which means it is a        | | ||||
| |             | reference to `post_id` 5. These are not processed in     | | ||||
| |             | thread OPs. >>0 may be used to refer to the OP. In       | | ||||
| |             | addition to the indices at i[1] and i[2], a fourth value | | ||||
| |             | is provided, which is an integer of the `post_id` being  | | ||||
| |             | quoted. Note that the string indices include the >>'s.   | | ||||
| |-------------|----------------------------------------------------------| | ||||
| | `linequote` | This is a line of text, denoted by a newline during      | | ||||
| |             | composure, representing text that is assumed to be       | | ||||
| |             | a quote of someone else. The indices span from the >     | | ||||
| |             | until (not including) the newline.                       | | ||||
| |-------------|----------------------------------------------------------| | ||||
| | `color`     | This is a block of text, denoted by [[color: body]]      | | ||||
| |             | during composure. The body may span across newlines.     | | ||||
| |             | A fourth item is provided in the array: it is one of the | | ||||
| |             | following strings representing the color.                | | ||||
| |             | `red`, `green`, `yellow`, `blue`, `magenta`, or `cyan`.  | | ||||
| |-------------|----------------------------------------------------------| | ||||
| | `bold`      | Like color, except that no additional attribute is       | | ||||
| | `italic`    | provided. it is denoted as [[directive: body]] during    | | ||||
| | `underline` | composure.                                               | | ||||
| |-------------|----------------------------------------------------------| | ||||
| 
 | ||||
| 
 | ||||
| Threads & Replies | ||||
| @ -57,13 +61,13 @@ available on the parent object: | ||||
| |---------------|------------------------------------------------------| | ||||
| | Name          | Description                                          | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `author`      | The ID of the author                                 | | ||||
| | `author`      | The ID string of the author.                         | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `thread_id`   | The ID of the thread.                                | | ||||
| | `thread_id`   | The ID string of the thread.                         | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `title`       | The title string of the thread                       | | ||||
| | `title`       | The title string of the thread.                      | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `body`        | The body of the post's text.                         | | ||||
| | `body`        | The body string of the post's text.                  | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `entities`    | A (possibly empty) array of entity objects for       | | ||||
| |               | the post `body`.                                     | | ||||
| @ -74,7 +78,7 @@ available on the parent object: | ||||
| |---------------|------------------------------------------------------| | ||||
| | `replies`     | An array containing full reply objects in            | | ||||
| |               | the order they were posted. Your clients             | | ||||
| |               | do not need to sort these.                           | | ||||
| |               | do not need to sort these. Array can be empty.       | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `reply_count` | An integer representing the number of replies        | | ||||
| |               | that have been posted in this thread.                | | ||||
| @ -82,8 +86,7 @@ available on the parent object: | ||||
| | `lastmod`     | Unix timestamp of when the thread was last           | | ||||
| |               | posted in, or a message was edited.                  | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `edited`      | Boolean of whether this post has been edited since   | | ||||
| |               | it was made.                                         | | ||||
| | `edited`      | Boolean of whether the post has been edited.     | | ||||
| |---------------|------------------------------------------------------| | ||||
| | `created`     | Unix timestamp of when the post was originally made. | | ||||
| |---------------|------------------------------------------------------| | ||||
| @ -97,11 +100,11 @@ The following attributes are available on each reply object in `replies`: | ||||
| | `post_id`  | An integer of the posts ID; unlike thread and user ids, | | ||||
| |            | this is not a uuid but instead is incremental, starting | | ||||
| |            | from 1 as the first reply and going up by one for each  | | ||||
| |            | post.                                                   | | ||||
| |            | post. These may be referenced by `quote` entities.      | | ||||
| |------------|---------------------------------------------------------| | ||||
| | `author`   | Author ID                                               | | ||||
| | `author`   | Author ID string                                        | | ||||
| |------------|---------------------------------------------------------| | ||||
| | `body`     | The body the reply's text.                              | | ||||
| | `body`     | The body string the reply's text.                       | | ||||
| |------------|---------------------------------------------------------| | ||||
| | `entities` | A (possibly empty) array of entity objects for          | | ||||
| |            | the reply `body`.                                       | | ||||
| @ -126,37 +129,43 @@ the problem. `description` is intended for human consumption; in your client | ||||
| code, use the error codes to handle conditions. The `presentable` column | ||||
| indicates whether the `description` should be shown to users verbatim. | ||||
| 
 | ||||
| |------|--------------|--------------------------------------------------| | ||||
| | Code | Presentable  | Documentation                                    | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    0 | Never, fix   | Malformed json input. `description` is the error | | ||||
| |      | your client  | string thrown by the server-side json decoder.   | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    1 | Not a good   | Internal server error. Unaltered exception text  | | ||||
| |      | idea, the    | is returned as `description`. This shouldn't     | | ||||
| |      | exceptions   | happen, and if it does, make a bug report.       | | ||||
| |      | are not      | clients should not attempt to intelligently      | | ||||
| |      | helpful      | recover from any errors of this class.           | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    2 | Nadda.       | Unknown `method` was requested.                  | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    3 | Fix. Your.   | Missing or malformed parameter values for the    | | ||||
| |      | Client.      | requested `method`.                              | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    4 | Only during  | Invalid or unprovided `user`. During             | | ||||
| |      | registration | registration, this code is returned if the name  | | ||||
| |      |              | is already occupied or contains illegal chars.   | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    5 | Always       | `user` is not registered.                        | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    6 | Always       | User `auth_hash` failed or was not provided.     | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    7 | Always       | Requested thread does not exist.                 | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    8 | Always       | Requested thread does not allow posts.           | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |    9 | Always       | Message edit failed; there is a 24hr limit for   | | ||||
| |      |              | editing posts.                                   | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |   10 | Always       | User action requires `admin` privilege.          | | ||||
| |------|--------------|--------------------------------------------------| | ||||
| |------|--------------|---------------------------------------------------| | ||||
| | Code | Presentable  | Documentation                                     | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    0 | Never, fix   | Malformed json input. `description` is the error  | | ||||
| |      | your client  | string thrown by the server-side json decoder.    | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    1 | Not a good   | Internal server error. Unaltered exception text   | | ||||
| |      | idea, the    | is returned as `description`. This shouldn't      | | ||||
| |      | exceptions   | happen, and if it does, make a bug report.        | | ||||
| |      | are not      | clients should not attempt to intelligently       | | ||||
| |      | helpful      | recover from any errors of this class.            | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    2 | Nadda.       | Unknown `method` was requested.                   | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    3 | Fix. Your.   | Missing or malformed parameter values for the     | | ||||
| |      | Client.      | requested `method`.                               | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    4 | Only during  | Invalid or unprovided `user`.                     | | ||||
| |      | registration |                                                   | | ||||
| |      |              | During registration, this code is returned with a | | ||||
| |      |              | `description` that should be shown to the user.   | | ||||
| |      |              | It could indicate an invalid name input, an       | | ||||
| |      |              | occupied username, invalid/missing `auth_hash`,   | | ||||
| |      |              | etc.                                              | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    5 | Always       | `user` is not registered.                         | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    6 | Always       | User `auth_hash` failed or was not provided.      | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    7 | Always       | Requested thread does not exist.                  | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    8 | Always       | Requested thread does not allow posts.            | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |    9 | Always       | Message edit failed; there is a 24hr limit for    | | ||||
| |      |              | editing posts.                                    | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |   10 | Always       | User action requires `admin` privilege.           | | ||||
| |------|--------------|---------------------------------------------------| | ||||
| |   11 | Always       | Invalid formatting directives in text submission. | | ||||
| |------|--------------|---------------------------------------------------| | ||||
|  | ||||
							
								
								
									
										77
									
								
								bbj.el
									
									
									
									
									
								
							
							
						
						
									
										77
									
								
								bbj.el
									
									
									
									
									
								
							| @ -6,32 +6,79 @@ | ||||
| (defvar bbj:user nil) | ||||
| (defvar bbj:hash nil) | ||||
| 
 | ||||
| (make-variable-buffer-local | ||||
|  (defvar bbj:aux-callback #'ignore)) | ||||
| 
 | ||||
| (define-derived-mode bbj-mode fundamental-mode "[BBJ]" | ||||
|   "Mode for browsing and posting to BBJ." | ||||
|   :group 'bbj-mode | ||||
|   (local-set-key (kbd "C-c C-c") 'bbj:aux) | ||||
|   (local-set-key (kbd "+") 'bbj:compose) | ||||
|   (local-set-key (kbd "RET") 'bbj:enter)) | ||||
| 
 | ||||
| (defun bbj:request (&rest cells) | ||||
|   (push (cons 'user bbj:user) cells) | ||||
|   (push (cons 'auth_hash bbj:hash) cells) | ||||
|   (with-temp-buffer | ||||
|     (insert (json-encode cells)) | ||||
|     (shell-command-on-region | ||||
|      (point-min) (point-max) | ||||
|      (format "nc %s %s" bbj:host bbj:port))) | ||||
|   (with-current-buffer "*Shell Command Output*" | ||||
|     (json-read-from-string | ||||
|      (buffer-substring-no-properties | ||||
|       (point-min) (point-max))))) | ||||
|     (goto-char (point-min)) | ||||
|     (let (json-false json-null) | ||||
|       (json-read)))) | ||||
| 
 | ||||
| 
 | ||||
| (bbj:request '(user . "desvox") | ||||
|              '(auth_hash . "nrr") | ||||
|              '(method . "check_auth")) | ||||
| (defun bbj:sethash (&optional password) | ||||
|   (unless password (setq password | ||||
|     (read-from-minibuffer "(Password)> "))) | ||||
|   (setq bbj:hash (secure-hash 'sha256 password))) | ||||
| 
 | ||||
| 
 | ||||
| (defun bbj:login () | ||||
|   (interactive) | ||||
|   (setq bbj:user (read-from-minibuffer "(BBJ Username)> ")) | ||||
|   (if (bbj:request '(method . "is_registered") | ||||
|                    `(target_user . ,bbj:user)) | ||||
|       (setq bbj:hash (secure-hash 'sha256 (read-from-minibuffer "(BBJ Password)> "))) | ||||
|     (when (y-or-n-p (format "Register for BBJ as %s? " bbj:user)) | ||||
|       (message | ||||
|        (bbj:request (cons 'auth_hash bbj:hash) | ||||
|                     (cons 'user bbj:user) | ||||
|                     (cons 'avatar nil) | ||||
|                     (cons 'bio (read-from-minibuffer "(Enter a short bio about youself!)> "))))))) | ||||
|   (cond | ||||
|    ((bbj:request '(method . "is_registered") | ||||
|                  `(target_user . ,bbj:user)) | ||||
|     (bbj:sethash) | ||||
|     (unless (bbj:request '(method . "check_auth")) | ||||
|       (message "(Invalid Password!)"))) | ||||
|    ((y-or-n-p (format "Register for BBJ as %s? " bbj:user)) | ||||
|     (let ((response (bbj:request | ||||
|                      (cons 'method "user_register") | ||||
|                      (cons 'auth_hash (bbj:sethash)) | ||||
|                      (cons 'user bbj:user) | ||||
|                      (cons 'quip (read-from-minibuffer "(Quip)> ")) | ||||
|                      (cons 'bio (read-from-minibuffer "(Bio)> "))))) | ||||
|       (if (alist-get 'error response) | ||||
|           (message "%s" (alist-get 'error response)) | ||||
|         (setq bbj:logged-in t) | ||||
|         (message "Logged in as %s!" bbj:user)))))) | ||||
| 
 | ||||
| 
 | ||||
| (defun bbj:compose-in-window (title callback &rest cbargs) | ||||
|   (let ((buffer (get-buffer-create "*BBJ: Compose*"))) | ||||
|     (pop-to-buffer buffer) | ||||
|     (with-current-buffer buffer | ||||
|       (erase-buffer) | ||||
|       (bbj-mode) | ||||
|       (setq header-line-format title | ||||
|             bbj:aux-callback callback)))) | ||||
| 
 | ||||
| 
 | ||||
| (defun bbj:consume-window (buffer) | ||||
|   (interactive) | ||||
|   (with-current-buffer buffer | ||||
|     (let ((content (buffer-substring-no-properties | ||||
|                     (point-min) (point-max)))) | ||||
|       (quit-window t) | ||||
|       content))) | ||||
| 
 | ||||
| 
 | ||||
| (defun bbj:browse-index () | ||||
|   (interactive) | ||||
|   (let ((response (bbj:request '(method . "thread_index")))) | ||||
|     (cl-loop for thread across (alist-get 'threads response) do | ||||
|              (message "%s" thread)))) | ||||
|  | ||||
| @ -30,7 +30,7 @@ def thread_index(key="lastmod"): | ||||
|         thread = thread_load(ID) | ||||
|         thread.pop("replies") | ||||
|         result.append(thread) | ||||
|     return sorted(result, key=lambda i: i[key]) | ||||
|     return sorted(result, key=lambda i: i[key], reverse=True) | ||||
| 
 | ||||
| 
 | ||||
| def thread_create(author, body, title, tags): | ||||
|  | ||||
| @ -31,11 +31,11 @@ def create_usermap(thread, index=False): | ||||
| 
 | ||||
| 
 | ||||
| def is_registered(json): | ||||
|     return dumps(bool(db.USERDB["mapname"].get(json["target_user"]))) | ||||
|     return bool(db.USERDB["mapname"].get(json["target_user"])) | ||||
| 
 | ||||
| 
 | ||||
| def check_auth(json): | ||||
|     return dumps(bool(db.user_auth(json["user"], json["auth_hash"]))) | ||||
|     return bool(db.user_auth(json["user"], json["auth_hash"])) | ||||
| 
 | ||||
| 
 | ||||
| def user_register(json): | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| from src import formatting | ||||
| from time import time | ||||
| 
 | ||||
| def base(): | ||||
| @ -48,12 +49,13 @@ def user_external(ID, name, quip, bio, admin): | ||||
| 
 | ||||
| 
 | ||||
| def thread(ID, author, body, title, tags): | ||||
|     text, entities = formatting.parse(body, doquotes=False) | ||||
|     now = time() | ||||
|     return { | ||||
|         "thread_id":   ID, | ||||
|         "author":      author, | ||||
|         "body":        body, | ||||
|         "entities":    list(), | ||||
|         "body":        text, | ||||
|         "entities":    entities, # of type list() | ||||
|         "title":       title, | ||||
|         "tags":        tags, | ||||
|         "replies":     list(), | ||||
| @ -65,12 +67,13 @@ def thread(ID, author, body, title, tags): | ||||
| 
 | ||||
| 
 | ||||
| def reply(ID, author, body): | ||||
|     text, entities = formatting.parse(body) | ||||
|     now = time() | ||||
|     return { | ||||
|         "post_id":  ID, | ||||
|         "author":   author, | ||||
|         "body":     body, | ||||
|         "entities": list(), | ||||
|         "body":     text, | ||||
|         "entities": entities, # of type list() | ||||
|         "lastmod":  now, | ||||
|         "edited":   False, | ||||
|         "created":  now | ||||
|  | ||||
| @ -8,7 +8,7 @@ import json | ||||
| class RequestHandler(StreamRequestHandler): | ||||
|     """ | ||||
|     Receieves and processes json input; dispatches input to the | ||||
|     approproate endpoint, or responds with error objects. | ||||
|     requested endpoint, or responds with error objects. | ||||
|     """ | ||||
| 
 | ||||
| 
 | ||||
| @ -22,52 +22,37 @@ class RequestHandler(StreamRequestHandler): | ||||
|             endpoint = request.get("method") | ||||
| 
 | ||||
|             if endpoint not in endpoints.endpoints: | ||||
|                 raise IndexError("Invalid endpoint") | ||||
|                 return self.reply(schema.error(2, "Invalid endpoint")) | ||||
| 
 | ||||
|             # check to make sure all the arguments for endpoint are provided | ||||
|             elif any([key not in request for key in endpoints.endpoints[endpoint]]): | ||||
|                 raise ValueError("{} requires: {}".format( | ||||
|                     endpoint, ", ".join(endpoints.endpoints[endpoint]))) | ||||
|                 return self.reply(schema.error(3, "{} requires: {}".format( | ||||
|                     endpoint, ", ".join(endpoints.endpoints[endpoint])))) | ||||
| 
 | ||||
|             elif endpoint not in endpoints.authless: | ||||
|                 if not request.get("user"): | ||||
|                     raise ConnectionError("No username provided.") | ||||
|                     return self.reply(schema.error(4, "No username provided.")) | ||||
| 
 | ||||
|                 user = db.user_resolve(request["user"]) | ||||
|                 request["user"] = user | ||||
| 
 | ||||
|                 if not user: | ||||
|                     raise ConnectionAbortedError("User not registered") | ||||
|                     return self.reply(schema.error(5, "User not registered")) | ||||
| 
 | ||||
|                 elif endpoint != "check_auth" and not db.user_auth(user, request.get("auth_hash")): | ||||
|                     raise ConnectionRefusedError("Authorization failed.") | ||||
|                 elif endpoint != "check_auth" and not \ | ||||
|                      db.user_auth(user, request.get("auth_hash")): | ||||
|                      return self.reply(schema.error(6, "Authorization failed.")) | ||||
| 
 | ||||
|             # exception handling is now passed to the endpoints; | ||||
|             # anything unhandled beyond here is a code 1 | ||||
|             self.reply(eval("endpoints." + endpoint)(request)) | ||||
| 
 | ||||
|         except json.decoder.JSONDecodeError as E: | ||||
|             return self.reply(schema.error(0, str(E))) | ||||
| 
 | ||||
|         except IndexError as E: | ||||
|             return self.reply(schema.error(2, str(E))) | ||||
| 
 | ||||
|         except ValueError as E: | ||||
|             return self.reply(schema.error(3, str(E))) | ||||
| 
 | ||||
|         except ConnectionError as E: | ||||
|             return self.reply(schema.error(4, str(E))) | ||||
| 
 | ||||
|         except ConnectionAbortedError as E: | ||||
|             return self.reply(schema.error(5, str(E))) | ||||
| 
 | ||||
|         except ConnectionRefusedError as E: | ||||
|             return self.reply(schema.error(6, str(E))) | ||||
| 
 | ||||
|         except Exception as E: | ||||
|             return self.reply(schema.error(1, str(E))) | ||||
| 
 | ||||
|         try: | ||||
|             self.reply(eval("endpoints." + endpoint)(request)) | ||||
|         except Exception as E: | ||||
|             self.reply(schema.error(1, str(E))) | ||||
| 
 | ||||
| 
 | ||||
| def run(host, port): | ||||
|     server = TCPServer((host, port), RequestHandler) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user