perf: View the internal message and convert the content into markdown

pull/14080/head
feng 2024-08-27 16:46:41 +08:00 committed by feng626
parent 25a473dc99
commit b9e64747ac
5 changed files with 52 additions and 29 deletions

View File

@ -95,12 +95,14 @@ class GatherAccountsManager(AccountBasePlaybookManager):
return None, None return None, None
users = User.objects.filter(id__in=recipients) users = User.objects.filter(id__in=recipients)
if not users: if not users.exists():
return users, None return users, None
asset_ids = self.asset_username_mapper.keys() asset_ids = self.asset_username_mapper.keys()
assets = Asset.objects.filter(id__in=asset_ids)
assets = Asset.objects.filter(id__in=asset_ids).prefetch_related('accounts')
gather_accounts = GatheredAccount.objects.filter(asset_id__in=asset_ids, present=True) gather_accounts = GatheredAccount.objects.filter(asset_id__in=asset_ids, present=True)
asset_id_map = {str(asset.id): asset for asset in assets} asset_id_map = {str(asset.id): asset for asset in assets}
asset_id_username = list(assets.values_list('id', 'accounts__username')) asset_id_username = list(assets.values_list('id', 'accounts__username'))
asset_id_username.extend(list(gather_accounts.values_list('asset_id', 'username'))) asset_id_username.extend(list(gather_accounts.values_list('asset_id', 'username')))
@ -109,26 +111,24 @@ class GatherAccountsManager(AccountBasePlaybookManager):
for asset_id, username in asset_id_username: for asset_id, username in asset_id_username:
system_asset_username_mapper[str(asset_id)].add(username) system_asset_username_mapper[str(asset_id)].add(username)
change_info = {} change_info = defaultdict(dict)
for asset_id, usernames in self.asset_username_mapper.items(): for asset_id, usernames in self.asset_username_mapper.items():
system_usernames = system_asset_username_mapper.get(asset_id) system_usernames = system_asset_username_mapper.get(asset_id)
if not system_usernames: if not system_usernames:
continue continue
add_usernames = usernames - system_usernames add_usernames = usernames - system_usernames
remove_usernames = system_usernames - usernames remove_usernames = system_usernames - usernames
k = f'{asset_id_map[asset_id]}[{asset_id}]'
if not add_usernames and not remove_usernames: if not add_usernames and not remove_usernames:
continue continue
change_info[k] = { change_info[str(asset_id_map[asset_id])] = {
'add_usernames': ', '.join(add_usernames), 'add_usernames': add_usernames,
'remove_usernames': ', '.join(remove_usernames), 'remove_usernames': remove_usernames
} }
return users, change_info return users, dict(change_info)
@staticmethod @staticmethod
def send_email_if_need(users, change_info): def send_email_if_need(users, change_info):

View File

@ -1,18 +1,29 @@
{% load i18n %} {% load i18n %}
<h3></h3>
<h3>{% trans 'Gather account change information' %}</h3> <table style="width: 100%; border-collapse: collapse; table-layout: fixed; text-align: left; margin-top: 20px;">
<table style="width: 100%; border-collapse: collapse; max-width: 100%; text-align: left; margin-top: 20px;">
<caption></caption> <caption></caption>
<tr style="background-color: #f2f2f2;"> <tr style="background-color: #f2f2f2;">
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Asset' %}</th> <th style="border: 1px solid #ddd; padding: 15px; text-align: left; vertical-align: top; line-height: 1.5;">
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Added account' %}</th> {% trans 'Asset' %}
<th style="border: 1px solid #ddd; padding: 10px;">{% trans 'Deleted account' %}</th> </th>
<th style="border: 1px solid #ddd; padding: 15px; text-align: left; vertical-align: top; line-height: 1.5;">
{% trans 'Added account' %}
</th>
<th style="border: 1px solid #ddd; padding: 15px; text-align: left; vertical-align: top; line-height: 1.5;">
{% trans 'Deleted account' %}
</th>
</tr> </tr>
{% for name, change in change_info.items %} {% for name, change in change_info.items %}
<tr style="{% cycle 'background-color: #ebf5ff;' 'background-color: #fff;' %}"> <tr style="{% cycle 'background-color: #ebf5ff;' 'background-color: #fff;' %}">
<td style="border: 1px solid #ddd; padding: 10px;">{{ name }}</td> <td style="border: 1px solid #ddd; padding: 10px; text-align: left; vertical-align: top;">
<td style="border: 1px solid #ddd; padding: 10px;">{{ change.add_usernames }}</td> {{ name | safe }}
<td style="border: 1px solid #ddd; padding: 10px;">{{ change.remove_usernames }}</td> </td>
<td style="border: 1px solid #ddd; padding: 10px; text-align: left; vertical-align: top;">
{{ change.add_usernames | join:" " | safe }}
</td>
<td style="border: 1px solid #ddd; padding: 10px; text-align: left; vertical-align: top;">
{{ change.remove_usernames | join:" " | safe }}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>

View File

@ -13,6 +13,7 @@ from collections import OrderedDict
from functools import wraps from functools import wraps
from itertools import chain from itertools import chain
import html2text
import psutil import psutil
from django.conf import settings from django.conf import settings
from django.templatetags.static import static from django.templatetags.static import static
@ -421,3 +422,14 @@ def distinct(seq, key=None):
def is_macos(): def is_macos():
return platform.system() == 'Darwin' return platform.system() == 'Darwin'
def convert_html_to_markdown(html_str):
h = html2text.HTML2Text()
h.body_width = 0
h.ignore_links = True
markdown = h.handle(html_str)
markdown = markdown.replace('\n\n', '\n')
markdown = markdown.replace('\n ', '\n')
return markdown

View File

@ -1,6 +1,7 @@
from rest_framework import serializers from rest_framework import serializers
from rest_framework.serializers import ModelSerializer from rest_framework.serializers import ModelSerializer
from common.utils import convert_html_to_markdown
from ..models import MessageContent from ..models import MessageContent
@ -16,6 +17,8 @@ class SenderMixin(ModelSerializer):
class MessageContentSerializer(SenderMixin, ModelSerializer): class MessageContentSerializer(SenderMixin, ModelSerializer):
message = serializers.SerializerMethodField()
class Meta: class Meta:
model = MessageContent model = MessageContent
fields = [ fields = [
@ -24,6 +27,11 @@ class MessageContentSerializer(SenderMixin, ModelSerializer):
'sender', 'sender',
] ]
@staticmethod
def get_message(site_msg):
markdown = convert_html_to_markdown(site_msg.message)
return markdown
class SiteMessageSerializer(SenderMixin, ModelSerializer): class SiteMessageSerializer(SenderMixin, ModelSerializer):
content = MessageContentSerializer(read_only=True) content = MessageContentSerializer(read_only=True)

View File

@ -1,8 +1,7 @@
import html2text
from django.template.loader import render_to_string from django.template.loader import render_to_string
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from common.utils import get_logger from common.utils import get_logger, convert_html_to_markdown
from tickets.const import TicketState, TicketType from tickets.const import TicketState, TicketType
from tickets.utils import ( from tickets.utils import (
send_ticket_processed_mail_to_applicant, send_ticket_processed_mail_to_applicant,
@ -97,9 +96,8 @@ class BaseHandler:
approve_info = _('{} {} the ticket').format(user_display, state_display) approve_info = _('{} {} the ticket').format(user_display, state_display)
context = self._diff_prev_approve_context(state) context = self._diff_prev_approve_context(state)
context.update({'approve_info': approve_info}) context.update({'approve_info': approve_info})
body = self.safe_html_script( html_str = render_to_string('tickets/ticket_approve_diff.html', context)
render_to_string('tickets/ticket_approve_diff.html', context) body = convert_html_to_markdown(html_str)
)
data = { data = {
'body': body, 'body': body,
'user': user, 'user': user,
@ -108,9 +106,3 @@ class BaseHandler:
'state': state 'state': state
} }
return self.ticket.comments.create(**data) return self.ticket.comments.create(**data)
@staticmethod
def safe_html_script(unsafe_html):
unsafe_html = unsafe_html.replace('\n', '')
html_str = html2text.html2text(unsafe_html)
return html_str