mirror of
https://github.com/guohuadeng/app-odoo.git
synced 2025-02-23 04:11:36 +02:00
init common and customize
This commit is contained in:
268
app_common/lib/user_agents/parsers.py
Normal file
268
app_common/lib/user_agents/parsers.py
Normal file
@@ -0,0 +1,268 @@
|
||||
from collections import namedtuple
|
||||
|
||||
from ..ua_parser import user_agent_parser
|
||||
from .compat import string_types
|
||||
|
||||
|
||||
MOBILE_DEVICE_FAMILIES = (
|
||||
'iPhone',
|
||||
'iPod',
|
||||
'Generic Smartphone',
|
||||
'Generic Feature Phone',
|
||||
'PlayStation Vita',
|
||||
'iOS-Device'
|
||||
)
|
||||
|
||||
PC_OS_FAMILIES = (
|
||||
'Windows 95',
|
||||
'Windows 98',
|
||||
'Solaris',
|
||||
)
|
||||
|
||||
MOBILE_OS_FAMILIES = (
|
||||
'Windows Phone',
|
||||
'Windows Phone OS', # Earlier versions of ua-parser returns Windows Phone OS
|
||||
'Symbian OS',
|
||||
'Bada',
|
||||
'Windows CE',
|
||||
'Windows Mobile',
|
||||
'Maemo',
|
||||
)
|
||||
|
||||
MOBILE_BROWSER_FAMILIES = (
|
||||
'IE Mobile',
|
||||
'Opera Mobile',
|
||||
'Opera Mini',
|
||||
'Chrome Mobile',
|
||||
'Chrome Mobile WebView',
|
||||
'Chrome Mobile iOS',
|
||||
)
|
||||
|
||||
TABLET_DEVICE_FAMILIES = (
|
||||
'iPad',
|
||||
'BlackBerry Playbook',
|
||||
'Blackberry Playbook', # Earlier versions of ua-parser returns "Blackberry" instead of "BlackBerry"
|
||||
'Kindle',
|
||||
'Kindle Fire',
|
||||
'Kindle Fire HD',
|
||||
'Galaxy Tab',
|
||||
'Xoom',
|
||||
'Dell Streak',
|
||||
)
|
||||
|
||||
TOUCH_CAPABLE_OS_FAMILIES = (
|
||||
'iOS',
|
||||
'Android',
|
||||
'Windows Phone',
|
||||
'Windows CE',
|
||||
'Windows Mobile',
|
||||
'Firefox OS',
|
||||
'MeeGo',
|
||||
)
|
||||
|
||||
TOUCH_CAPABLE_DEVICE_FAMILIES = (
|
||||
'BlackBerry Playbook',
|
||||
'Blackberry Playbook',
|
||||
'Kindle Fire',
|
||||
)
|
||||
|
||||
EMAIL_PROGRAM_FAMILIES = set((
|
||||
'Outlook',
|
||||
'Windows Live Mail',
|
||||
'AirMail',
|
||||
'Apple Mail',
|
||||
'Outlook',
|
||||
'Thunderbird',
|
||||
'Lightning',
|
||||
'ThunderBrowse',
|
||||
'Windows Live Mail',
|
||||
'The Bat!',
|
||||
'Lotus Notes',
|
||||
'IBM Notes',
|
||||
'Barca',
|
||||
'MailBar',
|
||||
'kmail2',
|
||||
'YahooMobileMail'
|
||||
))
|
||||
|
||||
def verify_attribute(attribute):
|
||||
if isinstance(attribute, string_types) and attribute.isdigit():
|
||||
return int(attribute)
|
||||
|
||||
return attribute
|
||||
|
||||
|
||||
def parse_version(major=None, minor=None, patch=None, patch_minor=None):
|
||||
# Returns version number tuple, attributes will be integer if they're numbers
|
||||
major = verify_attribute(major)
|
||||
minor = verify_attribute(minor)
|
||||
patch = verify_attribute(patch)
|
||||
patch_minor = verify_attribute(patch_minor)
|
||||
|
||||
return tuple(
|
||||
filter(lambda x: x is not None, (major, minor, patch, patch_minor))
|
||||
)
|
||||
|
||||
|
||||
Browser = namedtuple('Browser', ['family', 'version', 'version_string'])
|
||||
|
||||
|
||||
def parse_browser(family, major=None, minor=None, patch=None, patch_minor=None):
|
||||
# Returns a browser object
|
||||
version = parse_version(major, minor, patch)
|
||||
version_string = '.'.join([str(v) for v in version])
|
||||
return Browser(family, version, version_string)
|
||||
|
||||
|
||||
OperatingSystem = namedtuple('OperatingSystem', ['family', 'version', 'version_string'])
|
||||
|
||||
|
||||
def parse_operating_system(family, major=None, minor=None, patch=None, patch_minor=None):
|
||||
version = parse_version(major, minor, patch)
|
||||
version_string = '.'.join([str(v) for v in version])
|
||||
return OperatingSystem(family, version, version_string)
|
||||
|
||||
|
||||
Device = namedtuple('Device', ['family', 'brand', 'model'])
|
||||
|
||||
|
||||
def parse_device(family, brand, model):
|
||||
return Device(family, brand, model)
|
||||
|
||||
|
||||
class UserAgent(object):
|
||||
|
||||
def __init__(self, user_agent_string):
|
||||
ua_dict = user_agent_parser.Parse(user_agent_string)
|
||||
self.ua_string = user_agent_string
|
||||
self.os = parse_operating_system(**ua_dict['os'])
|
||||
self.browser = parse_browser(**ua_dict['user_agent'])
|
||||
self.device = parse_device(**ua_dict['device'])
|
||||
|
||||
def __str__(self):
|
||||
return "{device} / {os} / {browser}".format(
|
||||
device=self.get_device(),
|
||||
os=self.get_os(),
|
||||
browser=self.get_browser()
|
||||
)
|
||||
|
||||
def __unicode__(self):
|
||||
return unicode(str(self))
|
||||
|
||||
def _is_android_tablet(self):
|
||||
# Newer Android tablets don't have "Mobile" in their user agent string,
|
||||
# older ones like Galaxy Tab still have "Mobile" though they're not
|
||||
if ('Mobile Safari' not in self.ua_string and
|
||||
self.browser.family != "Firefox Mobile"):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _is_blackberry_touch_capable_device(self):
|
||||
# A helper to determine whether a BB phone has touch capabilities
|
||||
# Blackberry Bold Touch series begins with 99XX
|
||||
if 'Blackberry 99' in self.device.family:
|
||||
return True
|
||||
if 'Blackberry 95' in self.device.family: # BB Storm devices
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_device(self):
|
||||
return self.is_pc and "PC" or self.device.family
|
||||
|
||||
def get_os(self):
|
||||
return ("%s %s" % (self.os.family, self.os.version_string)).strip()
|
||||
|
||||
def get_browser(self):
|
||||
return ("%s %s" % (self.browser.family, self.browser.version_string)).strip()
|
||||
|
||||
@property
|
||||
def is_tablet(self):
|
||||
if self.device.family in TABLET_DEVICE_FAMILIES:
|
||||
return True
|
||||
if (self.os.family == 'Android' and self._is_android_tablet()):
|
||||
return True
|
||||
if self.os.family == 'Windows' and self.os.version_string.startswith('RT'):
|
||||
return True
|
||||
if self.os.family == 'Firefox OS' and 'Mobile' not in self.browser.family:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_mobile(self):
|
||||
# First check for mobile device and mobile browser families
|
||||
if self.device.family in MOBILE_DEVICE_FAMILIES:
|
||||
return True
|
||||
if self.browser.family in MOBILE_BROWSER_FAMILIES:
|
||||
return True
|
||||
# Device is considered Mobile OS is Android and not tablet
|
||||
# This is not fool proof but would have to suffice for now
|
||||
if ((self.os.family == 'Android' or self.os.family == 'Firefox OS')
|
||||
and not self.is_tablet):
|
||||
return True
|
||||
if self.os.family == 'BlackBerry OS' and self.device.family != 'Blackberry Playbook':
|
||||
return True
|
||||
if self.os.family in MOBILE_OS_FAMILIES:
|
||||
return True
|
||||
# TODO: remove after https://github.com/tobie/ua-parser/issues/126 is closed
|
||||
if 'J2ME' in self.ua_string or 'MIDP' in self.ua_string:
|
||||
return True
|
||||
# This is here mainly to detect Google's Mobile Spider
|
||||
if 'iPhone;' in self.ua_string:
|
||||
return True
|
||||
if 'Googlebot-Mobile' in self.ua_string:
|
||||
return True
|
||||
# Mobile Spiders should be identified as mobile
|
||||
if self.device.family == 'Spider' and 'Mobile' in self.browser.family:
|
||||
return True
|
||||
# Nokia mobile
|
||||
if 'NokiaBrowser' in self.ua_string and 'Mobile' in self.ua_string:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_touch_capable(self):
|
||||
# TODO: detect touch capable Nokia devices
|
||||
if self.os.family in TOUCH_CAPABLE_OS_FAMILIES:
|
||||
return True
|
||||
if self.device.family in TOUCH_CAPABLE_DEVICE_FAMILIES:
|
||||
return True
|
||||
if self.os.family == 'Windows':
|
||||
if self.os.version_string.startswith(('RT', 'CE')):
|
||||
return True
|
||||
if self.os.version_string.startswith('8') and 'Touch' in self.ua_string:
|
||||
return True
|
||||
if 'BlackBerry' in self.os.family and self._is_blackberry_touch_capable_device():
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_pc(self):
|
||||
# Returns True for "PC" devices (Windows, Mac and Linux)
|
||||
if 'Windows NT' in self.ua_string or self.os.family in PC_OS_FAMILIES or \
|
||||
self.os.family == 'Windows' and self.os.version_string == 'ME':
|
||||
return True
|
||||
# TODO: remove after https://github.com/tobie/ua-parser/issues/127 is closed
|
||||
if self.os.family == 'Mac OS X' and 'Silk' not in self.ua_string:
|
||||
return True
|
||||
# Maemo has 'Linux' and 'X11' in UA, but it is not for PC
|
||||
if 'Maemo' in self.ua_string:
|
||||
return False
|
||||
if 'Chrome OS' in self.os.family:
|
||||
return True
|
||||
if 'Linux' in self.ua_string and 'X11' in self.ua_string:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def is_bot(self):
|
||||
return True if self.device.family == 'Spider' else False
|
||||
|
||||
@property
|
||||
def is_email_client(self):
|
||||
if self.browser.family in EMAIL_PROGRAM_FAMILIES:
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def parse(user_agent_string):
|
||||
return UserAgent(user_agent_string)
|
||||
Reference in New Issue
Block a user