def integration_doc( request: HttpRequest, integration_name: str = REQ(default=None) ) -> HttpResponse: try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = {} # type: Dict[str, Any] add_context_for_single_integration(context, integration_name, request) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url if isinstance(integration, EmailIntegration): context['email_gateway_example'] = settings.EMAIL_GATEWAY_EXAMPLE doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def integration_doc(request: HttpRequest, integration_name: str=REQ(default=None)) -> HttpResponse: if not request.is_ajax(): return HttpResponseNotFound() try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = {} # type: Dict[str, Any] add_api_uri_context(context, request) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url if isinstance(integration, EmailIntegration): context['email_gateway_example'] = settings.EMAIL_GATEWAY_EXAMPLE if integration.name == 'freshdesk': # In our Freshdesk docs, some nested code blocks have characters such # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, # but the encoded form never gets rendered because the text ends up # inside a <pre> tag. So here, we explicitly set a directive that # a particular template should be "unescaped" before being displayed. # Note that this value is used by render_markdown_path. context['unescape_rendered_html'] = True doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def integration_doc( request: HttpRequest, integration_name: str = REQ(default=None) ) -> HttpResponse: if not request.is_ajax(): return HttpResponseNotFound() try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = {} # type: Dict[str, Any] add_api_uri_context(context, request) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url if isinstance(integration, EmailIntegration): context['email_gateway_example'] = settings.EMAIL_GATEWAY_EXAMPLE if integration.name == 'freshdesk': # In our Freshdesk docs, some nested code blocks have characters such # as '{' encoded as '{' to prevent clashes with Jinja2 syntax, # but the encoded form never gets rendered because the text ends up # inside a <pre> tag. So here, we explicitly set a directive that # a particular template should be "unescaped" before being displayed. # Note that this value is used by render_markdown_path. context['unescape_rendered_html'] = True doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def integration_doc(request: HttpRequest, integration_name: str=REQ(default=None)) -> HttpResponse: if not request.is_ajax(): return HttpResponseNotFound() try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = {} # type: Dict[str, Any] add_api_uri_context(context, request) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url if isinstance(integration, EmailIntegration): context['email_gateway_example'] = settings.EMAIL_GATEWAY_EXAMPLE doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def send_custom_email(users: List[UserProfile], options: Dict[str, Any]) -> None: """ Can be used directly with from a management shell with send_custom_email(user_profile_list, dict( markdown_template_path="/path/to/markdown/file.md", subject="Email Subject", from_name="Sender Name") ) """ with open(options["markdown_template_path"]) as f: text = f.read() parsed_email_template = Parser(policy=default).parsestr(text) email_template_hash = hashlib.sha256(text.encode('utf-8')).hexdigest()[0:32] email_filename = "custom/custom_email_%s.source.html" % (email_template_hash,) email_id = "zerver/emails/custom/custom_email_%s" % (email_template_hash,) markdown_email_base_template_path = "templates/zerver/emails/custom_email_base.pre.html" html_source_template_path = "templates/%s.source.html" % (email_id,) plain_text_template_path = "templates/%s.txt" % (email_id,) subject_path = "templates/%s.subject.txt" % (email_id,) os.makedirs(os.path.dirname(html_source_template_path), exist_ok=True) # First, we render the markdown input file just like our # user-facing docs with render_markdown_path. with open(plain_text_template_path, "w") as f: f.write(parsed_email_template.get_payload()) from zerver.templatetags.app_filters import render_markdown_path rendered_input = render_markdown_path(plain_text_template_path.replace("templates/", "")) # And then extend it with our standard email headers. with open(html_source_template_path, "w") as f: with open(markdown_email_base_template_path) as base_template: # Note that we're doing a hacky non-Jinja2 substitution here; # we do this because the normal render_markdown_path ordering # doesn't commute properly with inline_email_css. f.write(base_template.read().replace('{{ rendered_input }}', rendered_input)) with open(subject_path, "w") as f: f.write(get_header(options.get("subject"), parsed_email_template.get("subject"), "subject")) inline_template(email_filename) # Finally, we send the actual emails. for user_profile in filter(lambda user: not options.get('admins_only') or user.is_realm_admin, users): context = { 'realm_uri': user_profile.realm.uri, 'realm_name': user_profile.realm.name, } send_email(email_id, to_user_ids=[user_profile.id], from_address=FromAddress.SUPPORT, reply_to_email=options.get("reply_to"), from_name=get_header(options.get("from_name"), parsed_email_template.get("from"), "from_name"), context=context)
def integration_doc( request: HttpRequest, integration_name: str = REQ(default=None) ) -> HttpResponse: if not request.is_ajax(): return HttpResponseNotFound() try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = {} # type: Dict[str, Any] add_api_uri_context(context, request) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def send_custom_email(users: List[UserProfile], options: Dict[str, Any]) -> None: """ Can be used directly with from a management shell with send_custom_email(user_profile_list, dict( markdown_template_path="/path/to/markdown/file.md", subject="Email Subject", from_name="Sender Name") ) """ with open(options["markdown_template_path"], "r") as f: email_template_hash = hashlib.sha256( f.read().encode('utf-8')).hexdigest()[0:32] email_id = "zerver/emails/custom_email_%s" % (email_template_hash, ) markdown_email_base_template_path = "templates/zerver/emails/custom_email_base.pre.html" html_source_template_path = "templates/%s.source.html" % (email_id, ) plain_text_template_path = "templates/%s.txt" % (email_id, ) subject_path = "templates/%s.subject.txt" % (email_id, ) # First, we render the markdown input file just like our # user-facing docs with render_markdown_path. shutil.copyfile(options['markdown_template_path'], plain_text_template_path) rendered_input = render_markdown_path( plain_text_template_path.replace("templates/", "")) # And then extend it with our standard email headers. with open(html_source_template_path, "w") as f: with open(markdown_email_base_template_path, "r") as base_template: # Note that we're doing a hacky non-Jinja2 substitution here; # we do this because the normal render_markdown_path ordering # doesn't commute properly with inline-email-css. f.write(base_template.read().replace('{{ rendered_input }}', rendered_input)) with open(subject_path, "w") as f: f.write(options["subject"]) # Then, we compile the email template using inline-email-css to # add our standard styling to the paragraph tags (etc.). # # TODO: Ideally, we'd just refactor inline-email-css to # compile this one template, not all of them. subprocess.check_call(["./scripts/setup/inline-email-css"]) # Finally, we send the actual emails. for user_profile in users: context = { 'realm_uri': user_profile.realm.uri, 'realm_name': user_profile.realm.name, } send_email(email_id, to_user_ids=[user_profile.id], from_address=FromAddress.SUPPORT, reply_to_email=options.get("reply_to"), from_name=options["from_name"], context=context)
def help_content(self): # type: () -> Text doc_context = self.doc_context or {} if self.doc.endswith('.md'): return render_markdown_path(self.doc, doc_context) else: template = loader.get_template(self.doc) return mark_safe(template.render(doc_context))
def integration_doc(request, integration_name=REQ(default=None)): # type: (HttpRequest, str) -> HttpResponse try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = integration.doc_context or {} add_integrations_context(context) doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def integration_doc(request, integration_name=REQ(default=None)): # type: (HttpRequest, str) -> HttpResponse try: integration = INTEGRATIONS[integration_name] except KeyError: return HttpResponseNotFound() context = integration.doc_context or {} add_integrations_context(context) context['integration_name'] = integration.name context['integration_display_name'] = integration.display_name if hasattr(integration, 'stream_name'): context['recommended_stream_name'] = integration.stream_name if isinstance(integration, WebhookIntegration): context['integration_url'] = integration.url[3:] if isinstance(integration, HubotIntegration): context['hubot_docs_url'] = integration.hubot_docs_url doc_html_str = render_markdown_path(integration.doc, context) return HttpResponse(doc_html_str)
def help_content(self): # type: () -> Text doc_context = self.doc_context or {} return render_markdown_path(self.doc, doc_context)