2016-02-13 17:06:36 -06:00
# -*- coding: utf-8 -*-
2018-12-03 15:55:55 -06:00
""" A buffer is a (virtual) list of items. All items belong to a category (wall posts, messages, persons...) """
2019-01-11 17:00:58 -06:00
import time
2018-12-09 11:26:21 -06:00
import random
2018-12-03 15:55:55 -06:00
import logging
import webbrowser
2016-06-05 14:15:40 -05:00
import arrow
2016-02-15 05:43:40 -06:00
import wx
2019-01-06 22:51:20 -06:00
import presenters
import views
import interactors
2018-12-03 15:55:55 -06:00
import languageHandler
2016-02-13 17:06:36 -06:00
import widgetUtils
2016-03-27 00:11:52 -06:00
import output
2016-02-13 17:06:36 -06:00
from pubsub import pub
2018-12-09 05:21:52 -06:00
from vk_api . exceptions import VkApiError
2018-12-10 12:20:01 -06:00
from vk_api import upload
2018-12-18 05:32:41 -06:00
from requests . exceptions import ReadTimeout , ConnectionError
2019-02-26 13:57:37 -06:00
from mutagen . id3 import ID3
2019-02-06 11:35:07 -06:00
from presenters import player
2018-12-03 15:55:55 -06:00
from wxUI . tabs import home
2018-12-06 17:56:22 -06:00
from sessionmanager import session , renderers , utils
2016-02-15 05:43:40 -06:00
from mysc . thread_utils import call_threaded
2016-06-08 05:45:03 -05:00
from wxUI import commonMessages , menus
2019-01-01 19:42:53 -06:00
from sessionmanager . renderers import add_attachment
2019-02-06 11:35:07 -06:00
from . import selector
2016-02-13 17:06:36 -06:00
2016-05-10 20:23:48 -05:00
log = logging . getLogger ( " controller.buffers " )
2016-02-13 17:06:36 -06:00
class baseBuffer ( object ) :
2018-12-03 15:55:55 -06:00
""" a basic representation of a buffer. Other buffers should be derived from this class. This buffer represents the " news feed " """
2016-06-08 05:45:03 -05:00
def get_post ( self ) :
2018-12-03 15:55:55 -06:00
""" Return the currently focused post. """
2018-12-16 02:06:36 -06:00
# Handle case where there are no items in the buffer.
if self . tab . list . get_count ( ) == 0 :
wx . Bell ( )
return None
2016-06-08 05:45:03 -05:00
return self . session . db [ self . name ] [ " items " ] [ self . tab . list . get_selected ( ) ]
2019-01-07 15:05:43 -06:00
def __init__ ( self , parent = None , name = " " , session = None , composefunc = None , create_tab = True , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Constructor:
2018-12-03 15:55:55 -06:00
@parent wx . Treebook : parent for the buffer panel ,
@name str : Name for saving this buffer ' s data in the local storage variable,
@session sessionmanager . session . vkSession : Session for performing operations in the Vk API . This session should be logged in when this class is instanciated .
2018-12-30 10:41:47 -06:00
@composefunc str : This function will be called for composing the result which will be put in the listCtrl . Composefunc should exist in the sessionmanager . renderers module .
2018-12-03 15:55:55 -06:00
args and kwargs will be passed to get_items ( ) without any filtering . Be careful there .
"""
2016-02-13 17:06:36 -06:00
super ( baseBuffer , self ) . __init__ ( )
2019-01-07 15:05:43 -06:00
self . parent = parent
2016-02-13 17:06:36 -06:00
self . args = args
self . kwargs = kwargs
self . session = session
self . compose_function = composefunc
2019-01-07 15:05:43 -06:00
self . name = name
if create_tab :
self . create_tab ( self . parent )
2018-01-14 14:55:53 -06:00
#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.
# ToDo: Shall we allow dinamically set for update_function?
2016-02-13 17:06:36 -06:00
self . update_function = " get_page "
self . name = name
2018-01-14 14:55:53 -06:00
# 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.
2016-06-08 05:45:03 -05:00
self . user_key = " source_id "
self . post_key = " post_id "
2018-01-14 14:55:53 -06:00
# When set to False, update_function won't be executed here.
2016-06-29 12:33:09 -05:00
self . can_get_items = True
2016-02-13 17:06:36 -06:00
def create_tab ( self , parent ) :
2018-12-03 15:55:55 -06:00
""" Create the Wx panel. """
2016-02-13 17:06:36 -06:00
self . tab = home . homeTab ( parent )
2019-01-07 15:05:43 -06:00
# 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 )
2016-02-13 17:06:36 -06:00
def insert ( self , item , reversed = False ) :
2018-12-30 10:41:47 -06:00
""" 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. """
2018-12-06 15:37:16 -06:00
item_ = getattr ( renderers , self . compose_function ) ( item , self . session )
2016-02-13 17:06:36 -06:00
self . tab . list . insert_item ( reversed , * item_ )
2016-02-23 17:49:55 -06:00
def get_items ( self , show_nextpage = False ) :
2018-12-03 15:55:55 -06:00
""" Retrieve items from the VK API. This function is called repeatedly by the main controller and users could call it implicitly as well with the update buffer option.
@show_nextpage boolean : If it ' s true, it will try to load previous results.
2016-04-13 17:45:05 -05:00
"""
2016-06-29 12:33:09 -05:00
if self . can_get_items == False : return
2016-04-13 17:45:05 -05:00
retrieved = True # Control variable for handling unauthorised/connection errors.
try :
num = getattr ( self . session , " get_newsfeed " ) ( show_nextpage = show_nextpage , name = self . name , * self . args , * * self . kwargs )
2018-12-09 05:21:52 -06:00
except VkApiError as err :
2019-01-07 15:05:43 -06:00
log . error ( " Error {0} : {1} " . format ( err . code , err . error ) )
2016-04-13 17:45:05 -05:00
retrieved = err . code
return retrieved
2019-02-18 13:45:47 -06:00
except :
2018-12-18 05:32:41 -06:00
log . exception ( " Connection error when updating buffer %s . Will try again in 2 minutes " % ( self . name , ) )
return False
2019-01-07 15:05:43 -06:00
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.
2016-02-23 17:49:55 -06:00
if show_nextpage == False :
2016-02-13 17:06:36 -06:00
if self . tab . list . get_count ( ) > 0 and num > 0 :
2016-03-23 02:15:52 -06:00
v = [ i for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
v . reverse ( )
[ self . insert ( i , True ) for i in v ]
2016-02-13 17:06:36 -06:00
else :
[ self . insert ( i ) for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
2016-02-23 17:49:55 -06:00
else :
if num > 0 :
2019-02-11 03:55:16 -06:00
[ self . insert ( i , False ) for i in self . session . db [ self . name ] [ " items " ] [ - num : ] ]
2016-04-13 17:45:05 -05:00
return retrieved
2016-02-23 17:49:55 -06:00
2016-03-31 10:33:02 -06:00
def get_more_items ( self ) :
2018-01-14 14:55:53 -06:00
""" Returns previous items in the buffer. """
2016-02-23 17:49:55 -06:00
self . get_items ( show_nextpage = True )
2016-02-13 17:06:36 -06:00
def post ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Create a post in the current user ' s wall.
This process is handled in two parts . This is the first part , where the GUI is created and user can send the post .
During the second part ( threaded ) , the post will be sent to the API . """
2019-01-09 05:14:35 -06:00
p = presenters . createPostPresenter ( session = self . session , interactor = interactors . createPostInteractor ( ) , view = views . createPostDialog ( title = _ ( " Write your post " ) , message = " " , text = " " ) )
2019-01-07 13:16:20 -06:00
if hasattr ( p , " text " ) or hasattr ( p , " privacy " ) :
2016-04-11 11:48:35 -05:00
call_threaded ( self . do_last , p = p )
2019-01-02 17:30:34 -06:00
def do_last ( self , p , parent_endpoint = " wall " , child_endpoint = " post " , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Second part of post function. Here everything is going to be sent to the API """
2019-01-07 13:16:20 -06:00
msg = p . text
2016-04-11 11:48:35 -05:00
attachments = " "
if hasattr ( p , " attachments " ) :
attachments = self . upload_attachments ( p . 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 ] , " " )
2019-01-09 05:14:35 -06:00
if msg != " " :
kwargs . update ( message = msg )
kwargs . update ( privacy = p . privacy )
if attachments != " " :
kwargs . update ( attachments = attachments )
2019-01-02 17:30:34 -06:00
# Determines the correct functions to call here.
parent_endpoint = getattr ( self . session . vk . client , parent_endpoint )
endpoint = getattr ( parent_endpoint , child_endpoint )
2019-01-09 05:14:35 -06:00
post = endpoint ( * * kwargs )
2016-04-11 11:48:35 -05:00
pub . sendMessage ( " posted " , buffer = self . name )
2016-02-13 17:06:36 -06:00
2016-04-11 11:48:35 -05:00
def upload_attachments ( self , attachments ) :
2018-01-14 14:55:53 -06:00
""" Upload attachments to VK before posting them.
2019-01-28 05:36:51 -06:00
Returns attachments formatted as string , as required by VK API . """
2016-04-11 11:48:35 -05:00
# To do: Check the caption and description fields for this kind of attachments.
local_attachments = " "
2018-12-10 12:20:01 -06:00
uploader = upload . VkUpload ( self . session . vk . session_object )
2016-04-11 11:48:35 -05:00
for i in attachments :
2018-12-21 05:27:35 -06:00
if i [ " from " ] == " online " :
local_attachments + = " {0} {1} _ {2} , " . format ( i [ " type " ] , i [ " owner_id " ] , i [ " id " ] )
elif i [ " from " ] == " local " and i [ " type " ] == " photo " :
2016-04-11 11:48:35 -05:00
photos = i [ " file " ]
description = i [ " description " ]
r = uploader . photo_wall ( photos , caption = description )
id = r [ 0 ] [ " id " ]
owner_id = r [ 0 ] [ " owner_id " ]
local_attachments + = " photo {0} _ {1} , " . format ( owner_id , id )
2018-12-21 05:27:35 -06:00
elif i [ " from " ] == " local " and i [ " type " ] == " audio " :
2018-12-20 17:29:23 -06:00
audio = i [ " file " ]
2018-12-21 16:20:31 -06:00
title = " untitled "
artist = " unnamed "
if " artist " in i :
artist = i [ " artist " ]
if " title " in i :
title = i [ " title " ]
r = uploader . audio ( audio , title = title , artist = artist )
2018-12-20 17:29:23 -06:00
id = r [ " id " ]
owner_id = r [ " owner_id " ]
local_attachments + = " audio {0} _ {1} , " . format ( owner_id , id )
2019-01-28 05:36:51 -06:00
elif i [ " from " ] == " local " and i [ " type " ] == " document " :
document = i [ " file " ]
title = i [ " title " ]
r = uploader . document ( document , title = title , to_wall = True )
id = r [ " doc " ] [ " id " ]
owner_id = r [ " doc " ] [ " owner_id " ]
local_attachments + = " doc {0} _ {1} , " . format ( owner_id , id )
2016-04-11 11:48:35 -05:00
return local_attachments
2016-02-13 17:06:36 -06:00
def connect_events ( self ) :
2018-01-14 14:55:53 -06:00
""" Bind all events to this buffer """
2016-02-13 17:06:36 -06:00
widgetUtils . connect_event ( self . tab . post , widgetUtils . BUTTON_PRESSED , self . post )
2016-02-15 05:43:40 -06:00
widgetUtils . connect_event ( self . tab . list . list , widgetUtils . KEYPRESS , self . get_event )
2019-01-26 07:11:11 -06:00
widgetUtils . connect_event ( self . tab . list . list , wx . EVT_CONTEXT_MENU , self . show_menu )
2016-06-05 14:15:40 -05:00
self . tab . set_focus_function ( self . onFocus )
2016-02-15 05:43:40 -06:00
2016-06-08 05:45:03 -05:00
def show_menu ( self , ev , pos = 0 , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Show contextual menu when pressing menu key or right mouse click in a list item. """
2016-06-08 05:45:03 -05:00
if self . tab . list . get_count ( ) == 0 : return
menu = self . get_menu ( )
if pos != 0 :
self . tab . PopupMenu ( menu , pos )
else :
2018-12-30 10:41:47 -06:00
self . tab . PopupMenu ( menu , self . tab . list . list . GetPosition ( ) )
2016-06-08 05:45:03 -05:00
def show_menu_by_key ( self , ev ) :
2018-01-14 14:55:53 -06:00
""" Show contextual menu when menu key is pressed """
2016-06-08 05:45:03 -05:00
if self . tab . list . get_count ( ) == 0 :
return
if ev . GetKeyCode ( ) == wx . WXK_WINDOWS_MENU :
self . show_menu ( widgetUtils . MENU , pos = self . tab . list . list . GetPosition ( ) )
def get_menu ( self ) :
2018-01-14 14:55:53 -06:00
""" Returns contextual menu options. They will change according to the focused item """
2016-06-08 05:45:03 -05:00
p = self . get_post ( )
2018-12-16 02:06:36 -06:00
if p == None :
return
2019-01-03 12:08:38 -06:00
# determine if the current user is able to delete the object.
if " can_delete " in p :
can_delete = True == p [ " can_delete " ]
else :
can_delete = False
m = menus . postMenu ( can_delete = can_delete )
2019-01-01 19:42:53 -06:00
if ( " likes " in p ) == False :
2016-06-08 05:45:03 -05:00
m . like . Enable ( False )
elif p [ " likes " ] [ " user_likes " ] == 1 :
m . like . Enable ( False )
m . dislike . Enable ( True )
2019-01-01 19:42:53 -06:00
if ( " comments " in p ) == False :
2016-06-08 05:45:03 -05:00
m . comment . Enable ( False )
2019-04-13 18:43:48 -05:00
m . open_in_browser . Enable ( False )
2019-04-14 23:51:18 -05:00
if " type " in p and p [ " type " ] != " friend " and p [ " type " ] != " audio " and p [ " type " ] != " video " and p [ " type " ] != " playlist " or self . name != " home_timeline " :
2019-04-13 18:43:48 -05:00
m . open_in_browser . Enable ( True )
2016-06-08 05:45:03 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_post , menuitem = m . open )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . do_like , menuitem = m . like )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . do_dislike , menuitem = m . dislike )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . do_comment , menuitem = m . comment )
2019-04-13 18:43:48 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_in_browser , menuitem = m . open_in_browser )
2019-01-03 12:08:38 -06:00
if hasattr ( m , " view_profile " ) :
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_person_profile , menuitem = m . view_profile )
2019-01-03 13:40:11 -06:00
if hasattr ( m , " delete " ) :
widgetUtils . connect_event ( m , widgetUtils . MENU , self . delete , menuitem = m . delete )
2016-06-08 05:45:03 -05:00
return m
def do_like ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Set like in the currently focused post. """
2016-06-08 05:45:03 -05:00
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-06-08 05:45:03 -05:00
user = post [ self . user_key ]
id = post [ self . post_key ]
2019-01-01 19:42:53 -06:00
if " type " in post :
2016-06-08 05:45:03 -05:00
type_ = post [ " type " ]
else :
type_ = " post "
l = self . session . vk . client . likes . add ( owner_id = user , item_id = id , type = type_ )
self . session . db [ self . name ] [ " items " ] [ self . tab . list . get_selected ( ) ] [ " likes " ] [ " count " ] = l [ " likes " ]
self . session . db [ self . name ] [ " items " ] [ self . tab . list . get_selected ( ) ] [ " likes " ] [ " user_likes " ] = 1
2016-06-29 10:56:41 -05:00
# Translators: This will be used when user presses like.
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " You liked this " ) )
2016-06-08 05:45:03 -05:00
def do_dislike ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Set dislike (undo like) in the currently focused post. """
2016-06-08 05:45:03 -05:00
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-06-08 05:45:03 -05:00
user = post [ self . user_key ]
id = post [ self . post_key ]
2019-01-01 19:42:53 -06:00
if " type " in post :
2016-06-08 05:45:03 -05:00
type_ = post [ " type " ]
else :
type_ = " post "
l = self . session . vk . client . likes . delete ( owner_id = user , item_id = id , type = type_ )
self . session . db [ self . name ] [ " items " ] [ self . tab . list . get_selected ( ) ] [ " likes " ] [ " count " ] = l [ " likes " ]
self . session . db [ self . name ] [ " items " ] [ self . tab . list . get_selected ( ) ] [ " likes " ] [ " user_likes " ] = 2
2016-06-29 10:56:41 -05:00
# Translators: This will be user in 'dislike'
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " You don ' t like this " ) )
2016-06-08 05:45:03 -05:00
def do_comment ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Make a comment into the currently focused post. """
2018-12-16 02:06:36 -06:00
post = self . get_post ( )
if post == None :
return
2019-01-09 05:14:35 -06:00
comment = presenters . createPostPresenter ( session = self . session , interactor = interactors . createPostInteractor ( ) , view = views . createPostDialog ( title = _ ( " Add a comment " ) , message = " " , text = " " , mode = " comment " ) )
2019-01-07 13:16:20 -06:00
if hasattr ( comment , " text " ) or hasattr ( comment , " privacy " ) :
msg = comment . text
2016-06-08 05:45:03 -05:00
try :
user = post [ self . user_key ]
id = post [ self . post_key ]
self . session . vk . client . wall . addComment ( owner_id = user , post_id = id , text = msg )
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " You ' ve posted a comment " ) )
2016-06-08 05:45:03 -05:00
except Exception as msg :
2018-01-14 06:58:24 -06:00
log . error ( msg )
2016-06-08 05:45:03 -05:00
2019-01-03 13:40:11 -06:00
def delete ( self , * args , * * kwargs ) :
post = self . get_post ( )
if ( " type " in post and post [ " type " ] == " post " ) or self . name != " newsfeed " :
question = commonMessages . remove_post ( )
if question == widgetUtils . NO :
return
if " owner_id " in self . kwargs :
result = self . session . vk . client . wall . delete ( owner_id = self . kwargs [ " owner_id " ] , post_id = post [ self . post_key ] )
else :
result = self . session . vk . client . wall . delete ( post_id = post [ self . post_key ] )
pub . sendMessage ( " post_deleted " , post_id = post [ self . post_key ] )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
2016-02-15 05:43:40 -06:00
def get_event ( self , ev ) :
2018-01-14 14:55:53 -06:00
""" Parses keyboard input in the ListCtrl and executes the event associated with user keypresses. """
2019-04-25 09:17:48 -05:00
if ev . GetKeyCode ( ) == wx . WXK_RETURN : event = " open_post "
2016-02-15 05:43:40 -06:00
else :
event = None
ev . Skip ( )
if event != None :
try :
getattr ( self , event ) ( )
2016-02-22 05:53:37 -06:00
except AttributeError :
2016-02-15 05:43:40 -06:00
pass
def volume_down ( self ) :
2019-03-25 16:35:28 -06:00
""" Decreases player volume by 2 % """
player . player . volume = player . player . volume - 2
2016-02-15 05:43:40 -06:00
def volume_up ( self ) :
2019-03-25 16:35:28 -06:00
""" Increases player volume by 2 % """
player . player . volume = player . player . volume + 2
2016-02-13 17:06:36 -06:00
2016-02-16 16:32:40 -06:00
def play_audio ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Play audio in currently focused buffer, if possible. """
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2019-01-01 19:42:53 -06:00
if " type " in post and post [ " type " ] == " audio " :
2019-04-11 17:15:45 -05:00
pub . sendMessage ( " play " , object = post [ " audio " ] [ " items " ] [ 0 ] )
2016-07-18 17:34:37 -05:00
return True
2016-02-16 16:32:40 -06:00
2016-09-15 15:27:38 -05:00
def open_person_profile ( self , * args , * * kwargs ) :
2018-12-30 10:41:47 -06:00
""" Views someone ' s profile. """
2016-09-15 15:27:38 -05:00
selected = self . get_post ( )
2018-12-16 02:06:36 -06:00
if selected == None :
return
2018-01-14 14:55:53 -06:00
# Check all possible keys for an user object in VK API.
2016-09-21 13:54:52 -05:00
keys = [ " from_id " , " source_id " , " id " ]
2016-09-15 15:27:38 -05:00
for i in keys :
2019-01-01 19:42:53 -06:00
if i in selected :
2016-09-15 15:27:38 -05:00
pub . sendMessage ( " user-profile " , person = selected [ i ] )
2019-01-03 10:19:12 -06:00
break
2016-09-15 15:27:38 -05:00
2016-06-08 05:45:03 -05:00
def open_post ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Opens the currently focused post. """
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2019-01-01 19:42:53 -06:00
if " type " in post and post [ " type " ] == " audio " :
2019-01-08 17:56:51 -06:00
a = presenters . displayAudioPresenter ( session = self . session , postObject = post [ " audio " ] [ " items " ] , interactor = interactors . displayAudioInteractor ( ) , view = views . displayAudio ( ) )
2019-01-01 19:42:53 -06:00
elif " type " in post and post [ " type " ] == " friend " :
2019-04-15 17:50:56 -05:00
pub . sendMessage ( " open-post " , post_object = post , controller_ = " displayFriendship " , vars = dict ( caption = _ ( " {user1_nom} added the following friends " ) ) )
2016-02-17 17:37:57 -06:00
else :
2019-01-08 17:56:51 -06:00
pub . sendMessage ( " open-post " , post_object = post , controller_ = " displayPost " )
2016-02-17 17:37:57 -06:00
2016-02-19 17:36:19 -06:00
def pause_audio ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" pauses audio playback. """
2019-04-11 15:52:18 -05:00
pub . sendMessage ( " pause " )
2016-02-19 17:36:19 -06:00
2018-01-14 14:55:53 -06:00
def remove_buffer ( self , mandatory ) :
""" Function for removing a buffer. Returns True if removal is successful, False otherwise """
return False
2016-03-27 00:11:52 -06:00
2016-04-12 15:36:30 -05:00
def get_users ( self ) :
2018-01-14 14:55:53 -06:00
""" Returns source user in the post. """
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2019-01-01 19:42:53 -06:00
if ( " type " in post ) == False :
2016-04-15 09:06:18 -05:00
return [ post [ " from_id " ] ]
2016-04-12 15:36:30 -05:00
else :
return [ post [ " source_id " ] ]
2019-04-30 17:36:53 -05:00
def onFocus ( self , event , * args , * * kwargs ) :
2016-06-05 14:15:40 -05:00
""" Function executed when the item in a list is selected.
For this buffer it updates the date of posts in the list . """
2018-01-14 14:55:53 -06:00
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-06-05 14:15:40 -05:00
original_date = arrow . get ( post [ " date " ] )
2018-12-13 16:36:46 -06:00
created_at = original_date . humanize ( locale = languageHandler . curLang [ : 2 ] )
2018-09-03 08:33:05 -05:00
self . tab . list . list . SetItem ( self . tab . list . get_selected ( ) , 2 , created_at )
2019-04-30 17:36:53 -05:00
event . Skip ( )
2016-06-05 14:15:40 -05:00
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/wall {user_id} _ {post_id} " . format ( user_id = post [ " source_id " ] , post_id = post [ " post_id " ] )
webbrowser . open_new_tab ( url )
2016-02-13 17:06:36 -06:00
class feedBuffer ( baseBuffer ) :
2018-01-14 14:55:53 -06:00
""" This buffer represents an user ' s wall. It may be used either for the current user or someone else. """
2016-02-13 17:06:36 -06:00
2016-02-23 17:49:55 -06:00
def get_items ( self , show_nextpage = False ) :
2018-01-14 14:55:53 -06:00
""" Update buffer with newest items or get older items in the buffer. """
2016-06-29 12:33:09 -05:00
if self . can_get_items == False : return
2016-04-13 17:45:05 -05:00
retrieved = True
try :
num = getattr ( self . session , " get_page " ) ( show_nextpage = show_nextpage , name = self . name , * self . args , * * self . kwargs )
2018-12-18 05:32:41 -06:00
except VkApiError as err :
2019-01-07 15:05:43 -06:00
log . error ( " Error {0} : {1} " . format ( err . code , err . error ) )
2016-04-13 17:45:05 -05:00
retrieved = err . code
return retrieved
2019-02-18 13:45:47 -06:00
except :
2018-12-18 05:32:41 -06:00
log . exception ( " Connection error when updating buffer %s . Will try again in 2 minutes " % ( self . name , ) )
return False
2019-01-07 15:05:43 -06:00
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
2016-02-23 17:49:55 -06:00
if show_nextpage == False :
2016-02-13 17:06:36 -06:00
if self . tab . list . get_count ( ) > 0 and num > 0 :
2016-03-23 02:15:52 -06:00
v = [ i for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
v . reverse ( )
[ self . insert ( i , True ) for i in v ]
2016-02-13 17:06:36 -06:00
else :
[ self . insert ( i ) for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
2019-02-11 04:53:32 -06:00
else :
if num > 0 :
[ self . insert ( i , False ) for i in self . session . db [ self . name ] [ " items " ] [ - num : ] ]
2016-04-13 17:45:05 -05:00
return retrieved
2016-02-13 17:06:36 -06:00
2016-04-14 17:23:08 -05:00
def remove_buffer ( self , mandatory = False ) :
2018-01-14 14:55:53 -06:00
""" Remove buffer if the current buffer is not the logged user ' s wall. """
2016-04-14 17:23:08 -05:00
if " me_feed " == self . name :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer can ' t be deleted " ) )
2016-04-14 17:23:08 -05:00
return False
else :
if mandatory == False :
dlg = commonMessages . remove_buffer ( )
else :
dlg = widgetUtils . YES
if dlg == widgetUtils . YES :
self . session . db . pop ( self . name )
return True
else :
return False
2016-06-08 05:45:03 -05:00
def __init__ ( self , * args , * * kwargs ) :
super ( feedBuffer , self ) . __init__ ( * args , * * kwargs )
self . user_key = " from_id "
self . post_key = " id "
2019-01-02 17:46:01 -06:00
self . can_post = True
self . can_write_private_message = True
# if this is an user timeline we must check permissions to hide buttons when needed.
2019-01-10 17:35:32 -06:00
if " owner_id " in self . kwargs and self . kwargs [ " owner_id " ] > 0 :
2019-01-02 17:46:01 -06:00
permissions = self . session . vk . client . users . get ( user_ids = self . kwargs [ " owner_id " ] , fields = " can_post, can_see_all_posts, can_write_private_message " )
self . can_post = permissions [ 0 ] [ " can_post " ]
self . can_see_all_posts = permissions [ 0 ] [ " can_see_all_posts " ]
self . can_write_private_message = permissions [ 0 ] [ " can_write_private_message " ]
2016-06-08 05:45:03 -05:00
2019-01-02 17:30:34 -06:00
def post ( self , * args , * * kwargs ) :
""" Create a post in the wall for the specified user
This process is handled in two parts . This is the first part , where the GUI is created and user can send the post .
During the second part ( threaded ) , the post will be sent to the API . """
if " owner_id " not in self . kwargs :
return super ( feedBuffer , self ) . post ( )
owner_id = self . kwargs [ " owner_id " ]
2019-01-11 04:14:55 -06:00
user = self . session . get_user ( owner_id , key = " user1 " )
2019-02-26 11:18:02 -06:00
title = _ ( " Post to {user1_nom} ' s wall " ) . format ( * * user )
2019-01-11 04:14:55 -06:00
p = presenters . createPostPresenter ( session = self . session , interactor = interactors . createPostInteractor ( ) , view = views . createPostDialog ( title = title , message = " " , text = " " ) )
2019-01-07 13:16:20 -06:00
if hasattr ( p , " text " ) or hasattr ( p , " privacy " ) :
2019-01-02 17:30:34 -06:00
call_threaded ( self . do_last , p = p , owner_id = owner_id )
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/wall {user_id} _ {post_id} " . format ( user_id = post [ " from_id " ] , post_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2018-12-30 10:41:47 -06:00
class communityBuffer ( feedBuffer ) :
def create_tab ( self , parent ) :
self . tab = home . communityTab ( parent )
2019-01-07 15:05:43 -06:00
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 )
2018-12-30 10:41:47 -06:00
def connect_events ( self ) :
super ( communityBuffer , self ) . connect_events ( )
widgetUtils . connect_event ( self . tab . load , widgetUtils . BUTTON_PRESSED , self . load_community )
def load_community ( self , * args , * * kwargs ) :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Loading community... " ) )
2018-12-30 10:41:47 -06:00
self . can_get_items = True
self . tab . load . Enable ( False )
wx . CallAfter ( self . get_items )
2019-01-30 15:32:46 -06:00
def get_items ( self , * args , * * kwargs ) :
""" This method retrieves community information, useful to show different parts of the community itself. """
if self . can_get_items :
# Strangely, groups.get does not return counters so we need those to show options for loading specific posts for communities.
self . group_info = self . session . vk . client . groups . getById ( group_ids = - 1 * self . kwargs [ " owner_id " ] , fields = " counters " ) [ 0 ]
2019-02-18 13:45:47 -06:00
# print(self.group_info["counters"])
2019-01-30 15:32:46 -06:00
super ( communityBuffer , self ) . get_items ( * args , * * kwargs )
2019-01-31 16:46:26 -06:00
class topicBuffer ( feedBuffer ) :
def create_tab ( self , parent ) :
self . tab = home . topicTab ( 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 )
2019-04-30 17:36:53 -05:00
def onFocus ( self , event , * args , * * kwargs ) :
event . Skip ( )
2019-01-31 16:46:26 -06:00
def open_post ( self , * args , * * kwargs ) :
""" Opens the currently focused post. """
post = self . get_post ( )
if post == None :
return
a = presenters . displayTopicPresenter ( session = self . session , postObject = post , group_id = self . kwargs [ " group_id " ] , interactor = interactors . displayPostInteractor ( ) , view = views . displayTopic ( ) )
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
2019-04-14 23:51:18 -05:00
print ( post )
2019-04-13 18:43:48 -05:00
if post == None :
return
# In order to load the selected topic we firstly have to catch the group_id, which is present in self.kwargs
# After getting the group_id we should make it negative
group_id = self . kwargs [ " group_id " ] * - 1
url = " https://vk.com/topic {group_id} _ {topic_id} " . format ( group_id = group_id , topic_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2019-02-06 11:35:07 -06:00
class documentBuffer ( feedBuffer ) :
can_get_items = False
def create_tab ( self , parent ) :
self . tab = home . documentTab ( 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 )
2019-04-30 17:36:53 -05:00
def onFocus ( self , event , * args , * * kwargs ) :
2019-02-26 09:02:18 -06:00
post = self . get_post ( )
if post == None :
return
original_date = arrow . get ( post [ " date " ] )
created_at = original_date . humanize ( locale = languageHandler . curLang [ : 2 ] )
self . tab . list . list . SetItem ( self . tab . list . get_selected ( ) , 4 , created_at )
2019-04-30 17:36:53 -05:00
event . Skip ( )
2019-02-26 09:02:18 -06:00
2019-02-06 11:35:07 -06:00
def connect_events ( self ) :
super ( documentBuffer , self ) . connect_events ( )
2019-02-26 08:38:49 -06:00
# Check if we have a load button in the tab, because documents community buffers don't include it.
if hasattr ( self . tab , " load " ) :
widgetUtils . connect_event ( self . tab . load , widgetUtils . BUTTON_PRESSED , self . load_documents )
2019-02-06 11:35:07 -06:00
def load_documents ( self , * args , * * kwargs ) :
output . speak ( _ ( " Loading documents... " ) )
self . can_get_items = True
self . tab . load . Enable ( False )
wx . CallAfter ( self . get_items )
2019-02-05 12:20:50 -06:00
2019-02-26 08:38:49 -06:00
def get_menu ( self ) :
p = self . get_post ( )
if p == None :
return
if p [ " owner_id " ] == self . session . user_id :
added = True
else :
added = False
m = menus . documentMenu ( added )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . add_remove_document , menuitem = m . action )
2019-03-05 17:43:19 -06:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . download , menuitem = m . download )
2019-04-13 18:43:48 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_in_browser , menuitem = m . open_in_browser )
2019-02-26 08:38:49 -06:00
return m
def add_remove_document ( self , * args , * * kwargs ) :
p = self . get_post ( )
if p == None :
return
if p [ " owner_id " ] == self . session . user_id :
result = self . session . vk . client . docs . delete ( owner_id = p [ " owner_id " ] , doc_id = p [ " id " ] )
if result == 1 :
output . speak ( _ ( " The document has been successfully deleted. " ) )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
else :
result = self . session . vk . client . docs . add ( owner_id = p [ " owner_id " ] , doc_id = p [ " id " ] )
output . speak ( _ ( " The document has been successfully added. " ) )
2019-03-05 17:43:19 -06:00
def download ( self , * args , * * kwargs ) :
post = self . get_post ( )
filename = post [ " title " ]
# If document does not end in .extension we must fix it so the file dialog will save it properly later.
if filename . endswith ( post [ " ext " ] ) == False :
filename = filename + " . " + post [ " ext " ]
filepath = self . tab . get_download_path ( filename )
if filepath != None :
pub . sendMessage ( " download-file " , url = post [ " url " ] , filename = filepath )
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/doc {user_id} _ {post_id} " . format ( user_id = post [ " owner_id " ] , post_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2019-02-26 08:38:49 -06:00
class documentCommunityBuffer ( documentBuffer ) :
can_get_items = True
def create_tab ( self , parent ) :
self . tab = home . documentCommunityTab ( 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 )
2016-02-13 17:06:36 -06:00
class audioBuffer ( feedBuffer ) :
2018-01-14 14:55:53 -06:00
""" this buffer was supposed to be used with audio elements
but is deprecated as VK removed its audio support for third party apps . """
2016-02-13 17:06:36 -06:00
def create_tab ( self , parent ) :
self . tab = home . audioTab ( parent )
2019-01-07 15:05:43 -06:00
self . tab . name = self . name
self . connect_events ( )
2019-02-26 13:57:37 -06:00
if self . name == " me_audio " :
self . tab . post . Enable ( True )
2016-02-15 02:15:38 -06:00
2019-04-25 09:17:48 -05:00
def get_event ( self , ev ) :
if ev . GetKeyCode ( ) == wx . WXK_RETURN : event = " play_audio_from_keystroke "
else :
event = None
ev . Skip ( )
if event != None :
try :
getattr ( self , event ) ( )
except AttributeError :
pass
2016-02-15 02:15:38 -06:00
def connect_events ( self ) :
widgetUtils . connect_event ( self . tab . play , widgetUtils . BUTTON_PRESSED , self . play_audio )
2016-03-23 08:17:45 -06:00
widgetUtils . connect_event ( self . tab . play_all , widgetUtils . BUTTON_PRESSED , self . play_all )
2019-04-25 08:48:19 -05:00
pub . subscribe ( self . change_label , " playback-changed " )
2016-02-15 05:43:40 -06:00
super ( audioBuffer , self ) . connect_events ( )
2016-02-15 02:15:38 -06:00
def play_audio ( self , * args , * * kwargs ) :
2019-04-25 08:48:19 -05:00
if player . player . stream != None :
return player . player . pause ( )
2016-02-15 02:15:38 -06:00
selected = self . tab . list . get_selected ( )
2016-07-18 17:34:37 -05:00
if selected == - 1 :
selected = 0
2019-04-11 17:15:45 -05:00
pub . sendMessage ( " play " , object = self . session . db [ self . name ] [ " items " ] [ selected ] )
2016-07-18 17:34:37 -05:00
return True
2019-04-25 09:17:48 -05:00
def play_audio_from_keystroke ( self , * args , * * kwargs ) :
selected = self . tab . list . get_selected ( )
if selected == - 1 :
selected = 0
pub . sendMessage ( " play " , object = self . session . db [ self . name ] [ " items " ] [ selected ] )
return True
2016-07-18 17:34:37 -05:00
def play_next ( self , * args , * * kwargs ) :
selected = self . tab . list . get_selected ( )
2019-01-22 10:29:37 -06:00
if selected < 0 :
2016-07-18 17:34:37 -05:00
selected = 0
if self . tab . list . get_count ( ) < = selected + 1 :
newpos = 0
else :
newpos = selected + 1
self . tab . list . select_item ( newpos )
self . play_audio ( )
def play_previous ( self , * args , * * kwargs ) :
selected = self . tab . list . get_selected ( )
2018-12-22 05:39:21 -06:00
if selected < = 0 :
2016-07-18 17:34:37 -05:00
selected = self . tab . list . get_count ( )
newpos = selected - 1
self . tab . list . select_item ( newpos )
self . play_audio ( )
2016-02-15 02:15:38 -06:00
2016-06-08 05:45:03 -05:00
def open_post ( self , * args , * * kwargs ) :
2016-02-15 15:09:33 -06:00
selected = self . tab . list . get_selected ( )
2018-12-22 05:39:21 -06:00
if selected == - 1 :
2018-12-16 02:06:36 -06:00
return
2016-02-24 10:30:07 -06:00
audios = [ self . session . db [ self . name ] [ " items " ] [ selected ] ]
2019-01-08 17:56:51 -06:00
a = presenters . displayAudioPresenter ( session = self . session , postObject = audios , interactor = interactors . displayAudioInteractor ( ) , view = views . displayAudio ( ) )
2016-03-22 02:10:59 -06:00
2016-03-23 08:17:45 -06:00
def play_all ( self , * args , * * kwargs ) :
selected = self . tab . list . get_selected ( )
2016-03-23 11:36:07 -06:00
if selected == - 1 :
selected = 0
2018-12-16 02:06:36 -06:00
if self . name not in self . session . db :
return
2016-03-26 09:08:41 -06:00
audios = [ i for i in self . session . db [ self . name ] [ " items " ] [ selected : ] ]
2019-04-11 17:15:45 -05:00
pub . sendMessage ( " play-all " , list_of_songs = audios )
2016-07-18 17:34:37 -05:00
return True
2016-03-23 08:57:16 -06:00
2016-04-14 17:23:08 -05:00
def remove_buffer ( self , mandatory = False ) :
2016-03-27 00:11:52 -06:00
if " me_audio " == self . name or " popular_audio " == self . name or " recommended_audio " == self . name :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer can ' t be deleted " ) )
2016-03-27 00:11:52 -06:00
return False
else :
2016-04-13 17:45:05 -05:00
if mandatory == False :
dlg = commonMessages . remove_buffer ( )
else :
dlg = widgetUtils . YES
2016-03-27 00:11:52 -06:00
if dlg == widgetUtils . YES :
self . session . db . pop ( self . name )
return True
else :
return False
2016-03-31 10:33:02 -06:00
def get_more_items ( self , * args , * * kwargs ) :
2016-06-29 10:56:41 -05:00
# Translators: Some buffers can't use the get previous item feature due to API limitations.
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer doesn ' t support getting more items. " ) )
2016-03-31 10:33:02 -06:00
2019-04-30 17:36:53 -05:00
def onFocus ( self , event , * args , * * kwargs ) :
event . Skip ( )
2016-06-05 14:15:40 -05:00
2016-06-08 05:45:03 -05:00
def add_to_library ( self , * args , * * kwargs ) :
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-06-08 05:45:03 -05:00
args = { }
args [ " audio_id " ] = post [ " id " ]
2019-01-01 19:42:53 -06:00
if " album_id " in post :
2016-06-08 05:45:03 -05:00
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 :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Audio added to your library " ) )
2016-06-08 05:45:03 -05:00
def remove_from_library ( self , * args , * * kwargs ) :
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-06-08 05:45:03 -05:00
args = { }
args [ " audio_id " ] = post [ " id " ]
args [ " owner_id " ] = self . session . user_id
result = self . session . vk . client . audio . delete ( * * args )
if int ( result ) == 1 :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Removed audio from library " ) )
2019-01-26 18:51:34 -06:00
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
2016-07-12 05:00:07 -05:00
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
2016-06-08 05:45:03 -05:00
2016-06-29 04:08:37 -05:00
def move_to_album ( self , * args , * * kwargs ) :
2018-12-18 05:32:41 -06:00
if len ( self . session . audio_albums ) == 0 :
return commonMessages . no_audio_albums ( )
2018-12-16 02:06:36 -06:00
post = self . get_post ( )
if post == None :
return
2019-01-01 19:42:53 -06:00
album = selector . album ( _ ( " Select the album where you want to move this song " ) , self . session )
2016-06-29 04:08:37 -05:00
if album . item == None : return
2018-12-16 02:06:36 -06:00
id = post [ " id " ]
2019-01-26 18:44:23 -06:00
response = self . session . vk . client . audio . add ( playlist_id = album . item , audio_id = id , owner_id = post [ " owner_id " ] )
2016-06-29 04:08:37 -05:00
if response == 1 :
2016-06-29 10:56:41 -05:00
# Translators: Used when the user has moved an audio to an album.
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Moved " ) )
2016-06-29 04:08:37 -05:00
2016-06-08 05:45:03 -05:00
def get_menu ( self ) :
p = self . get_post ( )
2018-12-16 02:06:36 -06:00
if p == None :
return
2016-06-08 05:45:03 -05:00
m = menus . audioMenu ( )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_post , menuitem = m . open )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . play_audio , menuitem = m . play )
2016-06-29 04:08:37 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . move_to_album , menuitem = m . move )
2016-06-08 05:45:03 -05:00
# if owner_id is the current user, the audio is added to the user's audios.
if p [ " owner_id " ] == self . session . user_id :
2019-01-01 19:42:53 -06:00
m . library . SetItemLabel ( _ ( " &Remove from library " ) )
2016-06-08 05:45:03 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . remove_from_library , menuitem = m . library )
else :
widgetUtils . connect_event ( m , widgetUtils . MENU , self . add_to_library , menuitem = m . library )
return m
2019-02-26 13:57:37 -06:00
def post ( self , * args , * * kwargs ) :
""" Uploads an audio to the current user ' s library from the computer. """
file = self . tab . get_file_to_upload ( )
if file == None :
return
audio_tags = ID3 ( file )
if " TIT2 " in audio_tags :
title = audio_tags [ " TIT2 " ] . text [ 0 ]
else :
title = _ ( " Untitled " )
if " TPE1 " in audio_tags :
artist = audio_tags [ " TPE1 " ] . text [ 0 ]
else :
artist = _ ( " Unknown artist " )
uploader = upload . VkUpload ( self . session . vk . session_object )
call_threaded ( uploader . audio , file , title = title , artist = artist )
2016-06-08 05:45:03 -05:00
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/audio {user_id} _ {post_id} " . format ( user_id = post [ " owner_id " ] , post_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2019-04-25 08:48:19 -05:00
def change_label ( self , stopped ) :
if hasattr ( self . tab , " play " ) :
if stopped == False :
self . tab . play . SetLabel ( _ ( " P&ause " ) )
else :
self . tab . play . SetLabel ( _ ( " P&lay " ) )
def __del__ ( self ) :
pub . unsubscribe ( self . change_label , " playback-changed " )
2016-06-29 12:33:09 -05:00
class audioAlbum ( audioBuffer ) :
2018-01-14 14:55:53 -06:00
""" this buffer was supposed to be used with audio albums
but is deprecated as VK removed its audio support for third party apps . """
2016-06-29 12:33:09 -05:00
def create_tab ( self , parent ) :
self . tab = home . audioAlbumTab ( parent )
2016-06-30 09:30:17 -05:00
self . tab . play . Enable ( False )
self . tab . play_all . Enable ( False )
2019-01-07 15:05:43 -06:00
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 )
2016-06-29 12:33:09 -05:00
def connect_events ( self ) :
super ( audioAlbum , self ) . connect_events ( )
widgetUtils . connect_event ( self . tab . load , widgetUtils . BUTTON_PRESSED , self . load_album )
def load_album ( self , * args , * * kwargs ) :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Loading album... " ) )
2016-06-29 12:33:09 -05:00
self . can_get_items = True
self . tab . load . Enable ( False )
wx . CallAfter ( self . get_items )
2016-06-30 09:30:17 -05:00
self . tab . play . Enable ( True )
self . tab . play_all . Enable ( True )
2016-06-29 12:33:09 -05:00
2016-08-14 07:46:41 -05:00
class videoBuffer ( feedBuffer ) :
2018-01-14 14:55:53 -06:00
""" This buffer represents video elements, and it can be used for showing videos for the logged user or someone else. """
2016-08-14 07:46:41 -05:00
def create_tab ( self , parent ) :
self . tab = home . videoTab ( parent )
2019-01-07 15:05:43 -06:00
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 )
2016-08-14 07:46:41 -05:00
def connect_events ( self ) :
widgetUtils . connect_event ( self . tab . play , widgetUtils . BUTTON_PRESSED , self . play_audio )
super ( videoBuffer , self ) . connect_events ( )
def play_audio ( self , * args , * * kwargs ) :
2018-01-14 14:55:53 -06:00
""" Due to inheritance this method should be called play_audio, but play the currently focused video.
Opens a webbrowser pointing to the video ' s URL. " " "
2016-08-14 07:46:41 -05:00
selected = self . tab . list . get_selected ( )
2018-12-16 02:06:36 -06:00
if self . tab . list . get_count ( ) == 0 :
return
2016-08-14 07:46:41 -05:00
if selected == - 1 :
selected = 0
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Opening video in webbrowser... " ) )
2016-08-14 07:46:41 -05:00
webbrowser . open_new_tab ( self . session . db [ self . name ] [ " items " ] [ selected ] [ " player " ] )
2018-12-15 21:09:17 -06:00
# print self.session.db[self.name]["items"][selected]
2016-08-14 07:46:41 -05:00
return True
def open_post ( self , * args , * * kwargs ) :
2018-12-16 02:06:36 -06:00
pass
2016-08-14 07:46:41 -05:00
def remove_buffer ( self , mandatory = False ) :
if " me_video " == self . name :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer can ' t be deleted " ) )
2016-08-14 07:46:41 -05:00
return False
else :
if mandatory == False :
dlg = commonMessages . remove_buffer ( )
else :
dlg = widgetUtils . YES
if dlg == widgetUtils . YES :
self . session . db . pop ( self . name )
return True
else :
return False
def get_more_items ( self , * args , * * kwargs ) :
# Translators: Some buffers can't use the get previous item feature due to API limitations.
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer doesn ' t support getting more items. " ) )
2016-08-14 07:46:41 -05:00
2019-04-30 17:36:53 -05:00
def onFocus ( self , event , * args , * * kwargs ) :
event . Skip ( )
2016-08-14 07:46:41 -05:00
def add_to_library ( self , * args , * * kwargs ) :
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-08-14 07:46:41 -05:00
args = { }
args [ " video_id " ] = post [ " id " ]
2019-01-01 19:42:53 -06:00
if " album_id " in post :
2016-08-14 07:46:41 -05:00
args [ " album_id " ] = post [ " album_id " ]
args [ " owner_id " ] = post [ " owner_id " ]
video = self . session . vk . client . video . add ( * * args )
if video != None and int ( video ) > 21 :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Video added to your library " ) )
2016-08-14 07:46:41 -05:00
def remove_from_library ( self , * args , * * kwargs ) :
post = self . get_post ( )
2018-12-16 02:06:36 -06:00
if post == None :
return
2016-08-14 07:46:41 -05:00
args = { }
args [ " video_id " ] = post [ " id " ]
args [ " owner_id " ] = self . session . user_id
result = self . session . vk . client . video . delete ( * * args )
if int ( result ) == 1 :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Removed video from library " ) )
2016-08-14 07:46:41 -05:00
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
def move_to_album ( self , * args , * * kwargs ) :
2018-12-18 05:32:41 -06:00
if len ( self . session . video_albums ) == 0 :
return commonMessages . no_video_albums ( )
2018-12-16 02:06:36 -06:00
post = self . get_post ( )
if post == None :
return
2019-01-01 19:42:53 -06:00
album = selector . album ( _ ( " Select the album where you want to move this video " ) , self . session , " video_albums " )
2016-08-14 07:46:41 -05:00
if album . item == None : return
2018-12-16 02:06:36 -06:00
id = post [ " id " ]
2016-08-14 07:46:41 -05:00
response = self . session . vk . client . video . addToAlbum ( album_ids = album . item , video_id = id , target_id = self . session . user_id , owner_id = self . get_post ( ) [ " owner_id " ] )
if response == 1 :
# Translators: Used when the user has moved an video to an album.
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Moved " ) )
2016-08-14 07:46:41 -05:00
def get_menu ( self ) :
""" We ' ll use the same menu that is used for audio items, as the options are exactly the same """
p = self . get_post ( )
2018-12-16 02:06:36 -06:00
if p == None :
return
2016-08-14 07:46:41 -05:00
m = menus . audioMenu ( )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . move_to_album , menuitem = m . move )
# if owner_id is the current user, the audio is added to the user's audios.
if p [ " owner_id " ] == self . session . user_id :
2019-01-01 19:42:53 -06:00
m . library . SetItemLabel ( _ ( " &Remove from library " ) )
2016-08-14 07:46:41 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . remove_from_library , menuitem = m . library )
else :
widgetUtils . connect_event ( m , widgetUtils . MENU , self . add_to_library , menuitem = m . library )
return m
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/video {user_id} _ {video_id} " . format ( user_id = post [ " owner_id " ] , video_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2016-08-14 07:46:41 -05:00
class videoAlbum ( videoBuffer ) :
def create_tab ( self , parent ) :
self . tab = home . videoAlbumTab ( parent )
self . tab . play . Enable ( False )
2019-01-07 15:05:43 -06:00
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 )
2016-08-14 07:46:41 -05:00
def connect_events ( self ) :
super ( videoAlbum , self ) . connect_events ( )
widgetUtils . connect_event ( self . tab . load , widgetUtils . BUTTON_PRESSED , self . load_album )
def load_album ( self , * args , * * kwargs ) :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Loading album... " ) )
2016-08-14 07:46:41 -05:00
self . can_get_items = True
self . tab . load . Enable ( False )
wx . CallAfter ( self . get_items )
self . tab . play . Enable ( True )
2019-02-06 11:35:07 -06:00
class emptyBuffer ( object ) :
2016-03-23 08:57:16 -06:00
def __init__ ( self , name = None , parent = None , * args , * * kwargs ) :
self . tab = home . empty ( parent = parent , name = name )
self . name = name
def get_items ( self , * args , * * kwargs ) :
2019-01-07 15:05:43 -06:00
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
2016-03-23 08:57:16 -06:00
pass
2016-03-31 10:33:02 -06:00
def get_more_items ( self , * args , * * kwargs ) :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " This buffer doesn ' t support getting more items. " ) )
2016-03-27 00:11:52 -06:00
2016-04-14 17:23:08 -05:00
def remove_buffer ( self , mandatory = False ) : return False
2016-05-17 12:46:57 -05:00
class chatBuffer ( baseBuffer ) :
2018-12-09 10:53:50 -06:00
2018-12-04 16:58:40 -06:00
def insert ( self , item , reversed = False ) :
""" Add a new item to the list. Uses session.composefunc for parsing the dictionary and create a valid result for putting it in the list. """
2019-04-10 15:18:46 -05:00
# as this tab is based in a text control, we have to overwrite the defaults.
2018-12-06 15:37:16 -06:00
item_ = getattr ( renderers , self . compose_function ) ( item , self . session )
2018-12-05 12:43:33 -06:00
# the self.chat dictionary will have (first_line, last_line) as keys and message ID as a value for looking into it when needed.
# Here we will get first and last line of a chat message appended to the history.
2019-04-09 16:08:14 -05:00
values = self . tab . add_message ( item_ [ 0 ] , reverse = reversed )
2018-12-04 17:53:10 -06:00
self . chats [ values ] = item [ " id " ]
def get_focused_post ( self ) :
2018-12-05 12:43:33 -06:00
""" Gets chat message currently in focus """
# this function replaces self.get_post for normal buffers, as we rely in a TextCtrl control for getting chats.
# Instead of the traditional method to do the trick.
# Get text position here.
2018-12-04 17:53:10 -06:00
position = self . tab . history . PositionToXY ( self . tab . history . GetInsertionPoint ( ) )
id_ = None
2019-01-01 19:42:53 -06:00
for i in list ( self . chats . keys ( ) ) :
2018-12-05 12:43:33 -06:00
# Check if position[2] (line position) matches with something in self.chats
# (All messages, except the last one, should be able to be matched here).
# position[2]+1 is added because line may start with 0, while in wx.TextCtrl.GetNumberLines() that is not possible.
if position [ 2 ] + 1 > = i [ 0 ] and position [ 2 ] + 1 < i [ 1 ] :
2018-12-04 17:53:10 -06:00
id_ = self . chats [ i ]
2018-12-05 12:43:33 -06:00
break
# Retrieve here the object based in id_
2018-12-04 17:53:10 -06:00
if id_ != None :
for i in self . session . db [ self . name ] [ " items " ] :
if i [ " id " ] == id_ :
return i
return False
2018-12-04 16:58:40 -06:00
2018-12-04 17:53:10 -06:00
get_post = get_focused_post
def onFocus ( self , event , * args , * * kwargs ) :
2018-12-10 14:54:54 -06:00
if event . GetKeyCode ( ) == wx . WXK_UP or event . GetKeyCode ( ) == wx . WXK_DOWN or event . GetKeyCode ( ) == wx . WXK_START or event . GetKeyCode ( ) == wx . WXK_PAGEUP or event . GetKeyCode ( ) == wx . WXK_PAGEDOWN or event . GetKeyCode ( ) == wx . WXK_END :
2018-12-04 17:53:10 -06:00
msg = self . get_focused_post ( )
2018-12-05 12:43:33 -06:00
if msg == False : # Handle the case where the last line of the control cannot be matched to anything.
return
2019-04-10 15:18:46 -05:00
# Mark unread conversations as read.
if " read_state " in msg and msg [ " read_state " ] == 0 and " out " in msg and msg [ " out " ] == 0 :
2018-12-16 00:41:47 -06:00
self . session . soundplayer . play ( " message_unread.ogg " )
2019-04-10 15:18:46 -05:00
call_threaded ( self . session . vk . client . messages . markAsRead , peer_id = self . kwargs [ " peer_id " ] )
2018-12-04 17:53:10 -06:00
self . session . db [ self . name ] [ " items " ] [ - 1 ] [ " read_state " ] = 1
2019-01-01 19:42:53 -06:00
if " attachments " in msg and len ( msg [ " attachments " ] ) > 0 :
2018-12-04 17:53:10 -06:00
self . tab . attachments . list . Enable ( True )
self . attachments = list ( )
2018-12-10 02:32:57 -06:00
self . tab . attachments . clear ( )
2018-12-04 17:53:10 -06:00
self . parse_attachments ( msg )
else :
self . tab . attachments . list . Enable ( False )
self . tab . attachments . clear ( )
event . Skip ( )
2016-06-06 04:27:07 -05:00
2016-05-17 12:46:57 -05:00
def create_tab ( self , parent ) :
self . tab = home . chatTab ( parent )
2016-09-25 14:24:40 -05:00
self . attachments = list ( )
2019-01-07 15:05:43 -06:00
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 )
2016-05-17 12:46:57 -05:00
def connect_events ( self ) :
widgetUtils . connect_event ( self . tab . send , widgetUtils . BUTTON_PRESSED , self . send_chat_to_user )
2017-03-13 02:16:34 -06:00
widgetUtils . connect_event ( self . tab . attachment , widgetUtils . BUTTON_PRESSED , self . add_attachment )
2018-12-11 09:26:14 -06:00
widgetUtils . connect_event ( self . tab . text , widgetUtils . KEYPRESS , self . catch_enter )
2018-12-04 17:53:10 -06:00
self . tab . set_focus_function ( self . onFocus )
2016-05-17 12:46:57 -05:00
2018-12-11 09:26:14 -06:00
def catch_enter ( self , event , * args , * * kwargs ) :
2018-12-19 04:32:47 -06:00
shift = event . ShiftDown ( )
if event . GetKeyCode ( ) == wx . WXK_RETURN and shift == False :
2018-12-25 19:08:36 -06:00
return self . send_chat_to_user ( )
2019-01-11 17:22:52 -06:00
t = time . time ( )
2019-01-13 22:34:49 -06:00
if event . GetUnicodeKey ( ) != wx . WXK_NONE and t - self . last_keypress > 5 :
2019-01-11 17:22:52 -06:00
self . last_keypress = t
call_threaded ( self . session . vk . client . messages . setActivity , peer_id = self . kwargs [ " peer_id " ] , type = " typing " )
2018-12-11 09:26:14 -06:00
event . Skip ( )
2019-01-21 04:42:52 -06:00
def get_items ( self , show_nextpage = False ) :
2019-04-09 16:08:14 -05:00
""" Update buffer with newest items or get older items in the buffer. """
2016-06-29 12:33:09 -05:00
if self . can_get_items == False : return
2019-04-09 16:08:14 -05:00
retrieved = True
2016-05-17 12:46:57 -05:00
try :
2019-04-09 16:08:14 -05:00
num = getattr ( self . session , " get_page " ) ( show_nextpage = show_nextpage , name = self . name , * self . args , * * self . kwargs )
2018-12-18 05:32:41 -06:00
except VkApiError as err :
2019-01-07 15:05:43 -06:00
log . error ( " Error {0} : {1} " . format ( err . code , err . error ) )
2016-05-17 12:46:57 -05:00
retrieved = err . code
return retrieved
2019-02-18 13:45:47 -06:00
except :
2018-12-18 05:32:41 -06:00
log . exception ( " Connection error when updating buffer %s . Will try again in 2 minutes " % ( self . name , ) )
return False
2019-01-07 15:05:43 -06:00
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
2019-04-09 16:08:14 -05:00
2016-05-17 12:46:57 -05:00
if show_nextpage == False :
2018-12-05 12:43:33 -06:00
if self . tab . history . GetValue ( ) != " " and num > 0 :
2016-05-17 12:46:57 -05:00
v = [ i for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
2016-08-14 07:46:41 -05:00
[ self . insert ( i , False ) for i in v ]
2016-05-17 12:46:57 -05:00
else :
[ self . insert ( i ) for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
else :
if num > 0 :
2019-04-09 16:08:14 -05:00
# At this point we save more CPU and mathematical work if we just delete everything in the chat history and readd all messages.
# Otherwise we'd have to insert new lines at the top and recalculate positions everywhere else.
# Firstly, we'd have to save the current focused object so we will place the user in the right part of the text after loading everything again.
focused_post = self . get_post ( )
self . chats = dict ( )
self . tab . history . SetValue ( " " )
v = [ i for i in self . session . db [ self . name ] [ " items " ] ]
[ self . insert ( i ) for i in v ]
# Now it's time to set back the focus in the post.
for i in self . chats . keys ( ) :
if self . chats [ i ] == focused_post [ " id " ] :
line = i [ 0 ]
self . tab . history . SetInsertionPoint ( self . tab . history . XYToPosition ( 0 , line ) )
output . speak ( _ ( " Items loaded " ) )
break
2019-01-21 04:42:52 -06:00
if self . unread == True and num > 0 :
2018-12-16 00:41:47 -06:00
self . session . db [ self . name ] [ " items " ] [ - 1 ] . update ( read_state = 0 )
2016-05-17 12:46:57 -05:00
return retrieved
2019-04-09 16:08:14 -05:00
def get_more_items ( self ) :
output . speak ( _ ( " Getting more items... " ) )
call_threaded ( self . get_items , show_nextpage = True )
2017-03-13 02:16:34 -06:00
def add_attachment ( self , * args , * * kwargs ) :
2019-01-06 22:51:20 -06:00
a = presenters . attachPresenter ( session = self . session , view = views . attachDialog ( voice_messages = True ) , interactor = interactors . attachInteractor ( ) )
2018-12-21 05:54:52 -06:00
if len ( a . attachments ) != 0 :
self . attachments_to_be_sent = a . attachments
2017-03-13 02:16:34 -06:00
2016-05-17 12:46:57 -05:00
def send_chat_to_user ( self , * args , * * kwargs ) :
text = self . tab . text . GetValue ( )
2018-12-11 12:17:08 -06:00
if text == " " and not hasattr ( self , " attachments_to_be_sent " ) :
wx . Bell ( )
return
2018-12-24 12:52:58 -06:00
self . tab . text . SetValue ( " " )
2016-08-14 02:12:49 -05:00
call_threaded ( self . _send_message , text = text )
2018-12-21 05:54:52 -06:00
def upload_attachments ( self , attachments ) :
""" Upload attachments to VK before posting them.
Returns attachments formatted as string , as required by VK API .
"""
local_attachments = " "
uploader = upload . VkUpload ( self . session . vk . session_object )
for i in attachments :
if i [ " from " ] == " online " :
local_attachments + = " {0} {1} _ {2} , " . format ( i [ " type " ] , i [ " owner_id " ] , i [ " id " ] )
elif i [ " from " ] == " local " and i [ " type " ] == " photo " :
photos = i [ " file " ]
description = i [ " description " ]
r = uploader . photo_messages ( photos )
id = r [ 0 ] [ " id " ]
owner_id = r [ 0 ] [ " owner_id " ]
local_attachments + = " photo {0} _ {1} , " . format ( owner_id , id )
elif i [ " from " ] == " local " and i [ " type " ] == " audio " :
audio = i [ " file " ]
2018-12-21 16:20:31 -06:00
title = " untitled "
artist = " unnamed "
if " artist " in i :
artist = i [ " artist " ]
if " title " in i :
title = i [ " title " ]
r = uploader . audio ( audio , title = title , artist = artist )
2018-12-21 05:54:52 -06:00
id = r [ " id " ]
owner_id = r [ " owner_id " ]
local_attachments + = " audio {0} _ {1} , " . format ( owner_id , id )
2018-12-24 17:54:18 -06:00
elif i [ " from " ] == " local " and i [ " type " ] == " voice_message " :
2019-01-07 17:52:14 -06:00
r = uploader . audio_message ( i [ " file " ] , peer_id = self . kwargs [ " peer_id " ] )
2018-12-24 17:54:18 -06:00
id = r [ " audio_message " ] [ " id " ]
owner_id = r [ " audio_message " ] [ " owner_id " ]
local_attachments + = " audio_message {0} _ {1} , " . format ( owner_id , id )
2019-01-28 05:36:51 -06:00
elif i [ " from " ] == " local " and i [ " type " ] == " document " :
document = i [ " file " ]
title = i [ " title " ]
r = uploader . document ( document , title = title , message_peer_id = self . kwargs [ " peer_id " ] )
id = r [ " doc " ] [ " id " ]
owner_id = r [ " doc " ] [ " owner_id " ]
local_attachments + = " doc {0} _ {1} , " . format ( owner_id , id )
2018-12-21 05:54:52 -06:00
return local_attachments
def _send_message ( self , text , attachments = [ ] ) :
2019-01-23 09:17:33 -06:00
if hasattr ( self , " attachments_to_be_sent " ) and type ( self . attachments_to_be_sent ) == list :
2018-12-21 08:18:39 -06:00
self . attachments_to_be_sent = self . upload_attachments ( self . attachments_to_be_sent )
2018-12-09 11:26:21 -06:00
try :
2018-12-09 07:25:30 -06:00
# Let's take care about the random_id attribute.
# This should be unique per message and should be changed right after the message has been sent.
# If the message is tried to be sent twice this random_id should be the same for both copies.
# At the moment we just calculate len(text)_user_id, hope that will work.
2018-12-09 11:26:21 -06:00
random_id = random . randint ( 0 , 100000 )
if hasattr ( self , " attachments_to_be_sent " ) :
2019-01-07 17:52:14 -06:00
response = self . session . vk . client . messages . send ( peer_id = self . kwargs [ " peer_id " ] , message = text , attachment = self . attachments_to_be_sent , random_id = random_id )
2018-12-09 11:26:21 -06:00
else :
2019-01-07 17:52:14 -06:00
response = self . session . vk . client . messages . send ( peer_id = self . kwargs [ " peer_id " ] , message = text , random_id = random_id )
2018-12-09 11:26:21 -06:00
except ValueError as ex :
if ex . code == 9 :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " 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. " ) )
2019-01-23 09:17:33 -06:00
finally :
if hasattr ( self , " attachments_to_be_sent " ) :
del self . attachments_to_be_sent
2016-05-25 11:33:57 -05:00
2019-01-21 04:42:52 -06:00
def __init__ ( self , unread = False , * args , * * kwargs ) :
2016-06-06 04:27:07 -05:00
super ( chatBuffer , self ) . __init__ ( * args , * * kwargs )
2019-01-21 04:42:52 -06:00
self . unread = unread
2018-12-04 17:53:10 -06:00
self . chats = dict ( )
2019-01-11 17:00:58 -06:00
self . peer_typing = 0
2019-01-11 17:22:52 -06:00
self . last_keypress = time . time ( )
2016-06-06 04:27:07 -05:00
2016-09-25 14:24:40 -05:00
def parse_attachments ( self , post ) :
attachments = [ ]
2017-03-13 02:16:34 -06:00
2019-01-01 19:42:53 -06:00
if " attachments " in post :
2016-09-25 14:24:40 -05:00
for i in post [ " attachments " ] :
# We don't need the photos_list attachment, so skip it.
if i [ " type " ] == " photos_list " :
continue
attachments . append ( add_attachment ( i ) )
self . attachments . append ( i )
self . tab . attachments . list . Bind ( wx . EVT_LIST_ITEM_ACTIVATED , self . open_attachment )
self . tab . insert_attachments ( attachments )
def open_attachment ( self , * args , * * kwargs ) :
index = self . tab . attachments . get_selected ( )
attachment = self . attachments [ index ]
if attachment [ " type " ] == " audio " :
2019-01-08 17:56:51 -06:00
a = presenters . displayAudioPresenter ( session = self . session , postObject = [ attachment [ " audio " ] ] , interactor = interactors . displayAudioInteractor ( ) , view = views . displayAudio ( ) )
2018-12-13 11:48:17 -06:00
elif attachment [ " type " ] == " audio_message " :
link = attachment [ " audio_message " ] [ " link_mp3 " ]
2019-04-25 10:18:13 -05:00
pub . sendMessage ( " play-message " , message_url = link )
2018-12-13 11:48:17 -06:00
elif attachment [ " type " ] == " link " :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Opening URL... " ) , True )
2016-09-25 14:24:40 -05:00
webbrowser . open_new_tab ( attachment [ " link " ] [ " url " ] )
elif attachment [ " type " ] == " doc " :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Opening document in web browser... " ) )
2018-12-13 11:48:17 -06:00
webbrowser . open ( attachment [ " doc " ] [ " url " ] )
2016-09-25 14:24:40 -05:00
elif attachment [ " type " ] == " video " :
# it seems VK doesn't like to attach video links as normal URLS, so we'll have to
# get the full video object and use its "player" key which will open a webbrowser in their site with a player for the video.
# see https://vk.com/dev/attachments_w and and https://vk.com/dev/video.get
# However, the flash player isn't good for visually impaired people (when you press play you won't be able to close the window with alt+f4), so it could be good to use the HTML5 player.
# For firefox, see https://addons.mozilla.org/ru/firefox/addon/force-html5-video-player-at-vk/
# May be I could use a dialogue here for inviting people to use this addon in firefox. It seems it isn't possible to use this html5 player from the player URL.
object_id = " {0} _ {1} " . format ( attachment [ " video " ] [ " owner_id " ] , attachment [ " video " ] [ " id " ] )
video_object = self . session . vk . client . video . get ( owner_id = attachment [ " video " ] [ " owner_id " ] , videos = object_id )
video_object = video_object [ " items " ] [ 0 ]
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Opening video in web browser... " ) , True )
2016-09-25 14:24:40 -05:00
webbrowser . open_new_tab ( video_object [ " player " ] )
elif attachment [ " type " ] == " photo " :
2019-01-01 19:42:53 -06:00
output . speak ( _ ( " Opening photo in web browser... " ) , True )
2016-09-25 14:24:40 -05:00
# Possible photo sizes for looking in the attachment information. Try to use the biggest photo available.
possible_sizes = [ 1280 , 604 , 130 , 75 ]
url = " "
for i in possible_sizes :
2019-01-01 19:42:53 -06:00
if " photo_ {0} " . format ( i , ) in attachment [ " photo " ] :
2016-09-25 14:24:40 -05:00
url = attachment [ " photo " ] [ " photo_ {0} " . format ( i , ) ]
break
if url != " " :
webbrowser . open_new_tab ( url )
else :
log . debug ( " Unhandled attachment: %r " % ( attachment , ) )
2018-12-20 15:36:32 -06:00
def clear_reads ( self ) :
for i in self . session . db [ self . name ] [ " items " ] :
if " read_state " in i and i [ " read_state " ] == 0 :
i [ " read_state " ] = 1
2019-01-11 04:14:55 -06:00
def remove_buffer ( self , mandatory = False ) :
""" Remove buffer if the current buffer is not the logged user ' s wall. """
if mandatory == False :
dlg = commonMessages . remove_buffer ( )
else :
dlg = widgetUtils . YES
if dlg == widgetUtils . YES :
self . session . db . pop ( self . name )
return True
else :
return False
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
peer_id = self . kwargs [ " peer_id " ]
url = " https://vk.com/im?sel= {peer_id} " . format ( peer_id = peer_id )
webbrowser . open_new_tab ( url )
2016-05-25 11:33:57 -05:00
class peopleBuffer ( feedBuffer ) :
def create_tab ( self , parent ) :
self . tab = home . peopleTab ( parent )
2019-01-07 15:05:43 -06:00
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 )
2016-05-25 11:33:57 -05:00
def connect_events ( self ) :
super ( peopleBuffer , self ) . connect_events ( )
widgetUtils . connect_event ( self . tab . new_chat , widgetUtils . BUTTON_PRESSED , self . new_chat )
def new_chat ( self , * args , * * kwargs ) :
2018-12-16 02:06:36 -06:00
user = self . get_post ( )
if user == None :
return
user_id = user [ " id " ]
2016-06-05 14:15:40 -05:00
pub . sendMessage ( " new-chat " , user_id = user_id )
def onFocus ( self , * args , * * kwargs ) :
2018-12-16 02:06:36 -06:00
post = self . get_post ( )
if post == None :
return
2019-01-01 19:42:53 -06:00
if ( " last_seen " in post ) == False : return
2016-06-05 14:15:40 -05:00
original_date = arrow . get ( post [ " last_seen " ] [ " time " ] )
2019-02-14 13:09:44 -06:00
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 )
2016-06-08 05:45:03 -05:00
def open_timeline ( self , * args , * * kwargs ) :
pass
def get_menu ( self , * args , * * kwargs ) :
2018-12-10 17:35:36 -06:00
""" display menu for people buffers (friends and requests) """
# If this is an incoming requests buffer, there is a flag in the peopleMenu that shows a few new options.
# So let's make sure we call it accordingly.
if self . name == " friend_requests " :
m = menus . peopleMenu ( is_request = True )
# Connect the accept and decline methods from here.
widgetUtils . connect_event ( m , widgetUtils . MENU , self . accept_friendship , menuitem = m . accept )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . decline_friendship , menuitem = m . decline )
2018-12-10 17:52:01 -06:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . keep_as_follower , menuitem = m . keep_as_follower )
2019-01-21 04:42:52 -06:00
elif self . name == " subscribers " :
m = menus . peopleMenu ( is_subscriber = True )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . accept_friendship , menuitem = m . add )
2018-12-10 17:35:36 -06:00
else :
m = menus . peopleMenu ( is_request = False )
2019-01-24 17:10:32 -06:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . decline_friendship , menuitem = m . decline )
2019-04-13 18:43:48 -05:00
# It is not allowed to send messages to people who is not your friends, so let's disable it if we're in a pending or outgoing requests buffer.
2018-12-10 17:35:36 -06:00
if " friend_requests " in self . name :
m . message . Enable ( False )
2016-06-08 05:45:03 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . new_chat , menuitem = m . message )
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_timeline , menuitem = m . timeline )
2016-09-21 13:54:52 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_person_profile , menuitem = m . view_profile )
2019-04-13 18:43:48 -05:00
widgetUtils . connect_event ( m , widgetUtils . MENU , self . open_in_browser , menuitem = m . open_in_browser )
2016-07-08 16:34:28 -05:00
return m
def open_post ( self , * args , * * kwargs ) : pass
2016-07-18 17:34:37 -05:00
def play_audio ( self , * args , * * kwargs ) : return False
2016-07-08 16:34:28 -05:00
def pause_audio ( self , * args , * * kwargs ) : pass
2018-12-10 17:35:36 -06:00
def accept_friendship ( self , * args , * * kwargs ) :
pass
def decline_friendship ( self , * args , * * kwargs ) :
2019-01-21 05:42:21 -06:00
person = self . get_post ( )
if person == None :
return
user = self . session . get_user ( person [ " id " ] )
question = commonMessages . remove_friend ( user )
if question == widgetUtils . NO :
return
result = self . session . vk . client . friends . delete ( user_id = person [ " id " ] )
if " friend_deleted " in result :
2019-01-24 17:10:32 -06:00
msg = _ ( " You ' ve removed {user1_nom} from your friends. " ) . format ( * * user , )
2019-01-21 05:42:21 -06:00
pub . sendMessage ( " notify " , message = msg )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
2018-12-10 17:35:36 -06:00
2018-12-10 17:52:01 -06:00
def keep_as_follower ( self , * args , * * kwargs ) :
pass
2019-02-14 13:09:44 -06:00
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 :
2019-03-05 16:51:19 -06:00
# Ensure the user won't loose the focus after the new item is added.
focused_item = self . tab . list . get_selected ( ) + 1
2019-02-14 13:09:44 -06:00
self . session . db [ self . name ] [ " items " ] . insert ( 0 , person )
self . insert ( person , True )
2019-03-05 16:51:19 -06:00
# Selects back the previously focused item.
self . tab . list . select_item ( focused_item )
2019-02-14 13:09:44 -06:00
def remove_person ( self , user_id ) :
2019-03-05 16:51:19 -06:00
# Make sure the user is present in the buffer, otherwise don't attempt to remove a None Value from the list.
2019-02-14 13:09:44 -06:00
user = None
2019-03-05 16:51:19 -06:00
focused_user = self . get_post ( )
2019-02-14 13:09:44 -06:00
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 )
2019-03-05 16:51:19 -06:00
focused_item = self . tab . list . get_selected ( )
2019-02-14 13:09:44 -06:00
self . session . db [ self . name ] [ " items " ] . pop ( person_index )
self . tab . list . remove_item ( person_index )
2019-03-05 16:51:19 -06:00
if user != focused_user :
# Let's find the position of the previously focused user.
focus = None
for i in range ( 0 , len ( self . session . db [ self . name ] [ " items " ] ) ) :
if focused_user [ " id " ] == self . session . db [ self . name ] [ " items " ] [ i ] [ " id " ] :
self . tab . list . select_item ( i )
return
2019-04-19 14:41:57 -05:00
elif user == focused_user and person_index < self . tab . list . get_count ( ) :
self . tab . list . select_item ( person_index )
2019-03-05 16:51:19 -06:00
else :
self . tab . list . select_item ( self . tab . list . get_count ( ) - 1 )
2019-02-14 13:09:44 -06:00
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 " ] )
2019-04-13 18:43:48 -05:00
def open_in_browser ( self , * args , * * kwargs ) :
post = self . get_post ( )
if post == None :
return
url = " https://vk.com/id {user_id} " . format ( user_id = post [ " id " ] )
webbrowser . open_new_tab ( url )
2016-08-02 10:38:10 -05:00
class requestsBuffer ( peopleBuffer ) :
def get_items ( self , show_nextpage = False ) :
if self . can_get_items == False : return
retrieved = True
try :
ids = self . session . vk . client . friends . getRequests ( * self . args , * * self . kwargs )
2018-12-18 05:32:41 -06:00
except VkApiError as err :
2019-01-07 15:05:43 -06:00
log . error ( " Error {0} : {1} " . format ( err . code , err . error ) )
2016-08-02 10:38:10 -05:00
retrieved = err . code
return retrieved
2019-02-18 13:45:47 -06:00
except :
2018-12-18 05:32:41 -06:00
log . exception ( " Connection error when updating buffer %s . Will try again in 2 minutes " % ( self . name , ) )
return False
2016-08-02 10:38:10 -05:00
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 " )
2019-01-07 15:05:43 -06:00
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
2016-08-02 10:38:10 -05:00
if show_nextpage == False :
if self . tab . list . get_count ( ) > 0 and num > 0 :
v = [ i for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
v . reverse ( )
[ self . insert ( i , True ) for i in v ]
else :
[ self . insert ( i ) for i in self . session . db [ self . name ] [ " items " ] [ : num ] ]
return retrieved
2018-12-10 17:35:36 -06:00
def accept_friendship ( self , * args , * * kwargs ) :
2018-12-10 17:52:01 -06:00
""" Adds a person to a list of friends. This method is done for accepting someone else ' s friend request.
https : / / vk . com / dev / friends . add
"""
2018-12-10 17:35:36 -06:00
person = self . get_post ( )
2018-12-16 02:06:36 -06:00
if person == None :
return
2018-12-10 17:35:36 -06:00
result = self . session . vk . client . friends . add ( user_id = person [ " id " ] )
if result == 2 :
2019-01-01 19:42:53 -06:00
msg = _ ( " {0} {1} now is your friend. " ) . format ( person [ " first_name " ] , person [ " last_name " ] )
2018-12-10 17:35:36 -06:00
pub . sendMessage ( " notify " , message = msg )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
def decline_friendship ( self , * args , * * kwargs ) :
2018-12-10 17:52:01 -06:00
""" Declines a freind request.
https : / / vk . com / dev / friends . delete
"""
2018-12-10 17:35:36 -06:00
person = self . get_post ( )
2018-12-16 02:06:36 -06:00
if person == None :
return
2018-12-10 17:35:36 -06:00
result = self . session . vk . client . friends . delete ( user_id = person [ " id " ] )
if " out_request_deleted " in result :
2019-01-01 19:42:53 -06:00
msg = _ ( " You ' ve deleted the friends request to {0} {1} . " ) . format ( person [ " first_name " ] , person [ " last_name " ] )
2018-12-10 17:35:36 -06:00
elif " in_request_deleted " in result :
2019-01-01 19:42:53 -06:00
msg = _ ( " You ' ve declined the friend request of {0} {1} . " ) . format ( person [ " first_name " ] , person [ " last_name " ] )
2018-12-10 17:35:36 -06:00
pub . sendMessage ( " notify " , message = msg )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
2018-12-10 17:52:01 -06:00
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )
def keep_as_follower ( self , * args , * * kwargs ) :
""" Adds a person to The followers list of the current user.
https : / / vk . com / dev / friends . add
"""
person = self . get_post ( )
2018-12-16 02:06:36 -06:00
if person == None :
return
2018-12-10 17:52:01 -06:00
result = self . session . vk . client . friends . add ( user_id = person [ " id " ] , follow = 1 )
if result == 2 :
2019-01-01 19:42:53 -06:00
msg = _ ( " {0} {1} is following you. " ) . format ( person [ " first_name " ] , person [ " last_name " ] )
2018-12-10 17:52:01 -06:00
pub . sendMessage ( " notify " , message = msg )
self . session . db [ self . name ] [ " items " ] . pop ( self . tab . list . get_selected ( ) )
self . tab . list . remove_item ( self . tab . list . get_selected ( ) )