aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorEgor Tensin <Egor.Tensin@gmail.com>2016-06-17 03:12:51 +0300
committerEgor Tensin <Egor.Tensin@gmail.com>2016-06-17 03:12:51 +0300
commitd0d1fca2ba5337095b953e0f83dba8cf7a2ec3a8 (patch)
tree84689152079e3160263ff65f10675166c118caf3
parentrefactoring & support more user fields (diff)
downloadvk-scripts-d0d1fca2ba5337095b953e0f83dba8cf7a2ec3a8.tar.gz
vk-scripts-d0d1fca2ba5337095b953e0f83dba8cf7a2ec3a8.zip
add the platform a user was "last seen" using
-rw-r--r--vk/user.py69
-rw-r--r--vk/utils/tracking/db/record.py58
-rw-r--r--vk/utils/tracking/logger.py13
3 files changed, 108 insertions, 32 deletions
diff --git a/vk/user.py b/vk/user.py
index 4c8c71f..80702f6 100644
--- a/vk/user.py
+++ b/vk/user.py
@@ -7,6 +7,7 @@ from collections.abc import Hashable, Mapping, MutableMapping
from datetime import datetime, timezone
from enum import Enum
from numbers import Real, Integral
+import re
class UserField(Enum):
UID = 'uid'
@@ -21,10 +22,54 @@ class UserField(Enum):
class LastSeenField(Enum):
TIME = 'time'
+ PLATFORM = 'platform'
def __str__(self):
return self.value
+class Platform(Enum):
+ MOBILE = 1
+ IPHONE = 2
+ IPAD = 3
+ ANDROID = 4
+ WINDOWS_PHONE = 5
+ WINDOWS8 = 6
+ WEB = 7
+
+ def from_string(s):
+ return Platform(int(s))
+
+ def __str__(self):
+ return str(self.value)
+
+ @staticmethod
+ def _uppercase_first_letter(s):
+ m = re.search(r'\w', s)
+ if m is None:
+ return s
+ return s[:m.start()] + m.group().upper() + s[m.end():]
+
+ def get_description_for_header(self):
+ return self._uppercase_first_letter(_PLATFORM_DESCRIPTIONS[self])
+
+ def get_description_for_sentence(self):
+ s = _PLATFORM_DESCRIPTIONS[self]
+ s = s.replace('unrecognized', 'an unrecognized')
+ return 'the ' + s
+
+ def get_description_for_sentence_beginning(self):
+ return self._uppercase_first_letter(self.get_description_for_sentence())
+
+_PLATFORM_DESCRIPTIONS = {
+ Platform.MOBILE: '"mobile" web version (or unrecognized mobile app)',
+ Platform.IPHONE: 'official iPhone app',
+ Platform.IPAD: 'official iPad app',
+ Platform.ANDROID: 'official Android app',
+ Platform.WINDOWS_PHONE: 'official Windows Phone app',
+ Platform.WINDOWS8: 'official Windows 8 app',
+ Platform.WEB: 'web version (or unrecognized app)'
+}
+
class LastSeen(MutableMapping):
@staticmethod
def from_api_response(source):
@@ -71,8 +116,17 @@ class LastSeen(MutableMapping):
else:
raise TypeError()
+ def _parse_platform(x):
+ if x in Platform:
+ return x
+ if isinstance(x, str):
+ return Platform.from_string(x)
+ else:
+ return Platform(x)
+
_FIELD_PARSERS = {
LastSeenField.TIME: _parse_time,
+ LastSeenField.PLATFORM: _parse_platform,
}
_DEFAULT_FIELD_PARSER = str
@@ -86,6 +140,15 @@ class LastSeen(MutableMapping):
def set_time(self, t):
self[LastSeenField.TIME] = t
+ def has_platform(self):
+ return LastSeenField.PLATFORM in self
+
+ def get_platform(self):
+ return self[LastSeenField.PLATFORM]
+
+ def set_platform(self, platform):
+ self[LastSeenField.PLATFORM] = platform
+
class User(Hashable, MutableMapping):
@staticmethod
def from_api_response(source):
@@ -196,10 +259,10 @@ class User(Hashable, MutableMapping):
self[UserField.LAST_SEEN] = last_seen
def get_last_seen_time(self):
- return self.has_last_seen() and self.get_last_seen().has_time()
-
- def get_last_seen_time(self):
return self[UserField.LAST_SEEN].get_time()
def get_last_seen_time_local(self):
return self[UserField.LAST_SEEN].get_time().astimezone()
+
+ def get_last_seen_platform(self):
+ return self[UserField.LAST_SEEN].get_platform()
diff --git a/vk/utils/tracking/db/record.py b/vk/utils/tracking/db/record.py
index 4748a37..fd684cc 100644
--- a/vk/utils/tracking/db/record.py
+++ b/vk/utils/tracking/db/record.py
@@ -6,7 +6,7 @@ from collections import OrderedDict
from collections.abc import MutableMapping
from datetime import datetime, timezone
-from vk.user import LastSeen, User, UserField
+from vk.user import LastSeen, LastSeenField, User, UserField
class Timestamp:
@staticmethod
@@ -28,23 +28,14 @@ class Timestamp:
dt = self._new()
dt = dt.replace(microsecond=0)
dt = self._lose_timezone(dt)
- self._dt = dt
+ self.dt = dt
@staticmethod
def from_string(s):
return Timestamp(datetime.strptime(s, '%Y-%m-%dT%H:%M:%SZ'))
def __str__(self):
- return self._dt.isoformat() + 'Z'
-
- @staticmethod
- def from_last_seen(ls):
- return Timestamp(ls.get_time())
-
- def to_last_seen(self):
- ls = LastSeen()
- ls.set_time(self._dt)
- return ls
+ return self.dt.isoformat() + 'Z'
class Record(MutableMapping):
FIELDS = (
@@ -53,7 +44,8 @@ class Record(MutableMapping):
UserField.LAST_NAME,
UserField.SCREEN_NAME,
UserField.ONLINE,
- UserField.LAST_SEEN,
+ LastSeenField.TIME,
+ LastSeenField.PLATFORM,
)
def __init__(self, timestamp=None, fields=None):
@@ -65,21 +57,26 @@ class Record(MutableMapping):
self._fields = fields
def __getitem__(self, field):
- if field is UserField.LAST_SEEN:
- return Timestamp.from_last_seen(self._fields[field])
+ if field is LastSeenField.TIME:
+ return Timestamp(self._fields[field])
return self._fields[field]
def __setitem__(self, field, value):
- if field is UserField.LAST_SEEN:
+ if field is LastSeenField.TIME:
if isinstance(value, str):
- value = Timestamp.from_string(value).to_last_seen()
+ value = Timestamp.from_string(value).dt
elif isinstance(value, Timestamp):
- value = value.to_last_seen()
- elif isinstance(value, LastSeen):
+ value = value.dt
+ elif isinstance(value, datetime):
pass
else:
raise TypeError()
- self._fields[field] = User.parse(field, value)
+ if isinstance(field, LastSeenField):
+ self._fields[field] = LastSeen.parse(field, value)
+ elif isinstance(field, UserField):
+ self._fields[field] = User.parse(field, value)
+ else:
+ raise TypeError()
def __delitem__(self, field):
del self._fields[field]
@@ -95,13 +92,26 @@ class Record(MutableMapping):
@staticmethod
def from_user(user):
- instance = Record()
+ record = Record()
for field in Record.FIELDS:
- instance[field] = user[field]
- return instance
+ if isinstance(field, UserField):
+ record[field] = user[field]
+ elif isinstance(field, LastSeenField):
+ record[field] = user.get_last_seen()[field]
+ else:
+ assert False
+ return record
def to_user(self):
user = User()
+ last_seen = LastSeen()
for field in self:
- user[field] = self[field]
+ if isinstance(field, LastSeenField):
+ last_seen[field] = self[field]
+ elif isinstance(field, UserField):
+ user[field] = self[field]
+ else:
+ assert False
+ if len(last_seen):
+ user.set_last_seen(last_seen)
return user
diff --git a/vk/utils/tracking/logger.py b/vk/utils/tracking/logger.py
index a36e679..8da418a 100644
--- a/vk/utils/tracking/logger.py
+++ b/vk/utils/tracking/logger.py
@@ -42,20 +42,23 @@ class Logger:
@staticmethod
def _format_user_is_online(user):
- return '{} is ONLINE'.format(Logger._format_user(user))
+ return '{} is ONLINE.'.format(Logger._format_user(user))
@staticmethod
def _format_user_is_offline(user):
- return '{} is OFFLINE'.format(Logger._format_user(user))
+ return '{} is OFFLINE.'.format(Logger._format_user(user))
@staticmethod
def _format_user_last_seen(user):
- return '{} was last seen at {}'.format(Logger._format_user(user), user.get_last_seen_time_local())
+ return '{} was last seen at {} using {}.'.format(
+ Logger._format_user(user),
+ user.get_last_seen_time_local(),
+ user.get_last_seen_platform().get_description_for_sentence())
@staticmethod
def _format_user_went_online(user):
- return '{} went ONLINE'.format(Logger._format_user(user))
+ return '{} went ONLINE.'.format(Logger._format_user(user))
@staticmethod
def _format_user_went_offline(user):
- return '{} went OFFLINE'.format(Logger._format_user(user))
+ return '{} went OFFLINE.'.format(Logger._format_user(user))