annotate core/functions.py @ 989:2908859c2fe4

Smilies now use relative links. This is for upcoming switch to SSL. Currently we do not need absolute URLs for smilies. If this changes we can add it later.
author Brian Neal <bgneal@gmail.com>
date Thu, 29 Oct 2015 20:54:34 -0500
parents f5aa74dcdd7a
children e932f2ecd4a7
rev   line source
bgneal@700 1 """This file houses various core utility functions"""
bgneal@976 2 from contextlib import contextmanager
bgneal@176 3 import datetime
bgneal@700 4 import logging
bgneal@700 5 import os
bgneal@227 6 import re
bgneal@964 7 import tempfile
gremmie@1 8
gremmie@1 9 from django.contrib.sites.models import Site
gremmie@1 10 from django.conf import settings
bgneal@522 11 import django.core.mail
gremmie@1 12
bgneal@513 13 import core.tasks
bgneal@181 14
gremmie@1 15
bgneal@964 16 class TemporaryFile(object):
bgneal@964 17 """Context manager class for working with temporary files.
bgneal@964 18
bgneal@964 19 The file will be closed and removed when the context is exited.
bgneal@964 20 """
bgneal@964 21 def __init__(self, **kwargs):
bgneal@964 22 """kwargs will be passed to mkstemp."""
bgneal@964 23 self.kwargs = kwargs
bgneal@964 24
bgneal@964 25 def __enter__(self):
bgneal@964 26 self.fd, self.filename = tempfile.mkstemp(**self.kwargs)
bgneal@964 27 self.file = os.fdopen(self.fd, 'w+b')
bgneal@964 28 return self
bgneal@964 29
bgneal@964 30 def __exit__(self, exc_type, exc_value, traceback):
bgneal@964 31 self.file.close()
bgneal@964 32 os.remove(self.filename)
bgneal@700 33
bgneal@700 34
bgneal@976 35 @contextmanager
bgneal@976 36 def remove_file(path):
bgneal@976 37 """Context manager for removing a file when the context is exited."""
bgneal@976 38 try:
bgneal@976 39 yield path
bgneal@976 40 finally:
bgneal@976 41 os.remove(path)
bgneal@976 42
bgneal@976 43
bgneal@892 44 def send_mail(subject, message, from_email, recipient_list, reply_to=None, defer=True):
gremmie@1 45 """
bgneal@513 46 The main send email function. Use this function to send email from the
bgneal@513 47 site. All applications should use this function instead of calling
bgneal@513 48 Django's directly.
bgneal@522 49 If defer is True, the email will be sent to a Celery task to actually send
bgneal@522 50 the email. Otherwise it is sent on the caller's thread. In any event, the
bgneal@513 51 email will be logged at the DEBUG level.
bgneal@513 52
bgneal@513 53 """
bgneal@513 54 # Guard against empty email addresses
bgneal@418 55 recipient_list = [dest for dest in recipient_list if dest]
bgneal@418 56 if not recipient_list:
bgneal@418 57 logging.warning("Empty recipient_list in send_mail")
bgneal@418 58 return
gremmie@1 59
bgneal@892 60 logging.debug('EMAIL:\nFrom: %s\nTo: %s\nReply-To: %s\nSubject: %s\nMessage:\n%s',
bgneal@892 61 from_email, str(recipient_list), reply_to, subject, message)
bgneal@892 62
bgneal@892 63 headers = {'Reply-To': reply_to} if reply_to else None
bgneal@892 64 msg_kwargs = {
bgneal@892 65 'subject': subject,
bgneal@892 66 'body': message,
bgneal@892 67 'from_email': from_email,
bgneal@892 68 'to': recipient_list,
bgneal@892 69 'headers': headers,
bgneal@892 70 }
gremmie@1 71
bgneal@522 72 if defer:
bgneal@892 73 core.tasks.send_mail.delay(**msg_kwargs)
bgneal@522 74 else:
bgneal@892 75 msg = django.core.mail.EmailMessage(**msg_kwargs)
bgneal@892 76 msg.send()
bgneal@513 77
gremmie@1 78
gremmie@1 79 def email_admins(subject, message):
gremmie@1 80 """Emails the site admins. Goes through the site send_mail function."""
gremmie@1 81 site = Site.objects.get_current()
gremmie@1 82 subject = '[%s] %s' % (site.name, subject)
bgneal@316 83 send_mail(subject,
bgneal@316 84 message,
gremmie@1 85 '%s@%s' % (settings.GPP_NO_REPLY_EMAIL, site.domain),
gremmie@1 86 [mail_tuple[1] for mail_tuple in settings.ADMINS])
gremmie@1 87
gremmie@1 88
gremmie@1 89 def email_managers(subject, message):
gremmie@1 90 """Emails the site managers. Goes through the site send_mail function."""
gremmie@1 91 site = Site.objects.get_current()
gremmie@1 92 subject = '[%s] %s' % (site.name, subject)
bgneal@316 93 send_mail(subject,
bgneal@700 94 message,
gremmie@1 95 '%s@%s' % (settings.GPP_NO_REPLY_EMAIL, site.domain),
gremmie@1 96 [mail_tuple[1] for mail_tuple in settings.MANAGERS])
gremmie@1 97
gremmie@1 98
gremmie@1 99 def get_full_name(user):
gremmie@1 100 """Returns the user's full name if available, otherwise falls back
gremmie@1 101 to the username."""
gremmie@1 102 full_name = user.get_full_name()
gremmie@1 103 if full_name:
gremmie@1 104 return full_name
gremmie@1 105 return user.username
bgneal@9 106
bgneal@176 107
bgneal@176 108 BASE_YEAR = 2010
bgneal@176 109
bgneal@176 110 def copyright_str():
bgneal@176 111 curr_year = datetime.datetime.now().year
bgneal@176 112 if curr_year == BASE_YEAR:
bgneal@176 113 year_range = str(BASE_YEAR)
bgneal@176 114 else:
bgneal@176 115 year_range = "%d - %d" % (BASE_YEAR, curr_year)
bgneal@176 116
bgneal@176 117 return 'Copyright (C) %s, SurfGuitar101.com' % year_range
bgneal@227 118
bgneal@227 119
bgneal@227 120 IP_PAT = re.compile('(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})')
bgneal@227 121
bgneal@227 122 def get_ip(request):
bgneal@227 123 """Returns the IP from the request or None if it cannot be retrieved."""
bgneal@227 124 ip = request.META.get('HTTP_X_FORWARDED_FOR',
bgneal@227 125 request.META.get('REMOTE_ADDR'))
bgneal@227 126
bgneal@227 127 if ip:
bgneal@227 128 match = IP_PAT.match(ip)
bgneal@227 129 ip = match.group(1) if match else None
bgneal@227 130
bgneal@227 131 return ip
bgneal@241 132
bgneal@241 133
bgneal@241 134 def get_page(qdict):
bgneal@241 135 """Attempts to retrieve the value for "page" from the given query dict and
bgneal@241 136 return it as an integer. If the key cannot be found or converted to an
bgneal@241 137 integer, 1 is returned.
bgneal@241 138 """
bgneal@241 139 n = qdict.get('page', 1)
bgneal@241 140 try:
bgneal@241 141 n = int(n)
bgneal@241 142 except ValueError:
bgneal@241 143 n = 1
bgneal@241 144 return n
bgneal@566 145
bgneal@566 146
bgneal@566 147 def quote_message(who, message):
bgneal@566 148 """
bgneal@566 149 Builds a message reply by quoting the existing message in a
bgneal@566 150 typical email-like fashion. The quoting is compatible with Markdown.
bgneal@566 151 """
bgneal@816 152 msg = "> %s" % message.rstrip().replace('\n', '\n> ')
bgneal@566 153 if msg.endswith('\n> '):
bgneal@566 154 msg = msg[:-2]
bgneal@566 155
bgneal@566 156 return "*%s wrote:*\n\n%s\n\n" % (who, msg)