Handles permission errors when opening timelines. Closes #22

This commit is contained in:
Manuel Cortez 2019-01-07 15:05:43 -06:00
parent b4625335b6
commit 6b4feb3b91
3 changed files with 72 additions and 20 deletions

View File

@ -7,6 +7,7 @@
* Socializer will be able to handle all users correctly. Before, if an user that was not present in the local storage system was needed, the program was displaying "no specified user". ([#17,](https://code.manuelcortez.net/manuelcortez/socializer/issues/17)) * Socializer will be able to handle all users correctly. Before, if an user that was not present in the local storage system was needed, the program was displaying "no specified user". ([#17,](https://code.manuelcortez.net/manuelcortez/socializer/issues/17))
* It is possible to use user domains (short names for users) to create timelines. Just write @username and the program will create the needed timeline, regardless if the user is present in your friend list. ([#18,](https://code.manuelcortez.net/manuelcortez/socializer/issues/18)) * It is possible to use user domains (short names for users) to create timelines. Just write @username and the program will create the needed timeline, regardless if the user is present in your friend list. ([#18,](https://code.manuelcortez.net/manuelcortez/socializer/issues/18))
* When displaying someone's profile, the dialog should be loaded dramatically faster than before. A message will be spoken when all data of the profile is loaded. * When displaying someone's profile, the dialog should be loaded dramatically faster than before. A message will be spoken when all data of the profile is loaded.
* When opening a timeline, if the current user is not allowed to do it, an error message should be displayed and the buffer will not be created. Before the buffer was partially created in the main window. ([#22.](https://code.manuelcortez.net/manuelcortez/socializer/issues/22))
## Changes in version 0.17 (01.01.2019) ## Changes in version 0.17 (01.01.2019)

View File

@ -38,7 +38,7 @@ class baseBuffer(object):
return None return None
return self.session.db[self.name]["items"][self.tab.list.get_selected()] return self.session.db[self.name]["items"][self.tab.list.get_selected()]
def __init__(self, parent=None, name="", session=None, composefunc=None, *args, **kwargs): def __init__(self, parent=None, name="", session=None, composefunc=None, create_tab=True, *args, **kwargs):
""" Constructor: """ Constructor:
@parent wx.Treebook: parent for the buffer panel, @parent wx.Treebook: parent for the buffer panel,
@name str: Name for saving this buffer's data in the local storage variable, @name str: Name for saving this buffer's data in the local storage variable,
@ -47,21 +47,19 @@ class baseBuffer(object):
args and kwargs will be passed to get_items() without any filtering. Be careful there. args and kwargs will be passed to get_items() without any filtering. Be careful there.
""" """
super(baseBuffer, self).__init__() super(baseBuffer, self).__init__()
self.parent = parent
self.args = args self.args = args
self.kwargs = kwargs self.kwargs = kwargs
# Create GUI associated to this buffer.
self.create_tab(parent)
# Add name to the new control so we could look for it when needed.
self.tab.name = name
self.session = session self.session = session
self.compose_function = composefunc self.compose_function = composefunc
self.name = name
if create_tab:
self.create_tab(self.parent)
#Update_function will be called every 3 minutes and it should be able to #Update_function will be called every 3 minutes and it should be able to
# Get all new items in the buffer and sort them properly in the CtrlList. # Get all new items in the buffer and sort them properly in the CtrlList.
# ToDo: Shall we allow dinamically set for update_function? # ToDo: Shall we allow dinamically set for update_function?
self.update_function = "get_page" self.update_function = "get_page"
self.name = name self.name = name
# Bind local events (they will respond to events happened in the buffer).
self.connect_events()
# source_key and post_key will point to the keys for sender and posts in VK API objects. # source_key and post_key will point to the keys for sender and posts in VK API objects.
# They can be changed in the future for other item types in different buffers. # They can be changed in the future for other item types in different buffers.
self.user_key = "source_id" self.user_key = "source_id"
@ -72,6 +70,11 @@ class baseBuffer(object):
def create_tab(self, parent): def create_tab(self, parent):
""" Create the Wx panel.""" """ Create the Wx panel."""
self.tab = home.homeTab(parent) self.tab = home.homeTab(parent)
# Bind local events (they will respond to events happened in the buffer).
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def insert(self, item, reversed=False): def insert(self, item, reversed=False):
""" Add a new item to the list. Uses renderers.composefunc for parsing the dictionary and create a valid result for putting it in the list.""" """ Add a new item to the list. Uses renderers.composefunc for parsing the dictionary and create a valid result for putting it in the list."""
@ -87,12 +90,16 @@ class baseBuffer(object):
try: try:
num = getattr(self.session, "get_newsfeed")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) num = getattr(self.session, "get_newsfeed")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs)
except VkApiError as err: except VkApiError as err:
log.error("Error {0}: {1}".format(err.code, err.message)) log.error("Error {0}: {1}".format(err.code, err.error))
retrieved = err.code retrieved = err.code
return retrieved return retrieved
except ReadTimeout as ConnectionError: except ReadTimeout as ConnectionError:
log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,))
return False return False
if not hasattr(self, "tab"):
# Create GUI associated to this buffer.
self.create_tab(self.parent)
# Add name to the new control so we could look for it when needed.
if show_nextpage == False: if show_nextpage == False:
if self.tab.list.get_count() > 0 and num > 0: if self.tab.list.get_count() > 0 and num > 0:
v = [i for i in self.session.db[self.name]["items"][:num]] v = [i for i in self.session.db[self.name]["items"][:num]]
@ -380,12 +387,17 @@ class feedBuffer(baseBuffer):
try: try:
num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs) num = getattr(self.session, "get_page")(show_nextpage=show_nextpage, name=self.name, *self.args, **self.kwargs)
except VkApiError as err: except VkApiError as err:
log.error("Error {0}: {1}".format(err.code, err.message)) log.error("Error {0}: {1}".format(err.code, err.error))
retrieved = err.code retrieved = err.code
return retrieved return retrieved
except ReadTimeout as ConnectionError: except ReadTimeout as ConnectionError:
log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,))
return False return False
if not hasattr(self, "tab"):
# Create GUI associated to this buffer.
self.create_tab(self.parent)
# Add name to the new control so we could look for it when needed.
self.tab.name = self.name
if show_nextpage == False: if show_nextpage == False:
if self.tab.list.get_count() > 0 and num > 0: if self.tab.list.get_count() > 0 and num > 0:
v = [i for i in self.session.db[self.name]["items"][:num]] v = [i for i in self.session.db[self.name]["items"][:num]]
@ -423,8 +435,6 @@ class feedBuffer(baseBuffer):
self.can_post = permissions[0]["can_post"] self.can_post = permissions[0]["can_post"]
self.can_see_all_posts = permissions[0]["can_see_all_posts"] self.can_see_all_posts = permissions[0]["can_see_all_posts"]
self.can_write_private_message = permissions[0]["can_write_private_message"] self.can_write_private_message = permissions[0]["can_write_private_message"]
if self.can_post == False:
self.tab.post.Enable(False)
def post(self, *args, **kwargs): def post(self, *args, **kwargs):
""" Create a post in the wall for the specified user """ Create a post in the wall for the specified user
@ -442,6 +452,10 @@ class communityBuffer(feedBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.communityTab(parent) self.tab = home.communityTab(parent)
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
super(communityBuffer, self).connect_events() super(communityBuffer, self).connect_events()
@ -459,6 +473,10 @@ class audioBuffer(feedBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.audioTab(parent) self.tab = home.audioTab(parent)
self.tab.name = self.name
self.connect_events()
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio)
@ -595,6 +613,10 @@ class audioAlbum(audioBuffer):
self.tab = home.audioAlbumTab(parent) self.tab = home.audioAlbumTab(parent)
self.tab.play.Enable(False) self.tab.play.Enable(False)
self.tab.play_all.Enable(False) self.tab.play_all.Enable(False)
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
super(audioAlbum, self).connect_events() super(audioAlbum, self).connect_events()
@ -613,6 +635,10 @@ class videoBuffer(feedBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.videoTab(parent) self.tab = home.videoTab(parent)
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio) widgetUtils.connect_event(self.tab.play, widgetUtils.BUTTON_PRESSED, self.play_audio)
@ -717,6 +743,10 @@ class videoAlbum(videoBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.videoAlbumTab(parent) self.tab = home.videoAlbumTab(parent)
self.tab.play.Enable(False) self.tab.play.Enable(False)
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
super(videoAlbum, self).connect_events() super(videoAlbum, self).connect_events()
@ -736,6 +766,11 @@ class empty(object):
self.name = name self.name = name
def get_items(self, *args, **kwargs): def get_items(self, *args, **kwargs):
if not hasattr(self, "tab"):
# Create GUI associated to this buffer.
self.create_tab(self.parent)
# Add name to the new control so we could look for it when needed.
self.tab.name = self.name
pass pass
def get_more_items(self, *args, **kwargs): def get_more_items(self, *args, **kwargs):
@ -801,6 +836,10 @@ class chatBuffer(baseBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.chatTab(parent) self.tab = home.chatTab(parent)
self.attachments = list() self.attachments = list()
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
widgetUtils.connect_event(self.tab.send, widgetUtils.BUTTON_PRESSED, self.send_chat_to_user) widgetUtils.connect_event(self.tab.send, widgetUtils.BUTTON_PRESSED, self.send_chat_to_user)
@ -820,12 +859,17 @@ class chatBuffer(baseBuffer):
try: try:
num = getattr(self.session, "get_messages")(name=self.name, *self.args, **self.kwargs) num = getattr(self.session, "get_messages")(name=self.name, *self.args, **self.kwargs)
except VkApiError as err: except VkApiError as err:
log.error("Error {0}: {1}".format(err.code, err.message)) log.error("Error {0}: {1}".format(err.code, err.error))
retrieved = err.code retrieved = err.code
return retrieved return retrieved
except ReadTimeout as ConnectionError: except ReadTimeout as ConnectionError:
log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,))
return False return False
if not hasattr(self, "tab"):
# Create GUI associated to this buffer.
self.create_tab(self.parent)
# Add name to the new control so we could look for it when needed.
self.tab.name = self.name
if show_nextpage == False: if show_nextpage == False:
if self.tab.history.GetValue() != "" and num > 0: if self.tab.history.GetValue() != "" and num > 0:
v = [i for i in self.session.db[self.name]["items"][:num]] v = [i for i in self.session.db[self.name]["items"][:num]]
@ -975,6 +1019,10 @@ class peopleBuffer(feedBuffer):
def create_tab(self, parent): def create_tab(self, parent):
self.tab = home.peopleTab(parent) self.tab = home.peopleTab(parent)
self.connect_events()
self.tab.name = self.name
if hasattr(self, "can_post") and self.can_post == False and hasattr(self.tab, "post"):
self.tab.post.Enable(False)
def connect_events(self): def connect_events(self):
super(peopleBuffer, self).connect_events() super(peopleBuffer, self).connect_events()
@ -1042,13 +1090,18 @@ class requestsBuffer(peopleBuffer):
try: try:
ids = self.session.vk.client.friends.getRequests(*self.args, **self.kwargs) ids = self.session.vk.client.friends.getRequests(*self.args, **self.kwargs)
except VkApiError as err: except VkApiError as err:
log.error("Error {0}: {1}".format(err.code, err.message)) log.error("Error {0}: {1}".format(err.code, err.error))
retrieved = err.code retrieved = err.code
return retrieved return retrieved
except ReadTimeout as ConnectionError: except ReadTimeout as ConnectionError:
log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,)) log.exception("Connection error when updating buffer %s. Will try again in 2 minutes" % (self.name,))
return False return False
num = self.session.get_page(name=self.name, show_nextpage=show_nextpage, endpoint="get", parent_endpoint="users", count=1000, user_ids=", ".join([str(i) for i in ids["items"]]), fields="uid, first_name, last_name, last_seen") num = self.session.get_page(name=self.name, show_nextpage=show_nextpage, endpoint="get", parent_endpoint="users", count=1000, user_ids=", ".join([str(i) for i in ids["items"]]), fields="uid, first_name, last_name, last_seen")
if not hasattr(self, "tab"):
# Create GUI associated to this buffer.
self.create_tab(self.parent)
# Add name to the new control so we could look for it when needed.
self.tab.name = self.name
if show_nextpage == False: if show_nextpage == False:
if self.tab.list.get_count() > 0 and num > 0: if self.tab.list.get_count() > 0 and num > 0:
v = [i for i in self.session.db[self.name]["items"][:num]] v = [i for i in self.session.db[self.name]["items"][:num]]

View File

@ -354,27 +354,25 @@ class Controller(object):
return return
user_id = user_data["object_id"] user_id = user_data["object_id"]
if buffertype == "audio": if buffertype == "audio":
buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, endpoint="get", parent_endpoint="audio", owner_id=user_id) buffer = buffers.audioBuffer(parent=self.window.tb, name="{0}_audio".format(user_id,), composefunc="render_audio", session=self.session, create_tab=False, endpoint="get", parent_endpoint="audio", owner_id=user_id)
# Translators: {0} will be replaced with an user. # Translators: {0} will be replaced with an user.
name_ = _("{0}'s audios").format(self.session.get_user_name(user_id, "gen"),) name_ = _("{0}'s audios").format(self.session.get_user_name(user_id, "gen"),)
elif buffertype == "wall": elif buffertype == "wall":
buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id) buffer = buffers.feedBuffer(parent=self.window.tb, name="{0}_feed".format(user_id,), composefunc="render_status", session=self.session, create_tab=False, endpoint="get", parent_endpoint="wall", extended=1, count=self.session.settings["buffers"]["count_for_wall_buffers"], owner_id=user_id)
# Translators: {0} will be replaced with an user. # Translators: {0} will be replaced with an user.
name_ = _("{0}'s wall posts").format(self.session.get_user_name(user_id, "gen"),) name_ = _("{0}'s wall posts").format(self.session.get_user_name(user_id, "gen"),)
elif buffertype == "friends": elif buffertype == "friends":
buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen", user_id=user_id) buffer = buffers.peopleBuffer(parent=self.window.tb, name="friends_{0}".format(user_id,), composefunc="render_person", session=self.session, create_tab=False, endpoint="get", parent_endpoint="friends", count=5000, fields="uid, first_name, last_name, last_seen", user_id=user_id)
# Translators: {0} will be replaced with an user. # Translators: {0} will be replaced with an user.
name_ = _("{0}'s friends").format(self.session.get_user_name(user_id, "friends"),) name_ = _("{0}'s friends").format(self.session.get_user_name(user_id, "friends"),)
self.buffers.append(buffer) wx.CallAfter(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines"))
call_threaded(self.complete_buffer_creation, buffer=buffer, name_=name_, position=self.window.search("timelines"))
def complete_buffer_creation(self, buffer, name_, position): def complete_buffer_creation(self, buffer, name_, position):
answer = buffer.get_items() answer = buffer.get_items()
if answer is not True: if answer is not True:
self.buffers.remove(buffer)
del buffer
commonMessages.show_error_code(answer) commonMessages.show_error_code(answer)
return return
self.buffers.append(buffer)
self.window.insert_buffer(buffer.tab, name_, position) self.window.insert_buffer(buffer.tab, name_, position)
def search_chat_buffer(self, user_id): def search_chat_buffer(self, user_id):