2017-11-16 00:55:49 +01:00
|
|
|
from typing import Any, Dict, List
|
|
|
|
|
2017-08-06 09:56:29 +02:00
|
|
|
from django.core.management.base import BaseCommand
|
|
|
|
|
2020-01-14 21:59:46 +01:00
|
|
|
from zerver.lib.actions import bulk_add_subscriptions, do_add_reaction, \
|
|
|
|
do_change_avatar_fields, do_create_user, do_send_messages, ensure_stream, \
|
|
|
|
internal_prep_stream_message
|
2019-08-15 20:31:01 +02:00
|
|
|
from zerver.lib.emoji import emoji_name_to_emoji_code
|
2017-11-16 00:55:49 +01:00
|
|
|
from zerver.lib.upload import upload_avatar_image
|
|
|
|
from zerver.models import Message, UserProfile, get_realm
|
2017-08-06 09:56:29 +02:00
|
|
|
|
2020-01-14 21:59:46 +01:00
|
|
|
|
2017-08-06 09:56:29 +02:00
|
|
|
class Command(BaseCommand):
|
|
|
|
help = """Add a mock conversation to the development environment.
|
|
|
|
|
|
|
|
Usage: ./manage.py add_mock_conversation
|
|
|
|
|
|
|
|
After running the script:
|
|
|
|
|
|
|
|
From browser (ideally on high resolution screen):
|
|
|
|
* Refresh to get the rendered tweet
|
|
|
|
* Check that the whale emoji reaction comes before the thumbs_up emoji reaction
|
|
|
|
* Remove the blue box (it's a box shadow on .selected_message .messagebox-content;
|
|
|
|
inspecting the selected element will find it fairly quickly)
|
|
|
|
* Change the color of the stream to #a6c7e5
|
|
|
|
* Shrink screen till the mypy link only just fits
|
|
|
|
* Take screenshot that does not include the timestamps or bottom edge
|
|
|
|
|
|
|
|
From image editing program:
|
|
|
|
* Remove mute (and edit) icons from recipient bar
|
|
|
|
"""
|
|
|
|
|
2017-10-27 12:57:54 +02:00
|
|
|
def set_avatar(self, user: UserProfile, filename: str) -> None:
|
2017-08-06 09:56:29 +02:00
|
|
|
upload_avatar_image(open(filename, 'rb'), user, user)
|
|
|
|
do_change_avatar_fields(user, UserProfile.AVATAR_FROM_USER)
|
|
|
|
|
2017-10-27 12:57:54 +02:00
|
|
|
def add_message_formatting_conversation(self) -> None:
|
2017-08-06 09:56:29 +02:00
|
|
|
realm = get_realm('zulip')
|
2018-03-21 22:05:21 +01:00
|
|
|
stream = ensure_stream(realm, 'zulip features')
|
2017-08-06 09:56:29 +02:00
|
|
|
|
|
|
|
UserProfile.objects.filter(email__contains='stage').delete()
|
|
|
|
starr = do_create_user('1@stage.example.com', 'password', realm, 'Ada Starr', '')
|
2018-06-05 08:41:30 +02:00
|
|
|
self.set_avatar(starr, 'static/images/characters/starr.png')
|
2017-08-06 09:56:29 +02:00
|
|
|
fisher = do_create_user('2@stage.example.com', 'password', realm, 'Bel Fisher', '')
|
2018-06-05 08:41:30 +02:00
|
|
|
self.set_avatar(fisher, 'static/images/characters/fisher.png')
|
2017-08-06 09:56:29 +02:00
|
|
|
twitter_bot = do_create_user('3@stage.example.com', 'password', realm, 'Twitter Bot', '',
|
|
|
|
bot_type=UserProfile.DEFAULT_BOT)
|
|
|
|
self.set_avatar(twitter_bot, 'static/images/features/twitter.png')
|
|
|
|
|
|
|
|
bulk_add_subscriptions([stream], list(UserProfile.objects.filter(realm=realm)))
|
|
|
|
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
staged_messages: List[Dict[str, Any]] = [
|
2017-08-06 09:56:29 +02:00
|
|
|
{'sender': starr,
|
|
|
|
'content': "Hey @**Bel Fisher**, check out Zulip's Markdown formatting! "
|
|
|
|
"You can have:\n* bulleted lists\n * with sub-bullets too\n"
|
|
|
|
"* **bold**, *italic*, and ~~strikethrough~~ text\n"
|
|
|
|
"* LaTeX for mathematical formulas, both inline -- $$O(n^2)$$ -- and displayed:\n"
|
2018-07-02 00:05:24 +02:00
|
|
|
"```math\n\\int_a^b f(t)\\, dt=F(b)-F(a)\n```"},
|
2017-08-06 09:56:29 +02:00
|
|
|
{'sender': fisher,
|
|
|
|
'content': "My favorite is the syntax highlighting for code blocks\n"
|
2017-11-27 12:08:59 +01:00
|
|
|
"```python\ndef fib(n: int) -> int:\n # returns the n-th Fibonacci number\n"
|
2017-08-06 09:56:29 +02:00
|
|
|
" return fib(n-1) + fib(n-2)\n```"},
|
|
|
|
{'sender': starr,
|
|
|
|
'content': "I think you forgot your base case there, Bel :laughing:\n"
|
2017-11-27 12:08:59 +01:00
|
|
|
"```quote\n```python\ndef fib(n: int) -> int:\n # returns the n-th Fibonacci number\n"
|
2017-08-06 09:56:29 +02:00
|
|
|
" return fib(n-1) + fib(n-2)\n```\n```"},
|
|
|
|
{'sender': fisher,
|
|
|
|
'content': "I'm also a big fan of inline link, tweet, video, and image previews. "
|
|
|
|
"Check out this picture of Çet Whalin[](/static/images/features/whale.png)!"},
|
|
|
|
{'sender': starr,
|
2017-11-04 14:16:50 +01:00
|
|
|
'content': "I just set up a custom linkifier, "
|
|
|
|
"so `#1234` becomes [#1234](github.com/zulip/zulip/1234), "
|
2017-08-06 09:56:29 +02:00
|
|
|
"a link to the corresponding GitHub issue."},
|
|
|
|
{'sender': twitter_bot,
|
|
|
|
'content': 'https://twitter.com/gvanrossum/status/786661035637772288'},
|
|
|
|
{'sender': fisher,
|
|
|
|
'content': "Oops, the Twitter bot I set up shouldn't be posting here. Let me go fix that."},
|
python: Convert assignment type annotations to Python 3.6 style.
This commit was split by tabbott; this piece covers the vast majority
of files in Zulip, but excludes scripts/, tools/, and puppet/ to help
ensure we at least show the right error messages for Xenial systems.
We can likely further refine the remaining pieces with some testing.
Generated by com2ann, with whitespace fixes and various manual fixes
for runtime issues:
- invoiced_through: Optional[LicenseLedger] = models.ForeignKey(
+ invoiced_through: Optional["LicenseLedger"] = models.ForeignKey(
-_apns_client: Optional[APNsClient] = None
+_apns_client: Optional["APNsClient"] = None
- notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- signup_notifications_stream: Optional[Stream] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
+ signup_notifications_stream: Optional["Stream"] = models.ForeignKey('Stream', related_name='+', null=True, blank=True, on_delete=CASCADE)
- author: Optional[UserProfile] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
+ author: Optional["UserProfile"] = models.ForeignKey('UserProfile', blank=True, null=True, on_delete=CASCADE)
- bot_owner: Optional[UserProfile] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
+ bot_owner: Optional["UserProfile"] = models.ForeignKey('self', null=True, on_delete=models.SET_NULL)
- default_sending_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
- default_events_register_stream: Optional[Stream] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_sending_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
+ default_events_register_stream: Optional["Stream"] = models.ForeignKey('zerver.Stream', null=True, related_name='+', on_delete=CASCADE)
-descriptors_by_handler_id: Dict[int, ClientDescriptor] = {}
+descriptors_by_handler_id: Dict[int, "ClientDescriptor"] = {}
-worker_classes: Dict[str, Type[QueueProcessingWorker]] = {}
-queues: Dict[str, Dict[str, Type[QueueProcessingWorker]]] = {}
+worker_classes: Dict[str, Type["QueueProcessingWorker"]] = {}
+queues: Dict[str, Dict[str, Type["QueueProcessingWorker"]]] = {}
-AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional[LDAPSearch] = None
+AUTH_LDAP_REVERSE_EMAIL_SEARCH: Optional["LDAPSearch"] = None
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-22 01:09:50 +02:00
|
|
|
]
|
2017-08-06 09:56:29 +02:00
|
|
|
|
|
|
|
messages = [internal_prep_stream_message(
|
2019-02-09 03:01:35 +01:00
|
|
|
realm, message['sender'], stream,
|
python: Use trailing commas consistently.
Automatically generated by the following script, based on the output
of lint with flake8-comma:
import re
import sys
last_filename = None
last_row = None
lines = []
for msg in sys.stdin:
m = re.match(
r"\x1b\[35mflake8 \|\x1b\[0m \x1b\[1;31m(.+):(\d+):(\d+): (\w+)", msg
)
if m:
filename, row_str, col_str, err = m.groups()
row, col = int(row_str), int(col_str)
if filename == last_filename:
assert last_row != row
else:
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
with open(filename) as f:
lines = f.readlines()
last_filename = filename
last_row = row
line = lines[row - 1]
if err in ["C812", "C815"]:
lines[row - 1] = line[: col - 1] + "," + line[col - 1 :]
elif err in ["C819"]:
assert line[col - 2] == ","
lines[row - 1] = line[: col - 2] + line[col - 1 :].lstrip(" ")
if last_filename is not None:
with open(last_filename, "w") as f:
f.writelines(lines)
Signed-off-by: Anders Kaseorg <anders@zulipchat.com>
2020-04-10 05:23:40 +02:00
|
|
|
'message formatting', message['content'],
|
2017-08-06 09:56:29 +02:00
|
|
|
) for message in staged_messages]
|
|
|
|
|
|
|
|
message_ids = do_send_messages(messages)
|
|
|
|
|
|
|
|
preview_message = Message.objects.get(id__in=message_ids, content__icontains='image previews')
|
2019-08-15 20:31:01 +02:00
|
|
|
(emoji_code, reaction_type) = emoji_name_to_emoji_code(realm, 'whale')
|
|
|
|
do_add_reaction(starr, preview_message, 'whale', emoji_code, reaction_type)
|
2017-08-06 09:56:29 +02:00
|
|
|
|
|
|
|
twitter_message = Message.objects.get(id__in=message_ids, content__icontains='gvanrossum')
|
|
|
|
# Setting up a twitter integration in dev is a decent amount of work. If you need
|
|
|
|
# to update this tweet, either copy the format below, or send the link to the tweet
|
|
|
|
# to chat.zulip.org and ask an admin of that server to get you the rendered_content.
|
|
|
|
twitter_message.rendered_content = (
|
|
|
|
'<p><a>https://twitter.com/gvanrossum/status/786661035637772288</a></p>\n'
|
|
|
|
'<div class="inline-preview-twitter"><div class="twitter-tweet">'
|
|
|
|
'<a><img class="twitter-avatar" '
|
|
|
|
'src="https://pbs.twimg.com/profile_images/424495004/GuidoAvatar_bigger.jpg"></a>'
|
|
|
|
'<p>Great blog post about Zulip\'s use of mypy: '
|
|
|
|
'<a>http://blog.zulip.org/2016/10/13/static-types-in-python-oh-mypy/</a></p>'
|
|
|
|
'<span>- Guido van Rossum (@gvanrossum)</span></div></div>')
|
|
|
|
twitter_message.save(update_fields=['rendered_content'])
|
|
|
|
|
|
|
|
# Put a short pause between the whale reaction and this, so that the
|
|
|
|
# thumbs_up shows up second
|
2019-08-15 20:31:01 +02:00
|
|
|
(emoji_code, reaction_type) = emoji_name_to_emoji_code(realm, 'thumbs_up')
|
|
|
|
do_add_reaction(starr, preview_message, 'thumbs_up', emoji_code, reaction_type)
|
2017-08-06 09:56:29 +02:00
|
|
|
|
2017-10-27 12:57:54 +02:00
|
|
|
def handle(self, *args: Any, **options: str) -> None:
|
2017-08-06 09:56:29 +02:00
|
|
|
self.add_message_formatting_conversation()
|