mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2024-11-22 11:18:08 -06:00
Merge pull request #442 from manuelcortez/templates
Add Templates for invisible interface
This commit is contained in:
commit
33338ba09a
@ -1,6 +1,10 @@
|
||||
TWBlue Changelog
|
||||
## changes in this version
|
||||
|
||||
* We have added Experimental support for templates in the invisible interface. The GUI will remain unchanged for now:
|
||||
* Each object (tweet, received direct message, sent direct message and people) has its own template in the settings. You can edit those templates from the account settings dialog, in the new "templates" tab.
|
||||
* Every template is composed of the group of variables you want to display for each object. Each variable will start with a dollar sign ($) and cannot contain spaces or special characters. Templates can include arbitrary text that will not be processed. When editing the example templates, you can get an idea of the variables that are available for each object by using the template editing dialog. When you press enter on a variable from the list of available variables, it will be added to the template automatically. When you try to save a template, TWBlue will warn you if the template is incorrectly formatted or if it includes variables that do not exist in the information provided by objects. It is also possible to return to default values from the same dialog when editing a template.
|
||||
* TWBlue can display image descriptions within Tweet templates. For that, you can use the $image_description variable in your template.
|
||||
* We have restored conversation and threads support powered by Twitter API V2 thanks to a set of improvements we have done in the application, as well as more generous limits to Tweet monthly cap by Twitter.
|
||||
* In the Windows 11 Keymap, the default shortcut to open the keystrokes editor is now CTRL+Alt+Windows+K to avoid conflicts with the new global mute microphone shortcut.
|
||||
* Fixed issue when uploading attachments (images, videos or gif files) while sending tweets or replies.
|
||||
|
@ -48,6 +48,12 @@ ocr_language = string(default="")
|
||||
braille_reporting = boolean(default=True)
|
||||
speech_reporting = boolean(default=True)
|
||||
|
||||
[templates]
|
||||
tweet = string(default="$display_name, $text $image_descriptions $date. $source")
|
||||
dm = string(default="$sender_display_name, $text $date")
|
||||
dm_sent = string(default="Dm to $recipient_display_name, $text $date")
|
||||
person = string(default="$display_name (@$screen_name). $followers followers, $following following, $tweets tweets. Joined Twitter $created_at.")
|
||||
|
||||
[filters]
|
||||
|
||||
[user-aliases]
|
@ -19,7 +19,7 @@ import languageHandler
|
||||
import logging
|
||||
from audio_services import youtube_utils
|
||||
from controller.buffers.base import base
|
||||
from sessions.twitter import compose, utils, reduce
|
||||
from sessions.twitter import compose, utils, reduce, templates
|
||||
from mysc.thread_utils import call_threaded
|
||||
from tweepy.errors import TweepyException
|
||||
from tweepy.cursor import Cursor
|
||||
@ -100,8 +100,10 @@ class BaseBuffer(base.Buffer):
|
||||
return self.get_message()
|
||||
|
||||
def get_message(self):
|
||||
template = self.session.settings["templates"]["tweet"]
|
||||
tweet = self.get_right_tweet()
|
||||
return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))
|
||||
t = templates.render_tweet(tweet, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||
return t
|
||||
|
||||
def get_full_tweet(self):
|
||||
tweet = self.get_right_tweet()
|
||||
|
@ -8,7 +8,7 @@ import config
|
||||
import languageHandler
|
||||
import logging
|
||||
from controller import messages
|
||||
from sessions.twitter import compose, utils
|
||||
from sessions.twitter import compose, utils, templates
|
||||
from mysc.thread_utils import call_threaded
|
||||
from tweepy.errors import TweepyException
|
||||
from pubsub import pub
|
||||
@ -129,6 +129,12 @@ class DirectMessagesBuffer(base.BaseBuffer):
|
||||
def open_in_browser(self, *args, **kwargs):
|
||||
output.speak(_(u"This action is not supported in the buffer yet."))
|
||||
|
||||
def get_message(self):
|
||||
template = self.session.settings["templates"]["dm"]
|
||||
dm = self.get_right_tweet()
|
||||
t = templates.render_dm(dm, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||
return t
|
||||
|
||||
class SentDirectMessagesBuffer(DirectMessagesBuffer):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
@ -150,4 +156,10 @@ class SentDirectMessagesBuffer(DirectMessagesBuffer):
|
||||
else:
|
||||
for i in items:
|
||||
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
self.buffer.list.insert_item(False, *tweet)
|
||||
|
||||
def get_message(self):
|
||||
template = self.session.settings["templates"]["dm_sent"]
|
||||
dm = self.get_right_tweet()
|
||||
t = templates.render_dm(dm, template, self.session, relative_times=self.session.settings["general"]["relative_times"], offset_seconds=self.session.db["utc_offset"])
|
||||
return t
|
||||
|
@ -16,7 +16,7 @@ import logging
|
||||
from mysc.thread_utils import call_threaded
|
||||
from tweepy.errors import TweepyException
|
||||
from pubsub import pub
|
||||
from sessions.twitter import compose
|
||||
from sessions.twitter import compose, templates
|
||||
from . import base
|
||||
|
||||
log = logging.getLogger("controller.buffers.twitter.peopleBuffer")
|
||||
@ -84,7 +84,10 @@ class PeopleBuffer(base.BaseBuffer):
|
||||
pass
|
||||
|
||||
def get_message(self):
|
||||
return " ".join(self.compose_function(self.get_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))
|
||||
template = self.session.settings["templates"]["person"]
|
||||
user = self.get_right_tweet()
|
||||
t = templates.render_person(user, template, self.session, relative_times=True, offset_seconds=self.session.db["utc_offset"])
|
||||
return t
|
||||
|
||||
def delete_item(self): pass
|
||||
|
||||
|
40
src/controller/editTemplateController.py
Normal file
40
src/controller/editTemplateController.py
Normal file
@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import wx
|
||||
from typing import List
|
||||
from sessions.twitter.templates import tweet_variables, dm_variables, person_variables
|
||||
from wxUI.dialogs.twitterDialogs import templateDialogs
|
||||
|
||||
class EditTemplate(object):
|
||||
def __init__(self, template: str, type: str) -> None:
|
||||
super(EditTemplate, self).__init__()
|
||||
self.default_template = template
|
||||
if type == "tweet":
|
||||
self.variables = tweet_variables
|
||||
elif type == "dm":
|
||||
self.variables = dm_variables
|
||||
else:
|
||||
self.variables = person_variables
|
||||
self.template: str = template
|
||||
|
||||
def validate_template(self, template: str) -> bool:
|
||||
used_variables: List[str] = re.findall("\$\w+", template)
|
||||
validated: bool = True
|
||||
for var in used_variables:
|
||||
if var[1:] not in self.variables:
|
||||
validated = False
|
||||
return validated
|
||||
|
||||
def run_dialog(self) -> str:
|
||||
dialog = templateDialogs.EditTemplateDialog(template=self.template, variables=self.variables, default_template=self.default_template)
|
||||
response = dialog.ShowModal()
|
||||
if response == wx.ID_SAVE:
|
||||
validated: bool = self.validate_template(dialog.template.GetValue())
|
||||
if validated == False:
|
||||
templateDialogs.invalid_template()
|
||||
self.template = dialog.template.GetValue()
|
||||
return self.run_dialog()
|
||||
else:
|
||||
return dialog.template.GetValue()
|
||||
else:
|
||||
return ""
|
@ -334,17 +334,17 @@ class Controller(object):
|
||||
root_position =self.view.search(session.db["user_name"], session.db["user_name"])
|
||||
for i in session.settings['general']['buffer_order']:
|
||||
if i == 'home':
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Home"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="home_timeline", name="home_timeline", sessionObject=session, account=session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Home"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="home_timeline", name="home_timeline", sessionObject=session, account=session.db["user_name"], sound="tweet_received.ogg", include_ext_alt_text=True, tweet_mode="extended"))
|
||||
elif i == 'mentions':
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Mentions"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="mentions_timeline", name="mentions", sessionObject=session, account=session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Mentions"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="mentions_timeline", name="mentions", sessionObject=session, account=session.db["user_name"], sound="mention_received.ogg", include_ext_alt_text=True, tweet_mode="extended"))
|
||||
elif i == 'dm':
|
||||
pub.sendMessage("createBuffer", buffer_type="DirectMessagesBuffer", session_type=session.type, buffer_title=_("Direct messages"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_direct_messages", name="direct_messages", sessionObject=session, account=session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg"))
|
||||
elif i == 'sent_dm':
|
||||
pub.sendMessage("createBuffer", buffer_type="SentDirectMessagesBuffer", session_type=session.type, buffer_title=_("Sent direct messages"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function=None, name="sent_direct_messages", sessionObject=session, account=session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message"))
|
||||
elif i == 'sent_tweets':
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Sent tweets"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="sent_tweets", sessionObject=session, account=session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Sent tweets"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="sent_tweets", sessionObject=session, account=session.db["user_name"], screen_name=session.db["user_name"], include_ext_alt_text=True, tweet_mode="extended"))
|
||||
elif i == 'favorites':
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="favourites", sessionObject=session, account=session.db["user_name"], sound="favourite.ogg", tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="favourites", sessionObject=session, account=session.db["user_name"], sound="favourite.ogg", include_ext_alt_text=True, tweet_mode="extended"))
|
||||
elif i == 'followers':
|
||||
pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Followers"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_followers", name="followers", sessionObject=session, account=session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"]))
|
||||
elif i == 'friends':
|
||||
@ -356,11 +356,11 @@ class Controller(object):
|
||||
pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="timelines", account=session.db["user_name"]))
|
||||
timelines_position =self.view.search("timelines", session.db["user_name"])
|
||||
for i in session.settings["other_buffers"]["timelines"]:
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_(u"Timeline for {}").format(i,), parent_tab=timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="%s-timeline" % (i,), sessionObject=session, account=session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_(u"Timeline for {}").format(i,), parent_tab=timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="%s-timeline" % (i,), sessionObject=session, account=session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, include_ext_alt_text=True, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Likes timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="favs_timelines", account=session.db["user_name"]))
|
||||
favs_timelines_position =self.view.search("favs_timelines", session.db["user_name"])
|
||||
for i in session.settings["other_buffers"]["favourites_timelines"]:
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes for {}").format(i,), parent_tab=favs_timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="%s-favorite" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes for {}").format(i,), parent_tab=favs_timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="%s-favorite" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, include_ext_alt_text=True, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Followers timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="followers_timelines", account=session.db["user_name"]))
|
||||
followers_timelines_position =self.view.search("followers_timelines", session.db["user_name"])
|
||||
for i in session.settings["other_buffers"]["followers_timelines"]:
|
||||
@ -372,11 +372,11 @@ class Controller(object):
|
||||
pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Lists"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="lists", account=session.db["user_name"]))
|
||||
lists_position =self.view.search("lists", session.db["user_name"])
|
||||
for i in session.settings["other_buffers"]["lists"]:
|
||||
pub.sendMessage("createBuffer", buffer_type="ListBuffer", session_type=session.type, buffer_title=_(u"List for {}").format(i), parent_tab=lists_position, start=False, kwargs=dict(parent=self.view.nb, function="list_timeline", name="%s-list" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="ListBuffer", session_type=session.type, buffer_title=_(u"List for {}").format(i), parent_tab=lists_position, start=False, kwargs=dict(parent=self.view.nb, function="list_timeline", name="%s-list" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), include_ext_alt_text=True, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Searches"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="searches", account=session.db["user_name"]))
|
||||
searches_position =self.view.search("searches", session.db["user_name"])
|
||||
for i in session.settings["other_buffers"]["tweet_searches"]:
|
||||
pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=session.type, buffer_title=_(u"Search for {}").format(i), parent_tab=searches_position, start=False, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (i,), sessionObject=session, account=session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended"))
|
||||
pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=session.type, buffer_title=_(u"Search for {}").format(i), parent_tab=searches_position, start=False, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (i,), sessionObject=session, account=session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, include_ext_alt_text=True, tweet_mode="extended"))
|
||||
for i in session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||
pub.sendMessage("createBuffer", buffer_type="TrendsBuffer", session_type=session.type, buffer_title=_("Trending topics for %s") % (i), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="%s_tt" % (i,), sessionObject=session, account=session.db["user_name"], trendsFor=i, sound="trends_updated.ogg"))
|
||||
|
||||
@ -423,7 +423,7 @@ class Controller(object):
|
||||
buffer.session.settings["other_buffers"]["tweet_searches"].append(term)
|
||||
buffer.session.settings.write()
|
||||
args = {"lang": dlg.get_language(), "result_type": dlg.get_result_type()}
|
||||
pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=buffer.session.type, buffer_title=_("Search for {}").format(term), parent_tab=searches_position, start=True, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (term,), sessionObject=buffer.session, account=buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, tweet_mode="extended", **args))
|
||||
pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=buffer.session.type, buffer_title=_("Search for {}").format(term), parent_tab=searches_position, start=True, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (term,), sessionObject=buffer.session, account=buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, include_ext_alt_text=True, tweet_mode="extended", **args))
|
||||
else:
|
||||
log.error("A buffer for the %s search term is already created. You can't create a duplicate buffer." % (term,))
|
||||
return
|
||||
@ -872,7 +872,7 @@ class Controller(object):
|
||||
if usr.id_str in buff.session.settings["other_buffers"]["timelines"]:
|
||||
commonMessageDialogs.timeline_exist()
|
||||
return
|
||||
tl = buffers.twitter.BaseBuffer(self.view.nb, "user_timeline", "%s-timeline" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr.id_str, tweet_mode="extended")
|
||||
tl = buffers.twitter.BaseBuffer(self.view.nb, "user_timeline", "%s-timeline" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr.id_str, include_ext_alt_text=True, tweet_mode="extended")
|
||||
try:
|
||||
tl.start_stream(play_sound=False)
|
||||
except ValueError:
|
||||
@ -891,7 +891,7 @@ class Controller(object):
|
||||
if usr.id_str in buff.session.settings["other_buffers"]["favourites_timelines"]:
|
||||
commonMessageDialogs.timeline_exist()
|
||||
return
|
||||
tl = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, tweet_mode="extended")
|
||||
tl = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, include_ext_alt_text=True, tweet_mode="extended")
|
||||
try:
|
||||
tl.start_stream(play_sound=False)
|
||||
except ValueError:
|
||||
@ -1088,10 +1088,10 @@ class Controller(object):
|
||||
if position == page.buffer.list.get_selected():
|
||||
page.session.sound.play("limit.ogg")
|
||||
|
||||
try:
|
||||
output.speak(page.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(page.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def down(self, *args, **kwargs):
|
||||
page = self.get_current_buffer()
|
||||
@ -1100,16 +1100,16 @@ class Controller(object):
|
||||
return
|
||||
position = page.buffer.list.get_selected()
|
||||
index = position+1
|
||||
try:
|
||||
page.buffer.list.select_item(index)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
page.buffer.list.select_item(index)
|
||||
# except:
|
||||
# pass
|
||||
if position == page.buffer.list.get_selected():
|
||||
page.session.sound.play("limit.ogg")
|
||||
try:
|
||||
output.speak(page.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(page.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def left(self, *args, **kwargs):
|
||||
buff = self.view.get_current_buffer_pos()
|
||||
@ -1202,18 +1202,18 @@ class Controller(object):
|
||||
def go_home(self):
|
||||
buffer = self.get_current_buffer()
|
||||
buffer.buffer.list.select_item(0)
|
||||
try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def go_end(self):
|
||||
buffer = self.get_current_buffer()
|
||||
buffer.buffer.list.select_item(buffer.buffer.list.get_count()-1)
|
||||
try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def go_page_up(self):
|
||||
buffer = self.get_current_buffer()
|
||||
@ -1222,10 +1222,10 @@ class Controller(object):
|
||||
else:
|
||||
index = buffer.buffer.list.get_selected() - 20
|
||||
buffer.buffer.list.select_item(index)
|
||||
try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def go_page_down(self):
|
||||
buffer = self.get_current_buffer()
|
||||
@ -1234,10 +1234,10 @@ class Controller(object):
|
||||
else:
|
||||
index = buffer.buffer.list.get_selected() + 20
|
||||
buffer.buffer.list.select_item(index)
|
||||
try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
except:
|
||||
pass
|
||||
# try:
|
||||
output.speak(buffer.get_message(), True)
|
||||
# except:
|
||||
# pass
|
||||
|
||||
def url(self, *args, **kwargs):
|
||||
buffer = self.get_current_buffer()
|
||||
@ -1385,7 +1385,7 @@ class Controller(object):
|
||||
buff = self.search_buffer("home_timeline", account)
|
||||
if create == True:
|
||||
if buffer == "favourites":
|
||||
favourites = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended")
|
||||
favourites = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], include_ext_alt_text=True, tweet_mode="extended")
|
||||
self.buffers.append(favourites)
|
||||
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
||||
favourites.start_stream(play_sound=False)
|
||||
@ -1415,7 +1415,7 @@ class Controller(object):
|
||||
if create in buff.session.settings["other_buffers"]["lists"]:
|
||||
output.speak(_(u"This list is already opened"), True)
|
||||
return
|
||||
tl = buffers.twitter.ListBuffer(self.view.nb, "list_timeline", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), tweet_mode="extended")
|
||||
tl = buffers.twitter.ListBuffer(self.view.nb, "list_timeline", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), include_ext_alt_text=True, tweet_mode="extended")
|
||||
buff.session.lists.append(tl)
|
||||
pos=self.view.search("lists", buff.session.db["user_name"])
|
||||
self.insert_buffer(tl, pos)
|
||||
|
@ -1,6 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
import webbrowser
|
||||
import logging
|
||||
import sound_lib
|
||||
import paths
|
||||
import widgetUtils
|
||||
@ -8,17 +9,18 @@ import config
|
||||
import languageHandler
|
||||
import output
|
||||
import application
|
||||
import config_utils
|
||||
import keys
|
||||
from collections import OrderedDict
|
||||
from pubsub import pub
|
||||
from mysc import autostart as autostart_windows
|
||||
from wxUI.dialogs import configuration
|
||||
from wxUI import commonMessageDialogs
|
||||
from extra.autocompletionUsers import settings
|
||||
from extra.ocr import OCRSpace
|
||||
from pubsub import pub
|
||||
import logging
|
||||
import config_utils
|
||||
from .editTemplateController import EditTemplate
|
||||
|
||||
log = logging.getLogger("Settings")
|
||||
import keys
|
||||
from collections import OrderedDict
|
||||
from mysc import autostart as autostart_windows
|
||||
|
||||
class globalSettingsController(object):
|
||||
def __init__(self):
|
||||
@ -152,6 +154,15 @@ class accountSettingsController(globalSettingsController):
|
||||
self.dialog.create_reporting()
|
||||
self.dialog.set_value("reporting", "speech_reporting", self.config["reporting"]["speech_reporting"])
|
||||
self.dialog.set_value("reporting", "braille_reporting", self.config["reporting"]["braille_reporting"])
|
||||
tweet_template = self.config["templates"]["tweet"]
|
||||
dm_template = self.config["templates"]["dm"]
|
||||
sent_dm_template = self.config["templates"]["dm_sent"]
|
||||
person_template = self.config["templates"]["person"]
|
||||
self.dialog.create_templates(tweet_template=tweet_template, dm_template=dm_template, sent_dm_template=sent_dm_template, person_template=person_template)
|
||||
widgetUtils.connect_event(self.dialog.templates.tweet, widgetUtils.BUTTON_PRESSED, self.edit_tweet_template)
|
||||
widgetUtils.connect_event(self.dialog.templates.dm, widgetUtils.BUTTON_PRESSED, self.edit_dm_template)
|
||||
widgetUtils.connect_event(self.dialog.templates.sent_dm, widgetUtils.BUTTON_PRESSED, self.edit_sent_dm_template)
|
||||
widgetUtils.connect_event(self.dialog.templates.person, widgetUtils.BUTTON_PRESSED, self.edit_person_template)
|
||||
self.dialog.create_other_buffers()
|
||||
buffer_values = self.get_buffers_list()
|
||||
self.dialog.buffers.insert_buffers(buffer_values)
|
||||
@ -160,7 +171,6 @@ class accountSettingsController(globalSettingsController):
|
||||
widgetUtils.connect_event(self.dialog.buffers.up, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_up)
|
||||
widgetUtils.connect_event(self.dialog.buffers.down, widgetUtils.BUTTON_PRESSED, self.dialog.buffers.move_down)
|
||||
|
||||
|
||||
self.dialog.create_ignored_clients(self.config["twitter"]["ignored_clients"])
|
||||
widgetUtils.connect_event(self.dialog.ignored_clients.add, widgetUtils.BUTTON_PRESSED, self.add_ignored_client)
|
||||
widgetUtils.connect_event(self.dialog.ignored_clients.remove, widgetUtils.BUTTON_PRESSED, self.remove_ignored_client)
|
||||
@ -185,6 +195,42 @@ class accountSettingsController(globalSettingsController):
|
||||
self.dialog.set_title(_(u"Account settings for %s") % (self.user,))
|
||||
self.response = self.dialog.get_response()
|
||||
|
||||
def edit_tweet_template(self, *args, **kwargs):
|
||||
template = self.config["templates"]["tweet"]
|
||||
control = EditTemplate(template=template, type="tweet")
|
||||
result = control.run_dialog()
|
||||
if result != "": # Template has been saved.
|
||||
self.config["templates"]["tweet"] = result
|
||||
self.config.write()
|
||||
self.dialog.templates.tweet.SetLabel(_("Edit template for tweets. Current template: {}").format(result))
|
||||
|
||||
def edit_dm_template(self, *args, **kwargs):
|
||||
template = self.config["templates"]["dm"]
|
||||
control = EditTemplate(template=template, type="dm")
|
||||
result = control.run_dialog()
|
||||
if result != "": # Template has been saved.
|
||||
self.config["templates"]["dm"] = result
|
||||
self.config.write()
|
||||
self.dialog.templates.dm.SetLabel(_("Edit template for direct messages. Current template: {}").format(result))
|
||||
|
||||
def edit_sent_dm_template(self, *args, **kwargs):
|
||||
template = self.config["templates"]["dm_sent"]
|
||||
control = EditTemplate(template=template, type="dm")
|
||||
result = control.run_dialog()
|
||||
if result != "": # Template has been saved.
|
||||
self.config["templates"]["dm_sent"] = result
|
||||
self.config.write()
|
||||
self.dialog.templates.sent_dm.SetLabel(_("Edit template for sent direct messages. Current template: {}").format(result))
|
||||
|
||||
def edit_person_template(self, *args, **kwargs):
|
||||
template = self.settings["templates"]["person"]
|
||||
control = EditTemplate(template=template, type="person")
|
||||
result = control.run_dialog()
|
||||
if result != "": # Template has been saved.
|
||||
self.config["templates"]["person"] = result
|
||||
self.config.write()
|
||||
self.dialog.templates.person.SetLabel(_("Edit template for persons. Current template: {}").format(result))
|
||||
|
||||
def save_configuration(self):
|
||||
if self.config["general"]["relative_times"] != self.dialog.get_value("general", "relative_time"):
|
||||
self.needs_restart = True
|
||||
|
147
src/sessions/twitter/templates.py
Normal file
147
src/sessions/twitter/templates.py
Normal file
@ -0,0 +1,147 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import arrow
|
||||
import languageHandler
|
||||
from string import Template
|
||||
from . import utils
|
||||
|
||||
# Define variables that would be available for all template objects.
|
||||
# This will be used for the edit template dialog.
|
||||
# Available variables for tweet objects.
|
||||
tweet_variables = ["date", "display_name", "screen_name", "source", "lang", "text", "image_descriptions"]
|
||||
dm_variables = ["date", "sender_display_name", "sender_screen_name", "recipient_display_name", "recipient_display_name", "text"]
|
||||
person_variables = ["display_name", "screen_name", "location", "description", "followers", "following", "listed", "likes", "tweets", "created_at"]
|
||||
|
||||
# Default, translatable templates.
|
||||
tweet_default_template = _("$display_name, $text $image_descriptions $date. $source")
|
||||
dm_default_template = _("$sender_display_name, $text $date")
|
||||
dm_sent_default_template = _("Dm to $recipient_display_name, $text $date")
|
||||
person_default_template = _("$display_name (@$screen_name). $followers followers, $following following, $tweets tweets. Joined Twitter $created_at.")
|
||||
|
||||
def process_date(field, relative_times=True, offset_seconds=0):
|
||||
original_date = arrow.get(field, locale="en")
|
||||
if relative_times == True:
|
||||
ts = original_date.humanize(locale=languageHandler.curLang[:2])
|
||||
else:
|
||||
ts = original_date.shift(seconds=offset_seconds).format(_("dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.curLang[:2])
|
||||
return ts
|
||||
|
||||
def process_text(tweet):
|
||||
if hasattr(tweet, "full_text"):
|
||||
text = tweet.full_text
|
||||
elif hasattr(tweet, "text"):
|
||||
text = tweet.text
|
||||
# Cleanup mentions, so we'll remove more than 2 mentions to make the tweet easier to read.
|
||||
text = utils.clean_mentions(text)
|
||||
# Replace URLS for extended version of those.
|
||||
if hasattr(tweet, "entities"):
|
||||
text = utils.expand_urls(text, tweet.entities)
|
||||
text = re.sub(r"https://twitter.com/\w+/status/\d+", "", text)
|
||||
return text
|
||||
|
||||
def process_image_descriptions(entities):
|
||||
""" Attempt to extract information for image descriptions. """
|
||||
image_descriptions = []
|
||||
for media in entities["media"]:
|
||||
if media.get("ext_alt_text") != None:
|
||||
image_descriptions.append(media.get("ext_alt_text"))
|
||||
idescriptions = ""
|
||||
for image in image_descriptions:
|
||||
idescriptions += _("Image description: {}.").format(image)
|
||||
return idescriptions
|
||||
|
||||
def render_tweet(tweet, template, session, relative_times=False, offset_seconds=0):
|
||||
""" Renders any given Tweet according to the passed template.
|
||||
Available data for tweets will be stored in the following variables:
|
||||
$date: Creation date.
|
||||
$display_name: User profile name.
|
||||
$screen_name: User screen name, this is the same name used to reference the user in Twitter.
|
||||
$ source: Source client from where the current tweet was sent.
|
||||
$lang: Two letter code for the automatically detected language for the tweet. This detection is performed by Twitter.
|
||||
$text: Tweet text.
|
||||
$image_descriptions: Information regarding image descriptions added by twitter users.
|
||||
"""
|
||||
available_data = dict()
|
||||
created_at = process_date(tweet.created_at, relative_times, offset_seconds)
|
||||
available_data.update(date=created_at)
|
||||
# user.
|
||||
available_data.update(display_name=session.get_user(tweet.user).name, screen_name=session.get_user(tweet.user).screen_name)
|
||||
# Source client from where tweet was originated.
|
||||
available_data.update(source=tweet.source)
|
||||
if hasattr(tweet, "retweeted_status"):
|
||||
if hasattr(tweet.retweeted_status, "quoted_status"):
|
||||
text = "RT @{}: {} Quote from @{}: {}".format(session.get_user(tweet.retweeted_status.user).screen_name, process_text(tweet.retweeted_status), session.get_user(tweet.retweeted_status.quoted_status.user).screen_name, process_text(tweet.retweeted_status.quoted_status))
|
||||
else:
|
||||
text = "RT @{}: {}".format(session.get_user(tweet.retweeted_status.user).screen_name, process_text(tweet.retweeted_status))
|
||||
elif hasattr(tweet, "quoted_status"):
|
||||
text = "{} Quote from @{}: {}".format(process_text(tweet), session.get_user(tweet.quoted_status.user).screen_name, process_text(tweet.quoted_status))
|
||||
else:
|
||||
text = process_text(tweet)
|
||||
available_data.update(lang=tweet.lang, text=text)
|
||||
# process image descriptions
|
||||
image_descriptions = ""
|
||||
if hasattr(tweet, "quoted_status") and hasattr(tweet.quoted_status, "extended_entities"):
|
||||
image_descriptions = process_image_descriptions(tweet.quoted_status.extended_entities)
|
||||
elif hasattr(tweet, "retweeted_status") and hasattr(tweet.retweeted_status, "quoted_status") and hasattr(tweet.retweeted_status.quoted_status, "extended_entities"):
|
||||
image_descriptions = process_image_descriptions(tweet.retweeted_status.quoted_status.extended_entities)
|
||||
elif hasattr(tweet, "extended_entities"):
|
||||
image_descriptions = process_image_descriptions(tweet.extended_entities)
|
||||
if image_descriptions != "":
|
||||
available_data.update(image_descriptions=image_descriptions)
|
||||
result = Template(_(template)).safe_substitute(**available_data)
|
||||
result = re.sub(r"\$\w+", "", result)
|
||||
return result
|
||||
|
||||
def render_dm(dm, template, session, relative_times=False, offset_seconds=0):
|
||||
""" Renders direct messages by using the provided template.
|
||||
Available data will be stored in the following variables:
|
||||
$date: Creation date.
|
||||
$sender_display_name: User profile name for user who sent the dm.
|
||||
$sender_screen_name: User screen name for user sending the dm, this is the same name used to reference the user in Twitter.
|
||||
$recipient_display_name: User profile name for user who received the dm.
|
||||
$recipient_screen_name: User screen name for user receiving the dm, this is the same name used to reference the user in Twitter.
|
||||
$text: Text of the direct message.
|
||||
"""
|
||||
available_data = dict()
|
||||
available_data.update(text=utils.expand_urls(dm.message_create["message_data"]["text"], dm.message_create["message_data"]["entities"]))
|
||||
# Let's remove the last 3 digits in the timestamp string.
|
||||
# Twitter sends their "epoch" timestamp with 3 digits for milliseconds and arrow doesn't like it.
|
||||
original_date = arrow.get(int(dm.created_timestamp))
|
||||
if relative_times == True:
|
||||
ts = original_date.humanize(locale=languageHandler.curLang[:2])
|
||||
else:
|
||||
ts = original_date.shift(seconds=offset_seconds)
|
||||
available_data.update(date=ts)
|
||||
sender = session.get_user(dm.message_create["sender_id"])
|
||||
recipient = session.get_user(dm.message_create["target"]["recipient_id"])
|
||||
available_data.update(sender_display_name=sender.name, sender_screen_name=sender.screen_name, recipient_display_name=recipient.name, recipient_screen_name=recipient.screen_name)
|
||||
result = Template(_(template)).safe_substitute(**available_data)
|
||||
result = re.sub(r"\$\w+", "", result)
|
||||
return result
|
||||
|
||||
# Sesion object is not used in this function but we keep compatibility across all rendering functions.
|
||||
def render_person(user, template, session=None, relative_times=True, offset_seconds=0):
|
||||
""" Renders persons (any Twitter user) by using the provided template.
|
||||
Available data will be stored in the following variables:
|
||||
$display_name: The name of the user, as they’ve defined it. Not necessarily a person’s name. Typically capped at 50 characters, but subject to change.
|
||||
$screen_name: The screen name, handle, or alias that this user identifies themselves with.
|
||||
$location: The user-defined location for this account’s profile. Not necessarily a location, nor machine-parseable.
|
||||
$description: The user-defined UTF-8 string describing their account.
|
||||
$followers: The number of followers this account currently has. This value might be inaccurate.
|
||||
$following: The number of users this account is following (AKA their “followings”). This value might be inaccurate.
|
||||
$listed: The number of public lists that this user is a member of. This value might be inaccurate.
|
||||
$likes: The number of Tweets this user has liked in the account’s lifetime. This value might be inaccurate.
|
||||
$tweets: The number of Tweets (including retweets) issued by the user. This value might be inaccurate.
|
||||
$created_at: The date and time that the user account was created on Twitter.
|
||||
"""
|
||||
available_data = dict(display_name=user.name, screen_name=user.screen_name, followers=user.followers_count, following=user.friends_count, likes=user.favourites_count, listed=user.listed_count, tweets=user.statuses_count)
|
||||
# Nullable values.
|
||||
nullables = ["location", "description"]
|
||||
for nullable in nullables:
|
||||
if hasattr(user, nullable) and getattr(user, nullable) != None:
|
||||
available_data[nullable] = getattr(user, nullable)
|
||||
created_at = process_date(user.created_at, relative_times=relative_times, offset_seconds=offset_seconds)
|
||||
available_data.update(created_at=created_at)
|
||||
result = Template(_(template)).safe_substitute(**available_data)
|
||||
result = re.sub(r"\$\w+", "", result)
|
||||
return result
|
@ -233,6 +233,20 @@ class other_buffers(wx.Panel):
|
||||
buffers_list.append(self.buffers.get_text_column(i, 0))
|
||||
return buffers_list
|
||||
|
||||
class templates(wx.Panel, baseDialog.BaseWXDialog):
|
||||
def __init__(self, parent, tweet_template, dm_template, sent_dm_template, person_template):
|
||||
super(templates, self).__init__(parent)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
self.tweet = wx.Button(self, wx.ID_ANY, _("Edit template for tweets. Current template: {}").format(tweet_template))
|
||||
sizer.Add(self.tweet, 0, wx.ALL, 5)
|
||||
self.dm = wx.Button(self, wx.ID_ANY, _("Edit template for direct messages. Current template: {}").format(dm_template))
|
||||
sizer.Add(self.dm, 0, wx.ALL, 5)
|
||||
self.sent_dm = wx.Button(self, wx.ID_ANY, _("Edit template for sent direct messages. Current template: {}").format(sent_dm_template))
|
||||
sizer.Add(self.sent_dm, 0, wx.ALL, 5)
|
||||
self.person = wx.Button(self, wx.ID_ANY, _("Edit template for persons. Current template: {}").format(person_template))
|
||||
sizer.Add(self.person, 0, wx.ALL, 5)
|
||||
self.SetSizer(sizer)
|
||||
|
||||
class ignoredClients(wx.Panel):
|
||||
def __init__(self, parent, choices):
|
||||
super(ignoredClients, self).__init__(parent=parent)
|
||||
@ -380,6 +394,10 @@ class configurationDialog(baseDialog.BaseWXDialog):
|
||||
self.ignored_clients = ignoredClients(self.notebook, ignored_clients_list)
|
||||
self.notebook.AddPage(self.ignored_clients, _(u"Ignored clients"))
|
||||
|
||||
def create_templates(self, tweet_template, dm_template, sent_dm_template, person_template):
|
||||
self.templates = templates(self.notebook, tweet_template=tweet_template, dm_template=dm_template, sent_dm_template=sent_dm_template, person_template=person_template)
|
||||
self.notebook.AddPage(self.templates, _("Templates"))
|
||||
|
||||
def create_sound(self, output_devices, input_devices, soundpacks):
|
||||
self.sound = sound(self.notebook, output_devices, input_devices, soundpacks)
|
||||
self.notebook.AddPage(self.sound, _(u"Sound"))
|
||||
|
@ -1 +1,2 @@
|
||||
from .tweetDialogs import tweet, reply, dm, viewTweet, viewNonTweet, poll
|
||||
from .tweetDialogs import tweet, reply, dm, viewTweet, viewNonTweet, poll
|
||||
from .templateDialogs import EditTemplateDialog
|
52
src/wxUI/dialogs/twitterDialogs/templateDialogs.py
Normal file
52
src/wxUI/dialogs/twitterDialogs/templateDialogs.py
Normal file
@ -0,0 +1,52 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import wx
|
||||
import output
|
||||
from typing import List
|
||||
|
||||
class EditTemplateDialog(wx.Dialog):
|
||||
def __init__(self, template: str, variables: List[str] = [], default_template: str = "", *args, **kwds) -> None:
|
||||
super(EditTemplateDialog, self).__init__(parent=None, title=_("Edit Template"), *args, **kwds)
|
||||
self.default_template = default_template
|
||||
mainSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
sizer_1 = wx.BoxSizer(wx.HORIZONTAL)
|
||||
mainSizer.Add(sizer_1, 1, wx.EXPAND, 0)
|
||||
label_1 = wx.StaticText(self, wx.ID_ANY, _("Edit template"))
|
||||
sizer_1.Add(label_1, 0, 0, 0)
|
||||
self.template = wx.TextCtrl(self, wx.ID_ANY, template)
|
||||
sizer_1.Add(self.template, 0, 0, 0)
|
||||
sizer_2 = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Available variables")), wx.HORIZONTAL)
|
||||
mainSizer.Add(sizer_2, 1, wx.EXPAND, 0)
|
||||
self.variables = wx.ListBox(self, wx.ID_ANY, choices=["$"+v for v in variables])
|
||||
self.variables.Bind(wx.EVT_CHAR_HOOK, self.on_keypress)
|
||||
sizer_2.Add(self.variables, 0, 0, 0)
|
||||
sizer_3 = wx.StdDialogButtonSizer()
|
||||
mainSizer.Add(sizer_3, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
|
||||
self.button_SAVE = wx.Button(self, wx.ID_SAVE)
|
||||
self.button_SAVE.SetDefault()
|
||||
sizer_3.AddButton(self.button_SAVE)
|
||||
self.button_CANCEL = wx.Button(self, wx.ID_CANCEL)
|
||||
sizer_3.AddButton(self.button_CANCEL)
|
||||
self.button_RESTORE = wx.Button(self, wx.ID_ANY, _("Restore template"))
|
||||
self.button_RESTORE.Bind(wx.EVT_BUTTON, self.on_restore)
|
||||
sizer_3.AddButton(self.button_CANCEL)
|
||||
sizer_3.Realize()
|
||||
self.SetSizer(mainSizer)
|
||||
mainSizer.Fit(self)
|
||||
self.SetAffirmativeId(self.button_SAVE.GetId())
|
||||
self.SetEscapeId(self.button_CANCEL.GetId())
|
||||
self.Layout()
|
||||
|
||||
def on_keypress(self, event, *args, **kwargs):
|
||||
if event.GetKeyCode() == wx.WXK_RETURN:
|
||||
self.template.ChangeValue(self.template.GetValue()+self.variables.GetStringSelection()+", ")
|
||||
output.speak(self.template.GetValue()+self.variables.GetStringSelection()+", ")
|
||||
return
|
||||
event.Skip()
|
||||
|
||||
def on_restore(self, *args, **kwargs) -> None:
|
||||
self.template.ChangeValue(self.default_template)
|
||||
output.speak(_("Restored template to {}.").format(self.default_template))
|
||||
self.template.SetFocus()
|
||||
|
||||
def invalid_template() -> None:
|
||||
wx.MessageDialog(None, _("the template you have specified include variables that do not exists for the object. Please fix the template and try again. For your reference, you can see a list of all available variables in the variables list while editing your template."), _("Invalid template"), wx.ICON_ERROR).ShowModal()
|
Loading…
Reference in New Issue
Block a user