-
-
Notifications
You must be signed in to change notification settings - Fork 398
Initialize CLI interface for python-zulip-api. #663
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
| @@ -0,0 +1,194 @@ | ||||
| #!/usr/bin/env python3 | ||||
| import logging | ||||
| import sys | ||||
|
|
||||
| from typing import Any, Dict, List | ||||
|
|
||||
| import zulip | ||||
| import click | ||||
|
|
||||
| logging.basicConfig(stream=sys.stdout, level=logging.INFO) | ||||
| log = logging.getLogger("zulip-cli") | ||||
|
|
||||
| client = zulip.Client(config_file="~/zuliprc") | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems like a poor location for a config file, especially since it can’t be overridden.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not sure the best way to handle this. There is already
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should just add the argparse logic from the core library for how to find a zuliprc file. |
||||
|
|
||||
|
|
||||
| @click.group() | ||||
| def cli() -> None: | ||||
| pass | ||||
|
|
||||
|
|
||||
| def exit_on_result(result: str) -> None: | ||||
| if result == "success": | ||||
| sys.exit(0) | ||||
| sys.exit(1) | ||||
|
|
||||
|
|
||||
| def log_exit(response: Dict[str, Any]) -> None: | ||||
| result = response["result"] | ||||
| if result == "success": | ||||
| log.info(response) | ||||
| else: | ||||
| log.error(response) | ||||
| exit_on_result(result) | ||||
|
|
||||
|
|
||||
| # Messages API | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("recipients", type=str, nargs=-1) | ||||
| @click.option( | ||||
| "--stream", | ||||
| "-s", | ||||
| default="", | ||||
| help="Allows the user to specify a stream for the message.", | ||||
| ) | ||||
| @click.option( | ||||
| "--subject", | ||||
| "-S", | ||||
| default="", | ||||
| help="Allows the user to specify a subject for the message.", | ||||
| ) | ||||
| @click.option("--message", "-m", required=True) | ||||
| def send_message(recipients: List[str], stream: str, subject: str, message: str) -> None: | ||||
| """Sends a message and optionally prints status about the same.""" | ||||
|
|
||||
| # Sanity check user data | ||||
| has_stream = stream != "" | ||||
| has_subject = subject != "" | ||||
| if len(recipients) != 0 and has_stream: | ||||
| click.echo("You cannot specify both a username and a stream/subject.") | ||||
| raise SystemExit(1) | ||||
| if len(recipients) == 0 and (has_stream != has_subject): | ||||
| click.echo("Stream messages must have a subject") | ||||
| raise SystemExit(1) | ||||
| if len(recipients) == 0 and not has_stream: | ||||
| click.echo("You must specify a stream/subject or at least one recipient.") | ||||
| raise SystemExit(1) | ||||
|
|
||||
| message_data: Dict[str, Any] | ||||
| if has_stream: | ||||
| message_data = { | ||||
| "type": "stream", | ||||
| "content": message, | ||||
| "subject": subject, | ||||
| "to": stream, | ||||
| } | ||||
| else: | ||||
| message_data = { | ||||
| "type": "private", | ||||
| "content": message, | ||||
| "to": recipients, | ||||
| } | ||||
|
|
||||
| if message_data["type"] == "stream": | ||||
| log.info( | ||||
| 'Sending message to stream "%s", subject "%s"... ' | ||||
| % (message_data["to"], message_data["subject"]) | ||||
| ) | ||||
| else: | ||||
| log.info("Sending message to %s... " % message_data["to"]) | ||||
| response = client.send_message(message_data) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| def upload_file() -> None: | ||||
| """Upload a single file and get the corresponding URI.""" | ||||
| # TODO | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("message_id", type=int) | ||||
| @click.option("--message", "-m", required=True) | ||||
| def update_message(message_id: int, message: str) -> None: | ||||
| """Edit/update the content or topic of a message.""" | ||||
| request = { | ||||
| "message_id": message_id, | ||||
| "content": message, | ||||
| } | ||||
| response = client.update_message(request) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("message_id", type=int) | ||||
| def delete_message(message_id: int) -> None: | ||||
| """Permanently delete a message.""" | ||||
| response = client.delete_message(message_id) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| # TODO | ||||
| # https://zulip.com/api/get-messages | ||||
| # https://zulip.com/api/construct-narrow | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("message_id", type=int) | ||||
| @click.argument("emoji_name") | ||||
| def add_reaction(message_id: int, emoji_name: str) -> None: | ||||
| """Add an emoji reaction to a message.""" | ||||
| request = { | ||||
| "message_id": message_id, | ||||
| "emoji_name": emoji_name, | ||||
| } | ||||
|
|
||||
| response = client.add_reaction(request) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("message_id", type=int) | ||||
| @click.argument("emoji_name") | ||||
| def remove_reaction(message_id: int, emoji_name: str) -> None: | ||||
| """Remove an emoji reaction from a message.""" | ||||
| request = { | ||||
| "message_id": message_id, | ||||
| "emoji_name": emoji_name, | ||||
| } | ||||
|
|
||||
| response = client.remove_reaction(request) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| # TODO | ||||
| # https://zulip.com/api/render-message | ||||
| # https://zulip.com/api/get-raw-message | ||||
| # https://zulip.com/api/check-narrow-matches | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| @click.argument("message_id", type=int) | ||||
| def get_message_history(message_id: int) -> None: | ||||
| """Fetch the message edit history of a previously edited message. | ||||
| Note that edit history may be disabled in some organizations; see https://zulip.com/help/view-a-messages-edit-history. | ||||
| """ | ||||
| response = client.get_message_history(message_id) | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| # TODO | ||||
| # https://zulip.com/api/update-message-flags | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| def mark_all_as_read() -> None: | ||||
| """Marks all of the current user's unread messages as read.""" | ||||
| response = client.mark_all_as_read() | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| # Streams API | ||||
|
|
||||
|
|
||||
| @cli.command() | ||||
| def get_subscriptions() -> None: | ||||
| """Get all streams that the user is subscribed to.""" | ||||
| response = client.get_subscriptions() | ||||
| log_exit(response) | ||||
|
|
||||
|
|
||||
| if __name__ == "__main__": | ||||
| cli() | ||||
Uh oh!
There was an error while loading. Please reload this page.