mirror of https://github.com/zulip/zulip.git
slash commands: Add /ping command (via zcommand).
This adds a /ping command that will be useful for users to see what the round trip to the Zulip server is (including only a tiny bit of actual server time to basically give a 200). It also introduce the "/zcommand" endpoint and zcommand.js module.
This commit is contained in:
parent
87ba752758
commit
4b2e8b83c4
|
@ -74,6 +74,7 @@
|
||||||
"typing_status": false,
|
"typing_status": false,
|
||||||
"sent_messages": false,
|
"sent_messages": false,
|
||||||
"transmit": false,
|
"transmit": false,
|
||||||
|
"zcommand": false,
|
||||||
"compose": false,
|
"compose": false,
|
||||||
"compose_actions": false,
|
"compose_actions": false,
|
||||||
"compose_state": false,
|
"compose_state": false,
|
||||||
|
|
|
@ -55,6 +55,7 @@ set_global('reminder', {
|
||||||
global.document.location.protocol = 'https:';
|
global.document.location.protocol = 'https:';
|
||||||
global.document.location.host = 'foo.com';
|
global.document.location.host = 'foo.com';
|
||||||
|
|
||||||
|
zrequire('zcommand');
|
||||||
zrequire('compose_ui');
|
zrequire('compose_ui');
|
||||||
zrequire('util');
|
zrequire('util');
|
||||||
zrequire('common');
|
zrequire('common');
|
||||||
|
|
|
@ -299,11 +299,21 @@ exports.finish = function () {
|
||||||
exports.clear_private_stream_alert();
|
exports.clear_private_stream_alert();
|
||||||
notifications.clear_compose_notifications();
|
notifications.clear_compose_notifications();
|
||||||
|
|
||||||
|
var message_content = compose_state.message_content();
|
||||||
|
|
||||||
|
// Skip normal validation for zcommands, since they aren't
|
||||||
|
// actual messages with recipients; users only send them
|
||||||
|
// from the compose box for convenience sake.
|
||||||
|
if (zcommand.process(message_content)) {
|
||||||
|
exports.do_post_send_tasks();
|
||||||
|
clear_compose_box();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (! compose.validate()) {
|
if (! compose.validate()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var message_content = compose_state.message_content();
|
|
||||||
if (reminder.is_deferred_delivery(message_content)) {
|
if (reminder.is_deferred_delivery(message_content)) {
|
||||||
reminder.schedule_message();
|
reminder.schedule_message();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
var zcommand = (function () {
|
||||||
|
|
||||||
|
var exports = {};
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
What in the heck is a zcommand?
|
||||||
|
|
||||||
|
A zcommand is basically a specific type of slash
|
||||||
|
command where the client does almost no work and
|
||||||
|
the server just does something pretty simple like
|
||||||
|
flip a setting.
|
||||||
|
|
||||||
|
The first zcommand we wrote is for "/ping", and
|
||||||
|
the server just responds with a 200 for that.
|
||||||
|
|
||||||
|
Not all slash commands use zcommand under the hood.
|
||||||
|
For more exotic things like /poll see submessage.js
|
||||||
|
and widgetize.js
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
exports.send = function (opts) {
|
||||||
|
var command = opts.command;
|
||||||
|
var on_success = opts.on_success;
|
||||||
|
var data = {
|
||||||
|
command: command,
|
||||||
|
};
|
||||||
|
|
||||||
|
channel.post({
|
||||||
|
url: '/json/zcommand',
|
||||||
|
data: data,
|
||||||
|
success: function (data) {
|
||||||
|
on_success(data);
|
||||||
|
},
|
||||||
|
error: function () {
|
||||||
|
exports.tell_user('server did not respond');
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.tell_user = function (msg) {
|
||||||
|
// This is a bit hacky, but we don't have a super easy API now
|
||||||
|
// for just telling users stuff.
|
||||||
|
$('#compose-send-status').removeClass(common.status_classes)
|
||||||
|
.addClass('alert-error')
|
||||||
|
.stop(true).fadeTo(0, 1);
|
||||||
|
$('#compose-error-msg').text(msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
exports.process = function (message_content) {
|
||||||
|
|
||||||
|
var content = message_content.trim();
|
||||||
|
|
||||||
|
if (content === '/ping') {
|
||||||
|
var start_time = new Date();
|
||||||
|
|
||||||
|
exports.send({
|
||||||
|
command: 'ping',
|
||||||
|
on_success: function () {
|
||||||
|
var end_time = new Date();
|
||||||
|
var diff = end_time - start_time;
|
||||||
|
diff = Math.round(diff);
|
||||||
|
var msg = "ping time: " + diff + "ms";
|
||||||
|
exports.tell_user(msg);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It is incredibly important here to return false
|
||||||
|
// if we don't see an actual zcommand, so that compose.js
|
||||||
|
// knows this is a normal message.
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
return exports;
|
||||||
|
}());
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined') {
|
||||||
|
module.exports = zcommand;
|
||||||
|
}
|
|
@ -999,6 +999,17 @@ class SewMessageAndReactionTest(ZulipTestCase):
|
||||||
|
|
||||||
class MessagePOSTTest(ZulipTestCase):
|
class MessagePOSTTest(ZulipTestCase):
|
||||||
|
|
||||||
|
def test_zcommand(self) -> None:
|
||||||
|
self.login(self.example_email("hamlet"))
|
||||||
|
|
||||||
|
payload = dict(command="boil-ocean")
|
||||||
|
result = self.client_post("/json/zcommand", payload)
|
||||||
|
self.assert_json_error(result, "No such command: boil-ocean")
|
||||||
|
|
||||||
|
payload = dict(command="ping")
|
||||||
|
result = self.client_post("/json/zcommand", payload)
|
||||||
|
self.assert_json_success(result)
|
||||||
|
|
||||||
def test_message_to_self(self) -> None:
|
def test_message_to_self(self) -> None:
|
||||||
"""
|
"""
|
||||||
Sending a message to a stream to which you are subscribed is
|
Sending a message to a stream to which you are subscribed is
|
||||||
|
|
|
@ -681,6 +681,15 @@ def find_first_unread_anchor(sa_conn: Any,
|
||||||
|
|
||||||
return anchor
|
return anchor
|
||||||
|
|
||||||
|
@has_request_variables
|
||||||
|
def zcommand_backend(request: HttpRequest, user_profile: UserProfile,
|
||||||
|
command: str=REQ('command')) -> HttpResponse:
|
||||||
|
if command == 'ping':
|
||||||
|
ret = dict() # type: Dict[str, Any]
|
||||||
|
return json_success(ret)
|
||||||
|
|
||||||
|
raise JsonableError(_('No such command: %s') % (command,))
|
||||||
|
|
||||||
@has_request_variables
|
@has_request_variables
|
||||||
def get_messages_backend(request: HttpRequest, user_profile: UserProfile,
|
def get_messages_backend(request: HttpRequest, user_profile: UserProfile,
|
||||||
anchor: int=REQ(converter=int),
|
anchor: int=REQ(converter=int),
|
||||||
|
|
|
@ -968,6 +968,7 @@ JS_SPECS = {
|
||||||
'js/compose_state.js',
|
'js/compose_state.js',
|
||||||
'js/compose_actions.js',
|
'js/compose_actions.js',
|
||||||
'js/transmit.js',
|
'js/transmit.js',
|
||||||
|
'js/zcommand.js',
|
||||||
'js/compose.js',
|
'js/compose.js',
|
||||||
'js/upload.js',
|
'js/upload.js',
|
||||||
'js/stream_color.js',
|
'js/stream_color.js',
|
||||||
|
|
|
@ -162,6 +162,9 @@ v1_api_and_json_patterns = [
|
||||||
url(r'^mark_topic_as_read$', rest_dispatch,
|
url(r'^mark_topic_as_read$', rest_dispatch,
|
||||||
{'POST': 'zerver.views.messages.mark_topic_as_read'}),
|
{'POST': 'zerver.views.messages.mark_topic_as_read'}),
|
||||||
|
|
||||||
|
url(r'^zcommand$', rest_dispatch,
|
||||||
|
{'POST': 'zerver.views.messages.zcommand_backend'}),
|
||||||
|
|
||||||
# messages -> zerver.views.messages
|
# messages -> zerver.views.messages
|
||||||
# GET returns messages, possibly filtered, POST sends a message
|
# GET returns messages, possibly filtered, POST sends a message
|
||||||
url(r'^messages$', rest_dispatch,
|
url(r'^messages$', rest_dispatch,
|
||||||
|
|
Loading…
Reference in New Issue