Update API version

This commit is contained in:
Manuel Cortez 2017-03-13 02:16:34 -06:00
parent 2c6704ae9e
commit ead1f186f0
17 changed files with 199 additions and 52 deletions

View File

@ -4,12 +4,13 @@
* Added a new menu in the menu bar that allows you to control the audio playback. For some actions (like play, next and back), if you are not focusing an audio buffer, the program will take the song from the "my audios" buffer. * Added a new menu in the menu bar that allows you to control the audio playback. For some actions (like play, next and back), if you are not focusing an audio buffer, the program will take the song from the "my audios" buffer.
* Added two more buffers: "Followers" and "I follow", located in the people buffer, under "friendship requests". * Added two more buffers: "Followers" and "I follow", located in the people buffer, under "friendship requests".
* Added an experimental photo viewer. Will show options for seeing the next and previous photo if the current post contains multiple images. * Added an experimental photo viewer. Will show options for seeing the next and previous photo if the current post contains multiple images. Fullscreen button still doesn't work.
* Improved chats, now they should be more stable. Also you will be able to send the message by pressing enter in the text box. If you are trying to send the same message multiple times, you will be warned. * Improved chats, now they should be more stable. Also you will be able to send the message by pressing enter in the text box. If you are trying to send the same message multiple times, you will be warned.
* Added video management (my videos, video albums and video search). For playing videos, you will be redirected to a website in your browser. * Added video management (my videos, video albums and video search). For playing videos, you will be redirected to a website in your browser due to the VK'S policy.
* Added a setting that allows you to specify if you want socializer to load images when you are opening posts. It could be useful for slow connections or those who don't want images to be loaded. * Added a setting that allows you to specify if you want socializer to load images when you are opening posts. It could be useful for slow connections or those who don't want images to be loaded.
* Added basic tagging for users in posts and comments. You can tag only people in your friends buffer. * Added basic tagging for users in posts and comments. You can tag only people in your friends buffer.
* Added a basic user profile viewer. * Added a basic user profile viewer.
* Added support for listening voice messages in chats. Currently it is not possible to send them, until the new API will be released.
## Changes in build 2016.07.08 (08/07/2016) ## Changes in build 2016.07.08 (08/07/2016)

View File

@ -1,14 +1,17 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
""" Attachment upload methods for different kind of posts in VK."""
import os import os
import widgetUtils import widgetUtils
import logging import logging
from wxUI.dialogs import attach as gui from wxUI.dialogs import attach as gui
from wxUI.dialogs import selector
log = logging.getLogger("controller.attach") log = logging.getLogger("controller.attach")
class attach(object): class attachmentUploader(object):
def __init__(self): def __init__(self, voice_messages=False):
self.attachments = list() self.attachments = list()
self.dialog = gui.attachDialog() self.type = "local"
self.dialog = gui.attachDialog(voice_messages)
widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image) widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image)
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment) widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
self.dialog.get_response() self.dialog.get_response()
@ -37,3 +40,36 @@ class attach(object):
def check_remove_status(self): def check_remove_status(self):
if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0: if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0:
self.dialog.remove.Enable(False) self.dialog.remove.Enable(False)
class attach(object):
def __init__(self, session):
self.session = session
self.attachments = list()
self.type = "online"
self.dialog = gui.attachDialog()
widgetUtils.connect_event(self.dialog.audio, widgetUtils.BUTTON_PRESSED, self.add_audio)
# widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
self.dialog.get_response()
log.debug("Attachments controller started.")
def add_audio(self, *args, **kwargs):
list_of_audios = self.session.vk.client.audio.get(count=1000)
list_of_audios = list_of_audios["items"]
audios = []
for i in list_of_audios:
audios.append(u"{0}, {1}".format(i["title"], i["artist"]))
select = selector.selectAttachment(_(u"Select the audio files you want to send"), audios)
if select.get_response() == widgetUtils.OK and select.attachments.GetCount() > 0:
attachments = select.get_all_attachments()
for i in attachments:
print list_of_audios[i].keys()
list_of_audios[i]["type"] = "audio"
self.attachments.append(list_of_audios[i])
def parse_attachments(self):
result = ""
for i in self.attachments:
preresult = "{0}{1}_{2}".format(i["type"], i["owner_id"], i["id"])
result = preresult+","
return result

View File

@ -12,6 +12,7 @@ import logging
import selector import selector
import webbrowser import webbrowser
import posts import posts
import attach
from wxUI.tabs import home from wxUI.tabs import home
from pubsub import pub from pubsub import pub
from sessionmanager import session from sessionmanager import session
@ -19,6 +20,7 @@ from mysc.thread_utils import call_threaded
from wxUI import commonMessages, menus from wxUI import commonMessages, menus
from vk import upload from vk import upload
from vk.exceptions import VkAPIMethodError from vk.exceptions import VkAPIMethodError
from utils import add_attachment
log = logging.getLogger("controller.buffers") log = logging.getLogger("controller.buffers")
@ -591,6 +593,7 @@ class chatBuffer(baseBuffer):
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)
widgetUtils.connect_event(self.tab.attachment, widgetUtils.BUTTON_PRESSED, self.add_attachment)
self.tab.set_focus_function(self.onFocus) self.tab.set_focus_function(self.onFocus)
def get_items(self, show_nextpage=False): def get_items(self, show_nextpage=False):
@ -615,19 +618,29 @@ class chatBuffer(baseBuffer):
[self.insert(i, False) for i in self.session.db[self.name]["items"][:num]] [self.insert(i, False) for i in self.session.db[self.name]["items"][:num]]
return retrieved return retrieved
def add_attachment(self, *args, **kwargs):
a = attach.attach(self.session)
r = a.parse_attachments()
if r != "":
self.attachments_to_be_sent = r
def send_chat_to_user(self, *args, **kwargs): def send_chat_to_user(self, *args, **kwargs):
text = self.tab.text.GetValue() text = self.tab.text.GetValue()
if text == "": return # if text == "" and not hasattr(self, "attachments_to_be_sent"): return
call_threaded(self._send_message, text=text) call_threaded(self._send_message, text=text)
def _send_message(self, text): def _send_message(self, text):
try: # try:
if hasattr(self, "attachments_to_be_sent"):
response = self.session.vk.client.messages.send(user_id=self.kwargs["user_id"], message=text, attachment=self.attachments_to_be_sent)
print self.attachments_to_be_sent
else:
response = self.session.vk.client.messages.send(user_id=self.kwargs["user_id"], message=text) response = self.session.vk.client.messages.send(user_id=self.kwargs["user_id"], message=text)
except VkAPIMethodError as ex: # except VkAPIMethodError as ex:
if ex.code == 9: # if ex.code == 9:
output.speak(_(u"You have been sending a message that is already sent. Try to update the buffer if you can't see the new message in the history.")) # output.speak(_(u"You have been sending a message that is already sent. Try to update the buffer if you can't see the new message in the history."))
finally: # finally:
self.tab.text.SetValue("") # self.tab.text.SetValue("")
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(chatBuffer, self).__init__(*args, **kwargs) super(chatBuffer, self).__init__(*args, **kwargs)
@ -635,7 +648,7 @@ class chatBuffer(baseBuffer):
def parse_attachments(self, post): def parse_attachments(self, post):
attachments = [] attachments = []
from posts import add_attachment
if post.has_key("attachments"): if post.has_key("attachments"):
for i in post["attachments"]: for i in post["attachments"]:
# We don't need the photos_list attachment, so skip it. # We don't need the photos_list attachment, so skip it.

View File

@ -220,7 +220,7 @@ class Controller(object):
call_threaded(player.player.play, audio_object) call_threaded(player.player.play, audio_object)
def play_audios(self, audios): def play_audios(self, audios):
player.player.play_all(audios) player.player.play_all(audios, shuffle=self.window.player_shuffle.IsChecked())
def view_post(self, post_object, controller_): def view_post(self, post_object, controller_):
p = getattr(posts, controller_)(self.session, post_object) p = getattr(posts, controller_)(self.session, post_object)
@ -385,6 +385,12 @@ class Controller(object):
return return
# If the chat already exists, let's create a dictionary wich will contains data of the received message. # If the chat already exists, let's create a dictionary wich will contains data of the received message.
message = {"id": obj.message_id, "user_id": obj.user_id, "date": obj.timestamp, "body": obj.text, "attachments": obj.attachments} message = {"id": obj.message_id, "user_id": obj.user_id, "date": obj.timestamp, "body": obj.text, "attachments": obj.attachments}
# if attachments is true, let's request for the full message with attachments formatted in a better way.
# Todo: code improvements. We shouldn't need to request the same message again just for these attachments.
if len(message["attachments"]) != 0:
message_ids = message["id"]
results = self.session.vk.client.messages.getById(message_ids=message_ids)
message = results["items"][0]
# If outbox it's true, it means that message["from_id"] should be the current user. If not, the obj.user_id should be taken. # If outbox it's true, it means that message["from_id"] should be the current user. If not, the obj.user_id should be taken.
if obj.message_flags.has_key("outbox") == True: if obj.message_flags.has_key("outbox") == True:
message["from_id"] = self.session.user_id message["from_id"] = self.session.user_id

View File

@ -71,7 +71,7 @@ class post(object):
checker.clean() checker.clean()
def show_attach_dialog(self, *args, **kwargs): def show_attach_dialog(self, *args, **kwargs):
a = attach.attach() a = attach.attachmentUploader()
if len(a.attachments) != 0: if len(a.attachments) != 0:
self.attachments = a.attachments self.attachments = a.attachments

View File

@ -1,4 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import random
import output import output
import sound_lib import sound_lib
import logging import logging
@ -88,9 +89,11 @@ class audioPlayer(object):
if self.stream != None: if self.stream != None:
self.stream.volume = self.vol/100.0 self.stream.volume = self.vol/100.0
def play_all(self, list_of_urls): def play_all(self, list_of_urls, shuffle=False):
self.stop() self.stop()
self.queue = list_of_urls self.queue = list_of_urls
if shuffle:
random.shuffle(self.queue)
self.play(self.queue[0]) self.play(self.queue[0])
self.queue.remove(self.queue[0]) self.queue.remove(self.queue[0])
self.worker = RepeatingTimer(5, self.player_function) self.worker = RepeatingTimer(5, self.player_function)

View File

@ -20,6 +20,7 @@ from wxUI.dialogs import postDialogs, urlList
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 wxUI import menus from wxUI import menus
from utils import add_attachment
log = logging.getLogger("controller.post") log = logging.getLogger("controller.post")
@ -31,32 +32,6 @@ def get_user(id, profiles):
# Translators: This string is user when socializer can't find the right user information. # Translators: This string is user when socializer can't find the right user information.
return _(u"Unknown username") return _(u"Unknown username")
def add_attachment(attachment):
msg = u""
tpe = ""
if attachment["type"] == "link":
msg = u"{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"])
tpe = _(u"Link")
elif attachment["type"] == "photo":
tpe = _(u"Photo")
msg = attachment["photo"]["text"]
if msg == "":
msg = _(u"no description available")
elif attachment["type"] == "video":
msg = u"{0}".format(attachment["video"]["title"],)
tpe = _(u"Video")
elif attachment["type"] == "audio":
msg = u"{0}".format(" ".join(session.compose_audio(attachment["audio"])))
tpe = _(u"Audio")
elif attachment["type"] == "doc":
if attachment["doc"].has_key("preview") and attachment["doc"]["preview"].has_key("audio_msg"):
tpe = _(u"Voice message")
msg = utils.seconds_to_string(attachment["doc"]["preview"]["audio_msg"]["duration"])
else:
msg = u"{0}".format(attachment["doc"]["title"])
tpe = _(u"{0} file").format(attachment["doc"]["ext"])
return [tpe, msg]
def get_message(status): def get_message(status):
message = "" message = ""
if status.has_key("text"): if status.has_key("text"):
@ -400,7 +375,8 @@ class postController(object):
log.debug("Unhandled attachment: %r" % (attachment,)) log.debug("Unhandled attachment: %r" % (attachment,))
def __del__(self): def __del__(self):
self.worker.finished.set() if hasattr(self, "worker"):
self.worker.finished.set()
class comment(object): class comment(object):
def __init__(self, session, comment_object): def __init__(self, session, comment_object):

View File

@ -1,7 +1,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import sys import sys
import fix_requests import fix_requests
import fix_win32com if hasattr(sys, "frozen"):
import fix_win32com
def setup(): def setup():
fix_requests.fix() fix_requests.fix()

View File

@ -37,4 +37,4 @@ def setup():
call_threaded(r.login) call_threaded(r.login)
app.run() app.run()
setup() setup()

View File

@ -0,0 +1,20 @@
#!/usr/bin/python
import requests
from bs4 import BeautifulSoup as bs
class client(object):
""" uses the movile version of the VK website for retrieving some information that is not available in the API, such as audio items."""
def __init__(self, email, password):
super(client, self).__init__()
self.session = requests.session()
self.email = email
self.password = password
def login(self):
self.headers={"Referer": "https://m.vk.com/login?role=fast&to=&s=1&m=1&email=%s" % (self.email,),
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0'}
payload = {"email": self.email, "pass": self.password}
page = self.session.get("https://m.vk.com/login")
soup = bs(page.content, "lxml")
url = soup.find('form')['action']
p = self.session.post(url, data=payload, headers=self.headers)

View File

@ -4,6 +4,7 @@ import os
import requests import requests
import re import re
import logging import logging
from sessionmanager import session
log = logging.getLogger("utils") log = logging.getLogger("utils")
url_re = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*") url_re = re.compile("(?:\w+://|www\.)[^ ,.?!#%=+][^ ]*")
bad_chars = '\'\\.,[](){}:;"' bad_chars = '\'\\.,[](){}:;"'
@ -58,4 +59,32 @@ def clean_text(text):
""" Replaces all HTML entities and put the plain text equivalent if it's possible.""" """ Replaces all HTML entities and put the plain text equivalent if it's possible."""
text = text.replace("<br>", "\n") text = text.replace("<br>", "\n")
text = text.replace("\\n", "\n") text = text.replace("\\n", "\n")
return text return text
def add_attachment(attachment):
msg = u""
tpe = ""
if attachment["type"] == "link":
msg = u"{0}: {1}".format(attachment["link"]["title"], attachment["link"]["url"])
tpe = _(u"Link")
elif attachment["type"] == "photo":
tpe = _(u"Photo")
msg = attachment["photo"]["text"]
if msg == "":
msg = _(u"no description available")
elif attachment["type"] == "video":
msg = u"{0}".format(attachment["video"]["title"],)
tpe = _(u"Video")
elif attachment["type"] == "audio":
msg = u"{0}".format(" ".join(session.compose_audio(attachment["audio"])))
tpe = _(u"Audio")
elif attachment["type"] == "doc":
if attachment["doc"].has_key("preview") and attachment["doc"]["preview"].has_key("audio_msg"):
tpe = _(u"Voice message")
msg = seconds_to_string(attachment["doc"]["preview"]["audio_msg"]["duration"])
print attachment["doc"]["ext"]
else:
msg = u"{0}".format(attachment["doc"]["title"])
tpe = _(u"{0} file").format(attachment["doc"]["ext"])
return [tpe, msg]

View File

@ -1,7 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import requests import requests
class VkUpload(object): class VkUpload(object):
def __init__(self, vk): def __init__(self, vk):
""" """
@ -111,10 +110,10 @@ class VkUpload(object):
""" """
values = {'group_id': group_id} values = {'group_id': group_id}
url = self.vk.method('docs.getUploadServer', values)['upload_url'] url = self.vk.docs.getUploadServer(values)['upload_url']
with open(file_path, 'rb') as file: with open(file_path, 'rb') as file:
response = self.vk.http.post(url, files={'file': file}).json() response = self.session.post(url, files={'file': file}).json()
response.update({ response.update({
'title': title, 'title': title,

View File

@ -1,5 +1,5 @@
import platform import platform
if platform.system() == "Windows": #if platform.system() == "Windows":
from wxUtils import * from wxUtils import *
#elif platform.system() == "Linux": #elif platform.system() == "Linux":
# from gtkUtils import * # from gtkUtils import *

View File

@ -3,7 +3,7 @@ import wx
import widgetUtils import widgetUtils
class attachDialog(widgetUtils.BaseDialog): class attachDialog(widgetUtils.BaseDialog):
def __init__(self): def __init__(self, voice_messages=False):
super(attachDialog, self).__init__(None, title=_(u"Add an attachment")) super(attachDialog, self).__init__(None, title=_(u"Add an attachment"))
panel = wx.Panel(self) panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.VERTICAL) sizer = wx.BoxSizer(wx.VERTICAL)
@ -15,10 +15,16 @@ class attachDialog(widgetUtils.BaseDialog):
sizer.Add(box, 0, wx.ALL, 5) sizer.Add(box, 0, wx.ALL, 5)
static = wx.StaticBox(panel, label=_(u"Add attachments")) static = wx.StaticBox(panel, label=_(u"Add attachments"))
self.photo = wx.Button(panel, wx.NewId(), _(u"&Photo")) self.photo = wx.Button(panel, wx.NewId(), _(u"&Photo"))
self.audio = wx.Button(panel, wx.NewId(), _(u"Audio file"))
if voice_messages:
self.voice_message = wx.Button(panel, wx.NewId(), _(u"Voice message"))
self.remove = wx.Button(panel, wx.NewId(), _(u"Remove attachment")) self.remove = wx.Button(panel, wx.NewId(), _(u"Remove attachment"))
self.remove.Enable(False) self.remove.Enable(False)
btnsizer = wx.StaticBoxSizer(static, wx.HORIZONTAL) btnsizer = wx.StaticBoxSizer(static, wx.HORIZONTAL)
btnsizer.Add(self.photo, 0, wx.ALL, 5) btnsizer.Add(self.photo, 0, wx.ALL, 5)
btnsizer.Add(self.audio, 0, wx.ALL, 5)
if voice_messages:
btnsizer.Add(self.voice_message, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5) sizer.Add(btnsizer, 0, wx.ALL, 5)
ok = wx.Button(panel, wx.ID_OK) ok = wx.Button(panel, wx.ID_OK)
ok.SetDefault() ok.SetDefault()

View File

@ -83,4 +83,58 @@ class selectPeople(widgetUtils.BaseDialog):
self.indexes.remove(n) self.indexes.remove(n)
def get_all_users(self): def get_all_users(self):
return self.indexes
class selectAttachment(widgetUtils.BaseDialog):
def __init__(self, title="", attachments=[]):
super(selectAttachment, self).__init__(parent=None, title=title)
self.indexes = []
self.attachments_list = attachments
panel = wx.Panel(self)
sizer = wx.BoxSizer(wx.HORIZONTAL)
label = wx.StaticText(panel, -1, _(u"Available attachments"))
self.cb = wx.ComboBox(panel, -1, choices=attachments, value=attachments[0])
self.cb.SetFocus()
attachmentSizer = wx.BoxSizer()
attachmentSizer.Add(label, 0, wx.ALL, 5)
attachmentSizer.Add(self.cb, 0, wx.ALL, 5)
self.add = wx.Button(panel, wx.NewId(), _(u"Select"))
self.add.Bind(wx.EVT_BUTTON, self.add_attachment)
attachmentSizer.Add(self.add, 0, wx.ALL, 5)
sizer.Add(attachmentSizer, 0, wx.ALL, 5)
lbl = wx.StaticText(panel, wx.NewId(), _(u"Selected attachments"))
self.attachments = wx.ListBox(panel, -1)
self.remove = wx.Button(panel, wx.NewId(), _(u"Remove"))
self.remove.Bind(wx.EVT_BUTTON, self.remove_attachment)
selectionSizer = wx.BoxSizer(wx.HORIZONTAL)
selectionSizer.Add(lbl, 0, wx.ALL, 5)
selectionSizer.Add(self.attachments, 0, wx.ALL, 5)
selectionSizer.Add(self.remove, 0, wx.ALL, 5)
sizer.Add(selectionSizer, 0, wx.ALL, 5)
ok = wx.Button(panel, wx.ID_OK, _(u"&OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"&Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_attachment(self):
return self.cb.GetValue()
def add_attachment(self, *args, **kwargs):
selection = self.get_attachment()
if selection in self.attachments_list:
self.attachments.Append(selection)
self.indexes.append(self.cb.GetSelection())
def remove_attachment(self, *args, **kwargs):
n = self.attachments.GetSelection()
self.attachments.Delete(n)
self.indexes.remove(n)
def get_all_attachments(self):
return self.indexes return self.indexes

View File

@ -32,6 +32,7 @@ class mainWindow(wx.Frame):
self.player_stop = player.Append(wx.NewId(), _(u"Stop")) self.player_stop = player.Append(wx.NewId(), _(u"Stop"))
self.player_previous = player.Append(wx.NewId(), _(u"Previous")) self.player_previous = player.Append(wx.NewId(), _(u"Previous"))
self.player_next = player.Append(wx.NewId(), _(u"Next")) self.player_next = player.Append(wx.NewId(), _(u"Next"))
self.player_shuffle = player.AppendCheckItem(wx.NewId(), _(u"Shuffle"))
self.player_volume_down = player.Append(wx.NewId(), _(u"Volume down")) self.player_volume_down = player.Append(wx.NewId(), _(u"Volume down"))
self.player_volume_up = player.Append(wx.NewId(), _(u"Volume up")) self.player_volume_up = player.Append(wx.NewId(), _(u"Volume up"))
self.player_mute = player.Append(wx.NewId(), _(u"Mute")) self.player_mute = player.Append(wx.NewId(), _(u"Mute"))

View File

@ -143,6 +143,8 @@ class chatTab(wx.Panel):
sizer.Add(self.create_controls()) sizer.Add(self.create_controls())
sizer.Add(self.create_attachments(), 0, wx.ALL, 5) sizer.Add(self.create_attachments(), 0, wx.ALL, 5)
sizer.Add(self.create_chat(), 0, wx.ALL, 5) sizer.Add(self.create_chat(), 0, wx.ALL, 5)
self.attachment = wx.Button(self, wx.NewId(), _(u"Add"))
sizer.Add(self.attachment, 0, wx.ALL, 5)
self.send = wx.Button(self, -1, _(u"Send")) self.send = wx.Button(self, -1, _(u"Send"))
self.send.SetDefault() self.send.SetDefault()
sizer.Add(self.send, 0, wx.ALL, 5) sizer.Add(self.send, 0, wx.ALL, 5)