From 5780d3ca2138ae373a0071a62d8a4a79486f850a Mon Sep 17 00:00:00 2001 From: Manuel Cortez Date: Thu, 14 Feb 2019 13:09:44 -0600 Subject: [PATCH] Added online friends buffer --- changelog.md | 1 + src/controller/buffers.py | 54 ++++++++++++++++++++++++++++++-- src/controller/mainController.py | 23 ++++++++++++-- src/sessionmanager/renderers.py | 12 +++++-- src/sessionmanager/session.py | 7 ++++- src/wxUI/commonMessages.py | 3 ++ 6 files changed, 91 insertions(+), 9 deletions(-) diff --git a/changelog.md b/changelog.md index 2e04110..bfa1609 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,7 @@ ## changes in this version +* A new buffer, called online, has been added in the friends section. It contains friends currently connected to VK. Items in this buffer will be added as soon as new friends are online in the social network, and will be removed when friends are offline. This buffer needs a lot of testing. Please report any possible inconsistency on this method. * Added new options to open the config and logs folder, these options are located in the help menu and may be useful during error reporting. * Added experimental support to "subscribers" buffer, inside frienship requests. This shows friend requests that have been declined by the current user. * Fixed an error in Socializer that was making it unable to detect unread messages properly. diff --git a/src/controller/buffers.py b/src/controller/buffers.py index e15aa83..29b56ba 100644 --- a/src/controller/buffers.py +++ b/src/controller/buffers.py @@ -1139,8 +1139,15 @@ class peopleBuffer(feedBuffer): return if ("last_seen" in post) == False: return original_date = arrow.get(post["last_seen"]["time"]) - created_at = original_date.humanize(locale=languageHandler.curLang[:2]) - self.tab.list.list.SetItem(self.tab.list.get_selected(), 1, created_at) + now = arrow.now() + original_date.to(now.tzinfo) + diffdate = now-original_date + if diffdate.days == 0 and diffdate.seconds <= 360: + online_status = _("Online") + else: + # Translators: This is the date of last seen + online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) + self.tab.list.list.SetItem(self.tab.list.get_selected(), 1, online_status) def open_timeline(self, *args, **kwargs): pass @@ -1196,6 +1203,49 @@ class peopleBuffer(feedBuffer): def keep_as_follower(self, *args, **kwargs): pass + def add_person(self, person): + # This tracks if the user already exists here, in such case we just will update the last_seen variable + existing = False + for i in self.session.db[self.name]["items"]: + if person["id"] == i["id"]: + existing = True + i["last_seen"]["time"] = person["last_seen"]["time"] + break + # Add the new user to the buffer just if it does not exists previously. + if existing == False: + self.session.db[self.name]["items"].insert(0, person) + self.insert(person, True) + + def remove_person(self, user_id): + # Make sure the user is added in the buffer, otherwise don't attempt to remove a None Value from the list. + user = None + for i in self.session.db[self.name]["items"]: + if i["id"] == user_id: + user = i + break + if user != None: + person_index = self.session.db[self.name]["items"].index(user) + self.session.db[self.name]["items"].pop(person_index) + self.tab.list.remove_item(person_index) + + def get_friend(self, user_id): + for i in self.session.db["friends_"]["items"]: + if i["id"] == user_id: + return i + log.exception("Getting user manually...") + user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen")[0] + return user + + def update_online(self): + online_users = self.session.vk.client.friends.getOnline() + now = time.time() + for i in self.session.db[self.name]["items"]: + if i["id"] in online_users: + i["last_seen"]["time"] = now + else: + log.exception("Removing an user from online status manually... %r" % (i)) + self.remove_person(i["id"]) + class requestsBuffer(peopleBuffer): def get_items(self, show_nextpage=False): diff --git a/src/controller/mainController.py b/src/controller/mainController.py index 6fe965d..c33aa47 100644 --- a/src/controller/mainController.py +++ b/src/controller/mainController.py @@ -92,7 +92,8 @@ class Controller(object): pub.sendMessage("create_buffer", buffer_type="videoBuffer", buffer_title=_("My videos"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="me_video", composefunc="render_video", session=self.session, endpoint="get", parent_endpoint="video", count=self.session.settings["buffers"]["count_for_video_buffers"])) pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Albums"), parent_tab="videos", kwargs=dict(parent=self.window.tb, name="albums")) pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("People"), kwargs=dict(parent=self.window.tb, name="people")) - pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen")) + pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("Online"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="online_friends", composefunc="render_person", session=self.session, endpoint="getOnline", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen")) + pub.sendMessage("create_buffer", buffer_type="peopleBuffer", buffer_title=_("All friends"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="friends_", composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, order="hints", fields="uid, first_name, last_name, last_seen")) pub.sendMessage("create_buffer", buffer_type="emptyBuffer", buffer_title=_("Friendship requests"), parent_tab="people", kwargs=dict(parent=self.window.tb, name="requests")) pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("Pending requests"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests", composefunc="render_person", session=self.session, count=1000)) pub.sendMessage("create_buffer", buffer_type="requestsBuffer", buffer_title=_("I follow"), parent_tab="requests", kwargs=dict(parent=self.window.tb, name="friend_requests_sent", composefunc="render_person", session=self.session, count=1000, out=1)) @@ -243,9 +244,12 @@ class Controller(object): self.get_audio_albums(self.session.user_id, create_buffers=False) self.get_video_albums(self.session.user_id, create_buffers=False) for i in self.buffers: - if hasattr(i, "get_items"): + # Online friends buffer should not be updated, as chat LongPoll server already gives status about offline and online friends. + if hasattr(i, "get_items") and i.name != "online_friends": i.get_items() log.debug("Updated %s" % (i.name)) + else: + i.update_online() def reorder_buffer(self, buffer): """ this puts the chat buffers at the top of the list when there are new incoming messages. @@ -415,6 +419,17 @@ class Controller(object): msg = _("{user1_nom} is online.").format(**user_name) sound = "friend_online.ogg" self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + online_buffer = self.search("online_friends") + user = None + for i in self.session.db["friends_"]["items"]: + if i["id"] == event.user_id: + user = i + user["last_seen"]["time"] = time.time() + break + if user == None: + log.exception("Getting user manually...") + user = self.session.vk.client.users.get(user_ids=event.user_id, fields="last_seen")[0] + online_buffer.add_person(user) def user_offline(self, event): """ Sends a notification of an user logging off in VK. @@ -426,6 +441,8 @@ class Controller(object): msg = _("{user1_nom} is offline.").format(**user_name) sound = "friend_offline.ogg" self.notify(msg, sound, self.session.settings["chat"]["notifications"]) + online_friends = self.search("online_friends") + online_friends.remove_person(event.user_id) def notify(self, message="", sound="", type="native"): """ display a notification in Socializer. @@ -603,7 +620,7 @@ class Controller(object): params["adult"] = dlg.get_checkable("safe_search") params["sort"] = dlg.get_sort_order() # params["filters"] = "youtube, vimeo, short, long, mp4" - print(params) +# print(params) newbuff = buffers.videoBuffer(parent=self.window.tb, name="{0}_videosearch".format(params["q"],), session=self.session, composefunc="render_video", parent_endpoint="video", endpoint="search", **params) self.buffers.append(newbuff) call_threaded(newbuff.get_items) diff --git a/src/sessionmanager/renderers.py b/src/sessionmanager/renderers.py index c75b78a..3e592be 100644 --- a/src/sessionmanager/renderers.py +++ b/src/sessionmanager/renderers.py @@ -84,12 +84,18 @@ def render_person(status, session): Reference: https://vk.com/dev/fields""" if "last_seen" in status: original_date = arrow.get(status["last_seen"]["time"]) + now = arrow.now() + original_date.to(now.tzinfo) + diffdate = now-original_date + if diffdate.days == 0 and diffdate.seconds <= 360: + online_status = _("Online") + else: # Translators: This is the date of last seen - last_seen = _("{0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) + online_status = _("Last seen {0}").format(original_date.humanize(locale=languageHandler.curLang[:2]),) # Account suspended or deleted. elif ("last_seen" in status) == False and "deactivated" in status: - last_seen = _("Account deactivated") - return ["{0} {1}".format(status["first_name"], status["last_name"]), last_seen] + online_status = _("Account deactivated") + return ["{0} {1}".format(status["first_name"], status["last_name"]), online_status] def render_newsfeed_item(status, session): """ This meā˜»thod is used to render an item of the news feed. diff --git a/src/sessionmanager/session.py b/src/sessionmanager/session.py index 070b01a..3416d0e 100644 --- a/src/sessionmanager/session.py +++ b/src/sessionmanager/session.py @@ -55,6 +55,11 @@ class vkSession(object): @data list: A list with items and some information about cursors. returns the number of items that has been added in this execution""" global post_types + # When this method is called by friends.getOnlyne, it gives only friend IDS so we need to retrieve full objects from VK. + # ToDo: It would be nice to investigate whether reusing some existing objects would be a good idea, whenever possible. + if name == "online_friends": + newdata = self.vk.client.users.get(user_ids=",".join([str(z) for z in data]), fields="last_seen") + data = newdata first_addition = False num = 0 if (name in self.db) == False: @@ -62,7 +67,7 @@ class vkSession(object): self.db[name]["items"] = [] first_addition = True for i in data: - if "type" in i and (i["type"] == "wall_photo" or i["type"] == "photo_tag" or i["type"] == "photo"): + if "type" in i and not isinstance(i["type"], int) and (i["type"] == "wall_photo" or i["type"] == "photo_tag" or i["type"] == "photo"): log.debug("Skipping unsupported item... %r" % (i,)) continue # for some reason, VK sends post data if the post has been deleted already. diff --git a/src/wxUI/commonMessages.py b/src/wxUI/commonMessages.py index 4b6cbb8..321d078 100644 --- a/src/wxUI/commonMessages.py +++ b/src/wxUI/commonMessages.py @@ -26,6 +26,9 @@ def show_error_code(code): def bad_authorisation(): return wx.MessageDialog(None, _("authorisation failed. Your configuration will be deleted. If you recently changed your password in VK, you need to reauthorize Socializer. The application will be restarted and prompt you again for your user and password. Press OK to continue."), _("Error"), style=wx.ICON_ERROR).ShowModal() +def connection_error(): + return wx.MessageDialog(None, _("Socializer could not connect to VK due to a connection issue. Be sure you have a working internet connection. The application will be closed when you press the OK button. If your internet connection is working correctly, please try to open socializer in a few minutes. If this problem persists, contact the developers to receive further assistance."), _("Connection Error"), style=wx.ICON_ERROR).ShowModal() + def no_audio_albums(): return wx.MessageDialog(None, _("You do not have audio albums."), _("Error"), style=wx.ICON_ERROR).ShowModal()