Compare commits

...

101 Commits
v0.93 ... v0.94

Author SHA1 Message Date
Jose Manuel Delicado
52f27c87b9 Updated version to 0.94 2018-08-15 22:02:03 +02:00
3f5ef28a48 Updated info for a new Snapshot (coming soon) 2018-08-15 14:53:33 -05:00
4ec1e08606 Removed unneeded VLC plugins 2018-08-15 14:50:13 -05:00
f2cea695ee Play sound when a tweet has been sent and streaming is not available 2018-08-15 13:38:31 -05:00
e4a6ead606 Merge pull request #244 from Menelion/requirements
Make several modifications for better running from source
2018-08-15 12:38:36 -05:00
dc536c45de Fixed a few typos 2018-08-15 12:29:01 -05:00
95fcbe6ba4 Updated translations 2018-08-15 11:34:29 -05:00
60f55940b7 Updated translation templates 2018-08-15 11:22:51 -05:00
655331d405 Updated script for generating translation templates 2018-08-15 11:22:12 -05:00
4381992718 Made sound playback during startup as it was before 2018-08-15 11:19:31 -05:00
eb87d924c2 Setup.py: Fixed syntax error 2018-08-15 09:37:46 -05:00
1cebb29bdc Removed an output message from empty buffers 2018-08-15 05:08:25 -05:00
27c1ec990a Play sounds when updating buffers 2018-08-15 05:04:30 -05:00
d40b816c48 Started adding docstrings to buffer functions 2018-08-15 04:30:53 -05:00
ac5daec462 Set mandatory=True when updating buffers automatically to bypass 180 secs restriction 2018-08-15 04:30:27 -05:00
0835a34c71 Fixed a typo 2018-08-14 08:56:11 -05:00
babbc0a08d Updated changelog 2018-08-13 11:50:08 -05:00
04ac629b51 Added sent dm buffer working. Closes #233. Needs testing 2018-08-13 11:26:55 -05:00
Andre Polykanine
3920435eb7 Make several modifications for better running from source:
* Added a requirements file for easier dependencies installation
* Updated Gitignore to add VLC libraries (see #243)
* Updated the Readme file to reflect these changes.
2018-08-13 01:25:52 +03:00
2f0b20558e Create sent direct messages buffer during startup 2018-08-12 16:24:18 -05:00
9ca6e15a20 Added a new buffer for sen't dm. This will not be connected to any endpoint. #233 2018-08-12 16:23:45 -05:00
9c2dba7cf8 Added sent dm's to TWBlue settings #233 2018-08-12 16:23:07 -05:00
318b6caf5f Change type of vlc's environment variables 2018-08-12 16:19:15 -05:00
Jose Manuel Delicado
83612b6a3c Call os.chdir() before importing vlc, only if we are running from source. Restore the original current dir after that. Changed wx.NewId() calls to wx.ID_ANY 2018-08-12 14:50:58 +02:00
Jose Manuel Delicado
f4e20f8ed4 Load libvlccore.dll before importing the sound module 2018-08-12 13:38:39 +02:00
Jose Manuel Delicado
7883413210 When running from source, specify via two environment variables where is the vlc library located 2018-08-12 12:35:43 +02:00
Jose Manuel Delicado
ad54134c86 Updated windows dependencies and setup.py 2018-08-11 22:21:38 +02:00
Jose Manuel Delicado
ef0d3a9eae Updated readme 2018-08-11 22:03:49 +02:00
ea48733cef Updated changelog 2018-08-06 11:45:17 -05:00
6893d923a3 Don't put a sent dm in the buffer right after the event has been sent 2018-08-06 11:37:46 -05:00
d94b133e63 Update interval in buffers is configurable from global settings. Closes #223 2018-08-06 11:31:52 -05:00
28b6d554e2 Switched to new method for sending Direct messages #215 2018-07-25 11:22:57 -05:00
931cadfffa Modified Twython for sending data as json and added direct_messages/events/new #215 2018-07-25 11:11:20 -05:00
232d876c8f Allow Quoting and retweet from sent tweets. Closes #226. Fixes #238 2018-07-25 08:43:46 -05:00
c7f4fd2926 is_audio, find_urls and is_media should work with dm's #215 2018-07-20 10:04:53 -05:00
6b43ff1c0e Hide events buffer in accountSettingsDialog if streaming is disabled. Closes #227 2018-07-20 09:22:52 -05:00
5b5d762759 Fixed user actions from dm's buffer. Closes #237 2018-07-20 09:10:52 -05:00
b4020d0f95 Implemented get_more_items to dm's. Closes #235 2018-07-19 12:27:01 -05:00
d8da78e22d Fixed issue in database when storing dm's #215 2018-07-18 10:52:12 -05:00
c82bb4125b Removed sent direct messages from config. Closes #233 2018-07-18 10:34:08 -05:00
7b5e6477d3 Avoid putting sent dm's in the buffer as they are different to the new ones #215 2018-07-18 09:36:51 -05:00
41582a3770 Ignore dm's coming from streaming API as they are quite different. #215 2018-07-18 09:36:15 -05:00
e9cbe0d825 Created new dm's buffer for cursored results. Very unstable #215 2018-07-18 09:30:03 -05:00
dc563523bc Removed creation of sent direct messages buffer #215 2018-07-18 09:29:33 -05:00
b15eed9697 Added direct_messages/events/show and direct_messages/events/list in Twython #215 2018-07-18 09:29:00 -05:00
019e83c55b is_audio, is_geocoded, is_media, get_urls ignore dm's for now #215 2018-07-18 09:28:16 -05:00
7dad22189a Accept session object in all composers for searching users if needed #215 2018-07-18 09:27:37 -05:00
eebaf94cbf Modified cursored functions so they will match new endpoints #215 2018-07-18 09:27:02 -05:00
1726d5882c Added new parser for direct messages #215 2018-07-17 11:22:53 -05:00
64d843d98a Added helper for getting user object by id #232 2018-07-17 10:58:09 -05:00
610f18dcb6 Added all user objects to the local cache according to #232 2018-07-17 09:27:13 -05:00
cea638b680 Fixed a small isue 2018-07-13 17:29:54 -05:00
e1e0a4e092 Updated info for a new Snapshot 2018-06-18 04:37:56 -05:00
bc4a8bcba1 Check_connection: sets counter to 0 in the right conditional block 2018-06-17 19:38:29 -05:00
3db13062ed Fixed a few typos 2018-06-17 19:26:47 -05:00
9559f07013 Adds new VLC stuff in distributable file 2018-06-15 19:34:10 -05:00
dee30385cc Added VLC stuff (only x86 for now) to dependencies 2018-06-15 13:36:51 -05:00
49ce469c12 Don't display dialog when opening protected user's timeline. Closes #225 2018-06-15 13:32:12 -05:00
59e1299a0b Merge branch 'next-gen' of github.com:manuelcortez/TWBlue into next-gen 2018-06-15 08:46:12 -05:00
ab2667529f Added option to disable streaming from global settings. Closes #219 2018-06-15 08:45:10 -05:00
Jose Manuel Delicado
a7fd88b4be Updated Windows dependencies 2018-06-14 18:41:28 +02:00
a2cb4ba889 Fixed an issue related to high CPU Usage when Streaming is enabled. Closes #220 2018-06-06 11:14:42 -05:00
9847f7ad01 Get back to PIN code authorization due to Twitter changes. Closes #216 2018-06-06 09:11:37 -05:00
c2d81279fe Removed unneeded code 2018-06-06 08:23:07 -05:00
77489cab1e Sent dm's are added properly to the buffer if no streaming Enabled. Fixes #222 2018-05-29 17:35:04 -05:00
7d35dbc752 Stop using the Streaming API endpoints. Closes #213. Needs testing 2018-05-25 12:11:53 -05:00
f2ea4136c0 Skip creation of events buffer and made changes for #213. Closes #217 2018-05-25 12:11:17 -05:00
537d011b40 Remove support for multiple API calls in buffers. Closes #214 2018-05-25 11:35:24 -05:00
8af1e650b7 Added streaming_lives, wich will tell TWBlue if it should use Streaming Features or not 2018-05-25 09:46:39 -05:00
e3cbd8be87 Stop relying in home_timeline for everything. Fixes #171. Needs testing 2018-05-24 10:32:56 -05:00
7099875bc7 Added settings to turn off automatic speech or Braille feedback. #203 2018-05-18 13:38:58 -05:00
4a15fe1602 Add access keys to Spellchecking dialog. Closes #211 2018-05-16 10:22:54 -05:00
7478edd454 spellchecking dictionaries will be located in user's config directory. #208 2018-03-19 21:40:55 -06:00
da4658c220 Sessionmanager: Skip processing of dicts folder in user config. Needed for #208 2018-03-19 21:39:29 -06:00
6768bf85d5 Updated changelog 2018-03-19 21:38:25 -06:00
199a06c6e5 Move TWBlue to WX project phoenix (#207)
Move TWBlue to WX Python Phoenix
2018-03-19 01:55:09 -06:00
b967c32393 Updated readme 2018-03-14 15:24:44 -06:00
e9797ce6ac Updated menus 2018-03-14 15:16:27 -06:00
861de1f354 Moved about dialog and fixed a few bugs in tweet dialogs 2018-03-14 14:18:11 -06:00
6f838d12e9 Avoid converting items to string before passing to SetItem 2018-03-14 13:43:59 -06:00
010c0011aa Posted event codes and task bar icons 2018-03-14 13:34:56 -06:00
b1c5ddbca8 Display quoted tweets properly when original_tweet is made with Twishort 2018-03-14 11:34:49 -06:00
a16f16d36d Added additional checks for new filter improvements 2018-03-12 09:01:28 -06:00
e5196f0aad Changed chahracter limit for tweets in documentation 2018-03-12 09:00:52 -06:00
b8df56dcbb Updated changelog 2018-02-27 16:46:58 -06:00
612f4ffadf Filter by retweet, quotes and replies in filter creation #102 2018-02-27 16:43:16 -06:00
652d3c7ff8 Removed old function call. Closes #204 2018-02-27 13:57:28 -06:00
b6d49bb851 Removed unneded code 2018-02-21 16:22:19 -06:00
cb6f90a027 Use best audio stream for youtube videos 2018-02-21 16:21:20 -06:00
fff215fcdb Updated app info 2018-02-20 12:42:24 -06:00
8e9743cae1 Updated installation instructions 2018-02-20 11:52:53 -06:00
0e41fabbe6 Added youtube support. Closes #94 2018-02-20 11:47:33 -06:00
5ff5a4a6d2 youtube: Started code for playback from youtube. Not functionnal, yet 2018-02-16 17:58:57 -06:00
d4dadfcdc7 Added option for remembering state of mention all and long tweet 2018-02-06 17:37:49 -06:00
fac228dec1 Fixed a few issues 2018-02-06 16:47:47 -06:00
79490f8346 Set mention all checkbox disabled by default 2018-02-06 16:44:36 -06:00
635b467394 Fixed item ordering issue in reversed buffers for people objects 2018-02-06 15:18:42 -06:00
e886090830 Removed unneeded print 2018-01-31 17:15:23 -06:00
80cb5567d5 Show error messages in failed audio uploads. Hopefully Fixes api uploads in sndup 2018-01-31 17:12:43 -06:00
3c0824aad4 Added toggle likes to keystroke editor 2018-01-12 08:36:14 -06:00
0bbbb3f1b6 Merged like/unlike action for windows 10 users in invisible interface 2018-01-10 09:25:27 -06:00
134 changed files with 19793 additions and 30507 deletions

View File

@@ -1,5 +1,5 @@
Tw Blue is free software, licensed under the GNU GPL license, either version 2 or, at your option, any later version. You can view the license in the file named license.txt, or online at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html.
Copyright © 2013-2015. Manuel Cortéz
Copyright © 2013-2018. Manuel Cortéz
Documentation is written by Sukil Etxenike, Brian Hartgen and Bill Dengler, covered by the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 license. You can read the license at https://creativecommons.org/licenses/by-nc-sa/2.5/

View File

@@ -1,7 +1,7 @@
TWBlue -
======
TW Blue is an app designed to use Twitter simply and efficiently while using minimal system resources.
TW Blue is an app designed to use Twitter simply and efficiently while using minimal system resources.
With this app youll have access to twitter features such as:
* Create, reply to, like, retweet and delete tweets,
@@ -29,50 +29,39 @@ Although most dependencies can be found in the windows-dependencies directory, w
#### Dependencies packaged in windows installers
* [Python,](http://python.org) version 2.7.14
* [Python,](http://python.org) version 2.7.15
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python27 and python x64 to C:\python27x64, for example.
* [wxPython](http://www.wxpython.org) for Python 2.7, version 3.0.2.0
* [Python windows extensions (pywin32)](http://www.sourceforge.net/projects/pywin32/) for python 2.7, build 221
* [Python windows extensions (pywin32)](http://www.sourceforge.net/projects/pywin32/) for python 2.7, build 223
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
The windows installers are available only in the windows-dependencies folder
The windows installers are available only in the windows-dependencies folder.
To build a binary version:
* [Py2exe](http://www.sourceforge.net/projects/py2exe/) for Python 2.7, version 0.6.9
#### Dependencies that must be installed using easy_install
#### Dependencies that must be installed using pip
setuptools installs a script, called easy_install. You can find it in the python scripts directory. To install packages using easy_install, you have to navigate to the scripts directory using a command prompt, for example:
Python installs a tool called Pip that allows to install packages in a simple way. You can find it in the python scripts directory. To install packages using Pip, you have to navigate to the scripts directory using a command prompt, for example:
cd C:\python27x64\scripts
You can also add the scripts folder to your path environment variable.
You can also add the scripts folder to your path environment variable or choose the corresponding option when installing Python.
Note: pip and setuptools are included in the Python installer since version 2.7.9.
After that, run the following command to install a package, replacing packagename with the names listed below:
Pip is able to install packages listed in a special text file, called the requirements file. To install all remaining dependencies, perform the following command:
easy_install -Z package
pip install -r requirements.txt
The -z switch unzips the package, instead of installing it compressed. If you add the --upgrade switch, you can upgrade a package to its latest version. The following packages need to be installed:
Note that if you perform the command from the path where Pip is located, you need to specify the path to your Tw Blue root folder where the requirements file is located, for example:
* pypubsub==3.3.0
* configobj
* requests-oauthlib
* requests-toolbelt
* future
* pygeocoder
* arrow
* markdown
* winpaths
* PySocks
* win_inet_pton
* yandex.translate
pip install -r D:\repos\TwBlue\requirements.txt
easy_install will automatically get the additional libraries that these packages need to work properly.
Run the following command to quickly install and upgrade all packages and their dependencies:
easy_install -Z --upgrade six configobj markdown future requests oauthlib requests-oauthlib requests-toolbelt pypubsub==3.3.0 pygeocoder arrow python-dateutil futures winpaths PySocks win_inet_pton yandex.translate idna chardet urllib3
Pip will automatically get the additional libraries that the listed packages need to work properly.
If you need to update your dependencies, perform the following command:
pip install --upgrade -r requirements.txt
#### Other dependencies
@@ -82,16 +71,17 @@ These dependencies are located in the windows-dependencies directory. You don't
This dependency has been built using pure basic 4.61. Its source can be found at http://hg.q-continuum.net/updater
* [oggenc2.exe,](http://www.rarewares.org/ogg-oggenc.php) version 2.87
* Microsoft Visual c++ 2008 redistributable dlls.
* VLC plugins and DLL libraries.
#### Dependencies required to build the installer
* [NSIS,](http://nsis.sourceforge.net/) version 3.02.1
* [NSIS,](http://nsis.sourceforge.net/) version 3.03
#### Dependencies required to build the portableApps.com format archive
* [NSIS Portable,](http://portableapps.com/apps/development/nsis_portable) version 3.02.1
* [NSIS Portable,](http://portableapps.com/apps/development/nsis_portable) version 3.03
* [PortableApps.com Launcher,](http://portableapps.com/apps/development/portableapps.com_launcher) version 2.2.1
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.5.5
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.5.8
Important! Install these 3 apps into the same folder, otherwise you won't be able to build the pa.c version. For example: D:\portableApps\NSISPortable, D:\PortableApps\PortableApps.com installer, ...
@@ -101,19 +91,21 @@ In order to add the support for spell checking in more languages than english yo
### Running TW Blue from source
Now that you have installed all these packages, you can run TW Blue from source using a command prompt. Navigate to the repo's src directory, and type the following command:
Now that you have installed all these packages, you can run TW Blue from source using a command prompt. Navigate to the repo's `src` directory, and type the following command:
python main.py
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64
If necessary, change the first part of the command to reflect the location of your python executable. You can run TW Blue using python x86 and x64.
### Generating the documentation
To generate the documentation in html format, navigate to the doc folder inside this repo. After that, run these commands:
python document_importer.py
python generator.py
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example de, en, es, fr, it, ...) to src/documentation, creating the directory if necesary.
Also, copy the license.txt located in the root of the repo to the documentation folder.
python document_importer.py
python generator.py
The documentation will be generated, placing each language in a separate folder in the doc directory. Move these folders (for example `de`, `en`, `es`, `fr`, `it`, ...) to `src/documentation`, creating the directory if necessary.
Also, copy the `license.txt` file located in the root of the repo to the documentation folder.
### Building a binary version

View File

@@ -2,7 +2,7 @@
name = 'TWBlue'
snapshot = False
if snapshot == False:
version = "0.93"
version = "0.94"
update_url = 'http://twblue.es/updates/twblue_ngen.json'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
else:

View File

@@ -2,6 +2,28 @@
## changes in this version
* Added an option in the global settings dialog to disable the Streaming features of TWBlue. TWBlue will remove all Streaming features after August 16, so this option will give people an idea about how it will be. ([#219](https://github.com/manuelcortez/TWBlue/issues/219))
* Due to Twitter API changes, Switched authorisation method to Pin-code based authorisation. When you add new accounts to TWBlue, you will be required to paste a code displayed in the Twitter website in order to grant access to TWBlue. ([#216](https://github.com/manuelcortez/TWBlue/issues/216))
* In order to comply with latest Twitter changes, TWBlue has switched to the new method used to send and receive direct messages, according to issue [#215.](https://github.com/manuelcortez/twblue/issues/215)
* The new method does not allow direct messages to be processed in real time. Direct messages will be updated periodically.
* After august 16 or when streaming is disabled, the events buffer will no longer be created in TWBlue.
* You can configure frequency for buffer updates in TWBlue. By default, TWBlue will update all buffers every 2 minutes, but you can change this setting in the global settings dialog. ([#223](https://github.com/manuelcortez/TWBlue/issues/223))
* Added a new tab called feedback, in the account settings dialog. This tab allows you to control wether automatic speech or Braille feedbak in certain events (mentions and direct messages received) is enabled. Take into account that this option will take preference over automatic reading of buffers and any kind of automatic output. ([#203](https://github.com/manuelcortez/TWBlue/issues/203))
* The spell checking dialog now has access keys defined for the most important actions. ([#211](https://github.com/manuelcortez/TWBlue/issues/211))
* TWBlue now Uses WXPython 4.0.1. This will allow us to migrate all important components to Python 3 in the future. ([#207](https://github.com/manuelcortez/TWBlue/issues/207))
* When you quote a Tweet, if the original tweet was posted with Twishort, TWBlue should display properly the quoted tweet. Before it was displaying the original tweet only. ([#206](https://github.com/manuelcortez/TWBlue/issues/206))
* It is possible to filter by retweets, quotes and replies when creating a new filter.
* Added support for playing youtube Links directly from the client. ([#94](https://github.com/manuelcortez/TWBlue/issues/94))
* Replaced Bass with libVLC for playing URL streams.
* the checkbox for indicating wether TWBlue will include everyone in a reply or not, will be unchecked by default.
* You can request TWBlue to save the state for two checkboxes: Long tweet and mention all, from the global settings dialogue.
* For windows 10 users, some keystrokes in the invisible user interface have been changed or merged:
* control+Windows+alt+F will be used for toggling between adding and removing a tweet to user's likes. This function will execute the needed action based in the current status for the focused tweet.
* TWBlue will show an error if something goes wrong in an audio upload.
* And more. ([#171,](https://github.com/manuelcortez/TWBlue/issues/171)
## Changes in version 0.93
* A new soundpack has been added to TWBlue. Thanks to [@ValeriaK305](https://twitter.com/ValeriaK305)
* In the Windows 10 keymap, we have changed some default keystrokes as windows now uses some previously assigned shortcuts:
* For liking a tweet, press Control+Windows+alt+f

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: TW Blue documentation 0.89\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2017-03-25 15:15+0100\n"
"Last-Translator: Joan Rabat <joanrabat@hotmail.com>\n"
"Language-Team: Francisco Torres Gallego <frantorresgallego@gmail.com>\n"
@@ -114,9 +114,10 @@ msgid "## Usage"
msgstr "##funcionament"
#: ../doc/strings.py:21
#, fuzzy
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
@@ -521,9 +522,10 @@ msgid "#### Buttons in the application"
msgstr "###Botons en l'aplicació."
#: ../doc/strings.py:65
#, fuzzy
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: TWBlue Documentation\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-07-09 10:41+0200\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-08 11:01+0200\n"
"Last-Translator: Steffen Schultz <schulle3o@yahoo.de>\n"
"Language-Team: Steffen Schultz <schulle3o@yahoo.de>\n"
"Language: de\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 2.0.2\n"
"X-Generator: Poedit 2.0.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: ../doc/strings.py:3
@@ -111,17 +111,17 @@ msgstr "## Verwendung"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"Twitter ist ein soziales Netzwerk oder Micro-Blog, welches das Verfassen von "
"Status-Nachrichten von nicht mehr als 140 Zeichen Länge erlaubt. Dieser "
"Dienst ist perfekt für Freunde, Familien und Mitarbeiter, um schnell und "
"regelmäßig Kurznachrichten auszutauschen. Die Nachrichten können dabei allen "
"zugänglich gemacht oder nur auf den Freundeskreis beschränkt werden."
"Status-Nachrichten von bis zu 280 Zeichen Länge erlaubt. Dieser Dienst ist "
"perfekt für Freunde, Familien und Mitarbeiter, um schnell und regelmäßig "
"Kurznachrichten auszutauschen. Die Nachrichten können dabei allen zugänglich "
"gemacht oder nur auf den Freundeskreis beschränkt werden."
#: ../doc/strings.py:22
msgid ""
@@ -527,7 +527,7 @@ msgstr "#### Schaltflächen der Anwendung"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -541,7 +541,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* Tweet: Diese Schaltfläche öffnet einen Dialog zum Verfassen eines neuen "
"Tweets. Die Nachricht darf normalerweise 140 Zeichen nicht überschreiten, "
"Tweets. Die Nachricht darf normalerweise 280 Zeichen nicht überschreiten, "
"kann jedoch durch aktivieren der Checkbox \"Langer Tweet\" über den Twishort-"
"Dienst gesendet werden (maximal 10000 Zeichen). Geht eine Nachricht darüber "
"hinaus, kennzeichnet TWBlue dies durch einen Warnklang. Die Anzahl der "

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: twblue-documentation 0.84\n"
"POT-Creation-Date: 2017-12-06 15:59+Hora estndar central (Mxico)\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2017-01-18 09:13-0600\n"
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
@@ -116,9 +116,10 @@ msgid "## Usage"
msgstr "## Uso"
#: ../doc/strings.py:21
#, fuzzy
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
@@ -552,9 +553,10 @@ msgid "#### Buttons in the application"
msgstr "#### Botones de la aplicación"
#: ../doc/strings.py:65
#, fuzzy
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "

File diff suppressed because it is too large Load Diff

View File

@@ -5,7 +5,7 @@
msgid ""
msgstr ""
"Project-Id-Version: TW Blue documentation 0.46\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2015-11-27 08:33-0600\n"
"Last-Translator: Manuel Cortéz <manuel@manuelcortez.net>\n"
"Language-Team: Sukil Echenique <sukiletxe@yahoo.es>\n"
@@ -116,9 +116,10 @@ msgid "## Usage"
msgstr " Nola erabili"
#: ../doc/strings.py:21
#, fuzzy
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
@@ -446,7 +447,7 @@ msgstr "&Aplikazioa"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: TW Blue documentation 0.88\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-18 16:32+0100\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-11 12:25+0200\n"
"Last-Translator: Rémy Ruiz <remyruiz@gmail.com>\n"
"Language-Team: Rémy Ruiz <remyruiz@gmail.com>\n"
"Language: fr\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.8.9\n"
"X-Generator: Poedit 1.8.12\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
@@ -120,14 +120,14 @@ msgstr "## Utilisation"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"Twitter est un réseau social qui vous permet de créer vos mises à jour du "
"statut de vos activités en 140 caractères ou moins. Twitter est un moyen de "
"statut de vos activités en 280 caractères ou moins. Twitter est un moyen de "
"rester connecté avec vos amis, famille et collègues de travail à travers de "
"l'échange de messages courts. Vous pouvez restreindre vos mises à jour afin "
"que seuls vos amis puissent les voir, ou permettre à quiconque de les voir. "
@@ -568,7 +568,7 @@ msgstr "#### Boutons dans l'application"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -582,7 +582,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* Tweet: Ce bouton ouvre la boîte de dialogue pour écrire un tweet. Le "
"message ne doit pas dépasser au-delà de 140 caractères. Cependant, vous "
"message ne doit pas dépasser au-delà de 280 caractères. Cependant, vous "
"pouvez appuyer sur la case à cocher Long tweet et votre tweet sera affiché "
"via Twishort qui vous permettra d'écrire des tweets plus longs (10000 "
"caractères). Si vous écrivez au-delà de cette limite, un son sera joués pour "
@@ -1093,7 +1093,7 @@ msgid ""
"* Play/pause: try to play audio for the selected item (if available), or "
"stop the currently played audio."
msgstr ""
"* Lecture/Pause: essayez de lire l'audio de l'élément sélectionné (si "
"* Lecture / Pause: essayez de lire l'audio de l'élément sélectionné (si "
"disponible) ou arrêtez l'audio actuellement en cours de lecture."
#: ../doc/strings.py:117
@@ -1478,13 +1478,13 @@ msgstr "* Contrôle+Windows+Maj+A: Supprimer l'utilisateur de la liste."
#: ../doc/strings.py:187
msgid "* Control + Windows + Shift + M: Mute / unmute the current buffer."
msgstr ""
"* Contrôle+Windows+Maj+M: Activer muet /désactiver muet dans le tampon "
"* Contrôle+Windows+Maj+M: Activer muet / désactiver muet dans le tampon "
"actuel."
#: ../doc/strings.py:188
msgid "* Windows + Alt + M: Mute / unmute the current session."
msgstr ""
"* Windows +Alt+M: : Activer muet /désactiver muet dans la session actuelle."
"* Windows +Alt+M: : Activer muet / désactiver muet dans la session actuelle."
#: ../doc/strings.py:189
msgid ""

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: tw blue documentation 0.46\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-20 16:44+0100\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-08 11:34+0100\n"
"Last-Translator: Juan C. Buño <oprisniki@gmail.com>\n"
"Language-Team: Alba Quinteiro <alba_080695@hotmail.com>\n"
"Language: gl\n"
@@ -117,18 +117,19 @@ msgstr "## Uso"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"Twitter é unha rede social que che permite crear actualizacións de estado "
"sobre as túas actividades nun máximo de 140 caracteres. Twitter é un xeito "
"de manterte conectado cos teus amigos, familiares e compañeiros de traballo "
"a través do intercambio de mensaxes curtas. Podes restrinxir as túas "
"actualizacións para que só as vexan os teus amigos, ou permitir que calquera "
"poda velas. Esta segunda opción é o comportamento por defecto de Twitter."
"Twitter é unha rede social ou ferramenta de micro-blogging que che permite "
"compoñer curtas actualizacións de estado das túas actividades en 280 "
"caracteres ou menos. Twitter é un xeito para que amigos, familiares e "
"compañeiros de traballo se comuniquen e permanezan conectados a través do "
"intercambio de mensaxes rápidas e frecuentes. Podes restrinxir a entrega de "
"actualizacións aos membros do teu círculo de amigos ou, de xeito "
"predeterminado, permitir que calquera persoa teña aceso a elas."
#: ../doc/strings.py:22
msgid ""
@@ -546,7 +547,7 @@ msgstr "#### Botóns na aplicación"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -559,20 +560,20 @@ msgid ""
"hear a sound confirming it. Otherwise, the screen reader will speak an error "
"message in English describing the problem."
msgstr ""
"* Chío: este botón abre unha Caixa de diálogo para escreber o teu chío. Os "
"chíos normais non deben pasar dos 140 carácteres. Non obstante podes premer "
"a Caixa de verificación Chíos Longos e o chío publicarase a través do "
"Twishort, o que che permitirá escribir chíos máis longos (10000 carácteres). "
"Se te pasas escrebindo este límite, reproducirase un son para avisarte. Ten "
"en conta que a conta de carácteres amósase na barra de título. Poderás usar "
"os botón acurtar e expandir URL para aumentar os límites de carácteres. "
"Podes descargar un gráfico, correxir a ortografía, engadir audio ou traducir "
"a túa mensaxe seleccionando un dos botón disponibles na Caixa de diálogo. "
"Ademáis, podes autocompletar a introducción de usuarios premendo Alt + C ou "
"o botón para ese propósito se tes a base de datos de usuarios configurada. "
"Preme intro para enviar o chío. Se todo foi ben, escoitarás un son "
"confirmándocho. De outro xeito, o lector de pantallas falará unha mensaxe de "
"erro en inglés descrebindo o problema."
"* Chío: este botón abre una Caixa de diálogo para escreber os teus chíos. Os "
"chíos normais non deben exceder de 280 caracteres. Non obstante podes premer "
"a Caixa de verificación chíos longos e os teus chíos publicaránse a través "
"de Twishort, o que che permite escreber chíos máis longos (10000 "
"caracteres). Se escrebes pasando este límite, reproducirase un son para "
"advertirte. Ten en conta que o reconto de caracteres amósase na barra de "
"título. Podes usar os botons de acurtar e expandir URL para cumplir co "
"límite de caracteres. Podes cargar una imaxe, correxir a ortografía, "
"adxuntar audio ou traducir a túa mensaxe seleccionando un dos botóns "
"disponibles na caixa de diálogo. Ademáis, podes autocompretar a introducción "
"de usuarios premendo Alt + C ou o botón para ese propósito se tes a base de "
"datos de usuarios configurada. Preme intro para enviar o chío. Se todo foi "
"ben, escoitarás un son confirmándoo. Doutro xeito, o lector de pantalla "
"falará una mensaxe de erro en inglés descrebindo o problema."
#: ../doc/strings.py:66
msgid ""

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: TW Blue documentation 0.46\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-24 14:35+0100\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-09 11:51+0100\n"
"Last-Translator: Chris Leo Mameli <llajta2012@gmail.com>\n"
"Language-Team: \n"
"Language: it\n"
@@ -116,19 +116,19 @@ msgstr "## Caratteristiche"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"Twitter è un social network o strumento di micro-blogging che consente di "
"pubblicare gli aggiornamenti di stato delle vostre attività in 140 caratteri "
"o meno. È un modo per comunicare con amici, parenti, colleghi e rimanere in "
"contatto attraverso lo scambio frequente e rapido di messaggi. È possibile "
"limitare la visualizzazione degli aggiornamenti alla tua cerchia di amici o, "
"modificando come impostazione predefinita, consentire a chiunque di "
"accedervi."
"aTwitter è un social network o strumento di micro-blogging che consente di "
"pubblicare gli aggiornamenti di stato delle vostre attività con un massimo "
"di 180 caratteri. È un modo per comunicare con amici, parenti, colleghi e "
"restare in contatto attraverso lo scambio frequente e rapido di messaggi. È "
"possibile limitare la visualizzazione degli aggiornamenti alla tua cerchia "
"di amici o, modificando come impostazione predefinita, consentire a chiunque "
"di accedervi."
#: ../doc/strings.py:22
msgid ""
@@ -533,7 +533,7 @@ msgstr "#### Pulsanti dell'applicazione"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -547,7 +547,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* Twit: Questo pulsante apre una finestra di dialogo per digitare un tweet. "
"Il limite è 140 caratteri. Tuttavia, è possibile scrivere tweet lunghi "
"Il limite è 180 caratteri. Tuttavia, è possibile scrivere tweet lunghi "
"selezionando la casella di controllo apposita che attiva Twishort(il limite "
"in questo caso sarà 10000 caratteri). Quando si supera il limite, verrà "
"riprodotto un suono di avviso. Il numero dei caratteri digitati viene "

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: \n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-23 00:07+0900\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-08 19:09+0900\n"
"Last-Translator: Masamitsu Misono <misono@nvsupport.org>\n"
"Language-Team: NVDA Help Desk <nvdahelp@center-aikoh.net>\n"
"Language: ja_JP\n"
@@ -14,12 +14,12 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.8.7\n"
"X-Generator: Poedit 2.1.1\n"
"Plural-Forms: nplurals=1; plural=0;\n"
#: ../doc/strings.py:3
msgid "Documentation for TWBlue - 0.88"
msgstr "TWBlue 0.88 取扱説明書"
msgstr "TWBlue - 0.88 取扱説明書"
#: ../doc/strings.py:4
msgid "## Table of contents"
@@ -31,7 +31,7 @@ msgstr "[TOC]"
#: ../doc/strings.py:6
msgid "## Warning!"
msgstr "## 警告"
msgstr "## 警告!"
#: ../doc/strings.py:7
msgid ""
@@ -112,17 +112,17 @@ msgstr "## 使い方"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"ツイッターは、ソーシャルネットワークまたは小さなブログのようなもので、自分の"
"活動を文字以下で登校することができるツールです。ツイッターは、友達や家"
"族、同僚とコミュニケーションをとったり、接続を維持して、頻繁に素早くメッセー"
"ジを交換するための一つの方法です。あなたは、友人とのサークルなどのように、公"
"開範囲を制限するか、だれでもツイートをみえるようにすることができます。"
"活動を280文字以下で登校することができるツールです。ツイッターは、友達や家族、"
"同僚とコミュニケーションをとったり、接続を維持して、頻繁に素早くメッセージを"
"交換するための一つの方法です。あなたは、友人とのサークルなどのように、公開範"
"囲を制限するか、だれでもツイートをみえるようにすることができます。"
#: ../doc/strings.py:22
msgid ""
@@ -528,7 +528,7 @@ msgstr "#### アプリケーション上のボタン"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -542,7 +542,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* ツイート: このボタンはツイートを書き込むためのダイアログボックスを開きま"
"す。メッセージは140字以内です。書き込み字数が制限を超過した場合は警告音が鳴り"
"す。メッセージは280字以内です。書き込み字数が制限を超過した場合は警告音が鳴り"
"ます。タイトルバーには文字カウントを表示します。ツイートを短縮して投稿に"
"チェックを入れると、1万文字までのツイートをTwishortを経由して、投稿できます。"
"画像をアップロードボタンや、スペルチェックボタンや音声を添付ボタンを押すと、"

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: twblue-documentation 0.46\n"
"POT-Creation-Date: 2017-01-18 08:42+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-23 09:55+0200\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-08 10:32+0300\n"
"Last-Translator: Florian Ionașcu <florianionascu@hotmail.com>\n"
"Language-Team: Spanish <manuel@manuelcortez.net>\n"
"Language: ro\n"
@@ -14,7 +14,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: pygettext.py 1.5\n"
"X-Generator: Poedit 1.8.9\n"
"X-Generator: Poedit 2.0.6\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Poedit-SourceCharset: UTF-8\n"
@@ -115,9 +115,10 @@ msgid "## Usage"
msgstr "## Utilizare"
#: ../doc/strings.py:21
#, fuzzy
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
@@ -523,7 +524,7 @@ msgstr "#### Butoane în aplicație"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -537,7 +538,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* Postare: acest buton deschide o casetă de dialog pentru a vă scrie "
"postarea. Postările normale nu trebuie să depășească 140 de caractere. "
"postarea. Postările normale nu trebuie să depășească 280 de caractere. "
"Totuși, puteți bifa caseta postare lungă, iar postarea dumneavoastră va fi "
"postată prin Twishort, care vă permite să scrieți postări lungi (10000 de "
"caractere). Dacă depășiți această limită, se va reda un sunet pentru a vă "

File diff suppressed because it is too large Load Diff

View File

@@ -5,8 +5,8 @@
msgid ""
msgstr ""
"Project-Id-Version: TW Blue documentation 0.46\n"
"POT-Creation-Date: 2017-12-06 15:59+Hora estndar central (Mxico)\n"
"PO-Revision-Date: 2017-01-18 18:50+0400\n"
"POT-Creation-Date: 2018-08-07 13:19+Hora de verano central (Mexico)\n"
"PO-Revision-Date: 2018-08-14 21:44+0400\n"
"Last-Translator: Valeria <luciana.lu3a@gmail.com>\n"
"Language-Team: \n"
"Language: ru\n"
@@ -117,14 +117,14 @@ msgstr "## Использование"
#: ../doc/strings.py:21
msgid ""
"Twitter is a social networking or micro-blogging tool which allows you to "
"compose short status updates of your activities in 140 characters or less. "
"compose short status updates of your activities in 280 characters or less. "
"Twitter is a way for friends, family and co-workers to communicate and stay "
"connected through the exchange of quick, frequent messages. You can restrict "
"delivery of updates to those in your circle of friends or, by default, allow "
"anyone to access them."
msgstr ""
"Твиттер - это социальная сеть или инструмент для микро-блоггинга, "
"позволяющий создавать короткие, не более 140 символов заметки. Твиттер - это "
"позволяющий создавать короткие, не более 280 символов заметки. Твиттер - это "
"возможность общаться с друзьями, членами семьи и коллегами, обмениваясь "
"быстрыми, короткими сообщениями, и оставаясь всегда на связи. Обновления "
"можно ограничить только для круга друзей или, как выбрано по умолчанию, "
@@ -541,7 +541,7 @@ msgstr "#### Кнопки приложения"
#: ../doc/strings.py:65
msgid ""
"* Tweet: this button opens up a dialogue box to write your tweet. Normal "
"tweets must not exceed 140 characters. However you can press the long tweet "
"tweets must not exceed 280 characters. However you can press the long tweet "
"checkbox and your tweet will be posted throught Twishort, wich will allow "
"you to write longer tweets (10000 characters). If you write past this limit, "
"a sound will play to warn you. Note that the character count is displayed in "
@@ -555,7 +555,7 @@ msgid ""
"message in English describing the problem."
msgstr ""
"* Твит: этой кнопкой открывается диалоговое окно для написания твита. Длина "
"обычного сообщения не должна превышать 140 символов. Однако, можно отметить "
"обычного сообщения не должна превышать 280 символов. Однако, можно отметить "
"флажок длинный твит и ваша запись будет отправлена через сервис Twishort, "
"позволяющий отправлять более длинные сообщения (10000 символов). Если вы "
"привысите лимит, прозвучит предупреждающий сигнал. Обратите внимание, что "

View File

@@ -26,7 +26,7 @@ TWBlue is an application to make Twitter simple and fast, while using as few res
## Usage
Twitter is a social networking or micro-blogging tool which allows you to compose short status updates of your activities in 140 characters or less. Twitter is a way for friends, family and co-workers to communicate and stay connected through the exchange of quick, frequent messages. You can restrict delivery of updates to those in your circle of friends or, by default, allow anyone to access them.
Twitter is a social networking or micro-blogging tool which allows you to compose short status updates of your activities in 280 characters or less. Twitter is a way for friends, family and co-workers to communicate and stay connected through the exchange of quick, frequent messages. You can restrict delivery of updates to those in your circle of friends or, by default, allow anyone to access them.
You can monitor the status of updates from your friends, family or co-workers (known as following), and they in turn can read any updates you create, (known as followers). The updates are referred to as Tweets. The Tweets are posted to your Twitter profile or Blog and are searchable using Twitter Search.
@@ -98,7 +98,7 @@ In summary, the GUI contains two core components. These are the controls you wil
#### Buttons in the application
* Tweet: this button opens up a dialogue box to write your tweet. Normal tweets must not exceed 140 characters. However you can press the long tweet checkbox and your tweet will be posted throught Twishort, wich will allow you to write longer tweets (10000 characters). If you write past this limit, a sound will play to warn you. Note that the character count is displayed in the title bar. You may use the shorten and expand URL buttons to comply with the character limit. You can upload a picture, check spelling, attach audio or translate your message by selecting one of the available buttons in the dialogue box. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will speak an error message in English describing the problem.
* Tweet: this button opens up a dialogue box to write your tweet. Normal tweets must not exceed 280 characters. However you can press the long tweet checkbox and your tweet will be posted throught Twishort, wich will allow you to write longer tweets (10000 characters). If you write past this limit, a sound will play to warn you. Note that the character count is displayed in the title bar. You may use the shorten and expand URL buttons to comply with the character limit. You can upload a picture, check spelling, attach audio or translate your message by selecting one of the available buttons in the dialogue box. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured. Press enter to send the tweet. If all goes well, you'll hear a sound confirming it. Otherwise, the screen reader will speak an error message in English describing the problem.
* Retweet: this button retweets the message you're reading. After you press it, if you haven't configured the application not to do so, you'll be asked if you want to add a comment or simply send it as written. If you choose to add a comment, it will post a quoted tweet, that is, the comment with a link to the originating tweet.
* Reply: when you're viewing a tweet, you can reply to the user who sent it by pressing this button. A dialogue will open up similar to the one for tweeting. If there are more users referred to in the tweet, you can press tab and activate the mention to all checkbox, or enabling checkbox for the users you want to mention separately. When you're on the friends or followers lists, the button will be called mention instead.
* Direct message: exactly like sending a tweet, but it's a private message which can only be read by the user you send it to. Press shift-tab twice to see the recipient. If there were other users mentioned in the tweet you were reading, you can arrow up or down to choose which one to send it to, or write the username yourself without the at sign. In addition, you can autocomplete the entering of users by pressing Alt + C or the button for that purpose if you have the database of users configured.

View File

@@ -20,8 +20,8 @@ CommercialUse=true
EULAVersion=2
[Version]
PackageVersion=0.93.0.0
DisplayVersion=0.93
PackageVersion=0.94.0.0
DisplayVersion=0.94
[Control]
Icons=1

23
requirements.txt Normal file
View File

@@ -0,0 +1,23 @@
wxpython
six
configobj
markdown
future
requests
oauthlib
requests-oauthlib
requests-toolbelt
pypubsub==3.3.0
pygeocoder
arrow
python-dateutil
futures
winpaths
PySocks
win_inet_pton
yandex.translate
idna
chardet
urllib3
youtube-dl
python-vlc

View File

@@ -14,11 +14,11 @@ SetCompress auto
SetCompressor /solid lzma
SetDatablockOptimize on
VIAddVersionKey ProductName "TWBlue"
VIAddVersionKey LegalCopyright "Copyright 2016 Manuel Cortéz."
VIAddVersionKey ProductVersion "0.93"
VIAddVersionKey FileVersion "0.93"
VIProductVersion "0.93.0.0"
VIFileVersion "0.93.0.0"
VIAddVersionKey LegalCopyright "Copyright 2018 Manuel Cortéz."
VIAddVersionKey ProductVersion "0.94"
VIAddVersionKey FileVersion "0.94"
VIProductVersion "0.94.0.0"
VIFileVersion "0.94.0.0"
!insertmacro MUI_PAGE_WELCOME
!define MUI_LICENSEPAGE_RADIOBUTTONS
!insertmacro MUI_PAGE_LICENSE "license.txt"
@@ -72,10 +72,10 @@ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "D
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.93"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.94"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 93
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 94
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
SectionEnd

View File

@@ -9,12 +9,11 @@ relative_times = boolean(default=True)
max_api_calls = integer(default=1)
max_tweets_per_call = integer(default=100)
reverse_timelines = boolean(default=False)
time_to_check_streams = integer(default=30)
announce_stream_status = boolean(default=True)
retweet_mode = string(default="ask")
persist_size = integer(default=0)
show_screen_names = boolean(default=False)
buffer_order = list(default=list('home','mentions','dm','sent_dm','sent_tweets','favorites','followers','friends','blocks','muted','events'))
buffer_order = list(default=list('home','mentions', 'dm', 'sent_dm', 'sent_tweets','favorites','followers','friends','blocks','muted','events'))
[sound]
volume = float(default=1.0)
@@ -44,4 +43,8 @@ save_followers_in_autocompletion_db = boolean(default=False)
save_friends_in_autocompletion_db = boolean(default=False)
ocr_language = string(default="")
[reporting]
braille_reporting = boolean(default=True)
speech_reporting = boolean(default=True)
[filters]

View File

@@ -5,6 +5,7 @@ ignored_sessions = list(default=list())
[app-settings]
language = string(default="system")
update_period = integer(default=2)
hide_gui = boolean(default=False)
voice_enabled = boolean(default=False)
ask_at_exit = boolean(default=True)
@@ -17,6 +18,10 @@ log_level = string(default="error")
load_keymap = string(default="default.keymap")
donation_dialog_displayed = boolean(default=False)
check_for_updates = boolean(default=True)
remember_mention_and_longtweet = boolean(default=False)
longtweet = boolean(default=false)
mention_all = boolean(default=False)
no_streaming = boolean(default=False)
[proxy]
type = string(default="Direct connection")

View File

@@ -1,19 +1,35 @@
# -*- coding: utf-8 -*-
import datetime
name = 'TWBlue'
snapshot = False
if snapshot == False:
version = "0.93"
version = "0.94"
update_url = 'https://twblue.es/updates/stable.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
else:
version = "3"
version = "8"
update_url = 'https://twblue.es/updates/snapshot.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
authorEmail = "manuel@manuelcortez.net"
copyright = u"Copyright (C) 2013-2017, Manuel cortéz."
copyright = u"Copyright (C) 2013-2018, Manuel cortéz."
description = unicode(name+" is an app designed to use Twitter simply and efficiently while using minimal system resources. This app provides access to most Twitter features.")
translators = [u"Manuel Cortéz (English)", u"Mohammed Al Shara, Hatoun Felemban (Arabic)", u"Francisco Torres (Catalan)", u"Manuel cortéz (Spanish)", u"Sukil Etxenike Arizaleta (Basque)", u"Jani Kinnunen (finnish)", u"Rémy Ruiz (French)", u"Juan Buño (Galician)", u"Steffen Schultz (German)", u"Zvonimir Stanečić (Croatian)", u"Robert Osztolykan (Hungarian)", u"Christian Leo Mameli (Italian)", u"Riku (Japanese)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Florian Ionașcu, Nicușor Untilă (Romanian)", u"Natalia Hedlund, Valeria Kuznetsova (Russian)", u"Aleksandar Đurić (Serbian)", u"Burak Yüksek (Turkish)"]
url = u"https://twblue.es"
report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
supported_languages = []
supported_languages = []
def streaming_lives():
""" Check if we are in August 16.
ToDo: This method should be removed after deadline==True"""
# Let's import config here so we will avoid breaking things when setup.py is going to be used.
# Check if user has disabled the streaming API things from settings.
import config
if config.app != None:
no_streaming = config.app["app-settings"]["no_streaming"]
if no_streaming == True:
return False
deadline = datetime.date(2018, 8, 16)
now = datetime.datetime.now().date()
return deadline>now

View File

@@ -2,6 +2,7 @@ from audio_services import matches_url
import json
import re
import urllib
import youtube_utils
@matches_url('https://audioboom.com')
def convert_audioboom(url):
@@ -28,5 +29,9 @@ def convert_soundcloud (url):
else:
raise TypeError('%r is not streamable' % url)
@matches_url ('https://www.youtube.com/watch')
def convert_youtube_long (url):
return youtube_utils.get_video_url(url)
def convert_generic_audio(url):
return url

View File

@@ -17,6 +17,7 @@ import config
import sound
import languageHandler
import logging
import youtube_utils
from twitter import compose, utils
from mysc.thread_utils import call_threaded
from twython import TwythonError
@@ -33,21 +34,36 @@ def _tweets_exist(function):
return function_
class bufferController(object):
""" A basic buffer object. This should be the base class for all other derived buffers."""
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
"""Inits the main controller for this buffer:
@ parent wx.Treebook object: Container where we will put this buffer.
@ function str or None: function to be called periodically and update items on this buffer.
@ session sessionmanager.session object or None: Session handler for settings, database and Twitter access.
"""
super(bufferController, self).__init__()
self.function = function
# Compose_function will be used to render an object on this buffer. Normally, signature is as follows:
# compose_function(item, db, relative_times, show_screen_names=False, session=None)
# Compose functions will be defined in every buffer if items are different than tweets.
# Read more about compose functions in twitter/compose.py.
self.compose_function = None
self.args = args
self.kwargs = kwargs
# This will be used as a reference to the wx.Panel object wich stores the buffer GUI.
self.buffer = None
# This should countains the account associated to this buffer.
self.account = ""
# This controls wether the start_stream function should be called when starting the program.
self.needs_init = True
self.invisible = False # False if the buffer will be ignored on the invisible interface.
# if this is set to False, the buffer will be ignored on the invisible interface.
self.invisible = False
# Control variable, used to track time of execution for calls to start_stream.
self.execution_time = 0
def clear_list(self): pass
def get_event(self, ev):
""" Catches key presses in the WX interface and generate the corresponding event names."""
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
@@ -71,8 +87,7 @@ class bufferController(object):
self.session.settings["sound"]["volume"] = 0.0
else:
self.session.settings["sound"]["volume"] -=0.05
if hasattr(sound.URLPlayer, "stream"):
sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"]
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100.0))
self.session.sound.play("volume_changed.ogg")
self.session.settings.write()
@@ -82,14 +97,13 @@ class bufferController(object):
self.session.settings["sound"]["volume"] = 1.0
else:
self.session.settings["sound"]["volume"] +=0.05
if hasattr(sound.URLPlayer, "stream"):
sound.URLPlayer.stream.volume = self.session.settings["sound"]["volume"]
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100))
self.session.sound.play("volume_changed.ogg")
self.session.settings.write()
def start_stream(self, mandatory=False):
if mandatory == True:
output.speak(_(u"Unable to update this buffer."))
def start_stream(self, mandatory=False, play_sound=True):
# if mandatory == True:
# output.speak(_(u"Unable to update this buffer."))
pass
def get_more_items(self):
@@ -138,6 +152,9 @@ class bufferController(object):
caption = _(u"Write the tweet here")
tweet = messages.tweet(self.session, title, caption, "")
if tweet.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
config.app["app-settings"]["longtweet"] = tweet.message.long_tweet.GetValue()
config.app.write()
text = tweet.message.get_text()
if len(text) > 280 and tweet.message.get("long_tweet") == True:
if not hasattr(tweet, "attachments"):
@@ -145,9 +162,9 @@ class bufferController(object):
else:
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
call_threaded(self.session.api_call, call_name="update_status", status=text)
call_threaded(self.session.api_call, call_name="update_status", status=text, _sound="tweet_send.ogg")
else:
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments)
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg")
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
self.session.settings.write()
@@ -166,7 +183,6 @@ class bufferController(object):
except AttributeError:
pass
class accountPanel(bufferController):
def __init__(self, parent, name, account, account_id):
super(accountPanel, self).__init__(parent, None, name)
@@ -256,12 +272,13 @@ class baseBufferController(bufferController):
self.kwargs.pop("user_id")
def get_formatted_message(self):
if self.type == "dm" or self.name == "sent_tweets" or self.name == "sent_direct_messages": return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])[1]
if self.type == "dm" or self.name == "direct_messages":
return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)[1]
return self.get_message()
def get_message(self):
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"]))
return " ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session))
def get_full_tweet(self):
tweet = self.get_right_tweet()
@@ -298,16 +315,19 @@ class baseBufferController(bufferController):
tweetsList.append(tweet)
return (tweet, tweetsList)
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
self.execution_time = current_time
log.debug("Starting stream for buffer %s, account %s and type %s" % (self.name, self.account, self.type))
log.debug("args: %s, kwargs: %s" % (self.args, self.kwargs))
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
number_of_items = self.session.order_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
if self.name == "direct_messages":
number_of_items = self.session.get_cursored_stream(self.name, self.function, *self.args, **self.kwargs)
else:
val = self.session.call_paged(self.function, *self.args, **self.kwargs)
number_of_items = self.session.order_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
if "-timeline" in self.name:
@@ -315,7 +335,7 @@ class baseBufferController(bufferController):
elif "-favorite" in self.name:
self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"]
self.finished_timeline = True
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None:
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
return number_of_items
@@ -341,11 +361,11 @@ class baseBufferController(bufferController):
selection = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == False:
for i in elements:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
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(True, *tweet)
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"])
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.select_item(selection+elements)
# else:
@@ -393,36 +413,41 @@ class baseBufferController(bufferController):
self.remove_item(i)
def put_items_on_list(self, number_of_items):
# Define the list we're going to use as cursored stuff are a bit different.
if self.name != "direct_messages" and self.name != "sent_direct_messages":
list_to_use = self.session.db[self.name]
else:
list_to_use = self.session.db[self.name]["items"]
if number_of_items == 0 and self.session.settings["general"]["persist_size"] == 0: return
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
log.debug("Putting %d items on the list" % (number_of_items,))
if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
for i in list_to_use:
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.set_position(self.session.settings["general"]["reverse_timelines"])
elif self.buffer.list.get_count() > 0 and number_of_items > 0:
if self.session.settings["general"]["reverse_timelines"] == False:
items = self.session.db[self.name][len(self.session.db[self.name])-number_of_items:]
items = list_to_use[len(list_to_use)-number_of_items:]
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"])
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)
else:
items = self.session.db[self.name][0:number_of_items]
items = list_to_use[0:number_of_items]
items.reverse()
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"])
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(True, *tweet)
log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),))
def add_new_item(self, item):
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)
if self.session.settings["general"]["reverse_timelines"] == False:
self.buffer.list.insert_item(False, *tweet)
else:
self.buffer.list.insert_item(True, *tweet)
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
output.speak(" ".join(tweet[:2]))
output.speak(" ".join(tweet[:2]), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
#Improve performance on Windows
# if platform.system() == "Windows":
# call_threaded(utils.is_audio,item)
@@ -442,7 +467,7 @@ class baseBufferController(bufferController):
def show_menu(self, ev, pos=0, *args, **kwargs):
if self.buffer.list.get_count() == 0: return
if self.name == "sent_tweets" or self.name == "sent_direct_messages":
if self.name == "sent_tweets" or self.name == "direct_messages":
menu = menus.sentPanelMenu()
elif self.name == "direct_messages":
menu = menus.dmPanelMenu()
@@ -518,6 +543,11 @@ class baseBufferController(bufferController):
title=_("Reply")
message = messages.reply(self.session, title, _(u"Reply to %s") % (screen_name,), "", users=users, ids=ids)
if message.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
if len(users) > 0:
config.app["app-settings"]["mention_all"] = message.message.mentionAll.GetValue()
config.app.write()
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id,}
text = message.message.get_text()
if twishort_enabled == False:
@@ -546,8 +576,8 @@ class baseBufferController(bufferController):
def direct_message(self, *args, **kwargs):
tweet = self.get_right_tweet()
if self.type == "dm":
screen_name = tweet["sender"]["screen_name"]
users = utils.get_all_users(tweet, self.session.db)
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
users = [screen_name]
elif self.type == "people":
screen_name = tweet["screen_name"]
users = [screen_name]
@@ -556,13 +586,28 @@ class baseBufferController(bufferController):
users = utils.get_all_users(tweet, self.session.db)
dm = messages.dm(self.session, _(u"Direct message to %s") % (screen_name,), _(u"New direct message"), users)
if dm.message.get_response() == widgetUtils.OK:
val = self.session.api_call(call_name="send_direct_message", text=dm.message.get_text(), screen_name=dm.message.get("cb"))
screen_name = dm.message.get("cb")
user = self.session.get_user_by_screen_name(screen_name)
event_data = {
'event': {
'type': 'message_create',
'message_create': {
'target': {
'recipient_id': user,
},
'message_data': {
'text': dm.message.get_text(),
}
}
}
}
val = self.session.api_call(call_name="send_direct_message", **event_data)
if val != None:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db["sent_direct_messages"].append(val)
self.session.db["sent_direct_messages"]["items"].append(val["event"])
else:
self.session.db["sent_direct_messages"].insert(0, val)
pub.sendMessage("sent-dm", data=val, user=self.session.db["user_name"])
self.session.db["sent_direct_messages"]["items"].insert(0, val["event"])
pub.sendMessage("sent-dm", data=val["event"], user=self.session.db["user_name"])
if hasattr(dm.message, "destroy"): dm.message.destroy()
@_tweets_exist
@@ -606,7 +651,7 @@ class baseBufferController(bufferController):
# fix this:
original_date = arrow.get(self.session.db[self.name][self.buffer.list.get_selected()]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
ts = original_date.humanize(locale=languageHandler.getLanguage())
self.buffer.list.list.SetStringItem(self.buffer.list.get_selected(), 2, ts)
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet):
self.session.sound.play("audio.ogg")
if self.session.settings['sound']['indicate_geo'] and utils.is_geocoded(tweet):
@@ -614,10 +659,9 @@ class baseBufferController(bufferController):
if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet):
self.session.sound.play("image.ogg")
# @_tweets_exist
def audio(self, url='', *args, **kwargs):
if hasattr(sound.URLPlayer,'stream') and sound.URLPlayer.stream.is_playing == True:
return sound.URLPlayer.stop_audio(delete=True)
if sound.URLPlayer.player.is_playing():
return sound.URLPlayer.stop_audio()
tweet = self.get_tweet()
if tweet == None: return
urls = utils.find_urls(tweet)
@@ -668,19 +712,20 @@ class baseBufferController(bufferController):
try:
if self.name == "direct_messages" or self.name == "sent_direct_messages":
self.session.twitter.twitter.destroy_direct_message(id=self.get_right_tweet()["id"])
self.session.db[self.name]["items"].pop(index)
else:
self.session.twitter.twitter.destroy_status(id=self.get_right_tweet()["id"])
self.session.db[self.name].pop(index)
self.session.db[self.name].pop(index)
self.buffer.list.remove_item(index)
# if index > 0:
except TwythonError:
self.session.sound.play("error")
self.session.sound.play("error.ogg")
@_tweets_exist
def user_details(self):
tweet = self.get_right_tweet()
if self.type == "dm":
users = utils.get_all_users(tweet, self.session.db)
users = [self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
elif self.type == "people":
users = [tweet["screen_name"]]
else:
@@ -710,6 +755,106 @@ class baseBufferController(bufferController):
except IndexError: pass
return compose.compose_quoted_tweet(quoted_tweet, original_tweet, self.session.db, self.session.settings["general"]["relative_times"])
class directMessagesController(baseBufferController):
def get_more_items(self):
try:
items = self.session.get_more_items(self.function, dm=True, name=self.name, count=self.session.settings["general"]["max_tweets_per_call"], cursor=self.session.db[self.name]["cursor"], *self.args, **self.kwargs)
except TwythonError as e:
output.speak(e.message, True)
return
sent = []
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db["sent_direct_messages"]["items"].insert(0, i)
else:
self.session.db["sent_direct_messages"]["items"].append(i)
sent.append(i)
else:
if self.session.settings["general"]["reverse_timelines"] == False:
self.session.db[self.name]["items"].insert(0, i)
else:
self.session.db[self.name]["items"].append(i)
pub.sendMessage("more-sent-dms", data=sent, account=self.session.db["user_name"])
selected = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
continue
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(True, *tweet)
self.buffer.list.select_item(selected)
else:
for i in items:
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
continue
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(True, *tweet)
output.speak(_(u"%s items retrieved") % (len(items)), True)
def get_tweet(self):
tweet = self.session.db[self.name]["items"][self.buffer.list.get_selected()]
return tweet
get_right_tweet = get_tweet
@_tweets_exist
def reply(self, *args, **kwargs):
tweet = self.get_right_tweet()
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
if message.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
config.app.write()
if message.image == None:
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
else:
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
if hasattr(message.message, "destroy"): message.message.destroy()
def onFocus(self, *args, **kwargs):
tweet = self.get_tweet()
if platform.system() == "Windows" and self.session.settings["general"]["relative_times"] == True:
# fix this:
original_date = arrow.get(tweet["created_timestamp"][:-3])
ts = original_date.humanize(locale=languageHandler.getLanguage())
self.buffer.list.list.SetItem(self.buffer.list.get_selected(), 2, ts)
if self.session.settings['sound']['indicate_audio'] and utils.is_audio(tweet):
self.session.sound.play("audio.ogg")
if self.session.settings['sound']['indicate_img'] and utils.is_media(tweet):
self.session.sound.play("image.ogg")
def clear_list(self):
dlg = commonMessageDialogs.clear_list()
if dlg == widgetUtils.YES:
self.session.db[self.name]["items"] = []
self.buffer.list.clear()
class sentDirectMessagesController(directMessagesController):
def __init__(self, *args, **kwargs):
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
if self.session.db.has_key("sent_direct_messages") == False:
self.session.db["sent_direct_messages"] = {"items": []}
def get_more_items(self):
output.speak(_(u"Getting more items cannot be done in this buffer. Use the direct messages buffer instead."))
def start_stream(self, *args, **kwargs):
pass
def put_more_items(self, items):
if self.session.settings["general"]["reverse_timelines"] == True:
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(True, *tweet)
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(True, *tweet)
class listBufferController(baseBufferController):
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, list_id=None, *args, **kwargs):
super(listBufferController, self).__init__(parent, function, name, sessionObject, account, sound=None, bufferType=None, *args, **kwargs)
@@ -717,9 +862,9 @@ class listBufferController(baseBufferController):
self.list_id = list_id
self.kwargs["list_id"] = list_id
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
self.get_user_ids()
super(listBufferController, self).start_stream(mandatory)
super(listBufferController, self).start_stream(mandatory, play_sound)
def get_user_ids(self):
next_cursor = -1
@@ -771,7 +916,7 @@ class eventsBufferController(bufferController):
else:
self.buffer.list.insert_item(True, *tweet)
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
output.speak(" ".join(tweet))
output.speak(" ".join(tweet), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
if self.buffer.list.get_count() == 1:
self.buffer.list.select_item(0)
@@ -853,7 +998,7 @@ class peopleBufferController(baseBufferController):
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"]))
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))
def delete_item(self): pass
@@ -863,13 +1008,16 @@ class peopleBufferController(baseBufferController):
screen_name = tweet["screen_name"]
message = messages.reply(self.session, _(u"Mention"), _(u"Mention to %s") % (screen_name,), "@%s " % (screen_name,), [screen_name,])
if message.message.get_response() == widgetUtils.OK:
if config.app["app-settings"]["remember_mention_and_longtweet"]:
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
config.app.write()
if message.image == None:
call_threaded(self.session.api_call, call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
else:
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
if hasattr(message.message, "destroy"): message.message.destroy()
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
@@ -881,6 +1029,8 @@ class peopleBufferController(baseBufferController):
if hasattr(self, "finished_timeline") and self.finished_timeline == False:
self.username = self.session.api_call("show_user", **self.kwargs)["screen_name"]
self.finished_timeline = True
if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
return val
def get_more_items(self):
@@ -895,19 +1045,15 @@ class peopleBufferController(baseBufferController):
else:
self.session.db[self.name]["items"].append(i)
selected = self.buffer.list.get_selected()
# self.put_items_on_list(len(items))
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.select_item(selected)
else:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
# self.buffer.list.select_item(selection)
# else:
# self.buffer.list.select_item(selection-elements)
output.speak(_(u"%s items retrieved") % (len(items)), True)
def put_items_on_list(self, number_of_items):
@@ -915,7 +1061,7 @@ class peopleBufferController(baseBufferController):
# log.debug("Putting %d items on the list..." % (number_of_items,))
if self.buffer.list.get_count() == 0:
for i in self.session.db[self.name]["items"]:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(False, *tweet)
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
# self.buffer.set_list_position()
@@ -925,7 +1071,9 @@ class peopleBufferController(baseBufferController):
tweet = self.compose_function(i, self.session.db)
self.buffer.list.insert_item(False, *tweet)
else:
for i in self.session.db[self.name]["items"][0:number_of_items]:
items = self.session.db[self.name]["items"][0:number_of_items]
items.reverse()
for i in items:
tweet = self.compose_function(i, self.session.db)
self.buffer.list.insert_item(True, *tweet)
log.debug("now the list contains %d items" % (self.buffer.list.get_count(),))
@@ -935,7 +1083,7 @@ class peopleBufferController(baseBufferController):
return tweet
def add_new_item(self, item):
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(item, self.session.db, self.session.settings["general"]["relative_times"], self.session)
if self.session.settings["general"]["reverse_timelines"] == False:
self.buffer.list.insert_item(False, *tweet)
else:
@@ -970,7 +1118,7 @@ class peopleBufferController(baseBufferController):
pub.sendMessage("execute-action", action="user_details")
class searchBufferController(baseBufferController):
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
@@ -984,8 +1132,8 @@ class searchBufferController(baseBufferController):
# return None
num = self.session.order_buffer(self.name, val)
self.put_items_on_list(num)
if num > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
if num > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
return num
def remove_buffer(self, force=False):
@@ -1025,11 +1173,11 @@ class searchBufferController(baseBufferController):
selection = self.buffer.list.get_selected()
if self.session.settings["general"]["reverse_timelines"] == False:
for i in elements:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"])
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(True, *tweet)
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"])
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.select_item(selection+elements)
# else:
@@ -1049,7 +1197,7 @@ class searchPeopleBufferController(peopleBufferController):
if self.kwargs.has_key("page") == False:
self.kwargs["page"] = 1
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
@@ -1064,8 +1212,8 @@ class searchPeopleBufferController(peopleBufferController):
number_of_items = self.session.order_cursored_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if number_of_items > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
return number_of_items
def get_more_items(self, *args, **kwargs):
@@ -1084,19 +1232,18 @@ class searchPeopleBufferController(peopleBufferController):
# self.put_items_on_list(len(items))
if self.session.settings["general"]["reverse_timelines"] == True:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
self.buffer.list.select_item(selected)
else:
for i in items:
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"])
tweet = self.compose_function(i, self.session.db, self.session.settings["general"]["relative_times"], self.session)
self.buffer.list.insert_item(True, *tweet)
# self.buffer.list.select_item(selection)
# else:
# self.buffer.list.select_item(selection-elements)
output.speak(_(u"%s items retrieved") % (len(items)), True)
def remove_buffer(self, force=False):
if force == False:
dlg = commonMessageDialogs.remove_buffer()
@@ -1131,7 +1278,7 @@ class trendsBufferController(bufferController):
self.get_formatted_message = self.get_message
self.reply = self.search_topic
def start_stream(self, mandatory=False):
def start_stream(self, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
@@ -1144,7 +1291,7 @@ class trendsBufferController(bufferController):
self.name_ = data[0]["locations"][0]["name"]
self.trends = data[0]["trends"]
self.put_items_on_the_list()
if self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
if self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
def put_items_on_the_list(self):
@@ -1236,7 +1383,7 @@ class trendsBufferController(bufferController):
class conversationBufferController(searchBufferController):
def start_stream(self, start=False, mandatory=False):
def start_stream(self, start=False, mandatory=False, play_sound=True):
# starts stream every 3 minutes.
current_time = time.time()
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
@@ -1266,8 +1413,8 @@ class conversationBufferController(searchBufferController):
number_of_items = self.session.order_buffer(self.name, self.statuses)
log.debug("Number of items retrieved: %d" % (number_of_items,))
self.put_items_on_list(number_of_items)
if number_of_items > 0 and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"]:
self.session.sound.play("search_updated.ogg")
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
self.session.sound.play(self.sound)
return number_of_items
def remove_buffer(self, force=False):

View File

@@ -14,6 +14,9 @@ class filter(object):
contains = self.dialog.get("contains")
term = self.dialog.get("term")
regexp = self.dialog.get("regexp")
allow_rts = self.dialog.get("allow_rts")
allow_quotes = self.dialog.get("allow_quotes")
allow_replies = self.dialog.get("allow_replies")
load_language = self.dialog.get("load_language")
ignore_language = self.dialog.get("ignore_language")
lang_option = None
@@ -26,7 +29,7 @@ class filter(object):
for i in application.supported_languages:
if i["name"] in langs:
langcodes.append(i["code"])
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains)
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains, allow_rts=allow_rts, allow_quotes=allow_quotes, allow_replies=allow_replies)
if self.buffer.session.settings["filters"].has_key(title):
return commonMessageDialogs.existing_filter()
self.buffer.session.settings["filters"][title] = d
@@ -49,7 +52,6 @@ class filterManager(object):
def insert_filters(self, filters):
self.dialog.filters.clear()
for f in filters.keys():
# ToDo: Add titles to filters.
filterName = f
buffer = filters[f]["in_buffer"]
if filters[f]["if_word_exists"] == "True" and filters[f]["word"] != "":

View File

@@ -2,6 +2,7 @@
import platform
system = platform.system()
import application
import youtube_utils
if system == "Windows":
from update import updater
from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon)
@@ -53,26 +54,27 @@ class Controller(object):
name_ str: The name for the buffer
user str: The account for the buffer.
for example you may want to search the home_timeline buffer for the tw_blue2 user.
returns buffersController.buffer object with the result if there is one."""
Return type: buffersController.buffer object."""
for i in self.buffers:
if i.name == name_ and i.account == user: return i
def get_current_buffer(self):
""" Get the current bufferObject"""
""" Get the current focused bufferObject.
Return type: BuffersController.buffer object."""
buffer = self.view.get_current_buffer()
if hasattr(buffer, "account"):
buffer = self.search_buffer(buffer.name, buffer.account)
return buffer
def get_best_buffer(self):
""" Gets the best buffer for doing something using the session object.
""" Get the best buffer for doing something using the session object.
This function is useful when you need to open a timeline or post a tweet, and the user is in a buffer without a session, for example the events buffer.
This returns a bufferObject."""
Return type: buffersController.buffer object."""
# Gets the parent buffer to know what account is doing an action
view_buffer = self.view.get_current_buffer()
# If the account has no session attached, we will need to search the home_timeline for that account to use its session.
# If the account has no session attached, we will need to search the first available non-empty buffer for that account to use its session.
if view_buffer.type == "account" or view_buffer.type == "empty":
buffer = self.search_buffer("home_timeline", view_buffer.account)
buffer = self.get_first_buffer(view_buffer.account)
else:
buffer = self.search_buffer(view_buffer.name, view_buffer.account)
if buffer != None: return buffer
@@ -82,18 +84,23 @@ class Controller(object):
account str: A twitter username.
The first valid buffer is the home timeline."""
for i in self.buffers:
if i.account == account and i.invisible == True:
buff = i
break
return self.view.search(buff.name, buff.account)
if i.account == account and i.invisible == True and i.session != None:
return i
def get_last_buffer(self, account):
""" Gets the last valid buffer for an account.
account str: A twitter username.
The last valid buffer is the last buffer that contains a session object assigned."""
# results = self.get_buffers_for_account(account)
results = self.get_buffers_for_account(account)
return self.view.search(results[-1].name, results[-1].account)
return results[-1]
def get_first_buffer_index(self, account):
buff = self.get_first_buffer(account)
return self.view.search(buff.name, buff.account)
def get_last_buffer_index(self, account):
buff = self.get_last_buffer(account)
return self.view.search(buff.name, buff.account)
def get_buffers_for_account(self, account):
results = []
@@ -107,7 +114,6 @@ class Controller(object):
pub.subscribe(self.manage_home_timelines, "item-in-home")
pub.subscribe(self.manage_mentions, "mention")
pub.subscribe(self.manage_direct_messages, "direct-message")
pub.subscribe(self.manage_sent_dm, "sent-dm")
pub.subscribe(self.manage_sent_tweets, "sent-tweet")
pub.subscribe(self.manage_events, "event")
pub.subscribe(self.manage_followers, "follower")
@@ -119,21 +125,23 @@ class Controller(object):
pub.subscribe(self.manage_unblocked_user, "unblocked-user")
pub.subscribe(self.manage_item_in_timeline, "item-in-timeline")
pub.subscribe(self.manage_item_in_list, "item-in-list")
pub.subscribe(self.restart_streams_, "restart_streams")
pub.subscribe(self.on_tweet_deleted, "tweet-deleted")
pub.subscribe(self.buffer_title_changed, "buffer-title-changed")
widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_)
pub.subscribe(self.manage_stream_errors, "stream-error")
# pub.subscribe(self.restart_streams, "restart-streams")
def bind_other_events(self):
""" Binds the local application events with their functions."""
log.debug("Binding other application events...")
pub.subscribe(self.buffer_title_changed, "buffer-title-changed")
pub.subscribe(self.manage_sent_dm, "sent-dm")
widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_)
pub.subscribe(self.logout_account, "logout")
pub.subscribe(self.login_account, "login")
pub.subscribe(self.manage_stream_errors, "stream-error")
pub.subscribe(self.create_new_buffer, "create-new-buffer")
pub.subscribe(self.restart_streams, "restart-streams")
pub.subscribe(self.execute_action, "execute-action")
pub.subscribe(self.search_topic, "search")
pub.subscribe(self.update_sent_dms, "sent-dms-updated")
pub.subscribe(self.more_dms, "more-sent-dms")
if system == "Windows":
pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed")
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
@@ -157,7 +165,7 @@ class Controller(object):
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.unfav)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.fav)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.reverse_geocode, menuitem=self.view.view_coordinates)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
@@ -226,7 +234,8 @@ class Controller(object):
# This saves the current account (important in invisible mode)
self.current_account = ""
self.view.prepare()
self.bind_stream_events()
if application.streaming_lives():
self.bind_stream_events()
self.bind_other_events()
if system == "Windows":
self.set_systray_icon()
@@ -258,6 +267,9 @@ class Controller(object):
self.checker_function.start()
self.save_db = RepeatingTimer(300, self.save_data_in_db)
self.save_db.start()
log.debug("Setting updates to buffers every %d seconds..." % (60*config.app["app-settings"]["update_period"],))
self.update_buffers_function = RepeatingTimer(60*config.app["app-settings"]["update_period"], self.update_buffers)
self.update_buffers_function.start()
def start(self):
""" Starts all buffer objects. Loads their items."""
@@ -299,7 +311,7 @@ class Controller(object):
self.view.add_buffer(account.buffer , name=session.db["user_name"])
for i in session.settings['general']['buffer_order']:
if i == 'home':
home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], tweet_mode="extended")
home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended")
self.buffers.append(home)
self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'mentions':
@@ -307,24 +319,23 @@ class Controller(object):
self.buffers.append(mentions)
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'dm':
dm = buffersController.baseBufferController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", sound="dm_received.ogg", full_text=True)
dm = buffersController.directMessagesController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events")
self.buffers.append(dm)
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_dm':
sent_dm = buffersController.baseBufferController(self.view.nb, "get_sent_messages", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_dm", full_text=True)
sent_dm = buffersController.sentDirectMessagesController(self.view.nb, "", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message")
self.buffers.append(sent_dm)
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_tweets':
sent_tweets = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"], tweet_mode="extended")
sent_tweets = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
self.buffers.append(sent_tweets)
self.view.insert_buffer(sent_tweets.buffer, name=_(u"Sent tweets"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'favorites':
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], tweet_mode="extended")
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended")
self.buffers.append(favourites)
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'followers':
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], screen_name=session.db["user_name"])
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"])
self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'friends':
@@ -339,7 +350,7 @@ class Controller(object):
muted = buffersController.peopleBufferController(self.view.nb, "list_mutes", "muted", session, session.db["user_name"])
self.buffers.append(muted)
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'events':
elif i == 'events' and application.streaming_lives():
events = buffersController.eventsBufferController(self.view.nb, "events", session, session.db["user_name"], bufferType="dmPanel", screen_name=session.db["user_name"])
self.buffers.append(events)
self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
@@ -347,41 +358,35 @@ class Controller(object):
self.buffers.append(timelines)
self.view.insert_buffer(timelines.buffer , name=_(u"Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["timelines"]:
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], bufferType=None, user_id=i, tweet_mode="extended")
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended")
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", session.db["user_name"]))
favs_timelines = buffersController.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
self.buffers.append(favs_timelines)
self.view.insert_buffer(favs_timelines.buffer , name=_(u"Likes timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["favourites_timelines"]:
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, user_id=i, tweet_mode="extended")
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended")
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
followers_timelines = buffersController.emptyPanel(self.view.nb, "followers_timelines", session.db["user_name"])
self.buffers.append(followers_timelines)
self.view.insert_buffer(followers_timelines.buffer , name=_(u"Followers' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["followers_timelines"]:
tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], user_id=i)
tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"]))
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
friends_timelines = buffersController.emptyPanel(self.view.nb, "friends_timelines", session.db["user_name"])
self.buffers.append(friends_timelines)
self.view.insert_buffer(friends_timelines.buffer , name=_(u"Friends' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["friends_timelines"]:
tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], user_id=i)
tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"]))
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
lists = buffersController.emptyPanel(self.view.nb, "lists", session.db["user_name"])
self.buffers.append(lists)
self.view.insert_buffer(lists.buffer , name=_(u"Lists"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["lists"]:
tl = buffersController.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
tl = buffersController.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
session.lists.append(tl)
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"]))
@@ -389,18 +394,14 @@ class Controller(object):
self.buffers.append(searches)
self.view.insert_buffer(searches.buffer , name=_(u"Searches"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["tweet_searches"]:
tl = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", q=i, tweet_mode="extended")
tl = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended")
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Search for {}").format(i), pos=self.view.search("searches", session.db["user_name"]))
tl.timer = RepeatingTimer(180, tl.start_stream)
tl.timer.start()
for i in session.settings["other_buffers"]["trending_topic_buffers"]:
buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i)
buffer.start_stream()
buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i, sound="trends_updated.ogg")
buffer.start_stream(play_sound=False)
buffer.searchfunction = self.search
self.buffers.append(buffer)
buffer.timer = RepeatingTimer(300, buffer.start_stream)
buffer.timer.start()
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
def set_buffer_positions(self, session):
@@ -445,18 +446,16 @@ 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()}
search = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", q=term, tweet_mode="extended", **args)
search = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, 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
elif dlg.get("users") == True:
search = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, q=term)
search = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, sound="search_updated.ogg", q=term)
search.start_stream(mandatory=True)
pos=self.view.search("searches", buffer.session.db["user_name"])
self.insert_buffer(search, pos)
self.view.insert_buffer(search.buffer, name=_(u"Search for {}").format(term), pos=pos)
search.timer = RepeatingTimer(180, search.start_stream)
search.timer.start()
dlg.Destroy()
def find(self, *args, **kwargs):
@@ -492,7 +491,8 @@ class Controller(object):
output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True)
return
# Let's prevent filtering of some buffers (people buffers, direct messages, events and sent items).
if (page.name == "direct_messages" or page.name =="sent_direct_messages" or page.name == "sent_tweets" or page.name == "events") or page.type == "people":
# ToDo: Remove events from here after August 16.
if (page.name == "direct_messages" or page.name == "sent_tweets" or page.name == "events") or page.type == "people":
output.speak(_(u"Filters cannot be applied on this buffer"))
return
new_filter = filterController.filter(page)
@@ -503,13 +503,13 @@ class Controller(object):
def seekLeft(self, *args, **kwargs):
try:
sound.URLPlayer.seek(-5)
sound.URLPlayer.seek(-5000)
except:
output.speak("Unable to seek.",True)
def seekRight(self, *args, **kwargs):
try:
sound.URLPlayer.seek(5)
sound.URLPlayer.seek(5000)
except:
output.speak("Unable to seek.",True)
@@ -540,10 +540,12 @@ class Controller(object):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
if dlg.get_response() == widgetUtils.OK:
user = dlg.get_user()
@@ -555,10 +557,12 @@ class Controller(object):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
if dlg.get_response() == widgetUtils.OK:
user = dlg.get_user()
@@ -582,10 +586,12 @@ class Controller(object):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.utils.selectUserDialog(_(u"Select the user"), users)
if dlg.get_response() == widgetUtils.OK:
user = dlg.get_user()
@@ -666,7 +672,6 @@ class Controller(object):
session_.sessions[item].sound.cleaner.cancel()
log.debug("Shelving database for " + session_.sessions[item].session_id)
session_.sessions[item].shelve()
if system == "Windows":
self.systrayIcon.RemoveIcon()
widgetUtils.exit_application()
@@ -675,70 +680,84 @@ class Controller(object):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users)
def unfollow(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unfollow")
def mute(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "mute")
def unmute(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unmute")
def block(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "block")
def unblock(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "unblock")
def report(self, *args, **kwargs):
buff = self.get_current_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
u = userActionsController.userActionsController(buff, users, "report")
def post_tweet(self, event=None):
@@ -747,17 +766,14 @@ class Controller(object):
def post_reply(self, *args, **kwargs):
buffer = self.get_current_buffer()
if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return
elif buffer.name == "direct_messages":
if buffer.name == "direct_messages":
buffer.direct_message()
else:
buffer.reply()
def send_dm(self, *args, **kwargs):
buffer = self.get_current_buffer()
if buffer.name == "sent_direct_messages" or buffer.name == "sent-tweets": return
else:
buffer.direct_message()
buffer.direct_message()
def post_retweet(self, *args, **kwargs):
buffer = self.get_current_buffer()
@@ -782,6 +798,18 @@ class Controller(object):
id = buffer.get_tweet()["id"]
call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id)
def toggle_like(self, *args, **kwargs):
buffer = self.get_current_buffer()
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
return
else:
id = buffer.get_tweet()["id"]
tweet = buffer.session.twitter.twitter.show_status(id=id, include_ext_alt_text=True, tweet_mode="extended")
if tweet["favorited"] == False:
call_threaded(buffer.session.api_call, call_name="create_favorite", _sound="favourite.ogg", id=id)
else:
call_threaded(buffer.session.api_call, call_name="destroy_favorite", id=id)
def view_item(self, *args, **kwargs):
buffer = self.get_current_buffer()
if buffer.type == "baseBuffer" or buffer.type == "favourites_timeline" or buffer.type == "list" or buffer.type == "search":
@@ -803,10 +831,12 @@ class Controller(object):
buff = self.get_best_buffer()
if not hasattr(buff, "get_right_tweet"): return
tweet = buff.get_right_tweet()
if buff.type != "people":
users = utils.get_all_users(tweet, buff.session.db)
else:
if buff.type == "people":
users = [tweet["screen_name"]]
elif buff.type == "dm":
users = [buff.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]]
else:
users = utils.get_all_users(tweet, buff.session.db)
dlg = dialogs.userSelection.selectUserDialog(users=users, default=default)
if dlg.get_response() == widgetUtils.OK:
usr = utils.if_user_exists(buff.session.twitter.twitter, dlg.get_user())
@@ -818,8 +848,9 @@ class Controller(object):
if usr["following"] == False:
commonMessageDialogs.no_following()
return
answer = commonMessageDialogs.protected_user()
if answer == widgetUtils.NO: return
if application.streaming_lives():
answer = commonMessageDialogs.protected_user()
if answer == widgetUtils.NO: return
tl_type = dlg.get_action()
if tl_type == "tweets":
if usr["statuses_count"] == 0:
@@ -828,9 +859,9 @@ class Controller(object):
if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended")
tl = buffersController.baseBufferController(self.view.nb, "get_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")
try:
tl.start_stream()
tl.start_stream(play_sound=False)
except TwythonAuthError:
commonMessageDialogs.unauthorized()
return
@@ -848,17 +879,15 @@ class Controller(object):
if usr["id_str"] in buff.session.settings["other_buffers"]["favourites_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, user_id=usr["id_str"], tweet_mode="extended")
tl = buffersController.baseBufferController(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")
try:
tl.start_stream()
tl.start_stream(play_sound=False)
except TwythonAuthError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("favs_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Likes for {}").format(dlg.get_user()), pos=pos)
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
buff.session.settings["other_buffers"]["favourites_timelines"].append(usr["id_str"])
pub.sendMessage("buffer-title-changed", buffer=buff)
buff.session.sound.play("create_timeline.ogg")
@@ -869,17 +898,15 @@ class Controller(object):
if usr["id_str"] in buff.session.settings["other_buffers"]["followers_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"])
tl = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
try:
tl.start_stream()
tl.start_stream(play_sound=False)
except TwythonAuthError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("followers_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Followers for {}").format(dlg.get_user()), pos=pos)
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
buff.session.settings["other_buffers"]["followers_timelines"].append(usr["id_str"])
buff.session.sound.play("create_timeline.ogg")
pub.sendMessage("buffer-title-changed", buffer=i)
@@ -890,17 +917,15 @@ class Controller(object):
if usr["id_str"] in buff.session.settings["other_buffers"]["friends_timelines"]:
commonMessageDialogs.timeline_exist()
return
tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], user_id=usr["id_str"])
tl = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
try:
tl.start_stream()
tl.start_stream(play_sound=False)
except TwythonAuthError:
commonMessageDialogs.unauthorized()
return
pos=self.view.search("friends_timelines", buff.session.db["user_name"])
self.insert_buffer(tl, pos+1)
self.view.insert_buffer(buffer=tl.buffer, name=_(u"Friends for {}").format(dlg.get_user()), pos=pos)
tl.timer = RepeatingTimer(300, tl.start_stream)
tl.timer.start()
buff.session.settings["other_buffers"]["friends_timelines"].append(usr["id_str"])
buff.session.sound.play("create_timeline.ogg")
pub.sendMessage("buffer-title-changed", buffer=i)
@@ -912,15 +937,13 @@ class Controller(object):
buffer = self.get_current_buffer()
id = buffer.get_right_tweet()["id_str"]
user = buffer.get_right_tweet()["user"]["screen_name"]
search = buffersController.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", since_id=id, q="@{0}".format(user,))
search = buffersController.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,))
search.tweet = buffer.get_right_tweet()
search.start_stream(start=True)
pos=self.view.search("searches", buffer.session.db["user_name"])
# self.buffers.append(search)
self.insert_buffer(search, pos)
self.view.insert_buffer(search.buffer, name=_(u"Conversation with {0}").format(user), pos=pos)
search.timer = RepeatingTimer(300, search.start_stream)
search.timer.start()
def show_hide(self, *args, **kwargs):
km = self.create_invisible_keyboard_shorcuts()
@@ -942,14 +965,12 @@ class Controller(object):
if trends.dialog.get_response() == widgetUtils.OK:
woeid = trends.get_woeid()
if woeid in buff.session.settings["other_buffers"]["trending_topic_buffers"]: return
buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid)
buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid, sound="trends_updated.ogg")
buffer.searchfunction = self.search
pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos)
self.buffers.append(buffer)
buffer.start_stream()
buffer.timer = RepeatingTimer(300, buffer.start_stream)
buffer.timer.start()
buffer.session.settings["other_buffers"]["trending_topic_buffers"].append(woeid)
buffer.session.settings.write()
@@ -1087,8 +1108,8 @@ class Controller(object):
if not hasattr(buffer.buffer, "list"):
output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True)
return
if buff == self.get_first_buffer(buffer.account) or buff == 0:
self.view.change_buffer(self.get_last_buffer(buffer.account))
if buff == self.get_first_buffer_index(buffer.account) or buff == 0:
self.view.change_buffer(self.get_last_buffer_index(buffer.account))
else:
self.view.change_buffer(buff-1)
while self.get_current_buffer().invisible == False: self.skip_buffer(False)
@@ -1106,8 +1127,8 @@ class Controller(object):
if not hasattr(buffer.buffer, "list"):
output.speak(_(u"No session is currently in focus. Focus a session with the next or previous session shortcut."), True)
return
if buff == self.get_last_buffer(buffer.account) or buff+1 == self.view.get_buffer_count():
self.view.change_buffer(self.get_first_buffer(buffer.account))
if buff == self.get_last_buffer_index(buffer.account) or buff+1 == self.view.get_buffer_count():
self.view.change_buffer(self.get_first_buffer_index(buffer.account))
else:
self.view.change_buffer(buff+1)
while self.get_current_buffer().invisible == False: self.skip_buffer(True)
@@ -1127,7 +1148,11 @@ class Controller(object):
index = index+1
account = self.accounts[index]
self.current_account = account
buff = self.view.search("home_timeline", account)
buffer_object = self.get_first_buffer(account)
if buffer_object == None:
output.speak(_(u"{0}: This account is not logged into Twitter.").format(account), True)
return
buff = self.view.search(buffer_object.name, account)
if buff == None:
output.speak(_(u"{0}: This account is not logged into Twitter.").format(account), True)
return
@@ -1148,7 +1173,11 @@ class Controller(object):
index = index-1
account = self.accounts[index]
self.current_account = account
buff = self.view.search("home_timeline", account)
buffer_object = self.get_first_buffer(account)
if buffer_object == None:
output.speak(_(u"{0}: This account is not logged into Twitter.").format(account), True)
return
buff = self.view.search(buffer_object.name, account)
if buff == None:
output.speak(_(u"{0}: This account is not logged into twitter.").format(account), True)
return
@@ -1239,7 +1268,7 @@ class Controller(object):
if play_sound != None:
session.sound.play(play_sound)
if message != None:
output.speak(message)
output.speak(message, speech=session.settings["reporting"]["speech_reporting"], braille=session.settings["reporting"]["braille_reporting"])
def manage_home_timelines(self, data, user):
buffer = self.search_buffer("home_timeline", user)
@@ -1341,8 +1370,7 @@ class Controller(object):
if buffer == None: return
play_sound = "tweet_timeline.ogg"
if "%s-timeline" % (who,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False:
self.notify(buffer.session, play_sound=play_sound)
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
self.notify(buffer.session, play_sound=play_sound, message=_(u"One tweet from %s") % (data["user"]["name"]))
buffer.add_new_item(data)
def manage_item_in_list(self, data, user, where):
@@ -1350,8 +1378,7 @@ class Controller(object):
if buffer == None: return
play_sound = "list_tweet.ogg"
if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"] and buffer.session.settings["sound"]["session_mute"] == False:
self.notify(buffer.session, play_sound=play_sound)
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
self.notify(buffer.session, play_sound=play_sound, message=_(u"One tweet from %s") % (data["user"]["name"]))
buffer.add_new_item(data)
def start_buffers(self, session):
@@ -1363,7 +1390,10 @@ class Controller(object):
else:
change_title = False
try:
i.start_stream()
if "mentions" in i.name or "direct_messages" in i.name:
i.start_stream()
else:
i.start_stream(play_sound=False)
except TwythonAuthError:
buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True)
@@ -1376,8 +1406,9 @@ class Controller(object):
continue
if change_title:
pub.sendMessage("buffer-title-changed", buffer=i)
log.debug("Starting the streaming endpoint")
session.start_streaming()
if application.streaming_lives():
log.debug("Starting the streaming endpoint")
session.start_streaming()
def set_positions(self):
for i in session_.sessions:
@@ -1416,27 +1447,27 @@ class Controller(object):
favourites = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"])
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()
favourites.start_stream(play_sound=False)
if buffer == "followers":
followers = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
followers.start_stream()
followers.start_stream(play_sound=False)
elif buffer == "friends":
friends = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(friends)
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
friends.start_stream()
friends.start_stream(play_sound=False)
elif buffer == "blocked":
blocks = buffersController.peopleBufferController(self.view.nb, "list_blocks", "blocked", buff.session, buff.session.db["user_name"])
self.buffers.append(blocks)
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
blocks.start_stream()
blocks.start_stream(play_sound=False)
elif buffer == "muted":
muted = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", buff.session, buff.session.db["user_name"])
self.buffers.append(muted)
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
muted.start_stream()
muted.start_stream(play_sound=False)
elif buffer == "events":
events = buffersController.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"])
self.buffers.append(events)
@@ -1452,7 +1483,7 @@ class Controller(object):
pos=self.view.search("lists", buff.session.db["user_name"])
self.insert_buffer(tl, pos)
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(create), pos=self.view.search("lists", buff.session.db["user_name"]))
tl.start_stream()
tl.start_stream(play_sound=False)
buff.session.settings["other_buffers"]["lists"].append(create)
buff.session.settings.write()
pub.sendMessage("restart-streams", streams=["timelinesStream"], session=buff.session)
@@ -1561,11 +1592,11 @@ class Controller(object):
if hasattr(self, action):
getattr(self, action)()
def restart_streams_(self, session):
def update_buffers(self):
for i in self.buffers[:]:
if i.session != None and i.session.session_id == session:
if i.session != None and i.session.is_logged == True:
try:
i.start_stream()
i.start_stream(mandatory=True)
except TwythonAuthError:
buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True)
@@ -1636,6 +1667,16 @@ class Controller(object):
return
msg = messages.viewTweet(text["ParsedText"], [], False)
def update_sent_dms(self, total, account):
sent_dms = self.search_buffer("sent_direct_messages", account)
if sent_dms != None:
sent_dms.put_items_on_list(total)
def more_dms(self, data, account):
sent_dms = self.search_buffer("sent_direct_messages", account)
if sent_dms != None:
sent_dms.put_more_items(data)
def save_data_in_db(self):
for i in session_.sessions:
session_.sessions[i].shelve()
session_.sessions[i].shelve()

View File

@@ -7,9 +7,12 @@ import widgetUtils
import output
import url_shortener
import sound
import config
from pubsub import pub
if system == "Windows":
from wxUI.dialogs import message, urlList
from wxUI import commonMessageDialogs
from extra import translator, SpellChecker, autocompletionUsers
from extra.AudioUploader import audioUploader
elif system == "Linux":
@@ -26,14 +29,14 @@ class basicTweet(object):
self.message = getattr(message, messageType)(title, caption, text, *args, **kwargs)
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
widgetUtils.connect_event(self.message.attach, widgetUtils.BUTTON_PRESSED, self.attach)
# if system == "Windows":
# if messageType != "dm":
widgetUtils.connect_event(self.message.text, widgetUtils.ENTERED_TEXT, self.text_processor)
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
widgetUtils.connect_event(self.message.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
if hasattr(self.message, "long_tweet"):
widgetUtils.connect_event(self.message.long_tweet, widgetUtils.CHECKBOX, self.text_processor)
if config.app["app-settings"]["remember_mention_and_longtweet"]:
self.message.long_tweet.SetValue(config.app["app-settings"]["longtweet"])
self.attachments = []
def translate(self, event=None):
@@ -114,11 +117,12 @@ class basicTweet(object):
url = dlg.uploaderFunction.get_url()
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
dlg.uploaderDialog.destroy()
if url != 0:
if "sndup.net/" in url:
self.message.set_text(self.message.get_text()+url+" #audio")
self.text_processor()
else:
output.speak(_(u"Unable to upload the audio"))
commonMessageDialogs.common_error(url)
dlg.cleanup()
dlg = audioUploader.audioUploader(self.session.settings, completed_callback)
self.message.text_focus()
@@ -148,7 +152,8 @@ class reply(tweet):
if len(users) > 0:
widgetUtils.connect_event(self.message.mentionAll, widgetUtils.CHECKBOX, self.mention_all)
self.message.enable_button("mentionAll")
self.message.set("mentionAll", True)
if config.app["app-settings"]["remember_mention_and_longtweet"]:
self.message.mentionAll.SetValue(config.app["app-settings"]["mention_all"])
self.mention_all()
self.message.set_cursor_at_end()
self.text_processor()
@@ -194,6 +199,7 @@ class viewTweet(basicTweet):
param tweetList: If is_tweet is set to True, this could be a list of quoted tweets.
param is_tweet: True or false, depending wether the passed object is a tweet or not."""
if is_tweet == True:
self.title = _(u"Tweet")
image_description = []
text = ""
for i in xrange(0, len(tweetList)):
@@ -248,6 +254,7 @@ class viewTweet(basicTweet):
self.message.set_title(len(text))
[self.message.set_image_description(i) for i in image_description]
else:
self.title = _(u"View item")
text = tweet
self.message = message.viewNonTweet(text)
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)

View File

@@ -61,13 +61,16 @@ class globalSettingsController(object):
else:
self.dialog.general.autostart.Enable(False)
self.dialog.set_value("general", "ask_at_exit", config.app["app-settings"]["ask_at_exit"])
self.dialog.set_value("general", "no_streaming", config.app["app-settings"]["no_streaming"])
self.dialog.set_value("general", "play_ready_sound", config.app["app-settings"]["play_ready_sound"])
self.dialog.set_value("general", "speak_ready_msg", config.app["app-settings"]["speak_ready_msg"])
self.dialog.set_value("general", "handle_longtweets", config.app["app-settings"]["handle_longtweets"])
self.dialog.set_value("general", "use_invisible_shorcuts", config.app["app-settings"]["use_invisible_keyboard_shorcuts"])
self.dialog.set_value("general", "disable_sapi5", config.app["app-settings"]["voice_enabled"])
self.dialog.set_value("general", "hide_gui", config.app["app-settings"]["hide_gui"])
self.dialog.set_value("general", "update_period", config.app["app-settings"]["update_period"])
self.dialog.set_value("general", "check_for_updates", config.app["app-settings"]["check_for_updates"])
self.dialog.set_value("general", "remember_mention_and_longtweet", config.app["app-settings"]["remember_mention_and_longtweet"])
proxyTypes=config.proxyTypes
self.dialog.create_proxy([_(u"Direct connection")]+proxyTypes)
if config.app["proxy"]["type"] not in proxyTypes:
@@ -92,13 +95,18 @@ class globalSettingsController(object):
kmFile = open(paths.config_path("keymap.keymap"), "w")
kmFile.close()
self.needs_restart = True
if config.app["app-settings"]["autostart"] != self.dialog.get_value("general", "autostart") and paths.mode == "installed":
config.app["app-settings"]["autostart"] = self.dialog.get_value("general", "autostart")
autostart_windows.setAutoStart(application.name, enable=self.dialog.get_value("general", "autostart"))
if config.app["app-settings"]["use_invisible_keyboard_shorcuts"] != self.dialog.get_value("general", "use_invisible_shorcuts"):
config.app["app-settings"]["use_invisible_keyboard_shorcuts"] = self.dialog.get_value("general", "use_invisible_shorcuts")
pub.sendMessage("invisible-shorcuts-changed", registered=self.dialog.get_value("general", "use_invisible_shorcuts"))
if config.app["app-settings"]["no_streaming"] != self.dialog.get_value("general", "no_streaming"):
config.app["app-settings"]["no_streaming"] = self.dialog.get_value("general", "no_streaming")
self.needs_restart = True
if config.app["app-settings"]["update_period"] != self.dialog.get_value("general", "update_period"):
config.app["app-settings"]["update_period"] = self.dialog.get_value("general", "update_period")
self.needs_restart = True
config.app["app-settings"]["voice_enabled"] = self.dialog.get_value("general", "disable_sapi5")
config.app["app-settings"]["hide_gui"] = self.dialog.get_value("general", "hide_gui")
config.app["app-settings"]["ask_at_exit"] = self.dialog.get_value("general", "ask_at_exit")
@@ -106,6 +114,7 @@ class globalSettingsController(object):
config.app["app-settings"]["play_ready_sound"] = self.dialog.get_value("general", "play_ready_sound")
config.app["app-settings"]["speak_ready_msg"] = self.dialog.get_value("general", "speak_ready_msg")
config.app["app-settings"]["check_for_updates"] = self.dialog.get_value("general", "check_for_updates")
config.app["app-settings"]["remember_mention_and_longtweet"] = self.dialog.get_value("general", "remember_mention_and_longtweet")
if config.app["proxy"]["type"]!=self.dialog.get_value("proxy", "type") or config.app["proxy"]["server"] != self.dialog.get_value("proxy", "server") or config.app["proxy"]["port"] != self.dialog.get_value("proxy", "port") or config.app["proxy"]["user"] != self.dialog.get_value("proxy", "user") or config.app["proxy"]["password"] != self.dialog.get_value("proxy", "password"):
if self.is_started == True:
self.needs_restart = True
@@ -129,7 +138,8 @@ class accountSettingsController(globalSettingsController):
widgetUtils.connect_event(self.dialog.general.au, widgetUtils.BUTTON_PRESSED, self.manage_autocomplete)
self.dialog.set_value("general", "relative_time", self.config["general"]["relative_times"])
self.dialog.set_value("general", "show_screen_names", self.config["general"]["show_screen_names"])
self.dialog.set_value("general", "apiCalls", self.config["general"]["max_api_calls"])
if application.streaming_lives():
self.dialog.set_value("general", "apiCalls", self.config["general"]["max_api_calls"])
self.dialog.set_value("general", "itemsPerApiCall", self.config["general"]["max_tweets_per_call"])
self.dialog.set_value("general", "reverse_timelines", self.config["general"]["reverse_timelines"])
rt = self.config["general"]["retweet_mode"]
@@ -140,6 +150,9 @@ class accountSettingsController(globalSettingsController):
else:
self.dialog.set_value("general", "retweet_mode", _(u"Retweet with comments"))
self.dialog.set_value("general", "persist_size", str(self.config["general"]["persist_size"]))
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"])
self.dialog.create_other_buffers()
buffer_values = self.get_buffers_list()
self.dialog.buffers.insert_buffers(buffer_values)
@@ -178,7 +191,8 @@ class accountSettingsController(globalSettingsController):
self.needs_restart = True
self.config["general"]["relative_times"] = self.dialog.get_value("general", "relative_time")
self.config["general"]["show_screen_names"] = self.dialog.get_value("general", "show_screen_names")
self.config["general"]["max_api_calls"] = self.dialog.get_value("general", "apiCalls")
if application.streaming_lives():
self.config["general"]["max_api_calls"] = self.dialog.get_value("general", "apiCalls")
self.config["general"]["max_tweets_per_call"] = self.dialog.get_value("general", "itemsPerApiCall")
if self.config["general"]["persist_size"] != self.dialog.get_value("general", "persist_size"):
if self.dialog.get_value("general", "persist_size") == '':
@@ -204,6 +218,8 @@ class accountSettingsController(globalSettingsController):
if set(self.config["general"]["buffer_order"]) != set(buffers_list) or buffers_list != self.config["general"]["buffer_order"]:
self.needs_restart = True
self.config["general"]["buffer_order"] = buffers_list
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
self.config["reporting"]["braille_reporting"] = self.dialog.get_value("reporting", "braille_reporting")
self.config["mysc"]["ocr_language"] = OCRSpace.OcrLangs[self.dialog.extras.ocr_lang.GetSelection()]
# if self.config["other_buffers"]["show_followers"] != self.dialog.get_value("buffers", "followers"):
# self.config["other_buffers"]["show_followers"] = self.dialog.get_value("buffers", "followers")
@@ -277,7 +293,8 @@ class accountSettingsController(globalSettingsController):
all_buffers['friends']=_(u"Friends")
all_buffers['blocks']=_(u"Blocked users")
all_buffers['muted']=_(u"Muted users")
all_buffers['events']=_(u"Events")
if application.streaming_lives():
all_buffers['events']=_(u"Events")
list_buffers = []
hidden_buffers=[]
for i in all_buffers.keys():
@@ -291,27 +308,4 @@ class accountSettingsController(globalSettingsController):
def toggle_buffer_active(self, ev):
change = self.dialog.buffers.get_event(ev)
if change == True:
self.dialog.buffers.change_selected_item()
# def manage_pocket(self, *args, **kwargs):
# if self.dialog.services.get_pocket_status() == _(u"Connect your Pocket account"):
# self.connect_pocket()
# else:
# self.disconnect_pocket()
# def connect_pocket(self):
# dlg = self.dialog.services.show_pocket_dialog()
# if dlg == widgetUtils.YES:
# request_token = pocket.Pocket.get_request_token(consumer_key=keys.keyring.get("pocket_consumer_key"), redirect_uri="http://127.0.0.1:8080")
# auth_url = pocket.Pocket.get_auth_url(code=request_token, redirect_uri="http://127.0.0.1:8080")
# webbrowser.open_new_tab(auth_url)
# httpd = BaseHTTPServer.HTTPServer(('127.0.0.1', 8080), authorisationHandler.handler)
# while authorisationHandler.logged == False:
# httpd.handle_request()
# user_credentials = pocket.Pocket.get_credentials(consumer_key=keys.keyring.get("pocket_consumer_key"), code=request_token)
# self.dialog.services.set_pocket(True)
# self.config["services"]["pocket_access_token"] = user_credentials["access_token"]
def disconnect_dropbox(self):
self.config["services"]["pocket_access_token"] = ""
self.dialog.services.set_pocket(False)
self.dialog.buffers.change_selected_item()

View File

@@ -52,7 +52,7 @@ class audioUploader(object):
self.uploaderDialog = wx_transfer_dialogs.UploadDialog(self.file)
output.speak(_(u"Attaching..."))
if self.dialog.get("services") == "SNDUp":
base_url = "http://sndup.net/post.php"
base_url = "https://sndup.net/post.php"
if len(self.config["sound"]["sndup_api_key"]) > 0:
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
else:

View File

@@ -69,5 +69,15 @@ class Upload(object):
self.completed_callback(self.obj)
if hasattr(self,'fin') and callable(self.fin.close):
self.fin.close()
def get_url(self):
return self.response.json()['url']
try:
data = self.response.json()
except:
return _("Error in file upload: {0}").format(self.data.content,)
if data.has_key("url") and data["url"] != "0":
return data["url"]
elif data.has_key("error") and data["error"] != "0":
return data["error"]
else:
return _("Error in file upload: {0}").format(self.data.content,)

View File

@@ -6,7 +6,7 @@ import widgetUtils
class UploadDialog(widgetUtils.BaseDialog):
def __init__(self, filename, *args, **kwargs):
super(UploadDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs)
super(UploadDialog, self).__init__(parent=None, id=wx.ID_ANY, *args, **kwargs)
self.pane = wx.Panel(self)
self.progress_bar = wx.Gauge(parent=self.pane)
fileBox = wx.BoxSizer(wx.HORIZONTAL)

View File

@@ -1,4 +1,5 @@
# -*- coding: utf-8 -*-
import os
import logging
import wx_ui
import widgetUtils
@@ -16,6 +17,12 @@ log = logging.getLogger("extra.SpellChecker.spellChecker")
class spellChecker(object):
def __init__(self, text, dictionary):
super(spellChecker, self).__init__()
# Set Dictionary path if not set in a previous call to this method.
# Dictionary path will be located in user config, see https://github.com/manuelcortez/twblue/issues/208
dict_path = enchant.get_param("enchant.myspell.dictionary.path")
if dict_path == None:
enchant.set_param("enchant.myspell.dictionary.path", os.path.join(paths.config_path(), "dicts"))
log.debug("Dictionary path set to %s" % (os.path.join(paths.config_path(), "dicts"),))
log.debug("Creating the SpellChecker object. Dictionary: %s" % (dictionary,))
self.active = True
try:

View File

@@ -39,11 +39,11 @@ class spellCheckerDialog(wx.Dialog):
suggestionsBox = wx.BoxSizer(wx.HORIZONTAL)
suggestionsBox.Add(suggest, 0, wx.ALL, 5)
suggestionsBox.Add(self.suggestions, 0, wx.ALL, 5)
self.ignore = wx.Button(panel, -1, _(u"Ignore"))
self.ignoreAll = wx.Button(panel, -1, _(u"Ignore all"))
self.replace = wx.Button(panel, -1, _(u"Replace"))
self.replaceAll = wx.Button(panel, -1, _(u"Replace all"))
self.add = wx.Button(panel, -1, _(u"Add to personal dictionary"))
self.ignore = wx.Button(panel, -1, _(u"&Ignore"))
self.ignoreAll = wx.Button(panel, -1, _(u"I&gnore all"))
self.replace = wx.Button(panel, -1, _(u"&Replace"))
self.replaceAll = wx.Button(panel, -1, _(u"R&eplace all"))
self.add = wx.Button(panel, -1, _(u"&Add to personal dictionary"))
close = wx.Button(panel, wx.ID_CANCEL)
btnBox = wx.BoxSizer(wx.HORIZONTAL)
btnBox.Add(self.ignore, 0, wx.ALL, 5)

View File

@@ -10,7 +10,7 @@ class menu(wx.Menu):
def append_options(self, options):
for i in options:
item = wx.MenuItem(self, wx.NewId(), "%s (@%s)" % (i[1], i[0]))
item = wx.MenuItem(self, wx.ID_ANY, "%s (@%s)" % (i[1], i[0]))
self.AppendItem(item)
self.Bind(wx.EVT_MENU, lambda evt, temp=i[0]: self.select_text(evt, temp), item)

View File

@@ -16,8 +16,7 @@ post_tweet = string(default="alt+win+n")
post_reply = string(default="control+win+r")
post_retweet = string(default="alt+win+shift+r")
send_dm = string(default="alt+win+shift+d")
add_to_favourites = string(default="control+alt+win+f")
remove_from_favourites = string(default="alt+shift+win+f")
toggle_like = string(default="control+alt+win+f")
follow = string(default="alt+win+shift+s")
user_details = string(default="alt+win+shift+n")
view_item = string(default="alt+win+v")

View File

@@ -12,6 +12,7 @@ actions = {
"post_retweet": _(u"Retweet"),
"send_dm": _(u"Send direct message"),
"add_to_favourites": _(u"Like a tweet"),
"toggle_like": _(u"Like/unlike a tweet"),
"remove_from_favourites": _(u"Unlike a tweet"),
"follow": _(u"Open the user actions dialogue"),
"user_details": _(u"See user details"),

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -19,14 +19,12 @@ if os.path.exists(paths.app_path(u"Uninstall.exe")):
paths.mode="installed"
import commandline
import config
import sound
import output
import logging
import application
import keys
from mysc.thread_utils import call_threaded
import fixes
#extra variables to control the temporary stdout and stderr, while the final files are opened. We understand that some errors could happen while all outputs are closed, so let's try to avoid it.
import widgetUtils
import webbrowser
from wxUI import commonMessageDialogs
@@ -42,12 +40,20 @@ if system == "Windows":
else:
sys.stdout=stdout
sys.stderr=stderr
#the final log files have been opened succesfully, let's close the temporal files
# We are running from source, let's prepare vlc module for that situation
if system=="Windows":
arch="x86"
if platform.architecture()[0][:2] == "64":
arch="x64"
os.environ['PYTHON_VLC_MODULE_PATH']=str(os.path.abspath(paths.app_path("..", "windows-dependencies", arch)))
os.environ['PYTHON_VLC_LIB_PATH']=str(os.path.abspath(paths.app_path("..", "windows-dependencies", arch, "libvlc.dll")))
#the final log files have been opened succesfully, let's close the temporary files
stdout_temp.close()
stderr_temp.close()
#finally, remove the temporal files. TW Blue doesn't need them anymore, and we will get more free space on the harddrive
#finally, remove the temporary files. TW Blue doesn't need them anymore, and we will get more free space on the harddrive
os.remove(stdout_temp.name)
os.remove(stderr_temp.name)
import sound
if system == "Linux":
from gi.repository import Gdk, GObject, GLib

Some files were not shown because too many files have changed in this diff Show More