mirror of
https://github.com/django-helpdesk/django-helpdesk.git
synced 2025-08-10 00:17:54 +02:00
run ruff formatter
This commit is contained in:
145
helpdesk/lib.py
145
helpdesk/lib.py
@ -6,34 +6,52 @@ django-helpdesk - A Django powered ticket tracker for small enterprise.
|
||||
lib.py - Common functions (eg multipart e-mail)
|
||||
"""
|
||||
|
||||
|
||||
from datetime import date, datetime, time
|
||||
from django.conf import settings
|
||||
from django.core.exceptions import ValidationError, ImproperlyConfigured
|
||||
from django.utils.encoding import smart_str
|
||||
from helpdesk.settings import CUSTOMFIELD_DATE_FORMAT, CUSTOMFIELD_DATETIME_FORMAT, CUSTOMFIELD_TIME_FORMAT
|
||||
from helpdesk.settings import (
|
||||
CUSTOMFIELD_DATE_FORMAT,
|
||||
CUSTOMFIELD_DATETIME_FORMAT,
|
||||
CUSTOMFIELD_TIME_FORMAT,
|
||||
)
|
||||
import logging
|
||||
import mimetypes
|
||||
|
||||
|
||||
logger = logging.getLogger('helpdesk')
|
||||
logger = logging.getLogger("helpdesk")
|
||||
|
||||
|
||||
def ticket_template_context(ticket):
|
||||
context = {}
|
||||
|
||||
for field in ('title', 'created', 'modified', 'submitter_email',
|
||||
'status', 'get_status_display', 'on_hold', 'description',
|
||||
'resolution', 'priority', 'get_priority_display',
|
||||
'last_escalation', 'ticket', 'ticket_for_url', 'merged_to',
|
||||
'get_status', 'ticket_url', 'staff_url', '_get_assigned_to'
|
||||
):
|
||||
for field in (
|
||||
"title",
|
||||
"created",
|
||||
"modified",
|
||||
"submitter_email",
|
||||
"status",
|
||||
"get_status_display",
|
||||
"on_hold",
|
||||
"description",
|
||||
"resolution",
|
||||
"priority",
|
||||
"get_priority_display",
|
||||
"last_escalation",
|
||||
"ticket",
|
||||
"ticket_for_url",
|
||||
"merged_to",
|
||||
"get_status",
|
||||
"ticket_url",
|
||||
"staff_url",
|
||||
"_get_assigned_to",
|
||||
):
|
||||
attr = getattr(ticket, field, None)
|
||||
if callable(attr):
|
||||
context[field] = '%s' % attr()
|
||||
context[field] = "%s" % attr()
|
||||
else:
|
||||
context[field] = attr
|
||||
context['assigned_to'] = context['_get_assigned_to']
|
||||
context["assigned_to"] = context["_get_assigned_to"]
|
||||
|
||||
return context
|
||||
|
||||
@ -41,7 +59,7 @@ def ticket_template_context(ticket):
|
||||
def queue_template_context(queue):
|
||||
context = {}
|
||||
|
||||
for field in ('title', 'slug', 'email_address', 'from_address', 'locale'):
|
||||
for field in ("title", "slug", "email_address", "from_address", "locale"):
|
||||
attr = getattr(queue, field, None)
|
||||
if callable(attr):
|
||||
context[field] = attr()
|
||||
@ -67,10 +85,10 @@ def safe_template_context(ticket):
|
||||
"""
|
||||
|
||||
context = {
|
||||
'queue': queue_template_context(ticket.queue),
|
||||
'ticket': ticket_template_context(ticket),
|
||||
"queue": queue_template_context(ticket.queue),
|
||||
"ticket": ticket_template_context(ticket),
|
||||
}
|
||||
context['ticket']['queue'] = context['queue']
|
||||
context["ticket"]["queue"] = context["queue"]
|
||||
|
||||
return context
|
||||
|
||||
@ -87,41 +105,42 @@ def text_is_spam(text, request):
|
||||
return False
|
||||
from django.contrib.sites.models import Site
|
||||
from django.core.exceptions import ImproperlyConfigured
|
||||
|
||||
try:
|
||||
site = Site.objects.get_current()
|
||||
except ImproperlyConfigured:
|
||||
site = Site(domain='configure-django-sites.com')
|
||||
site = Site(domain="configure-django-sites.com")
|
||||
|
||||
# see https://akismet.readthedocs.io/en/latest/overview.html#using-akismet
|
||||
|
||||
apikey = None
|
||||
|
||||
if hasattr(settings, 'TYPEPAD_ANTISPAM_API_KEY'):
|
||||
if hasattr(settings, "TYPEPAD_ANTISPAM_API_KEY"):
|
||||
apikey = settings.TYPEPAD_ANTISPAM_API_KEY
|
||||
elif hasattr(settings, 'PYTHON_AKISMET_API_KEY'):
|
||||
elif hasattr(settings, "PYTHON_AKISMET_API_KEY"):
|
||||
# new env var expected by python-akismet package
|
||||
apikey = settings.PYTHON_AKISMET_API_KEY
|
||||
elif hasattr(settings, 'AKISMET_API_KEY'):
|
||||
elif hasattr(settings, "AKISMET_API_KEY"):
|
||||
# deprecated, but kept for backward compatibility
|
||||
apikey = settings.AKISMET_API_KEY
|
||||
else:
|
||||
return False
|
||||
|
||||
ak = Akismet(
|
||||
blog_url='http://%s/' % site.domain,
|
||||
blog_url="http://%s/" % site.domain,
|
||||
key=apikey,
|
||||
)
|
||||
|
||||
if hasattr(settings, 'TYPEPAD_ANTISPAM_API_KEY'):
|
||||
ak.baseurl = 'api.antispam.typepad.com/1.1/'
|
||||
if hasattr(settings, "TYPEPAD_ANTISPAM_API_KEY"):
|
||||
ak.baseurl = "api.antispam.typepad.com/1.1/"
|
||||
|
||||
if ak.verify_key():
|
||||
ak_data = {
|
||||
'user_ip': request.META.get('REMOTE_ADDR', '127.0.0.1'),
|
||||
'user_agent': request.headers.get('User-Agent', ''),
|
||||
'referrer': request.headers.get('Referer', ''),
|
||||
'comment_type': 'comment',
|
||||
'comment_author': '',
|
||||
"user_ip": request.META.get("REMOTE_ADDR", "127.0.0.1"),
|
||||
"user_agent": request.headers.get("User-Agent", ""),
|
||||
"referrer": request.headers.get("Referer", ""),
|
||||
"comment_type": "comment",
|
||||
"comment_author": "",
|
||||
}
|
||||
|
||||
return ak.comment_check(smart_str(text), data=ak_data)
|
||||
@ -131,12 +150,12 @@ def text_is_spam(text, request):
|
||||
|
||||
def process_attachments(followup, attached_files):
|
||||
max_email_attachment_size = getattr(
|
||||
settings, 'HELPDESK_MAX_EMAIL_ATTACHMENT_SIZE', 512000)
|
||||
settings, "HELPDESK_MAX_EMAIL_ATTACHMENT_SIZE", 512000
|
||||
)
|
||||
attachments = []
|
||||
errors = set()
|
||||
|
||||
for attached in attached_files:
|
||||
|
||||
if attached.size:
|
||||
from helpdesk.models import FollowUpAttachment
|
||||
|
||||
@ -145,9 +164,9 @@ def process_attachments(followup, attached_files):
|
||||
followup=followup,
|
||||
file=attached,
|
||||
filename=filename,
|
||||
mime_type=attached.content_type or
|
||||
mimetypes.guess_type(filename, strict=False)[0] or
|
||||
'application/octet-stream',
|
||||
mime_type=attached.content_type
|
||||
or mimetypes.guess_type(filename, strict=False)[0]
|
||||
or "application/octet-stream",
|
||||
size=attached.size,
|
||||
)
|
||||
try:
|
||||
@ -176,7 +195,7 @@ def format_time_spent(time_spent):
|
||||
if time_spent:
|
||||
time_spent = "{0:02d}h:{1:02d}m".format(
|
||||
int(time_spent.total_seconds()) // 3600,
|
||||
int(time_spent.total_seconds()) % 3600 // 60
|
||||
int(time_spent.total_seconds()) % 3600 // 60,
|
||||
)
|
||||
else:
|
||||
time_spent = ""
|
||||
@ -184,7 +203,7 @@ def format_time_spent(time_spent):
|
||||
|
||||
|
||||
def convert_value(value):
|
||||
""" Convert date/time data type to known fixed format string """
|
||||
"""Convert date/time data type to known fixed format string"""
|
||||
if type(value) is datetime:
|
||||
return value.strftime(CUSTOMFIELD_DATETIME_FORMAT)
|
||||
elif type(value) is date:
|
||||
@ -201,39 +220,65 @@ def daily_time_spent_calculation(earliest, latest, open_hours):
|
||||
time_spent_seconds = 0
|
||||
|
||||
# avoid rendering day in different locale
|
||||
weekday = ('monday', 'tuesday', 'wednesday', 'thursday',
|
||||
'friday', 'saturday', 'sunday')[earliest.weekday()]
|
||||
|
||||
weekday = (
|
||||
"monday",
|
||||
"tuesday",
|
||||
"wednesday",
|
||||
"thursday",
|
||||
"friday",
|
||||
"saturday",
|
||||
"sunday",
|
||||
)[earliest.weekday()]
|
||||
|
||||
# enforce correct settings
|
||||
MIDNIGHT = 23.9999
|
||||
start, end = open_hours.get(weekday, (0, MIDNIGHT))
|
||||
if not 0 <= start <= end <= MIDNIGHT:
|
||||
raise ImproperlyConfigured("HELPDESK_FOLLOWUP_TIME_SPENT_OPENING_HOURS"
|
||||
f" setting for {weekday} out of (0, 23.9999) boundary")
|
||||
|
||||
raise ImproperlyConfigured(
|
||||
"HELPDESK_FOLLOWUP_TIME_SPENT_OPENING_HOURS"
|
||||
f" setting for {weekday} out of (0, 23.9999) boundary"
|
||||
)
|
||||
|
||||
# transform decimals to minutes and seconds
|
||||
start_hour, start_minute, start_second = int(start), int(start % 1 * 60), int(start * 60 % 1 * 60)
|
||||
end_hour, end_minute, end_second = int(end), int(end % 1 * 60), int(end * 60 % 1 * 60)
|
||||
start_hour, start_minute, start_second = (
|
||||
int(start),
|
||||
int(start % 1 * 60),
|
||||
int(start * 60 % 1 * 60),
|
||||
)
|
||||
end_hour, end_minute, end_second = (
|
||||
int(end),
|
||||
int(end % 1 * 60),
|
||||
int(end * 60 % 1 * 60),
|
||||
)
|
||||
|
||||
# translate time for delta calculation
|
||||
earliest_f = earliest.hour + earliest.minute / 60 + earliest.second / 3600
|
||||
latest_f = latest.hour + latest.minute / 60 + latest.second / (60 * 60) + latest.microsecond / (60 * 60 * 999999)
|
||||
latest_f = (
|
||||
latest.hour
|
||||
+ latest.minute / 60
|
||||
+ latest.second / (60 * 60)
|
||||
+ latest.microsecond / (60 * 60 * 999999)
|
||||
)
|
||||
|
||||
# if latest time is midnight and close hour is midnight, add a second to the time spent
|
||||
if latest_f >= MIDNIGHT and end == MIDNIGHT:
|
||||
time_spent_seconds += 1
|
||||
|
||||
|
||||
if earliest_f < start:
|
||||
earliest = earliest.replace(hour=start_hour, minute=start_minute, second=start_second)
|
||||
earliest = earliest.replace(
|
||||
hour=start_hour, minute=start_minute, second=start_second
|
||||
)
|
||||
elif earliest_f >= end:
|
||||
earliest = earliest.replace(hour=end_hour, minute=end_minute, second=end_second)
|
||||
|
||||
|
||||
if latest_f < start:
|
||||
latest = latest.replace(hour=start_hour, minute=start_minute, second=start_second)
|
||||
latest = latest.replace(
|
||||
hour=start_hour, minute=start_minute, second=start_second
|
||||
)
|
||||
elif latest_f >= end:
|
||||
latest = latest.replace(hour=end_hour, minute=end_minute, second=end_second)
|
||||
|
||||
|
||||
day_delta = latest - earliest
|
||||
time_spent_seconds += day_delta.seconds
|
||||
|
||||
return time_spent_seconds
|
||||
|
||||
return time_spent_seconds
|
||||
|
Reference in New Issue
Block a user