messages can now have toggleable formatting at the database level
parent
662f9c3b70
commit
fa9cc49337
|
@ -550,6 +550,21 @@ class BBJ(object):
|
|||
return response["data"]
|
||||
|
||||
|
||||
def set_post_raw(self, thread_id, post_id, value):
|
||||
"""
|
||||
This is a subset of `edit_message` that retains the old
|
||||
body and just sets its `send_raw` to your supplied `value`.
|
||||
The `edited` parameter of the message on the server is not
|
||||
modified.
|
||||
"""
|
||||
response = self(
|
||||
"set_post_raw",
|
||||
thread_id=thread_id,
|
||||
post_id=post_id,
|
||||
value=bool(value))
|
||||
return response["data"]
|
||||
|
||||
|
||||
def user_is_admin(self, user_name_or_id):
|
||||
"""
|
||||
Return boolean True or False whether the given user identifier
|
||||
|
|
|
@ -500,6 +500,13 @@ class App(object):
|
|||
width=30, height=6)
|
||||
|
||||
|
||||
def toggle_formatting(self, button, message):
|
||||
self.remove_overlays()
|
||||
raw = not message["send_raw"]
|
||||
network.set_post_raw(message["thread_id"], message["post_id"], raw)
|
||||
return self.refresh()
|
||||
|
||||
|
||||
def on_post(self, button, message):
|
||||
quotes = self.get_quotes(message)
|
||||
author = self.usermap[message["author"]]
|
||||
|
@ -520,7 +527,11 @@ class App(object):
|
|||
msg = "Thread"
|
||||
else: msg = "Post"
|
||||
|
||||
raw = message["send_raw"]
|
||||
buttons.insert(0, urwid.Button("Delete %s" % msg, self.deletion_dialog, message))
|
||||
buttons.insert(0, urwid.Button(
|
||||
"Enable Formatting" if raw else "Disable Formatting",
|
||||
self.toggle_formatting, message))
|
||||
buttons.insert(0, urwid.Button("Edit Post", self.edit_post, message))
|
||||
|
||||
if not buttons:
|
||||
|
@ -550,6 +561,8 @@ class App(object):
|
|||
but can be passed `str` for strings.
|
||||
"""
|
||||
quotes = []
|
||||
if msg_object["send_raw"]:
|
||||
return quotes
|
||||
for paragraph in msg_object["body"]:
|
||||
# yes python is lisp fuck you
|
||||
[quotes.append(cdr) for car, cdr in paragraph if car == "quote"]
|
||||
|
@ -1297,6 +1310,9 @@ class MessageBody(urwid.Text):
|
|||
An urwid.Text object that works with the BBJ formatting directives.
|
||||
"""
|
||||
def __init__(self, message):
|
||||
if message["send_raw"]:
|
||||
return super(MessageBody, self).__init__(message["body"])
|
||||
|
||||
text_objects = message["body"]
|
||||
result = []
|
||||
last_directive = None
|
||||
|
|
|
@ -32,5 +32,6 @@ create table messages (
|
|||
author text, -- string (uuid1, user.user_id)
|
||||
created real, -- floating point unix timestamp (when reply was posted)
|
||||
edited int, -- bool
|
||||
body text -- string
|
||||
body text, -- string
|
||||
send_raw int -- bool (1/true == never apply formatting)
|
||||
);
|
||||
|
|
57
server.py
57
server.py
|
@ -214,11 +214,15 @@ class API(object):
|
|||
def thread_create(self, args, database, user, **kwargs):
|
||||
"""
|
||||
Creates a new thread and returns it. Requires the non-empty
|
||||
string arguments `body` and `title`
|
||||
string arguments `body` and `title`.
|
||||
|
||||
If the argument `send_raw` is specified and has a non-nil
|
||||
value, the OP message will never recieve special formatting.
|
||||
"""
|
||||
validate(args, ["body", "title"])
|
||||
thread = db.thread_create(
|
||||
database, user["user_id"], args["body"], args["title"])
|
||||
database, user["user_id"], args["body"],
|
||||
args["title"], args.get("send_raw"))
|
||||
cherrypy.thread_data.usermap = \
|
||||
create_usermap(database, thread["messages"])
|
||||
return thread
|
||||
|
@ -229,10 +233,14 @@ class API(object):
|
|||
"""
|
||||
Creates a new reply for the given thread and returns it.
|
||||
Requires the string arguments `thread_id` and `body`
|
||||
|
||||
If the argument `send_raw` is specified and has a non-nil
|
||||
value, the message will never recieve special formatting.
|
||||
"""
|
||||
validate(args, ["thread_id", "body"])
|
||||
return db.thread_reply(
|
||||
database, user["user_id"], args["thread_id"], args["body"])
|
||||
database, user["user_id"], args["thread_id"],
|
||||
args["body"], args.get("send_raw"))
|
||||
|
||||
|
||||
@api_method
|
||||
|
@ -266,13 +274,19 @@ class API(object):
|
|||
of a post without actually attempting to replace it, use
|
||||
`edit_query` first.
|
||||
|
||||
Optionally you may also include the argument `send_raw` to
|
||||
set the message's formatting flag. However, if this is the
|
||||
only change you would like to make, you should use the
|
||||
endpoint `set_post_raw` instead.
|
||||
|
||||
Returns the new message object.
|
||||
"""
|
||||
if user == db.anon:
|
||||
raise BBJUserError("Anons cannot edit messages.")
|
||||
validate(args, ["body", "thread_id", "post_id"])
|
||||
return db.message_edit_commit(
|
||||
database, user["user_id"], args["thread_id"], args["post_id"], args["body"])
|
||||
database, user["user_id"], args["thread_id"],
|
||||
args["post_id"], args["body"], args.get("send_raw"))
|
||||
|
||||
|
||||
@api_method
|
||||
|
@ -286,6 +300,8 @@ class API(object):
|
|||
or have admin rights. The same error descriptions and code
|
||||
are returned on falilure. Boolean true is returned on
|
||||
success.
|
||||
|
||||
If the post_id is 0, the whole thread is deleted.
|
||||
"""
|
||||
if user == db.anon:
|
||||
raise BBJUserError("Anons cannot delete messages.")
|
||||
|
@ -294,6 +310,31 @@ class API(object):
|
|||
database, user["user_id"], args["thread_id"], args["post_id"])
|
||||
|
||||
|
||||
@api_method
|
||||
def set_post_raw(self, args, database, user, **kwargs):
|
||||
"""
|
||||
Requires the boolean argument of `value`, string argument
|
||||
`thread_id`, and integer argument `post_id`. `value`, when false,
|
||||
means that the message will be passed through message formatters
|
||||
before being sent to clients. When `value` is true, this means
|
||||
it will never go through formatters, all of its whitespace is
|
||||
sent to clients verbatim and expressions are not processed.
|
||||
|
||||
The same rules for editing messages (see `edit_query`) apply here
|
||||
and the same error objects are returned for violations.
|
||||
|
||||
You may optionally set this value as well when using `edit_post`,
|
||||
but if this is the only change you want to make to the message,
|
||||
using this endpoint instead is preferable.
|
||||
"""
|
||||
if user == db.anon:
|
||||
raise BBJUserError("Anons cannot edit messages.")
|
||||
validate(args, ["value", "thread_id", "post_id"])
|
||||
return db.message_edit_commit(
|
||||
database, user["user_id"],
|
||||
args["thread_id"], args["post_id"],
|
||||
None, args["value"], None)
|
||||
|
||||
|
||||
@api_method
|
||||
def is_admin(self, args, database, user, **kwargs):
|
||||
|
@ -343,17 +384,17 @@ class API(object):
|
|||
@api_method
|
||||
def set_thread_pin(self, args, database, user, **kwargs):
|
||||
"""
|
||||
Requires the arguments `thread_id` and `pinned`. Pinned
|
||||
Requires the arguments `thread_id` and `value`. `value`
|
||||
must be a boolean of what the pinned status should be.
|
||||
This method requires that the caller is logged in and
|
||||
has admin status on their account.
|
||||
|
||||
Returns the same boolean you supply as `pinned`
|
||||
Returns the same boolean you supply as `value`
|
||||
"""
|
||||
validate(args, ["thread_id", "pinned"])
|
||||
validate(args, ["thread_id", "value"])
|
||||
if not user["is_admin"]:
|
||||
raise BBJUserError("Only admins can set thread pins")
|
||||
return db.set_thread_pin(database, args["thread_id"], args["pinned"])
|
||||
return db.set_thread_pin(database, args["thread_id"], args["value"])
|
||||
|
||||
|
||||
@api_method
|
||||
|
|
66
src/db.py
66
src/db.py
|
@ -93,7 +93,7 @@ def thread_set_pin(connection, thread_id, pin_bool):
|
|||
return pin_bool
|
||||
|
||||
|
||||
def thread_create(connection, author_id, body, title):
|
||||
def thread_create(connection, author_id, body, title, send_raw=False):
|
||||
"""
|
||||
Create a new thread and return it.
|
||||
"""
|
||||
|
@ -116,31 +116,32 @@ def thread_create(connection, author_id, body, title):
|
|||
# the thread is initially commited with reply_count -1 so that i can
|
||||
# just pass the message to the reply method, instead of duplicating
|
||||
# its code here. It then increments to 0.
|
||||
thread_reply(connection, author_id, thread_id, body, time_override=now)
|
||||
thread_reply(connection, author_id, thread_id, body, send_raw, time_override=now)
|
||||
# fetch the new thread out of the database instead of reusing the returned
|
||||
# objects, just to be 100% sure what is returned is what was committed
|
||||
return thread_get(connection, thread_id)
|
||||
|
||||
|
||||
def thread_reply(connection, author_id, thread_id, body, time_override=None):
|
||||
def thread_reply(connection, author_id, thread_id, body, send_raw=False, time_override=None):
|
||||
"""
|
||||
Submit a new reply for thread_id. Return the new reply object.
|
||||
|
||||
time_overide can be time() value to set as the new message time.
|
||||
time_overide can be a time() value to set as the new message time.
|
||||
This is to keep post_id 0 in exact parity with its parent thread.
|
||||
"""
|
||||
validate([("body", body)])
|
||||
|
||||
now = time_override or time()
|
||||
thread = thread_get(connection, thread_id, messages=False)
|
||||
count = thread["reply_count"] + 1
|
||||
thread["reply_count"] += 1
|
||||
count = thread["reply_count"]
|
||||
scheme = schema.message(
|
||||
thread_id, count, author_id,
|
||||
now, False, body)
|
||||
now, False, body, bool(send_raw))
|
||||
|
||||
connection.execute("""
|
||||
INSERT INTO messages
|
||||
VALUES (?,?,?,?,?,?)
|
||||
VALUES (?,?,?,?,?,?,?)
|
||||
""", schema_values("message", scheme))
|
||||
|
||||
connection.execute("""
|
||||
|
@ -157,7 +158,7 @@ def thread_reply(connection, author_id, thread_id, body, time_override=None):
|
|||
def message_delete(connection, author, thread_id, post_id):
|
||||
"""
|
||||
'Delete' a message from a thread. If the message being
|
||||
deleted is an OP [pid 0], delete the whole thread.
|
||||
deleted is an OP [post_id == 0], delete the whole thread.
|
||||
|
||||
Requires an author id, the thread_id, and post_id.
|
||||
The same rules for edits apply to deletions: the same
|
||||
|
@ -215,25 +216,58 @@ def message_edit_query(connection, author, thread_id, post_id):
|
|||
return message
|
||||
|
||||
|
||||
def message_edit_commit(connection, author_id, thread_id, post_id, new_body):
|
||||
def message_edit_commit(
|
||||
connection,
|
||||
author_id,
|
||||
thread_id,
|
||||
post_id,
|
||||
new_body,
|
||||
send_raw=None,
|
||||
set_display=True):
|
||||
"""
|
||||
Attempt to commit new_body to the existing message. Touches base with
|
||||
message_edit_query first. Returns the newly updated message object.
|
||||
Attempt to commit new_body, and optionally send_raw (default doesnt modify),
|
||||
to the existing message.
|
||||
|
||||
The send_raw and set_display paramter may be specified as the NoneType
|
||||
to leave its old value intact. Otherwise its given value is coerced to
|
||||
a boolean and is set on the message. send_raw when not explicitly specified
|
||||
will keep its old value, while an unspecified set_display will set it to True.
|
||||
|
||||
new_body may also be a NoneType to retain its old value.
|
||||
|
||||
Touches base with message_edit_query first. Returns
|
||||
the newly updated message object.
|
||||
"""
|
||||
validate([("body", new_body)])
|
||||
message = message_edit_query(connection, author_id, thread_id, post_id)
|
||||
message["body"] = new_body
|
||||
message["edited"] = True
|
||||
|
||||
if new_body == None:
|
||||
new_body = message["body"]
|
||||
validate([("body", new_body)])
|
||||
|
||||
if send_raw == None:
|
||||
send_raw = message["send_raw"]
|
||||
else:
|
||||
send_raw = bool(send_raw)
|
||||
|
||||
if set_display == None:
|
||||
display = message["edited"]
|
||||
else:
|
||||
display = bool(set_display)
|
||||
|
||||
connection.execute("""
|
||||
UPDATE messages SET
|
||||
body = ?,
|
||||
send_raw = ?,
|
||||
edited = ?
|
||||
WHERE thread_id = ?
|
||||
AND post_id = ?
|
||||
""", (new_body, True, thread_id, post_id))
|
||||
|
||||
""", (new_body, send_raw, display, thread_id, post_id))
|
||||
connection.commit()
|
||||
|
||||
message["body"] = new_body
|
||||
message["send_raw"] = send_raw
|
||||
message["edited"] = display
|
||||
|
||||
return message
|
||||
|
||||
|
||||
|
|
|
@ -180,6 +180,7 @@ def apply_formatting(msg_obj, formatter):
|
|||
documentation for each formatter.
|
||||
"""
|
||||
for x, obj in enumerate(msg_obj):
|
||||
if not msg_obj[x]["send_raw"]:
|
||||
msg_obj[x]["body"] = formatter(obj["body"])
|
||||
return msg_obj
|
||||
|
||||
|
|
|
@ -147,7 +147,8 @@ def message(
|
|||
author, # string (uuid1, user.user_id)
|
||||
created, # floating point unix timestamp (when reply was posted)
|
||||
edited, # bool
|
||||
body): # string
|
||||
body, # string
|
||||
send_raw): # bool
|
||||
|
||||
return {
|
||||
"thread_id": thread_id,
|
||||
|
@ -155,5 +156,6 @@ def message(
|
|||
"author": author,
|
||||
"created": created,
|
||||
"edited": bool(edited),
|
||||
"body": body
|
||||
"body": body,
|
||||
"send_raw": bool(send_raw)
|
||||
}
|
||||
|
|
|
@ -27,4 +27,4 @@ def schema_values(scheme, obj):
|
|||
elif scheme == "message":
|
||||
return ordered_keys(obj,
|
||||
"thread_id", "post_id", "author",
|
||||
"created", "edited", "body")
|
||||
"created", "edited", "body", "send_raw")
|
||||
|
|
Loading…
Reference in New Issue