]> git.openstreetmap.org Git - osqa.git/blob - forum_modules/updates/base.py
ce5bc8b23599c23a003df229bdee17b4e398ca29
[osqa.git] / forum_modules / updates / base.py
1 # -*- coding: utf-8 -*-
2
3 import os
4 import sys
5 import platform
6 import bz2
7 import urllib2, urllib
8 import binascii
9 import string
10 import random
11 import re
12 import urllib2
13 import settings
14 import datetime
15 import logging
16
17
18 from xml.dom.minidom import parse, parseString
19 from forum.base import get_database_engine
20 from forum.models import Question, Answer, Comment, User
21 from forum.settings import APP_URL, SVN_REVISION, APP_TITLE, APP_DESCRIPTION
22 from django import VERSION as DJANGO_VERSION
23 from django.utils import simplejson
24 from django.utils.html import escape
25 from django.utils.encoding import smart_unicode
26 from django.conf import settings as django_settings
27 from django.utils.translation import ugettext as _
28
29
30 def generate_installation_key():
31     gen = lambda length: "".join( [random.choice(string.digits+string.letters) for i in xrange(length)])
32     return '%s-%s-%s-%s' % (gen(4), gen(4), gen(4), gen(4))
33
34 # To get the site views count we get the SUM of all questions views.
35 def get_site_views():
36     views = 0
37
38     # Go through all questions and increase the views count
39     for question in Question.objects.all():
40         views += question.view_count
41
42     return views
43
44 # Gets the active users count since the last visit
45 def get_active_users():
46     users_count = 0
47
48     try:
49         if settings.LATEST_UPDATE_DATETIME:
50             users_count = User.objects.filter(last_login__gt=settings.LATEST_UPDATE_DATETIME).count()
51     except:
52         pass
53
54     return users_count
55
56 def get_server_name():
57     url = '%s/' % APP_URL
58
59     try:
60         # Make the request
61         request = urllib2.Request(url)
62         response = urllib2.urlopen(request)
63
64         # Get the response information
65         response_info = response.info()
66
67         server_name = re.findall("Server: (?P<server_name>.*)$", str(response_info))[0]
68         server_name = ''.join(server_name.splitlines())
69
70         return server_name
71     except:
72         return 'Unknown'
73
74 def get_admin_emails():
75     emails = []
76
77     for user in User.objects.filter(is_superuser=True):
78         emails.append(user.email)
79
80     return emails
81
82 def check_for_updates():
83     # Get the SVN Revision
84     try:
85         svn_revision = int(SVN_REVISION.replace('SVN-', ''))
86     except ValueError:
87         # Here we'll have to find another way of getting the SVN revision
88         svn_revision = 0
89
90     admin_emails_xml = '<emails>'
91     for email in get_admin_emails():
92         admin_emails_xml += '<email value="%s" />' % email
93     admin_emails_xml += '</emails>'
94
95     database_type = get_database_engine()
96
97     statistics = u"""<check>
98     <key value="%(site_key)s" />
99     <app_url value="%(app_url)s" />
100     <app_title value="%(app_title)s" />
101     <app_description value="%(app_description)s" />
102     <svn_revision value="%(svn_revision)d" />
103     <views value="%(site_views)d" />
104     <questions_count value="%(questions_count)d" />
105     <answers_count value="%(answers_count)d" />
106     <comments_count value="%(comments_count)d" />
107     <active_users value="%(active_users)d" />
108     <server value="%(server_name)s" />
109     <python_version value="%(python_version)s" />
110     <django_version value="%(django_version)s" />
111     <database value="%(database)s" />
112     <os value="%(os)s" />
113     %(emails)s
114 </check> """ % {
115         'site_key' : settings.SITE_KEY,
116         'app_url' : APP_URL,
117         'app_title' : escape(APP_TITLE.value),
118         'app_description' : escape(APP_DESCRIPTION.value),
119         'svn_revision' : svn_revision,
120         'site_views' : get_site_views(),
121         'server_name' : get_server_name(),
122         'questions_count' : Question.objects.filter_state(deleted=False).count(),
123         'answers_count' : Answer.objects.filter_state(deleted=False).count(),
124         'comments_count' : Comment.objects.filter_state(deleted=False).count(),
125         'active_users' : get_active_users(),
126         'python_version' : ''.join(sys.version.splitlines()),
127         'django_version' : str(DJANGO_VERSION),
128         'database' : database_type,
129         'os' : str(platform.uname()),
130         'emails' : admin_emails_xml,
131     }
132
133     # Compress the statistics XML dump
134     statistics = statistics.encode('ascii', 'xmlcharrefreplace')
135     statistics_compressed = bz2.compress(statistics)
136
137     # Pass the compressed statistics to the update server
138     post_data = {
139         'statistics' : binascii.b2a_base64(statistics_compressed),
140     }
141     data = urllib.urlencode(post_data)
142
143     # We simulate some browser, otherwise the server can return 403 response
144     user_agent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_5_8; en-us) AppleWebKit/531.21.8 (KHTML, like Gecko) Version/4.0.4 Safari/5'
145     headers={ 'User-Agent' : user_agent,}
146
147     try:
148         check_request = urllib2.Request('%s%s' % (settings.UPDATE_SERVER_URL, '/site_check/'), data, headers=headers)
149         check_response = urllib2.urlopen(check_request)
150         content = check_response.read()
151     except urllib2.HTTPError, error:
152         content = error.read()
153     except:
154         return _("Wasn't able to check to the update server.")
155
156     # Read the messages from the Update Server
157     try:
158         messages_xml_url = '%s%s' % (settings.UPDATE_SERVER_URL, '/messages/xml/')
159         messages_request = urllib2.Request(messages_xml_url, headers=headers)
160         messages_response = urllib2.urlopen(messages_request)
161         messages_xml = messages_response.read()
162     except:
163         return _("Wasn't able to retreive the update messages.")
164
165     # Store the messages XML in a Setting object
166     settings.UPDATE_MESSAGES_XML.set_value(messages_xml)
167
168     messages_dom = parseString(messages_xml)
169     messages_count = len(messages_dom.getElementsByTagName('message'))
170
171     # Set the latest update datetime to now.
172     now = datetime.datetime.now()
173     settings.LATEST_UPDATE_DATETIME.set_value(now)
174
175     return _('%d update messages have been downloaded.') % messages_count
176
177 def update_trigger():
178     # Trigger the update process
179     now = datetime.datetime.now()
180     if (now - settings.LATEST_UPDATE_DATETIME) > datetime.timedelta(days=1):
181         try:
182             update_status = check_for_updates()
183             logging.log(logging.INFO, smart_unicode("Update process has been triggered: %s" % update_status))
184         except Exception, e:
185             logging.errror(smart_unicode(e))
186         finally:
187             settings.LATEST_UPDATE_DATETIME.set_value(now)