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").annotate(Count("user_agent"))
19 result
= {x
["user_agent"]: x
["user_agent__count"] for x
in result
}
20 self
._useragents
= Counter(result
)
22 return self
._useragents
26 uas
= self
.get_entries()
28 return uas
.most_common(1)[0][1]
33 def total_users(self
):
34 uas
= self
.get_entries()
36 return sum(uas
.values())
41 # regular expressions for detecting a client application from a User-Agent
42 RE_GPODROID
= re
.compile(
43 r
"GpodRoid ([0-9.]+) Mozilla/5.0 \(Linux; U; Android ([0-9a-z.-]+);"
45 RE_GPODDER
= re
.compile(r
"mygpoclient/([0-9.]+) \([^)]+\) gPodder/([0-9.]+)")
46 RE_MYGPOCLIENT
= re
.compile(r
"mygpoclient/([0-9.]+) \([^)]+\)")
47 RE_CLEMENTINE
= re
.compile(r
"Clementine ([0-9a-z.-]+)")
48 RE_AMAROK
= re
.compile(r
"amarok/([0-9.]+)")
49 RE_GPNACCOUNT
= re
.compile(r
"GPodder.net Account for Android")
52 class ClientStats(UserAgentStats
):
53 """Provides statistics about client applications"""
57 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
71 def parse_ua_string(self
, ua_string
):
73 m
= RE_GPODROID
.search(ua_string
)
75 return Client("gpodroid", m
.group(1), None, None, "android", m
.group(2))
77 m
= RE_GPODDER
.search(ua_string
)
79 return Client("gpodder", m
.group(2), "mygpoclient", m
.group(1), None, None)
81 m
= RE_MYGPOCLIENT
.search(ua_string
)
83 return Client(None, None, "mygpoclient", m
.group(1), None, None)
85 m
= RE_CLEMENTINE
.search(ua_string
)
87 return Client("clementine", m
.group(1), None, None, None, None)
89 m
= RE_AMAROK
.search(ua_string
)
91 return Client("amarok", m
.group(1), None, None, None, None)
93 m
= RE_GPNACCOUNT
.search(ua_string
)
96 None, None, "gpodder.net-account-android", None, "android", None