Reordered presenters for post display and cretion

This commit is contained in:
Manuel Cortez 2019-04-16 12:24:42 -05:00
parent 14cdeb0b5a
commit 5f224a077c
12 changed files with 514 additions and 416 deletions

View File

@ -13,7 +13,7 @@
""" """
from .attach import * from .attach import *
from .audioRecorder import * from .audioRecorder import *
from .postCreation import * from .createPosts import *
from .postDisplayer import * from .displayPosts import *
from .configuration import * from .configuration import *
from .profiles import * from .profiles import *

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
""" A "presenter" in the socializer's terminology is a module that handles business logic in the application's workflow.
All presenter classes should derive from base.basePresenter and will be completely abstracted from views (the GUI elements). It means presenters and views don't know anything about the each other.
Both Presenters and views can communicate through the interactors. Interactors are responsible to receive user input and send requests to the presenters, aswell as receiving presenter requests and render those in the view.
So, in a tipical user interaction made in socializer, the following could happen when someone decides to do something:
1. A new presenter is created, with two mandatory arguments: The corresponding view and interactor.
2. The presenter will call to the install() method in the interactor, to connect all GUI events to their corresponding methods. All of these functions will be present in the interactor only.
3. After install(), the presenter will run the View, which will display the graphical user interface that users can see and interact with. The view is the only layer directly accessible from the user world and does not handle any kind of logic.
4. If the user presses a button or generates an event connected to a function in the interactor side, the function will be executed in the interactor. The interactor is aware of the View, and holds a reference to the presenter. The interactor should call other GUI elements if necessary and handle some logic (related to GUI, like yes/no dialogs). The interactor can call the presenter to retrieve some information, though the interactor cannot perform any business logic (like altering the cache database, retrieving usernames and so on).
5. If the interactor calls something in the presenter, it will be executed. The presenter knows everything about VK and the session object, so it will fetch data, save it in the cache, call other methods from VK and what not. If the presenter wants to change something in the GUI elements (for example, hiding a control or displaying something else), it will send a pubsub event that the interactor will receive and act on accordingly.
By using this design pattern it allows more decoupled code, easier testing (as we don't need to instantiate the views) and easy to switch (or add) a new graphical user interface by replacing interactors and views.
"""
from .attach import *
from .audioRecorder import *
from .postCreation import *
from .postDisplayer import *
from .configuration import *
from .profiles import *

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-
from .basePost import *

View File

@ -7,8 +7,8 @@ import output
from logging import getLogger from logging import getLogger
from pubsub import pub from pubsub import pub
from extra import SpellChecker, translator from extra import SpellChecker, translator
from .import attach from presenters import attach
from .import base from presenters import base
log = getLogger("controller.message") log = getLogger("controller.message")

View File

@ -0,0 +1,8 @@
# -*- coding: utf-8 -*-
from .basePost import *
from .audio import *
from .comment import *
from .peopleList import *
from .poll import *
from .topic import *
from .topicComment import *

View File

@ -0,0 +1,98 @@
# -*- coding: utf-8 -*-
import logging
from sessionmanager import utils
from pubsub import pub
from mysc.thread_utils import call_threaded
from presenters import base
log = logging.getLogger(__file__)
class displayAudioPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor):
super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio")
self.added_audios = {}
self.session = session
self.post = postObject
self.load_audios()
self.fill_information(0)
self.run()
def add_to_library(self, audio_index):
post = self.post[audio_index]
args = {}
args["audio_id"] = post["id"]
if "album_id" in post:
args["album_id"] = post["album_id"]
args["owner_id"] = post["owner_id"]
audio = self.session.vk.client.audio.add(**args)
if audio != None and int(audio) > 21:
self.added_audios[post["id"]] = audio
self.send_message("disable_control", control="add")
self.send_message("enable_control", control="remove")
def remove_from_library(self, audio_index):
post = self.post[audio_index]
args = {}
if post["id"] in self.added_audios:
args["audio_id"] = self.added_audios[post["id"]]
args["owner_id"] = self.session.user_id
else:
args["audio_id"] = post["id"]
args["owner_id"] = post["owner_id"]
result = self.session.vk.client.audio.delete(**args)
if int(result) == 1:
self.send_message("enable_control", control="add")
self.send_message("disable_control", control="remove")
if post["id"] in self.added_audios:
self.added_audios.pop(post["id"])
def fill_information(self, index):
post = self.post[index]
if "artist" in post:
self.send_message("set", control="artist", value=post["artist"])
if "title" in post:
self.send_message("set", control="title", value=post["title"])
if "duration" in post:
self.send_message("set", control="duration", value=utils.seconds_to_string(post["duration"]))
self.send_message("set_title", value="{0} - {1}".format(post["title"], post["artist"]))
call_threaded(self.get_lyrics, index)
if post["owner_id"] == self.session.user_id or (post["id"] in self.added_audios) == True:
self.send_message("enable_control", control="remove")
self.send_message("disable_control", control="add")
else:
self.send_message("enable_control", control="add")
self.send_message("disable_control", control="remove")
def get_lyrics(self, audio_index):
post = self.post[audio_index]
if "lyrics_id" in post:
l = self.session.vk.client.audio.getLyrics(lyrics_id=int(post["lyrics_id"]))
self.send_message("set", control="lyric", value=l["text"])
else:
self.send_message("disable_control", control="lyric")
def get_suggested_filename(self, audio_index):
post = self.post[audio_index]
return "{0} - {1}.mp3".format(post["title"], post["artist"])
def download(self, audio_index, path):
post = self.post[audio_index]
if path != None:
pub.sendMessage("download-file", url=post["url"], filename=path)
def play(self, audio_index):
post = self.post[audio_index]
pub.sendMessage("play", object=post)
def load_audios(self):
audios = []
for i in self.post:
s = "{0} - {1}. {2}".format(i["title"], i["artist"], utils.seconds_to_string(i["duration"]))
audios.append(s)
self.send_message("add_items", control="list", items=audios)
if len(self.post) == 1:
self.send_message("disable_control", control="list")
self.send_message("focus_control", control="title")
def handle_changes(self, audio_index):
self.fill_information(audio_index)

View File

@ -1,6 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import os
import six
import threading import threading
import arrow import arrow
import requests import requests
@ -15,8 +13,9 @@ from sessionmanager import session, renderers, utils # We'll use some functions
from pubsub import pub from pubsub import pub
from extra import SpellChecker, translator from extra import SpellChecker, translator
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from .import base from presenters import base
from .postCreation import createPostPresenter from presenters.createPosts.basePost import createPostPresenter
from . import audio, poll
log = logging.getLogger(__file__) log = logging.getLogger(__file__)
@ -354,9 +353,10 @@ class displayPostPresenter(base.basePresenter):
call_threaded(self.do_last, comment, owner_id=c["owner_id"], reply_to_comment=c["id"], post_id=c["post_id"], reply_to_user=c["owner_id"]) call_threaded(self.do_last, comment, owner_id=c["owner_id"], reply_to_comment=c["id"], post_id=c["post_id"], reply_to_user=c["owner_id"])
def show_comment(self, comment_index): def show_comment(self, comment_index):
from . import comment
c = self.comments["items"][comment_index] c = self.comments["items"][comment_index]
c["post_id"] = self.post[self.post_identifier] c["post_id"] = self.post[self.post_identifier]
a = displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment()) a = comment.displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment())
def translate(self, text, language): def translate(self, text, language):
msg = translator.translator.translate(text, language) msg = translator.translator.translate(text, language)
@ -374,7 +374,7 @@ class displayPostPresenter(base.basePresenter):
def open_attachment(self, index): def open_attachment(self, index):
attachment = self.attachments[index] attachment = self.attachments[index]
if attachment["type"] == "audio": if attachment["type"] == "audio":
a = displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio()) a = audio.displayAudioPresenter(session=self.session, postObject=[attachment["audio"]], interactor=interactors.displayAudioInteractor(), view=views.displayAudio())
elif attachment["type"] == "link": elif attachment["type"] == "link":
output.speak(_("Opening URL..."), True) output.speak(_("Opening URL..."), True)
webbrowser.open_new_tab(attachment["link"]["url"]) webbrowser.open_new_tab(attachment["link"]["url"])
@ -405,7 +405,7 @@ class displayPostPresenter(base.basePresenter):
if url != "": if url != "":
webbrowser.open_new_tab(url) webbrowser.open_new_tab(url)
elif attachment["type"] == "poll": elif attachment["type"] == "poll":
a = displayPollPresenter(session=self.session, poll=attachment, interactor=interactors.displayPollInteractor(), view=views.displayPoll()) a = poll.displayPollPresenter(session=self.session, poll=attachment, interactor=interactors.displayPollInteractor(), view=views.displayPoll())
else: else:
log.debug("Unhandled attachment: %r" % (attachment,)) log.debug("Unhandled attachment: %r" % (attachment,))
@ -430,408 +430,4 @@ class displayPostPresenter(base.basePresenter):
result = self.session.vk.client.likes.getList(**data) result = self.session.vk.client.likes.getList(**data)
if result["count"] > 0: if result["count"] > 0:
post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}} post = {"source_id": self.post[self.user_identifier], "friends": {"items": result["items"]}}
pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who shared this"))) pub.sendMessage("open-post", post_object=post, controller_="displayFriendship", vars=dict(caption=_("people who shared this")))
class displayCommentPresenter(displayPostPresenter):
def __init__(self, session, postObject, view, interactor):
self.type = "comment"
self.modulename = "display_comment"
self.interactor = interactor
self.view = view
self.interactor.install(view=view, presenter=self, modulename=self.modulename)
self.session = session
self.post = postObject
self.user_identifier = "from_id"
self.post_identifier = "id"
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
self.run()
def load_all_components(self):
self.get_post_information()
self.get_likes()
self.send_message("disable_control", control="comment")
self.get_comments()
if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0:
self.send_message("disable_control", "like")
elif self.post["likes"]["user_likes"] == 1:
self.send_message("set_label", control="like", label=_("&Dislike"))
def get_post_information(self):
from_ = self.session.get_user(self.post[self.user_identifier])
if ("from_id" in self.post and "owner_id" in self.post):
user2 = self.session.get_user(self.post["owner_id"], "user2")
user2.update(from_)
title = _("Comment from {user1_nom} in the {user2_nom}'s post").format(**user2)
self.send_message("set_title", value=title)
message = ""
message = get_message(self.post)
self.send_message("set", control="post_view", value=message)
self.get_attachments(self.post, message)
self.check_image_load()
def reply(self, *args, **kwargs):
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(self.post["from_id"])), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
call_threaded(self.do_last, comment, owner_id=self.post["owner_id"], reply_to_comment=self.post["id"], post_id=self.post["post_id"], reply_to_user=self.post["owner_id"])
def get_comments(self):
""" Get comments and insert them in a list."""
comments_ = []
if "thread" not in self.post:
return
for i in self.post["thread"]["items"]:
# If comment has a "deleted" key it should not be displayed, obviously.
if "deleted" in i:
continue
from_ = self.session.get_user(i["from_id"])
if "reply_to_user" in i:
extra_info = self.session.get_user(i["reply_to_user"], "user2")
extra_info.update(from_)
from_ = _("{user1_nom} > {user2_nom}").format(**extra_info)
else:
from_ = from_["user1_nom"]
# As we set the comment reply properly in the from_ field, let's remove the first username from here if it exists.
fixed_text = utils.clean_text(i["text"])
if len(fixed_text) > 140:
text = fixed_text[:141]
else:
text = fixed_text
original_date = arrow.get(i["date"])
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
likes = str(i["likes"]["count"])
replies = ""
comments_.append((from_, text, created_at, likes, replies))
self.send_message("add_items", control="comments", items=comments_)
def show_comment(self, comment_index):
c = self.post["thread"]["items"][comment_index]
c["post_id"] = self.post["post_id"]
a = displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment())
self.clear_comments_list()
class displayTopicCommentPresenter(displayCommentPresenter):
def get_post_information(self):
from_ = self.session.get_user(self.post[self.user_identifier])
title = from_["user1_nom"]
self.send_message("set_title", value=title)
message = ""
message = get_message(self.post)
self.send_message("set", control="post_view", value=message)
self.get_attachments(self.post, message)
self.check_image_load()
self.send_message("disable_control", control="reply")
self.send_message("disable_control", control="comments")
class displayTopicPresenter(displayPostPresenter):
def __init__(self, session, postObject, group_id, view, interactor):
self.type = "topic"
self.modulename = "display_topic"
self.interactor = interactor
self.view = view
self.interactor.install(view=view, presenter=self, modulename=self.modulename)
self.session = session
self.post = postObject
self.group_id = group_id
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
result = self.get_post_information()
# Stop loading everything else if post was deleted.
if result == False:
self.interactor.uninstall()
return
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.run()
def load_all_components(self):
self.get_comments()
def get_post_information(self):
title = self.post["title"]
self.send_message("set_title", value=title)
return True
def get_comments(self):
""" Get comments and insert them in a list."""
self.comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1)
comments_ = []
data = dict(profiles=self.comments["profiles"], groups=[])
self.session.process_usernames(data)
for i in self.comments["items"]:
# If comment has a "deleted" key it should not be displayed, obviously.
if "deleted" in i:
continue
from_ = self.session.get_user(i["from_id"])["user1_nom"]
# match user mentions inside text comment.
original_date = arrow.get(i["date"])
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
likes = str(i["likes"]["count"])
text = utils.clean_text(text=i["text"])
comments_.append((from_, text, created_at, likes))
self.send_message("add_items", control="comments", items=comments_)
def post_like(self):
c = self.interactor.view.comments.get_selected()
id = self.comments["items"][c]["id"]
if self.comments["items"][c]["likes"]["user_likes"] == 1:
l = self.session.vk.client.likes.delete(owner_id=-1*self.group_id, item_id=id, type="topic_comment")
output.speak(_("You don't like this"))
self.comments["items"][c]["likes"]["count"] = l["likes"]
self.comments["items"][c]["likes"]["user_likes"] = 2
self.send_message("set_label", control="like", label=_("&Like"))
else:
l = self.session.vk.client.likes.add(owner_id=-1*self.group_id, item_id=id, type="topic_comment")
output.speak(_("You liked this"))
self.send_message("set_label", control="like", label=_("&Dislike"))
self.comments["items"][c]["likes"]["count"] = l["likes"]
self.comments["items"][c]["likes"]["user_likes"] = 1
self.clear_comments_list()
def change_comment(self, comment):
comment = self.comments["items"][comment]
self.send_message("clean_list", list="attachments")
self.get_attachments(comment, "")
if comment["likes"]["user_likes"] == 1:
self.send_message("set_label", control="like", label=_("&Dislike"))
else:
self.send_message("set_label", control="like", label=_("&Like"))
def add_comment(self):
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
group_id = self.group_id
topic_id = self.post["id"]
call_threaded(self.do_last, comment, group_id=group_id, topic_id=topic_id)
def do_last(self, comment, **kwargs):
msg = comment.text
attachments = ""
if hasattr(comment, "attachments"):
attachments = self.upload_attachments(comment.attachments)
urls = utils.find_urls_in_text(msg)
if len(urls) != 0:
if len(attachments) == 0: attachments = urls[0]
else: attachments += urls[0]
msg = msg.replace(urls[0], "")
if msg != "":
kwargs.update(message=msg)
if attachments != "":
kwargs.update(attachments=attachments)
if "message" not in kwargs and "attachments" not in kwargs:
return # No comment made here.
result = self.session.vk.client.board.createComment(**kwargs)
self.clear_comments_list()
def reply(self, comment):
c = self.comments["items"][comment]
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
user = self.session.get_user(c["from_id"])
name = user["user1_nom"].split(" ")[0]
comment.text = "[post{post_id}|{name}], {text}".format(post_id=c["id"], text=comment.text, name=name)
group_id = self.group_id
topic_id = self.post["id"]
call_threaded(self.do_last, comment, group_id=group_id, topic_id=topic_id, reply_to_comment=c["id"])
def show_comment(self, comment_index):
c = self.comments["items"][comment_index]
c["post_id"] = self.post["id"]
a = displayTopicCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment())
class displayPollPresenter(base.basePresenter):
def __init__(self, session, poll, view, interactor, show_results=False):
super(displayPollPresenter, self).__init__(view=view, interactor=interactor, modulename="display_poll")
self.poll = poll["poll"]
self.session = session
self.get_poll()
self.load_poll(show_results)
self.run()
def get_poll(self):
# Retrieve the poll again so we will have a fresh and updated object.
data = dict(owner_id=self.poll["owner_id"], is_board=int(self.poll["is_board"]), poll_id=self.poll["id"])
self.poll = self.session.vk.client.polls.getById(**data)
def load_poll(self, load_results=False):
user = self.session.get_user(self.poll["author_id"])
title = _("Poll from {user1_nom}").format(**user)
self.send_message("set_title", value=title)
self.send_message("set", control="question", value=self.poll["question"])
if len(self.poll["answer_ids"]) > 0 or ("is_closed" in self.poll and self.poll["is_closed"] == True) or load_results == True or ("can_vote" in self.poll and self.poll["can_vote"] == False):
options = []
for i in self.poll["answers"]:
options.append((i["text"], i["votes"], i["rate"]))
self.send_message("add_options", options=options, multiple=self.poll["multiple"])
self.send_message("done")
self.send_message("disable_control", control="ok")
else:
options = []
for i in self.poll["answers"]:
options.append(i["text"])
self.send_message("add_options", options=options, multiple=self.poll["multiple"])
self.send_message("done")
def vote(self, answers):
ids = ""
for i in range(0, len(self.poll["answers"])):
if answers[i] == True:
ids = ids+"{answer_id},".format(answer_id=self.poll["answers"][i]["id"])
if self.poll["multiple"] == False:
break
if ids == "":
log.exception("An error occurred when retrieving answer IDS for the following poll: %r. Provided answer list: %r" % (self.poll, answers))
return
data = dict(owner_id=self.poll["owner_id"], poll_id=self.poll["id"], answer_ids=ids, is_board=int(self.poll["is_board"]))
result = self.session.vk.client.polls.addVote(**data)
if result == 1:
output.speak(_("Your vote has been added to this poll."))
class displayAudioPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor):
super(displayAudioPresenter, self).__init__(view=view, interactor=interactor, modulename="display_audio")
self.added_audios = {}
self.session = session
self.post = postObject
self.load_audios()
self.fill_information(0)
self.run()
def add_to_library(self, audio_index):
post = self.post[audio_index]
args = {}
args["audio_id"] = post["id"]
if "album_id" in post:
args["album_id"] = post["album_id"]
args["owner_id"] = post["owner_id"]
audio = self.session.vk.client.audio.add(**args)
if audio != None and int(audio) > 21:
self.added_audios[post["id"]] = audio
self.send_message("disable_control", control="add")
self.send_message("enable_control", control="remove")
def remove_from_library(self, audio_index):
post = self.post[audio_index]
args = {}
if post["id"] in self.added_audios:
args["audio_id"] = self.added_audios[post["id"]]
args["owner_id"] = self.session.user_id
else:
args["audio_id"] = post["id"]
args["owner_id"] = post["owner_id"]
result = self.session.vk.client.audio.delete(**args)
if int(result) == 1:
self.send_message("enable_control", control="add")
self.send_message("disable_control", control="remove")
if post["id"] in self.added_audios:
self.added_audios.pop(post["id"])
def fill_information(self, index):
post = self.post[index]
if "artist" in post:
self.send_message("set", control="artist", value=post["artist"])
if "title" in post:
self.send_message("set", control="title", value=post["title"])
if "duration" in post:
self.send_message("set", control="duration", value=utils.seconds_to_string(post["duration"]))
self.send_message("set_title", value="{0} - {1}".format(post["title"], post["artist"]))
call_threaded(self.get_lyrics, index)
if post["owner_id"] == self.session.user_id or (post["id"] in self.added_audios) == True:
self.send_message("enable_control", control="remove")
self.send_message("disable_control", control="add")
else:
self.send_message("enable_control", control="add")
self.send_message("disable_control", control="remove")
def get_lyrics(self, audio_index):
post = self.post[audio_index]
if "lyrics_id" in post:
l = self.session.vk.client.audio.getLyrics(lyrics_id=int(post["lyrics_id"]))
self.send_message("set", control="lyric", value=l["text"])
else:
self.send_message("disable_control", control="lyric")
def get_suggested_filename(self, audio_index):
post = self.post[audio_index]
return "{0} - {1}.mp3".format(post["title"], post["artist"])
def download(self, audio_index, path):
post = self.post[audio_index]
if path != None:
pub.sendMessage("download-file", url=post["url"], filename=path)
def play(self, audio_index):
post = self.post[audio_index]
pub.sendMessage("play", object=post)
def load_audios(self):
audios = []
for i in self.post:
s = "{0} - {1}. {2}".format(i["title"], i["artist"], utils.seconds_to_string(i["duration"]))
audios.append(s)
self.send_message("add_items", control="list", items=audios)
if len(self.post) == 1:
self.send_message("disable_control", control="list")
self.send_message("focus_control", control="title")
def handle_changes(self, audio_index):
self.fill_information(audio_index)
class displayFriendshipPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor, caption=""):
self.session = session
self.post = postObject
super(displayFriendshipPresenter, self).__init__(view=view, interactor=interactor, modulename="display_friendship")
list_of_friends = self.get_friend_names()
from_ = self.session.get_user(self.post["source_id"])
title = caption.format(**from_)
self.send_message("set_title", value=title)
self.set_friends_list(list_of_friends)
self.run()
def get_friend_names(self):
self.friends = self.post["friends"]["items"]
friends = list()
for i in self.friends:
if "user_id" in i:
friends.append(self.session.get_user(i["user_id"])["user1_nom"])
else:
friends.append(self.session.get_user(i["id"])["user1_nom"])
return friends
def set_friends_list(self, friendslist):
self.send_message("add_items", control="friends", items=friendslist)
def view_profile(self, item):
user = self.friends[item]
if "user_id" in user:
id = user["user_id"]
else:
id = user["id"]
pub.sendMessage("user-profile", person=id)
def open_in_browser(self, item):
user = self.friends[item]
if "user_id" in user:
id = user["user_id"]
else:
id = user["id"]
url = "https://vk.com/id{user_id}".format(user_id=id)
webbrowser.open_new_tab(url)

View File

@ -0,0 +1,105 @@
# -*- coding: utf-8 -*-
import threading
import arrow
import languageHandler
import views
import interactors
import logging
from sessionmanager import renderers, utils # We'll use some functions from there
from mysc.thread_utils import call_threaded
from presenters import base
from presenters.createPosts.basePost import createPostPresenter
from . import basePost
log = logging.getLogger(__file__)
def get_message(status):
message = ""
if "text" in status:
message = utils.clean_text(status["text"])
return message
class displayCommentPresenter(basePost.displayPostPresenter):
def __init__(self, session, postObject, view, interactor):
self.type = "comment"
self.modulename = "display_comment"
self.interactor = interactor
self.view = view
self.interactor.install(view=view, presenter=self, modulename=self.modulename)
self.session = session
self.post = postObject
self.user_identifier = "from_id"
self.post_identifier = "id"
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
self.run()
def load_all_components(self):
self.get_post_information()
self.get_likes()
self.send_message("disable_control", control="comment")
self.get_comments()
if self.post["likes"]["can_like"] == 0 and self.post["likes"]["user_likes"] == 0:
self.send_message("disable_control", "like")
elif self.post["likes"]["user_likes"] == 1:
self.send_message("set_label", control="like", label=_("&Dislike"))
def get_post_information(self):
from_ = self.session.get_user(self.post[self.user_identifier])
if ("from_id" in self.post and "owner_id" in self.post):
user2 = self.session.get_user(self.post["owner_id"], "user2")
user2.update(from_)
title = _("Comment from {user1_nom} in the {user2_nom}'s post").format(**user2)
self.send_message("set_title", value=title)
message = ""
message = get_message(self.post)
self.send_message("set", control="post_view", value=message)
self.get_attachments(self.post, message)
self.check_image_load()
def reply(self, *args, **kwargs):
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(self.post["from_id"])), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
call_threaded(self.do_last, comment, owner_id=self.post["owner_id"], reply_to_comment=self.post["id"], post_id=self.post["post_id"], reply_to_user=self.post["owner_id"])
def get_comments(self):
""" Get comments and insert them in a list."""
comments_ = []
if "thread" not in self.post:
return
for i in self.post["thread"]["items"]:
# If comment has a "deleted" key it should not be displayed, obviously.
if "deleted" in i:
continue
from_ = self.session.get_user(i["from_id"])
if "reply_to_user" in i:
extra_info = self.session.get_user(i["reply_to_user"], "user2")
extra_info.update(from_)
from_ = _("{user1_nom} > {user2_nom}").format(**extra_info)
else:
from_ = from_["user1_nom"]
# As we set the comment reply properly in the from_ field, let's remove the first username from here if it exists.
fixed_text = utils.clean_text(i["text"])
if len(fixed_text) > 140:
text = fixed_text[:141]
else:
text = fixed_text
original_date = arrow.get(i["date"])
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
likes = str(i["likes"]["count"])
replies = ""
comments_.append((from_, text, created_at, likes, replies))
self.send_message("add_items", control="comments", items=comments_)
def show_comment(self, comment_index):
c = self.post["thread"]["items"][comment_index]
c["post_id"] = self.post["post_id"]
a = displayCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment())
self.clear_comments_list()

View File

@ -0,0 +1,50 @@
# -*- coding: utf-8 -*-
import webbrowser
import logging
from pubsub import pub
from presenters import base
log = logging.getLogger(__file__)
class displayFriendshipPresenter(base.basePresenter):
def __init__(self, session, postObject, view, interactor, caption=""):
self.session = session
self.post = postObject
super(displayFriendshipPresenter, self).__init__(view=view, interactor=interactor, modulename="display_friendship")
list_of_friends = self.get_friend_names()
from_ = self.session.get_user(self.post["source_id"])
title = caption.format(**from_)
self.send_message("set_title", value=title)
self.set_friends_list(list_of_friends)
self.run()
def get_friend_names(self):
self.friends = self.post["friends"]["items"]
friends = list()
for i in self.friends:
if "user_id" in i:
friends.append(self.session.get_user(i["user_id"])["user1_nom"])
else:
friends.append(self.session.get_user(i["id"])["user1_nom"])
return friends
def set_friends_list(self, friendslist):
self.send_message("add_items", control="friends", items=friendslist)
def view_profile(self, item):
user = self.friends[item]
if "user_id" in user:
id = user["user_id"]
else:
id = user["id"]
pub.sendMessage("user-profile", person=id)
def open_in_browser(self, item):
user = self.friends[item]
if "user_id" in user:
id = user["user_id"]
else:
id = user["id"]
url = "https://vk.com/id{user_id}".format(user_id=id)
webbrowser.open_new_tab(url)

View File

@ -0,0 +1,55 @@
# -*- coding: utf-8 -*-
import output
import logging
from presenters import base
log = logging.getLogger(__file__)
class displayPollPresenter(base.basePresenter):
def __init__(self, session, poll, view, interactor, show_results=False):
super(displayPollPresenter, self).__init__(view=view, interactor=interactor, modulename="display_poll")
self.poll = poll["poll"]
self.session = session
self.get_poll()
self.load_poll(show_results)
self.run()
def get_poll(self):
# Retrieve the poll again so we will have a fresh and updated object.
data = dict(owner_id=self.poll["owner_id"], is_board=int(self.poll["is_board"]), poll_id=self.poll["id"])
self.poll = self.session.vk.client.polls.getById(**data)
def load_poll(self, load_results=False):
user = self.session.get_user(self.poll["author_id"])
title = _("Poll from {user1_nom}").format(**user)
self.send_message("set_title", value=title)
self.send_message("set", control="question", value=self.poll["question"])
if len(self.poll["answer_ids"]) > 0 or ("is_closed" in self.poll and self.poll["is_closed"] == True) or load_results == True or ("can_vote" in self.poll and self.poll["can_vote"] == False):
options = []
for i in self.poll["answers"]:
options.append((i["text"], i["votes"], i["rate"]))
self.send_message("add_options", options=options, multiple=self.poll["multiple"])
self.send_message("done")
self.send_message("disable_control", control="ok")
else:
options = []
for i in self.poll["answers"]:
options.append(i["text"])
self.send_message("add_options", options=options, multiple=self.poll["multiple"])
self.send_message("done")
def vote(self, answers):
ids = ""
for i in range(0, len(self.poll["answers"])):
if answers[i] == True:
ids = ids+"{answer_id},".format(answer_id=self.poll["answers"][i]["id"])
if self.poll["multiple"] == False:
break
if ids == "":
log.exception("An error occurred when retrieving answer IDS for the following poll: %r. Provided answer list: %r" % (self.poll, answers))
return
data = dict(owner_id=self.poll["owner_id"], poll_id=self.poll["id"], answer_ids=ids, is_board=int(self.poll["is_board"]))
result = self.session.vk.client.polls.addVote(**data)
if result == 1:
output.speak(_("Your vote has been added to this poll."))

View File

@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
import threading
import arrow
import languageHandler
import views
import interactors
import output
import logging
from sessionmanager import utils # We'll use some functions from there
from mysc.thread_utils import call_threaded
from presenters import base
from presenters.createPosts.basePost import createPostPresenter
from . import basePost
from .topicComment import *
log = logging.getLogger(__file__)
class displayTopicPresenter(basePost.displayPostPresenter):
def __init__(self, session, postObject, group_id, view, interactor):
self.type = "topic"
self.modulename = "display_topic"
self.interactor = interactor
self.view = view
self.interactor.install(view=view, presenter=self, modulename=self.modulename)
self.session = session
self.post = postObject
self.group_id = group_id
self.load_images = False
# We'll put images here, so it will be easier to work with them.
self.images = []
self.imageIndex = 0
result = self.get_post_information()
# Stop loading everything else if post was deleted.
if result == False:
self.interactor.uninstall()
return
self.worker = threading.Thread(target=self.load_all_components)
self.worker.finished = threading.Event()
self.worker.start()
self.attachments = []
self.run()
def load_all_components(self):
self.get_comments()
def get_post_information(self):
title = self.post["title"]
self.send_message("set_title", value=title)
return True
def get_comments(self):
""" Get comments and insert them in a list."""
self.comments = self.session.vk.client.board.getComments(group_id=self.group_id, topic_id=self.post["id"], need_likes=1, count=100, extended=1)
comments_ = []
data = dict(profiles=self.comments["profiles"], groups=[])
self.session.process_usernames(data)
for i in self.comments["items"]:
# If comment has a "deleted" key it should not be displayed, obviously.
if "deleted" in i:
continue
from_ = self.session.get_user(i["from_id"])["user1_nom"]
# match user mentions inside text comment.
original_date = arrow.get(i["date"])
created_at = original_date.humanize(locale=languageHandler.curLang[:2])
likes = str(i["likes"]["count"])
text = utils.clean_text(text=i["text"])
comments_.append((from_, text, created_at, likes))
self.send_message("add_items", control="comments", items=comments_)
def post_like(self):
c = self.interactor.view.comments.get_selected()
id = self.comments["items"][c]["id"]
if self.comments["items"][c]["likes"]["user_likes"] == 1:
l = self.session.vk.client.likes.delete(owner_id=-1*self.group_id, item_id=id, type="topic_comment")
output.speak(_("You don't like this"))
self.comments["items"][c]["likes"]["count"] = l["likes"]
self.comments["items"][c]["likes"]["user_likes"] = 2
self.send_message("set_label", control="like", label=_("&Like"))
else:
l = self.session.vk.client.likes.add(owner_id=-1*self.group_id, item_id=id, type="topic_comment")
output.speak(_("You liked this"))
self.send_message("set_label", control="like", label=_("&Dislike"))
self.comments["items"][c]["likes"]["count"] = l["likes"]
self.comments["items"][c]["likes"]["user_likes"] = 1
self.clear_comments_list()
def change_comment(self, comment):
comment = self.comments["items"][comment]
self.send_message("clean_list", list="attachments")
self.get_attachments(comment, "")
if comment["likes"]["user_likes"] == 1:
self.send_message("set_label", control="like", label=_("&Dislike"))
else:
self.send_message("set_label", control="like", label=_("&Like"))
def add_comment(self):
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Add a comment"), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
group_id = self.group_id
topic_id = self.post["id"]
call_threaded(self.do_last, comment, group_id=group_id, topic_id=topic_id)
def do_last(self, comment, **kwargs):
msg = comment.text
attachments = ""
if hasattr(comment, "attachments"):
attachments = self.upload_attachments(comment.attachments)
urls = utils.find_urls_in_text(msg)
if len(urls) != 0:
if len(attachments) == 0: attachments = urls[0]
else: attachments += urls[0]
msg = msg.replace(urls[0], "")
if msg != "":
kwargs.update(message=msg)
if attachments != "":
kwargs.update(attachments=attachments)
if "message" not in kwargs and "attachments" not in kwargs:
return # No comment made here.
result = self.session.vk.client.board.createComment(**kwargs)
self.clear_comments_list()
def reply(self, comment):
c = self.comments["items"][comment]
comment = createPostPresenter(session=self.session, interactor=interactors.createPostInteractor(), view=views.createPostDialog(title=_("Reply to {user1_nom}").format(**self.session.get_user(c["from_id"])), message="", text="", mode="comment"))
if hasattr(comment, "text") or hasattr(comment, "privacy"):
user = self.session.get_user(c["from_id"])
name = user["user1_nom"].split(" ")[0]
comment.text = "[post{post_id}|{name}], {text}".format(post_id=c["id"], text=comment.text, name=name)
group_id = self.group_id
topic_id = self.post["id"]
call_threaded(self.do_last, comment, group_id=group_id, topic_id=topic_id, reply_to_comment=c["id"])
def show_comment(self, comment_index):
c = self.comments["items"][comment_index]
c["post_id"] = self.post["id"]
a = displayTopicCommentPresenter(session=self.session, postObject=c, interactor=interactors.displayPostInteractor(), view=views.displayComment())

View File

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
import logging
from sessionmanager import renderers, utils # We'll use some functions from there
from presenters import base
from presenters.createPosts.basePost import createPostPresenter
from . import comment
log = logging.getLogger(__file__)
def get_message(status):
message = ""
if "text" in status:
message = utils.clean_text(status["text"])
return message
class displayTopicCommentPresenter(comment.displayCommentPresenter):
def get_post_information(self):
from_ = self.session.get_user(self.post[self.user_identifier])
title = from_["user1_nom"]
self.send_message("set_title", value=title)
message = ""
message = get_message(self.post)
self.send_message("set", control="post_view", value=message)
self.get_attachments(self.post, message)
self.check_image_load()
self.send_message("disable_control", control="reply")
self.send_message("disable_control", control="comments")