Skip to content
This repository has been archived by the owner on Jan 13, 2022. It is now read-only.

Commit

Permalink
Merge pull request #148 from glogiotatidis/fxa-activity-project-fuel-…
Browse files Browse the repository at this point in the history
…1179878

[bug 1179878] Pass user agent info from FxA to Exact Target.
  • Loading branch information
pmac committed Sep 11, 2015
2 parents 58176a8 + d27329e commit eaba8d0
Show file tree
Hide file tree
Showing 3 changed files with 160 additions and 6 deletions.
19 changes: 14 additions & 5 deletions news/tasks.py
Expand Up @@ -10,6 +10,7 @@
from django.core.cache import get_cache
from django_statsd.clients import statsd

import user_agents
from celery.task import Task, task

from news.backends.common import NewsletterException, NewsletterNoResultsException
Expand Down Expand Up @@ -201,16 +202,24 @@ def get_external_user_data(email=None, token=None, fields=None, database=None):

@et_task
def add_fxa_activity(data):
user_agent = user_agents.parse(data['user_agent'])
device_type = 'D'
if user_agent.is_mobile:
device_type = 'M'
elif user_agent.is_tablet:
device_type = 'T'

record = {
'FXA_ID': data['fxa_id'],
'LOGIN_DATE': gmttime(),
'FIRST_DEVICE': 'y' if data['first_device'] else 'n',
'OS': user_agent.os.family,
'OS_VERSION': user_agent.os.version_string,
'BROWSER': '{0} {1}'.format(user_agent.browser.family,
user_agent.browser.version_string),
'DEVICE_NAME': user_agent.device.family,
'DEVICE_TYPE': device_type,
}
# now do magic to parse the UA string.
# good deps I've found for this:
# * https://pypi.python.org/pypi/user-agents # depends on ua-parser
# * https://pypi.python.org/pypi/ua-parser
# doesn't seem either of those support py2.6 :(

apply_updates('Sync_Device_Logins', record)

Expand Down
145 changes: 145 additions & 0 deletions news/tests/test_tasks.py
Expand Up @@ -10,6 +10,7 @@
from news.models import FailedTask, Subscriber
from news.newsletters import clear_sms_cache
from news.tasks import (
add_fxa_activity,
add_sms_user,
et_task,
mogrify_message_id,
Expand Down Expand Up @@ -232,3 +233,147 @@ def myfunc():
myfunc()

myfunc.retry.assert_called_with(exc=error, countdown=16 * 60)


class AddFxaActivityTests(TestCase):
def _base_test(self, user_agent=None, fxa_id='123', first_device=True):
if not user_agent:
user_agent = 'Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0'

data = {
'fxa_id': fxa_id,
'first_device': first_device,
'user_agent': user_agent
}
with patch('news.tasks.apply_updates') as apply_updates_mock:
add_fxa_activity(data)
record = apply_updates_mock.call_args[0][1]
return record

def test_login_date(self):
with patch('news.tasks.gmttime') as gmttime_mock:
gmttime_mock.return_value = 'this is time'
record = self._base_test()
self.assertEqual(record['LOGIN_DATE'], 'this is time')

def test_first_device(self):
record = self._base_test(first_device=True)
self.assertEqual(record['FIRST_DEVICE'], 'y')

record = self._base_test(first_device=False)
self.assertEqual(record['FIRST_DEVICE'], 'n')

def test_fxa_id(self):
record = self._base_test(fxa_id='This is id')
self.assertEqual(record['FXA_ID'], 'This is id')

def test_windows(self):
ua = 'Mozilla/5.0 (Windows NT 6.1; rv:10.0) Gecko/20100101 Firefox/10.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Windows 7')
self.assertEqual(record['OS_VERSION'], '') # Not sure if we expect '7' here.
self.assertEqual(record['BROWSER'], 'Firefox 10')
self.assertEqual(record['DEVICE_NAME'], 'Other')
self.assertEqual(record['DEVICE_TYPE'], 'D')

def test_mac(self):
ua = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/30.2'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Mac OS X')
self.assertEqual(record['OS_VERSION'], '10.6')
self.assertEqual(record['BROWSER'], 'Firefox 30.2')
self.assertEqual(record['DEVICE_NAME'], 'Other')
self.assertEqual(record['DEVICE_TYPE'], 'D')

def test_linux(self):
ua = 'Mozilla/5.0 (X11; Linux i686 on x86_64; rv:10.0) Gecko/20100101 Firefox/42.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Linux')
self.assertEqual(record['OS_VERSION'], '')
self.assertEqual(record['BROWSER'], 'Firefox 42')
self.assertEqual(record['DEVICE_NAME'], 'Other')
self.assertEqual(record['DEVICE_TYPE'], 'D')

def test_android_phone_below_version_41(self):
ua = 'Mozilla/5.0 (Android; Mobile; rv:40.0) Gecko/40.0 Firefox/40.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Android')
self.assertEqual(record['OS_VERSION'], '')
self.assertEqual(record['BROWSER'], 'Firefox Mobile 40')
self.assertEqual(record['DEVICE_NAME'], 'Generic Smartphone')
self.assertEqual(record['DEVICE_TYPE'], 'M')

def test_android_tablet_below_version_41(self):
ua = 'Mozilla/5.0 (Android; Tablet; rv:40.0) Gecko/40.0 Firefox/40.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Android')
self.assertEqual(record['OS_VERSION'], '')
self.assertEqual(record['BROWSER'], 'Firefox 40')
self.assertEqual(record['DEVICE_NAME'], 'Generic Tablet')
self.assertEqual(record['DEVICE_TYPE'], 'T')

def test_android_phone_from_version_41(self):
ua = 'Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firefox/41.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Android')
self.assertEqual(record['OS_VERSION'], '4.4')
self.assertEqual(record['BROWSER'], 'Firefox Mobile 41')
self.assertEqual(record['DEVICE_NAME'], 'Generic Smartphone')
self.assertEqual(record['DEVICE_TYPE'], 'M')

# TODO This reports Android 5 instead of Firefox 40
#
# def test_android_tablet_from_version_41(self):
# ua = 'Mozilla/5.0 (Android 5.0; Tablet; rv:41.0) Gecko/41.0 Firefox/41.0'
# record = self._base_test(ua)
# self.assertEqual(record['OS'], 'Android')
# self.assertEqual(record['OS_VERSION'], '5')
# self.assertEqual(record['BROWSER'], 'Firefox 40')
# self.assertEqual(record['DEVICE_NAME'], 'Generic Tablet')
# self.assertEqual(record['DEVICE_TYPE'], 'T')

def test_firefox_os_phone(self):
ua = 'Mozilla/5.0 (Mobile; rv:26.0) Gecko/26.0 Firefox/26.0'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Firefox OS')
self.assertEqual(record['OS_VERSION'], '1.2')
self.assertEqual(record['BROWSER'], 'Firefox Mobile 26')
self.assertEqual(record['DEVICE_NAME'], 'Generic Smartphone')
self.assertEqual(record['DEVICE_TYPE'], 'M')

def test_firefox_os_tablet(self):
ua = 'Mozilla/5.0 (Tablet; rv:26.0) Gecko/26.0 Firefox/26.0'
record = self._base_test(ua)

self.assertEqual(record['OS'], 'Firefox OS')
self.assertEqual(record['OS_VERSION'], '1.2')
self.assertEqual(record['BROWSER'], 'Firefox 26')
self.assertEqual(record['DEVICE_NAME'], 'Generic Tablet')
self.assertEqual(record['DEVICE_TYPE'], 'T')

def test_firefox_os_device_specific(self):
ua = 'Mozilla/5.0 (Mobile; ZTEOPEN; rv:18.1) Gecko/18.1 Firefox/18.1'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'Firefox OS')
self.assertEqual(record['OS_VERSION'], '1.1')
self.assertEqual(record['BROWSER'], 'Firefox Mobile 18.1')
self.assertEqual(record['DEVICE_NAME'], 'ZTE OPEN')
self.assertEqual(record['DEVICE_TYPE'], 'M')

def test_firefox_ios_iphone(self):
ua = 'Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'iOS')
self.assertEqual(record['OS_VERSION'], '8.3')
self.assertEqual(record['BROWSER'], 'Firefox iOS 1')
self.assertEqual(record['DEVICE_NAME'], 'iPhone')
self.assertEqual(record['DEVICE_TYPE'], 'M')

def test_firefox_ios_tablet(self):
ua = 'Mozilla/5.0 (iPad; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4'
record = self._base_test(ua)
self.assertEqual(record['OS'], 'iOS')
self.assertEqual(record['OS_VERSION'], '8.3')
self.assertEqual(record['BROWSER'], 'Firefox iOS 1')
self.assertEqual(record['DEVICE_NAME'], 'iPad')
self.assertEqual(record['DEVICE_TYPE'], 'T')
2 changes: 1 addition & 1 deletion vendor
Submodule vendor updated 38 files
+36 −0 lib/python/PyYAML-3.11-py2.7.egg-info/PKG-INFO
+27 −0 lib/python/PyYAML-3.11-py2.7.egg-info/SOURCES.txt
+1 −0 lib/python/PyYAML-3.11-py2.7.egg-info/dependency_links.txt
+39 −0 lib/python/PyYAML-3.11-py2.7.egg-info/installed-files.txt
+2 −0 lib/python/PyYAML-3.11-py2.7.egg-info/top_level.txt
+1 −0 lib/python/ua_parser/__init__.py
+1 −0 lib/python/ua_parser/regexes.json
+4,744 −0 lib/python/ua_parser/regexes.yaml
+533 −0 lib/python/ua_parser/user_agent_parser.py
+245 −0 lib/python/ua_parser/user_agent_parser_test.py
+201 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/PKG-INFO
+13 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/SOURCES.txt
+1 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/dependency_links.txt
+15 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/installed-files.txt
+1 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/not-zip-safe
+1 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/requires.txt
+1 −0 lib/python/user_agents-1.0.1-py2.7.egg-info/top_level.txt
+3 −0 lib/python/user_agents/__init__.py
+10 −0 lib/python/user_agents/compat.py
+230 −0 lib/python/user_agents/parsers.py
+241 −0 lib/python/user_agents/tests.py
+315 −0 lib/python/yaml/__init__.py
+139 −0 lib/python/yaml/composer.py
+675 −0 lib/python/yaml/constructor.py
+85 −0 lib/python/yaml/cyaml.py
+62 −0 lib/python/yaml/dumper.py
+1,140 −0 lib/python/yaml/emitter.py
+75 −0 lib/python/yaml/error.py
+86 −0 lib/python/yaml/events.py
+40 −0 lib/python/yaml/loader.py
+49 −0 lib/python/yaml/nodes.py
+589 −0 lib/python/yaml/parser.py
+190 −0 lib/python/yaml/reader.py
+484 −0 lib/python/yaml/representer.py
+224 −0 lib/python/yaml/resolver.py
+1,457 −0 lib/python/yaml/scanner.py
+111 −0 lib/python/yaml/serializer.py
+104 −0 lib/python/yaml/tokens.py

0 comments on commit eaba8d0

Please sign in to comment.