2 from collections
import namedtuple
, Counter
4 from mygpo
.users
.models
import Client
7 Client
= namedtuple('Client', 'client client_version lib lib_version os os_version')
10 class UserAgentStats(object):
11 """ Provides User-Agent statistics """
14 self
._useragents
= None
16 def get_entries(self
):
17 if self
._useragents
is None:
18 result
= Client
.objects
.values('user_agent')\
19 .annotate(Count('user_agent'))
20 result
= {x
['user_agent']: x
['user_agent__count'] for x
in result
}
21 self
._useragents
= Counter(result
)
23 return self
._useragents
27 uas
= self
.get_entries()
29 return uas
.most_common(1)[0][1]
34 def total_users(self
):
35 uas
= self
.get_entries()
37 return sum(uas
.values())
42 # regular expressions for detecting a client application from a User-Agent
43 RE_GPODROID
= re
.compile('GpodRoid ([0-9.]+) Mozilla/5.0 \(Linux; U; Android ([0-9a-z.-]+);')
44 RE_GPODDER
= re
.compile('mygpoclient/([0-9.]+) \([^)]+\) gPodder/([0-9.]+)')
45 RE_MYGPOCLIENT
= re
.compile('mygpoclient/([0-9.]+) \([^)]+\)')
46 RE_CLEMENTINE
= re
.compile('Clementine ([0-9a-z.-]+)')
47 RE_AMAROK
= re
.compile('amarok/([0-9.]+)')
48 RE_GPNACCOUNT
= re
.compile('GPodder.net Account for Android')
51 class ClientStats(UserAgentStats
):
52 """ Provides statistics about client applications """
56 super(ClientStats
, self
).__init
__()
59 def get_entries(self
):
61 if self
._clients
is None:
62 self
._clients
= Counter()
64 uas
= super(ClientStats
, self
).get_entries()
65 for ua_string
, count
in uas
.items():
66 client
= self
.parse_ua_string(ua_string
) or ua_string
67 self
._clients
[client
] += count
72 def parse_ua_string(self
, ua_string
):
74 m
= RE_GPODROID
.search(ua_string
)
76 return Client('gpodroid', m
.group(1), None, None, 'android', m
.group(2))
78 m
= RE_GPODDER
.search(ua_string
)
80 return Client('gpodder', m
.group(2), 'mygpoclient', m
.group(1), None, None)
82 m
= RE_MYGPOCLIENT
.search(ua_string
)
84 return Client(None, None, 'mygpoclient', m
.group(1), None, None)
86 m
= RE_CLEMENTINE
.search(ua_string
)
88 return Client('clementine', m
.group(1), None, None, None, None)
90 m
= RE_AMAROK
.search(ua_string
)
92 return Client('amarok', m
.group(1), None, None, None, None)
94 m
= RE_GPNACCOUNT
.search(ua_string
)
96 return Client(None, None, 'gpodder.net-account-android', None, 'android', None)