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@1032
|
13 from .tasks import send_mail as send_mail_task
|
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@1032
|
73 send_mail_task.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)
|