mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-08-26 01:49:22 +00:00
Compare commits
81 Commits
snapshot10
...
v0.82
Author | SHA1 | Date | |
---|---|---|---|
![]() |
238607bbe7 | ||
0aa51d9529 | |||
3815ce0a67 | |||
5e91808b73 | |||
08259cdf16 | |||
0bbb3afde0 | |||
3c0110528f | |||
18b52e8909 | |||
037cfec91a | |||
695b35031e | |||
f9d869e824 | |||
c1c001ad96 | |||
d768afc329 | |||
![]() |
4186f1a3e6 | ||
![]() |
2eac158a39 | ||
1ee629d731 | |||
5590ab47ee | |||
b555ed736c | |||
da39f40048 | |||
b1cf1c5590 | |||
48232a6cf8 | |||
3bc92af55f | |||
![]() |
5e9218b072 | ||
![]() |
65f860ceef | ||
![]() |
b9b8145bca | ||
![]() |
7fab6bcf54 | ||
![]() |
7ad5e6fa37 | ||
![]() |
f6fec67d52 | ||
![]() |
b3cac85c4e | ||
![]() |
ff49bd2488 | ||
![]() |
45f23a4c8a | ||
![]() |
a67a5e6264 | ||
8988d63f33 | |||
2268619101 | |||
a312b7f63c | |||
92d803717f | |||
2124f6c60b | |||
29c87dbd3f | |||
1ea3c5d23b | |||
![]() |
547f9393b9 | ||
![]() |
16b34c827b | ||
![]() |
56f0f37f39 | ||
3e9143d607 | |||
da07859138 | |||
dfc2b605f5 | |||
8badd3987a | |||
7139a2bcb3 | |||
c4e2c3b57a | |||
ed95270d3b | |||
edd45a1adf | |||
f24d5fec4e | |||
a9b47bb1a4 | |||
8849ce9039 | |||
![]() |
8b4f16ef84 | ||
dbbe6c0600 | |||
3caef5fc81 | |||
7cd58708cc | |||
0814af3bf4 | |||
72ba5a74f5 | |||
cbc301141e | |||
f466516289 | |||
4eef236b1c | |||
![]() |
ce00083aa2 | ||
![]() |
f92e05ce72 | ||
c02a11f269 | |||
![]() |
c79e659b74 | ||
da8009aea0 | |||
2778d2e85d | |||
ce9a50903c | |||
9a7d39c125 | |||
89759e7d49 | |||
7ca9d42f5f | |||
![]() |
6a6bec880c | ||
7b22c7d0f8 | |||
058866831b | |||
229f698e72 | |||
32067d3171 | |||
![]() |
70169a2a4a | ||
![]() |
0875b7ef92 | ||
![]() |
e3e4fa42db | ||
![]() |
6e0c6de0af |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,4 +16,5 @@ src/Microsoft.VC90.CRT
|
|||||||
src/Microsoft.VC90.MFC
|
src/Microsoft.VC90.MFC
|
||||||
src/launcher.bat
|
src/launcher.bat
|
||||||
src/sounds/iOs
|
src/sounds/iOs
|
||||||
release-snapshot/
|
release-snapshot/
|
||||||
|
src/com_cache/
|
24
README.md
24
README.md
@@ -1,13 +1,12 @@
|
|||||||
TWBlue -
|
TWBlue -
|
||||||
======
|
======
|
||||||
|
|
||||||
Copyright (C) 2015. [Technow S.L.](https://www.technow.es)
|
Copyright (C) 2016. [Technow S.L.](https://www.technow.es)
|
||||||
|
|
||||||
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 you’ll have access to twitter features such as:
|
With this app you’ll have access to twitter features such as:
|
||||||
|
|
||||||
* Create, reply to, retweet and delete tweets,
|
* Create, reply to, like, retweet and delete tweets,
|
||||||
* Add and remove tweets from favourites,
|
|
||||||
* Send and delete direct messages,
|
* Send and delete direct messages,
|
||||||
* See your friends and followers,
|
* See your friends and followers,
|
||||||
* Follow, unfollow, block and report users as spam,
|
* Follow, unfollow, block and report users as spam,
|
||||||
@@ -18,9 +17,9 @@ With this app you’ll have access to twitter features such as:
|
|||||||
|
|
||||||
See [TWBlue's webpage](http://twblue.es) for more details.
|
See [TWBlue's webpage](http://twblue.es) for more details.
|
||||||
|
|
||||||
## Using TWBlue from sources
|
## Running TWBlue from source
|
||||||
|
|
||||||
This document describes how to run tw blue from source, and, after that, how to build a binary version, which doesn't need Python and the other dependencies to run.
|
This document describes how to run tw blue from source and how to build a binary version which doesn't need Python and the other dependencies to run.
|
||||||
|
|
||||||
### Required dependencies.
|
### Required dependencies.
|
||||||
|
|
||||||
@@ -36,7 +35,6 @@ Although most dependencies can be found in the windows-dependencies directory, w
|
|||||||
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.
|
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
|
* [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 220
|
* [Python windows extensions (pywin32)](http://www.sourceforge.net/projects/pywin32/) for python 2.7, build 220
|
||||||
* [Pycurl](http://pycurl.sourceforge.net) 7.21.5 for Python 2.7: [downloads](https://pypi.python.org/pypi/pycurl/7.21.5)
|
|
||||||
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
|
* [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
|
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
|
||||||
|
|
||||||
@@ -48,7 +46,7 @@ To build a binary version:
|
|||||||
|
|
||||||
#### Dependencies that must be installed using easy_install
|
#### Dependencies that must be installed using easy_install
|
||||||
|
|
||||||
setuptools install 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:
|
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:
|
||||||
|
|
||||||
cd C:\python27x64\scripts
|
cd C:\python27x64\scripts
|
||||||
|
|
||||||
@@ -64,6 +62,7 @@ setuptools install a script, called easy_install. You can find it in the python
|
|||||||
* pypubsub
|
* pypubsub
|
||||||
* configobj
|
* configobj
|
||||||
* requests-oauthlib
|
* requests-oauthlib
|
||||||
|
* requests-toolbelt
|
||||||
* future
|
* future
|
||||||
* pygeocoder
|
* pygeocoder
|
||||||
* suds
|
* suds
|
||||||
@@ -74,7 +73,7 @@ setuptools install a script, called easy_install. You can find it in the python
|
|||||||
|
|
||||||
easy_install will automatically get the additional libraries that these packages need to work properly.
|
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:
|
Run the following command to quickly install and upgrade all packages and their dependencies:
|
||||||
easy_install -Z --upgrade six configobj goslate markdown future suds requests oauthlib requests-oauthlib pypubsub pygeocoder arrow python-dateutil futures markdown microsofttranslator
|
easy_install -Z --upgrade six configobj goslate markdown future suds requests oauthlib requests-oauthlib requests-toolbelt pypubsub pygeocoder arrow==0.6 python-dateutil futures markdown microsofttranslator winpaths
|
||||||
|
|
||||||
#### Other dependencies
|
#### Other dependencies
|
||||||
|
|
||||||
@@ -91,8 +90,11 @@ This dependency has been built using pure basic 4.61. Its source can be found at
|
|||||||
|
|
||||||
#### Dependencies required to build the portableApps.com format archive
|
#### Dependencies required to build the portableApps.com format archive
|
||||||
|
|
||||||
|
* [NSIS Unicode Portable,](http://portableapps.com/apps/development/nsis_portable) version 2.46.5 rev 3
|
||||||
* [PortableApps.com Launcher,](http://portableapps.com/apps/development/portableapps.com_launcher) version 2.2
|
* [PortableApps.com Launcher,](http://portableapps.com/apps/development/portableapps.com_launcher) version 2.2
|
||||||
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.0.20
|
* [PortableApps.com Installer,](http://portableapps.com/apps/development/portableapps.com_installer) version 3.1.3
|
||||||
|
|
||||||
|
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, ...
|
||||||
|
|
||||||
### Running TW Blue from source
|
### Running TW Blue from source
|
||||||
|
|
||||||
@@ -121,7 +123,7 @@ To build it, run the following command from the src folder:
|
|||||||
|
|
||||||
### Building an installer
|
### Building an installer
|
||||||
|
|
||||||
If you want to install TWBlue in your computer, you must create the installer first. Follow these steps:
|
If you want to install TWBlue on your computer, you must create the installer first. Follow these steps:
|
||||||
|
|
||||||
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
||||||
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
|
* Move the dist directory to the scripts folder in this repo, and rename it to twblue
|
||||||
@@ -136,7 +138,7 @@ Run the gen_pot.bat file, located in the tools directory. Your python installati
|
|||||||
|
|
||||||
### How to build the portableApps.com archive
|
### How to build the portableApps.com archive
|
||||||
|
|
||||||
If you want to have TWBlue in your PortableApps.com platform, follow these steps:
|
If you want to have TWBlue on your PortableApps.com platform, follow these steps:
|
||||||
|
|
||||||
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
* Navigate to the src directory, and create a binary version for x86: C:\python27\python setup.py py2exe
|
||||||
* Move the dist directory to the misc\pa.c format\app folder in this repo, and rename it to twblue
|
* Move the dist directory to the misc\pa.c format\app folder in this repo, and rename it to twblue
|
||||||
|
@@ -34,4 +34,12 @@ Holly Scott-Gardner
|
|||||||
Anibal Hernández
|
Anibal Hernández
|
||||||
Sussan Leiva
|
Sussan Leiva
|
||||||
Brian Hartgen
|
Brian Hartgen
|
||||||
PEDRO REINA COLOBON
|
PEDRO REINA COLOBON
|
||||||
|
Moora-Moora Arrilla
|
||||||
|
Blake Oliver
|
||||||
|
Steffen Schultz
|
||||||
|
Riku
|
||||||
|
Burak Yüksek
|
||||||
|
florian Ionașcu
|
||||||
|
Christian Leo Mameli
|
||||||
|
Natalia Hedlund (Наталья Хедлунд)
|
@@ -2,6 +2,17 @@
|
|||||||
name = 'TWBlue'
|
name = 'TWBlue'
|
||||||
snapshot = False
|
snapshot = False
|
||||||
if snapshot == False:
|
if snapshot == False:
|
||||||
version = "0.80"
|
version = "0.82"
|
||||||
|
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
||||||
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||||
else:
|
else:
|
||||||
version = "7"
|
version = "10.99"
|
||||||
|
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
||||||
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||||
|
author = u"Manuel Cortéz"
|
||||||
|
authorEmail = "manuel@manuelcortez.net"
|
||||||
|
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2013-2015, 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"Bryner Villalobos, Bill Dengler (English)", u"Mohammed Al Shara (Arabic)", u"Joan Rabat, Juan Carlos Rivilla (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"Robert Osztolykan (Hungarian)", u"Paweł Masarczyk (Polish)", u"Odenilton Júnior Santos (Portuguese)", u"Alexander Jaszyn (Russian)", u"Burak (Turkish)"]
|
||||||
|
url = u"http://twblue.es"
|
||||||
|
report_bugs_url = "http://twblue.es/bugs/api/soap/mantisconnect.php?wsdl"
|
@@ -7,7 +7,7 @@ languageHandler.setLanguage("en")
|
|||||||
import strings
|
import strings
|
||||||
|
|
||||||
# the list of supported language codes of TW Blue
|
# the list of supported language codes of TW Blue
|
||||||
languages = ["en", "es", "fr", "de", "it", "gl", "ja"]
|
languages = ["en", "es", "fr", "de", "it", "gl", "ja", "ru"]
|
||||||
#"eu", "ar", "ca", "es", "fi", "fr", "gl", "hu", "it", "pl", "pt", "ru", "tr"]
|
#"eu", "ar", "ca", "es", "fi", "fr", "gl", "hu", "it", "pl", "pt", "ru", "tr"]
|
||||||
|
|
||||||
def generate_document(language):
|
def generate_document(language):
|
||||||
|
BIN
doc/locales/ru/lc_messages/twblue-documentation.mo
Normal file
BIN
doc/locales/ru/lc_messages/twblue-documentation.mo
Normal file
Binary file not shown.
1609
doc/locales/ru/lc_messages/twblue-documentation.po
Normal file
1609
doc/locales/ru/lc_messages/twblue-documentation.po
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
|||||||
[Format]
|
[Format]
|
||||||
Type=PortableApps.comFormat
|
Type=PortableApps.comFormat
|
||||||
Version=3.0
|
Version=3.3
|
||||||
|
|
||||||
[Details]
|
[Details]
|
||||||
Name=tw blue portable
|
Name=tw blue portable
|
||||||
@@ -20,8 +20,8 @@ CommercialUse=true
|
|||||||
EULAVersion=2
|
EULAVersion=2
|
||||||
|
|
||||||
[Version]
|
[Version]
|
||||||
PackageVersion=0.80.0.0
|
PackageVersion=0.82.0.0
|
||||||
DisplayVersion=0.80
|
DisplayVersion=0.82
|
||||||
|
|
||||||
[Control]
|
[Control]
|
||||||
Icons=1
|
Icons=1
|
||||||
|
@@ -12,10 +12,10 @@ SetCompress auto
|
|||||||
SetCompressor /solid lzma
|
SetCompressor /solid lzma
|
||||||
SetDatablockOptimize on
|
SetDatablockOptimize on
|
||||||
VIAddVersionKey ProductName "TWBlue"
|
VIAddVersionKey ProductName "TWBlue"
|
||||||
VIAddVersionKey LegalCopyright "Copyright 2015 Manuel Cortéz."
|
VIAddVersionKey LegalCopyright "Copyright 2016 Manuel Cortéz."
|
||||||
VIAddVersionKey ProductVersion "0.80"
|
VIAddVersionKey ProductVersion "0.82"
|
||||||
VIAddVersionKey FileVersion "0.80"
|
VIAddVersionKey FileVersion "0.82"
|
||||||
VIProductVersion "0.80.0.0"
|
VIProductVersion "0.82.0.0"
|
||||||
!insertmacro MUI_PAGE_WELCOME
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
!define MUI_LICENSEPAGE_RADIOBUTTONS
|
||||||
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
!insertmacro MUI_PAGE_LICENSE "license.txt"
|
||||||
@@ -69,10 +69,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\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
|
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" "Publisher" "Manuel Cortéz"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.80"
|
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.82"
|
||||||
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es"
|
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" "VersionMajor" 0
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 80
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 82
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
|
||||||
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
|
||||||
SectionEnd
|
SectionEnd
|
||||||
|
@@ -39,6 +39,3 @@ spelling_language = string(default="")
|
|||||||
save_followers_in_autocompletion_db = boolean(default=False)
|
save_followers_in_autocompletion_db = boolean(default=False)
|
||||||
save_friends_in_autocompletion_db = boolean(default=False)
|
save_friends_in_autocompletion_db = boolean(default=False)
|
||||||
twishort_enabled = boolean(default=False)
|
twishort_enabled = boolean(default=False)
|
||||||
|
|
||||||
[services]
|
|
||||||
pocket_access_token = string(default="")
|
|
@@ -15,6 +15,7 @@ speak_ready_msg = boolean(default=True)
|
|||||||
log_level = string(default="error")
|
log_level = string(default="error")
|
||||||
load_keymap = string(default="default.keymap")
|
load_keymap = string(default="default.keymap")
|
||||||
donation_dialog_displayed = boolean(default=False)
|
donation_dialog_displayed = boolean(default=False)
|
||||||
|
check_for_updates = boolean(default=True)
|
||||||
|
|
||||||
[proxy]
|
[proxy]
|
||||||
server = string(default="")
|
server = string(default="")
|
||||||
|
@@ -1,12 +1,14 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
name = 'TWBlue'
|
name = 'TWBlue'
|
||||||
snapshot = True
|
snapshot = False
|
||||||
if snapshot == False:
|
if snapshot == False:
|
||||||
version = "0.80"
|
version = "0.82"
|
||||||
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
update_url = 'http://twblue.es/updates/twblue_ngen.json'
|
||||||
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||||
else:
|
else:
|
||||||
version = "10.99"
|
version = "10.99"
|
||||||
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
update_url = 'http://twblue.es/updates/snapshots_ngen.json'
|
||||||
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||||
author = u"Manuel Cortéz"
|
author = u"Manuel Cortéz"
|
||||||
authorEmail = "manuel@manuelcortez.net"
|
authorEmail = "manuel@manuelcortez.net"
|
||||||
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2013-2015, Manuel cortéz."
|
copyright = u"Copyright (C) 2015, Technow S.L. \nCopyright (C) 2013-2015, Manuel cortéz."
|
||||||
|
@@ -10,7 +10,7 @@ def convert_audioboom(url):
|
|||||||
audio_id = url.split('.com/')[-1]
|
audio_id = url.split('.com/')[-1]
|
||||||
return 'https://audioboom.com/%s.mp3' % audio_id
|
return 'https://audioboom.com/%s.mp3' % audio_id
|
||||||
|
|
||||||
@matches_url ('http://soundcloud.com/')
|
@matches_url ('https://soundcloud.com/')
|
||||||
def convert_soundcloud (url):
|
def convert_soundcloud (url):
|
||||||
client_id = "df8113ca95c157b6c9731f54b105b473"
|
client_id = "df8113ca95c157b6c9731f54b105b473"
|
||||||
permalink = urllib.urlopen ('http://api.soundcloud.com/resolve.json?client_id=%s&url=%s' %(client_id, url))
|
permalink = urllib.urlopen ('http://api.soundcloud.com/resolve.json?client_id=%s&url=%s' %(client_id, url))
|
||||||
|
4966
src/cacert.pem
4966
src/cacert.pem
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,9 @@ from configobj import ConfigObj, ParseError
|
|||||||
from validate import Validator, ValidateError
|
from validate import Validator, ValidateError
|
||||||
import os
|
import os
|
||||||
import string
|
import string
|
||||||
|
from logging import getLogger
|
||||||
|
log = getLogger("config_utils")
|
||||||
|
|
||||||
class ConfigLoadError(Exception): pass
|
class ConfigLoadError(Exception): pass
|
||||||
|
|
||||||
def load_config(config_path, configspec_path=None, *args, **kwargs):
|
def load_config(config_path, configspec_path=None, *args, **kwargs):
|
||||||
@@ -14,10 +17,12 @@ def load_config(config_path, configspec_path=None, *args, **kwargs):
|
|||||||
except ParseError:
|
except ParseError:
|
||||||
raise ConfigLoadError("Unable to load %r" % config_path)
|
raise ConfigLoadError("Unable to load %r" % config_path)
|
||||||
validator = Validator()
|
validator = Validator()
|
||||||
validated = config.validate(validator, copy=True)
|
validated = config.validate(validator, preserve_errors=False, copy=True)
|
||||||
if validated == True:
|
if validated == True:
|
||||||
config.write()
|
config.write()
|
||||||
return config
|
return config
|
||||||
|
else:
|
||||||
|
log.exception("Error in config file: {0}".format(validated,))
|
||||||
|
|
||||||
def is_blank(arg):
|
def is_blank(arg):
|
||||||
"Check if a line is blank."
|
"Check if a line is blank."
|
||||||
@@ -25,6 +30,7 @@ def is_blank(arg):
|
|||||||
if c not in string.whitespace:
|
if c not in string.whitespace:
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def get_keys(path):
|
def get_keys(path):
|
||||||
"Gets the keys of a configobj config file."
|
"Gets the keys of a configobj config file."
|
||||||
res=[]
|
res=[]
|
||||||
|
38
src/controller/attach.py
Normal file
38
src/controller/attach.py
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import widgetUtils
|
||||||
|
import logging
|
||||||
|
from wxUI.dialogs import attach as gui
|
||||||
|
log = logging.getLogger("controller.attach")
|
||||||
|
|
||||||
|
class attach(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.attachments = list()
|
||||||
|
self.dialog = gui.attachDialog()
|
||||||
|
widgetUtils.connect_event(self.dialog.photo, widgetUtils.BUTTON_PRESSED, self.upload_image)
|
||||||
|
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.remove_attachment)
|
||||||
|
self.dialog.get_response()
|
||||||
|
log.debug("Attachments controller started.")
|
||||||
|
|
||||||
|
def upload_image(self, *args, **kwargs):
|
||||||
|
image, description = self.dialog.get_image()
|
||||||
|
if image != None:
|
||||||
|
imageInfo = {"type": "photo", "file": image, "description": description}
|
||||||
|
log.debug("Image data to upload: %r" % (imageInfo,))
|
||||||
|
self.attachments.append(imageInfo)
|
||||||
|
info = [_(u"Photo"), description]
|
||||||
|
self.dialog.attachments.insert_item(False, *info)
|
||||||
|
self.dialog.remove.Enable(True)
|
||||||
|
|
||||||
|
def remove_attachment(self, *args, **kwargs):
|
||||||
|
current_item = self.dialog.attachments.get_selected()
|
||||||
|
log.debug("Removing item %d" % (current_item,))
|
||||||
|
if current_item == -1: current_item = 0
|
||||||
|
self.attachments.pop(current_item)
|
||||||
|
self.dialog.attachments.remove_item(current_item)
|
||||||
|
self.check_remove_status()
|
||||||
|
log.debug("Removed")
|
||||||
|
|
||||||
|
def check_remove_status(self):
|
||||||
|
if len(self.attachments) == 0 and self.dialog.attachments.get_count() == 0:
|
||||||
|
self.dialog.remove.Enable(False)
|
@@ -49,6 +49,7 @@ class bufferController(object):
|
|||||||
|
|
||||||
|
|
||||||
def get_event(self, ev):
|
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"
|
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
|
||||||
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
||||||
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
||||||
@@ -136,16 +137,25 @@ class bufferController(object):
|
|||||||
self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue()
|
self.session.settings["mysc"]["twishort_enabled"] = tweet.message.long_tweet.GetValue()
|
||||||
text = tweet.message.get_text()
|
text = tweet.message.get_text()
|
||||||
if len(text) > 140 and tweet.message.get("long_tweet") == True:
|
if len(text) > 140 and tweet.message.get("long_tweet") == True:
|
||||||
if tweet.image == None:
|
if not hasattr(tweet, "attachments"):
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
||||||
else:
|
else:
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
||||||
if tweet.image == None:
|
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)
|
||||||
else:
|
else:
|
||||||
call_threaded(self.session.api_call, call_name="update_status_with_media", status=text, media=tweet.image)
|
call_threaded(self.post_with_media, text=text, attachments=tweet.attachments)
|
||||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
||||||
|
|
||||||
|
def post_with_media(self, text, attachments):
|
||||||
|
media_ids = []
|
||||||
|
for i in attachments:
|
||||||
|
photo = open(i["file"], "rb")
|
||||||
|
img = self.session.twitter.twitter.upload_media(media=photo)
|
||||||
|
self.session.twitter.twitter.set_description(media_id=img["media_id"], alt_text=dict(text=i["description"]))
|
||||||
|
media_ids.append(img["media_id"])
|
||||||
|
self.session.twitter.twitter.update_status(status=text, media_ids=media_ids)
|
||||||
|
|
||||||
def save_positions(self):
|
def save_positions(self):
|
||||||
try:
|
try:
|
||||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||||
@@ -200,7 +210,7 @@ class accountPanel(bufferController):
|
|||||||
|
|
||||||
class emptyPanel(bufferController):
|
class emptyPanel(bufferController):
|
||||||
def __init__(self, parent, name, account):
|
def __init__(self, parent, name, account):
|
||||||
super(emptyPanel, self).__init__(parent, None, name)
|
super(emptyPanel, self).__init__(parent=parent)
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
self.buffer = buffers.emptyPanel(parent, name)
|
self.buffer = buffers.emptyPanel(parent, name)
|
||||||
self.type = self.buffer.type
|
self.type = self.buffer.type
|
||||||
@@ -242,11 +252,11 @@ class baseBufferController(bufferController):
|
|||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
tweetsList = []
|
tweetsList = []
|
||||||
tweet_id = tweet["id"]
|
tweet_id = tweet["id"]
|
||||||
uri = None
|
message = None
|
||||||
if tweet.has_key("long_uri"):
|
if tweet.has_key("message"):
|
||||||
uri = tweet["long_uri"]
|
message = tweet["message"]
|
||||||
try:
|
try:
|
||||||
tweet = self.session.twitter.twitter.show_status(id=tweet_id)
|
tweet = self.session.twitter.twitter.show_status(id=tweet_id, include_ext_alt_text=True)
|
||||||
urls = utils.find_urls_in_text(tweet["text"])
|
urls = utils.find_urls_in_text(tweet["text"])
|
||||||
for url in range(0, len(urls)):
|
for url in range(0, len(urls)):
|
||||||
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||||
@@ -254,14 +264,13 @@ class baseBufferController(bufferController):
|
|||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
utils.twitter_error(e)
|
utils.twitter_error(e)
|
||||||
return
|
return
|
||||||
if uri != None:
|
if message != None:
|
||||||
tweet["text"] = twishort.get_full_text(uri)
|
tweet["message"] = message
|
||||||
l = tweets.is_long(tweet)
|
l = tweets.is_long(tweet)
|
||||||
while l != False:
|
while l != False:
|
||||||
tweetsList.append(tweet)
|
tweetsList.append(tweet)
|
||||||
id = tweets.get_id(l)
|
|
||||||
try:
|
try:
|
||||||
tweet = self.session.twitter.twitter.show_status(id=id)
|
tweet = self.session.twitter.twitter.show_status(id=l, include_ext_alt_text=True)
|
||||||
urls = utils.find_urls_in_text(tweet["text"])
|
urls = utils.find_urls_in_text(tweet["text"])
|
||||||
for url in range(0, len(urls)):
|
for url in range(0, len(urls)):
|
||||||
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
try: tweet["text"] = tweet["text"].replace(urls[url], tweet["entities"]["urls"][url]["expanded_url"])
|
||||||
@@ -300,7 +309,9 @@ class baseBufferController(bufferController):
|
|||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
for i in items:
|
for i in items:
|
||||||
if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == True:
|
if utils.is_allowed(i, self.session.settings["twitter"]["ignored_clients"]) == True and utils.find_item(i["id"], self.session.db[self.name]) == None:
|
||||||
|
i = self.session.check_quoted_status(i)
|
||||||
|
i = self.session.check_long_tweet(i)
|
||||||
elements.append(i)
|
elements.append(i)
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
self.session.db[self.name].insert(0, i)
|
self.session.db[self.name].insert(0, i)
|
||||||
@@ -326,6 +337,7 @@ class baseBufferController(bufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
||||||
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -334,6 +346,7 @@ class baseBufferController(bufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
||||||
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -341,7 +354,15 @@ class baseBufferController(bufferController):
|
|||||||
output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True)
|
output.speak(_(u"This buffer is not a timeline; it can't be deleted."), True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def remove_tweet(self, id):
|
||||||
|
if type(self.session.db[self.name]) == dict: return
|
||||||
|
for i in xrange(0, len(self.session.db[self.name])):
|
||||||
|
if self.session.db[self.name][i]["id"] == id:
|
||||||
|
self.session.db[self.name].pop(i)
|
||||||
|
self.remove_item(i)
|
||||||
|
|
||||||
def put_items_on_list(self, number_of_items):
|
def put_items_on_list(self, number_of_items):
|
||||||
|
if number_of_items == 0: return
|
||||||
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
|
log.debug("The list contains %d items " % (self.buffer.list.get_count(),))
|
||||||
log.debug("Putting %d items on the list" % (number_of_items,))
|
log.debug("Putting %d items on the list" % (number_of_items,))
|
||||||
if self.buffer.list.get_count() == 0:
|
if self.buffer.list.get_count() == 0:
|
||||||
@@ -351,11 +372,14 @@ class baseBufferController(bufferController):
|
|||||||
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
self.buffer.set_position(self.session.settings["general"]["reverse_timelines"])
|
||||||
elif self.buffer.list.get_count() > 0:
|
elif self.buffer.list.get_count() > 0:
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
for i in self.session.db[self.name][:number_of_items]:
|
items = self.session.db[self.name][len(self.session.db[self.name])-number_of_items:]
|
||||||
|
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.buffer.list.insert_item(False, *tweet)
|
self.buffer.list.insert_item(False, *tweet)
|
||||||
else:
|
else:
|
||||||
for i in self.session.db[self.name][0:number_of_items]:
|
items = self.session.db[self.name][0:number_of_items]
|
||||||
|
items.reverse()
|
||||||
|
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.buffer.list.insert_item(True, *tweet)
|
self.buffer.list.insert_item(True, *tweet)
|
||||||
log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),))
|
log.debug("Now the list contains %d items " % (self.buffer.list.get_count(),))
|
||||||
@@ -664,6 +688,7 @@ class listBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
||||||
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -735,6 +760,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
||||||
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -743,6 +769,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
||||||
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -819,7 +846,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
# self.buffer.set_list_position()
|
# self.buffer.set_list_position()
|
||||||
elif self.buffer.list.get_count() > 0:
|
elif self.buffer.list.get_count() > 0:
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
for i in self.session.db[self.name]["items"][:number_of_items]:
|
for i in self.session.db[self.name]["items"][len(self.session.db[self.name]["items"])-number_of_items:]:
|
||||||
tweet = self.compose_function(i, self.session.db)
|
tweet = self.compose_function(i, self.session.db)
|
||||||
self.buffer.list.insert_item(False, *tweet)
|
self.buffer.list.insert_item(False, *tweet)
|
||||||
else:
|
else:
|
||||||
@@ -892,6 +919,7 @@ class searchBufferController(baseBufferController):
|
|||||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||||
self.timer.cancel()
|
self.timer.cancel()
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -932,6 +960,7 @@ class searchPeopleBufferController(peopleBufferController):
|
|||||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||||
self.timer.cancel()
|
self.timer.cancel()
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
@@ -955,10 +984,10 @@ class trendsBufferController(bufferController):
|
|||||||
self.get_formatted_message = self.get_message
|
self.get_formatted_message = self.get_message
|
||||||
self.reply = self.search_topic
|
self.reply = self.search_topic
|
||||||
|
|
||||||
def start_stream(self):
|
def start_stream(self, mandatory=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
||||||
self.execution_time = current_time
|
self.execution_time = current_time
|
||||||
try:
|
try:
|
||||||
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
|
data = self.session.call_paged("get_place_trends", id=self.trendsFor)
|
||||||
@@ -999,10 +1028,14 @@ class trendsBufferController(bufferController):
|
|||||||
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||||
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
||||||
self.timer.cancel()
|
self.timer.cancel()
|
||||||
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def url(self, *args, **kwargs):
|
||||||
|
self.tweet_about_this_trend()
|
||||||
|
|
||||||
def search_topic(self, *args, **kwargs):
|
def search_topic(self, *args, **kwargs):
|
||||||
topic = self.trends[self.buffer.list.get_selected()]["name"]
|
topic = self.trends[self.buffer.list.get_selected()]["name"]
|
||||||
pub.sendMessage("search", term=topic)
|
pub.sendMessage("search", term=topic)
|
||||||
@@ -1052,10 +1085,10 @@ class trendsBufferController(bufferController):
|
|||||||
|
|
||||||
class conversationBufferController(searchBufferController):
|
class conversationBufferController(searchBufferController):
|
||||||
|
|
||||||
def start_stream(self, start=False):
|
def start_stream(self, start=False, mandatory=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
||||||
self.execution_time = current_time
|
self.execution_time = current_time
|
||||||
if start == True:
|
if start == True:
|
||||||
self.statuses = []
|
self.statuses = []
|
||||||
@@ -1064,7 +1097,10 @@ class conversationBufferController(searchBufferController):
|
|||||||
self.ids.append(self.tweet["id"])
|
self.ids.append(self.tweet["id"])
|
||||||
tweet = self.tweet
|
tweet = self.tweet
|
||||||
while tweet["in_reply_to_status_id"] != None:
|
while tweet["in_reply_to_status_id"] != None:
|
||||||
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
|
try:
|
||||||
|
tweet = self.session.twitter.twitter.show_status(id=tweet["in_reply_to_status_id"])
|
||||||
|
except TwythonError as err:
|
||||||
|
break
|
||||||
self.statuses.insert(0, tweet)
|
self.statuses.insert(0, tweet)
|
||||||
self.ids.append(tweet["id"])
|
self.ids.append(tweet["id"])
|
||||||
if tweet["in_reply_to_status_id"] == None:
|
if tweet["in_reply_to_status_id"] == None:
|
||||||
|
@@ -119,6 +119,7 @@ class Controller(object):
|
|||||||
pub.subscribe(self.manage_item_in_timeline, "item-in-timeline")
|
pub.subscribe(self.manage_item_in_timeline, "item-in-timeline")
|
||||||
pub.subscribe(self.manage_item_in_list, "item-in-list")
|
pub.subscribe(self.manage_item_in_list, "item-in-list")
|
||||||
pub.subscribe(self.restart_streams_, "restart_streams")
|
pub.subscribe(self.restart_streams_, "restart_streams")
|
||||||
|
pub.subscribe(self.on_tweet_deleted, "tweet-deleted")
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_)
|
widgetUtils.connect_event(self.view, widgetUtils.CLOSE_EVENT, self.exit_)
|
||||||
|
|
||||||
def bind_other_events(self):
|
def bind_other_events(self):
|
||||||
@@ -191,6 +192,7 @@ class Controller(object):
|
|||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.update_profile, menuitem=self.systrayIcon.update_profile)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.update_profile, menuitem=self.systrayIcon.update_profile)
|
||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.show_hide, menuitem=self.systrayIcon.show_hide)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.show_hide, menuitem=self.systrayIcon.show_hide)
|
||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.check_for_updates, menuitem=self.systrayIcon.check_for_updates)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.check_for_updates, menuitem=self.systrayIcon.check_for_updates)
|
||||||
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.view_documentation, menuitem=self.systrayIcon.doc)
|
||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.exit, menuitem=self.systrayIcon.exit)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.MENU, self.exit, menuitem=self.systrayIcon.exit)
|
||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_LEFT_CLICK, self.taskbar_left_click)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_LEFT_CLICK, self.taskbar_left_click)
|
||||||
widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_RIGHT_CLICK, self.taskbar_right_click)
|
widgetUtils.connect_event(self.systrayIcon, widgetUtils.TASKBAR_RIGHT_CLICK, self.taskbar_right_click)
|
||||||
@@ -923,7 +925,7 @@ class Controller(object):
|
|||||||
x = tweet["coordinates"]["coordinates"][0]
|
x = tweet["coordinates"]["coordinates"][0]
|
||||||
y = tweet["coordinates"]["coordinates"][1]
|
y = tweet["coordinates"]["coordinates"][1]
|
||||||
address = geocoder.reverse_geocode(y, x)
|
address = geocoder.reverse_geocode(y, x)
|
||||||
dlg = messages.viewTweet(address[0].__str__(), False)
|
dlg = commonMessageDialogs.view_geodata(address[0].__str__())
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"There are no coordinates in this tweet"))
|
output.speak(_(u"There are no coordinates in this tweet"))
|
||||||
except GeocoderError:
|
except GeocoderError:
|
||||||
@@ -1275,7 +1277,7 @@ class Controller(object):
|
|||||||
buffer = self.search_buffer("%s-timeline" % (who,), user)
|
buffer = self.search_buffer("%s-timeline" % (who,), user)
|
||||||
if buffer == None: return
|
if buffer == None: return
|
||||||
play_sound = "tweet_timeline.ogg"
|
play_sound = "tweet_timeline.ogg"
|
||||||
if "%s-timeline" % (who,) not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
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)
|
self.notify(buffer.session, play_sound=play_sound)
|
||||||
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
|
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
|
||||||
buffer.add_new_item(data)
|
buffer.add_new_item(data)
|
||||||
@@ -1284,7 +1286,7 @@ class Controller(object):
|
|||||||
buffer = self.search_buffer("%s" % (where,), user)
|
buffer = self.search_buffer("%s" % (where,), user)
|
||||||
if buffer == None: return
|
if buffer == None: return
|
||||||
play_sound = "list_tweet.ogg"
|
play_sound = "list_tweet.ogg"
|
||||||
if "%s" % (where,) not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
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)
|
self.notify(buffer.session, play_sound=play_sound)
|
||||||
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
|
output.speak(_(u"One tweet from %s") % (data["user"]["name"]))
|
||||||
buffer.add_new_item(data)
|
buffer.add_new_item(data)
|
||||||
@@ -1484,4 +1486,10 @@ class Controller(object):
|
|||||||
output.speak(_(u"Updating buffer..."))
|
output.speak(_(u"Updating buffer..."))
|
||||||
n = bf.start_stream(mandatory=True)
|
n = bf.start_stream(mandatory=True)
|
||||||
if n != None:
|
if n != None:
|
||||||
output.speak(_(u"{0} items retrieved").format(n,))
|
output.speak(_(u"{0} items retrieved").format(n,))
|
||||||
|
|
||||||
|
def on_tweet_deleted(self, data):
|
||||||
|
id = data["delete"]["status"]["id"]
|
||||||
|
for i in self.buffers:
|
||||||
|
if hasattr(i, "remove_tweet") and hasattr(i, "name"):
|
||||||
|
i.remove_tweet(id)
|
@@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import re
|
import re
|
||||||
import platform
|
import platform
|
||||||
|
import attach
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import output
|
import output
|
||||||
@@ -32,6 +33,7 @@ class basicTweet(object):
|
|||||||
widgetUtils.connect_event(self.message.shortenButton, widgetUtils.BUTTON_PRESSED, self.shorten)
|
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.unshortenButton, widgetUtils.BUTTON_PRESSED, self.unshorten)
|
||||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||||
|
self.attachments = []
|
||||||
|
|
||||||
def translate(self, event=None):
|
def translate(self, event=None):
|
||||||
dlg = translator.gui.translateDialog()
|
dlg = translator.gui.translateDialog()
|
||||||
@@ -102,7 +104,7 @@ class basicTweet(object):
|
|||||||
self.message.text_focus()
|
self.message.text_focus()
|
||||||
|
|
||||||
def attach(self, *args, **kwargs):
|
def attach(self, *args, **kwargs):
|
||||||
def completed_callback():
|
def completed_callback(dlg):
|
||||||
url = dlg.uploaderFunction.get_url()
|
url = dlg.uploaderFunction.get_url()
|
||||||
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
|
pub.unsubscribe(dlg.uploaderDialog.update, "uploading")
|
||||||
dlg.uploaderDialog.destroy()
|
dlg.uploaderDialog.destroy()
|
||||||
@@ -125,16 +127,9 @@ class tweet(basicTweet):
|
|||||||
except AttributeError: pass
|
except AttributeError: pass
|
||||||
|
|
||||||
def upload_image(self, *args, **kwargs):
|
def upload_image(self, *args, **kwargs):
|
||||||
if self.message.get("upload_image") == _(u"Discard image"):
|
a = attach.attach()
|
||||||
del self.image
|
if len(a.attachments) != 0:
|
||||||
self.image = None
|
self.attachments = a.attachments
|
||||||
output.speak(_(u"Discarded"))
|
|
||||||
self.message.set("upload_image", _(u"Upload a picture"))
|
|
||||||
else:
|
|
||||||
self.image = self.message.get_image()
|
|
||||||
if self.image != None:
|
|
||||||
self.message.set("upload_image", _(u"Discard image"))
|
|
||||||
self.message.text_focus()
|
|
||||||
|
|
||||||
def autocomplete_users(self, *args, **kwargs):
|
def autocomplete_users(self, *args, **kwargs):
|
||||||
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
c = autocompletionUsers.completion.autocompletionUsers(self.message, self.session.session_id)
|
||||||
@@ -165,24 +160,56 @@ class dm(basicTweet):
|
|||||||
|
|
||||||
class viewTweet(basicTweet):
|
class viewTweet(basicTweet):
|
||||||
def __init__(self, tweet, tweetList, is_tweet=True):
|
def __init__(self, tweet, tweetList, is_tweet=True):
|
||||||
|
""" This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event.
|
||||||
|
param tweet: A dictionary that represents a full tweet or a string for non-tweets.
|
||||||
|
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:
|
if is_tweet == True:
|
||||||
|
image_description = []
|
||||||
text = ""
|
text = ""
|
||||||
for i in xrange(0, len(tweetList)):
|
for i in xrange(0, len(tweetList)):
|
||||||
if tweetList[i].has_key("retweeted_status"):
|
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
||||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["text"])
|
if tweetList[i].has_key("message") and tweetList[i]["is_quote_status"] == False:
|
||||||
|
value = "message"
|
||||||
else:
|
else:
|
||||||
text = text + "@%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i]["text"])
|
value = "text"
|
||||||
|
if tweetList[i].has_key("retweeted_status") and tweetList[i]["is_quote_status"] == False:
|
||||||
|
if tweetList[i].has_key("message") == False:
|
||||||
|
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["text"])
|
||||||
|
else:
|
||||||
|
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
||||||
|
else:
|
||||||
|
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
||||||
|
# tweets with extended_entities could include image descriptions.
|
||||||
|
if tweetList[i].has_key("extended_entities") and tweetList[i]["extended_entities"].has_key("media"):
|
||||||
|
for z in tweetList[i]["extended_entities"]["media"]:
|
||||||
|
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||||
|
image_description.append(z["ext_alt_text"])
|
||||||
|
# set rt and likes counters.
|
||||||
rt_count = str(tweet["retweet_count"])
|
rt_count = str(tweet["retweet_count"])
|
||||||
favs_count = str(tweet["favorite_count"])
|
favs_count = str(tweet["favorite_count"])
|
||||||
source = str(re.sub(r"(?s)<.*?>", "", tweet["source"]))
|
# Gets the client from where this tweet was made.
|
||||||
|
source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8")))
|
||||||
if text == "":
|
if text == "":
|
||||||
if tweet.has_key("retweeted_status"):
|
if tweet.has_key("message"):
|
||||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
|
value = "message"
|
||||||
else:
|
else:
|
||||||
text = tweet["text"]
|
value = "text"
|
||||||
|
if tweet.has_key("retweeted_status"):
|
||||||
|
if tweet.has_key("message") == False:
|
||||||
|
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["text"])
|
||||||
|
else:
|
||||||
|
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
||||||
|
else:
|
||||||
|
text = tweet[value]
|
||||||
text = self.clear_text(text)
|
text = self.clear_text(text)
|
||||||
self.message = message.viewTweet(text, rt_count, favs_count,source)
|
if tweet.has_key("extended_entities") and tweet["extended_entities"].has_key("media"):
|
||||||
|
for z in tweet["extended_entities"]["media"]:
|
||||||
|
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
||||||
|
image_description.append(z["ext_alt_text"])
|
||||||
|
self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8"))
|
||||||
self.message.set_title(len(text))
|
self.message.set_title(len(text))
|
||||||
|
[self.message.set_image_description(i) for i in image_description]
|
||||||
else:
|
else:
|
||||||
text = tweet
|
text = tweet
|
||||||
self.message = message.viewNonTweet(text)
|
self.message = message.viewNonTweet(text)
|
||||||
@@ -202,5 +229,5 @@ class viewTweet(basicTweet):
|
|||||||
urls = utils.find_urls_in_text(text)
|
urls = utils.find_urls_in_text(text)
|
||||||
for i in urls:
|
for i in urls:
|
||||||
if "https://twitter.com/" in i:
|
if "https://twitter.com/" in i:
|
||||||
text = text.replace(i, "")
|
text = text.replace(i, "\n")
|
||||||
return text
|
return text
|
||||||
|
@@ -64,11 +64,13 @@ class globalSettingsController(object):
|
|||||||
self.dialog.set_value("general", "use_invisible_shorcuts", config.app["app-settings"]["use_invisible_keyboard_shorcuts"])
|
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", "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", "hide_gui", config.app["app-settings"]["hide_gui"])
|
||||||
|
self.dialog.set_value("general", "check_for_updates", config.app["app-settings"]["check_for_updates"])
|
||||||
self.dialog.create_proxy()
|
self.dialog.create_proxy()
|
||||||
self.dialog.set_value("proxy", "server", config.app["proxy"]["server"])
|
self.dialog.set_value("proxy", "server", config.app["proxy"]["server"])
|
||||||
self.dialog.set_value("proxy", "port", config.app["proxy"]["port"])
|
self.dialog.set_value("proxy", "port", config.app["proxy"]["port"])
|
||||||
self.dialog.set_value("proxy", "user", config.app["proxy"]["user"])
|
self.dialog.set_value("proxy", "user", config.app["proxy"]["user"])
|
||||||
self.dialog.set_value("proxy", "password", config.app["proxy"]["password"])
|
self.dialog.set_value("proxy", "password", config.app["proxy"]["password"])
|
||||||
|
|
||||||
self.dialog.realize()
|
self.dialog.realize()
|
||||||
self.response = self.dialog.get_response()
|
self.response = self.dialog.get_response()
|
||||||
|
|
||||||
@@ -92,6 +94,7 @@ class globalSettingsController(object):
|
|||||||
config.app["app-settings"]["handle_longtweets"] = self.dialog.get_value("general", "handle_longtweets")
|
config.app["app-settings"]["handle_longtweets"] = self.dialog.get_value("general", "handle_longtweets")
|
||||||
config.app["app-settings"]["play_ready_sound"] = self.dialog.get_value("general", "play_ready_sound")
|
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"]["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")
|
||||||
if 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 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:
|
if self.is_started == True:
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
|
@@ -31,6 +31,8 @@ class profileController(object):
|
|||||||
|
|
||||||
def get_data(self, screen_name):
|
def get_data(self, screen_name):
|
||||||
self.data = self.session.twitter.twitter.show_user(screen_name=screen_name)
|
self.data = self.session.twitter.twitter.show_user(screen_name=screen_name)
|
||||||
|
if screen_name != self.session.db["user_name"]:
|
||||||
|
self.friendship_status = self.session.twitter.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name)
|
||||||
|
|
||||||
def fill_profile_fields(self):
|
def fill_profile_fields(self):
|
||||||
self.dialog.set_name(self.data["name"])
|
self.dialog.set_name(self.data["name"])
|
||||||
@@ -90,6 +92,17 @@ class profileController(object):
|
|||||||
if self.data["protected"] == True: protected = _(u"Yes")
|
if self.data["protected"] == True: protected = _(u"Yes")
|
||||||
else: protected = _(u"No")
|
else: protected = _(u"No")
|
||||||
string = string+ _(u"Protected: %s\n") % (protected)
|
string = string+ _(u"Protected: %s\n") % (protected)
|
||||||
|
if hasattr(self, "friendship_status"):
|
||||||
|
relation = False
|
||||||
|
friendship = "Relationship: "
|
||||||
|
if self.friendship_status["relationship"]["target"]["followed_by"]:
|
||||||
|
friendship += _(u"You follow {0}. ").format(self.data["name"],)
|
||||||
|
relation = True
|
||||||
|
if self.friendship_status["relationship"]["target"]["following"]:
|
||||||
|
friendship += _(u"{0} is following you.").format(self.data["name"],)
|
||||||
|
relation = True
|
||||||
|
if relation == True:
|
||||||
|
string = string+friendship+"\n"
|
||||||
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"])
|
string = string+_(u"Followers: %s\n Friends: %s\n") % (self.data["followers_count"], self.data["friends_count"])
|
||||||
if self.data["verified"] == True: verified = _(u"Yes")
|
if self.data["verified"] == True: verified = _(u"Yes")
|
||||||
else: verified = _(u"No")
|
else: verified = _(u"No")
|
||||||
|
@@ -57,18 +57,16 @@ class audioUploader(object):
|
|||||||
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
|
url = base_url + '?apikey=' + self.config['sound']['sndup_api_key']
|
||||||
else:
|
else:
|
||||||
url = base_url
|
url = base_url
|
||||||
self.uploaderFunction = transfer.Upload(field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
|
||||||
elif self.dialog.get("services") == "TwUp":
|
elif self.dialog.get("services") == "TwUp":
|
||||||
url = "http://api.twup.me/post.json"
|
url = "http://api.twup.me/post.json"
|
||||||
self.uploaderFunction = transfer.Upload(field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
self.uploaderFunction = transfer.Upload(obj=self, field='file', url=url, filename=self.file, completed_callback=completed_callback)
|
||||||
pub.subscribe(self.uploaderDialog.update, "uploading")
|
pub.subscribe(self.uploaderDialog.update, "uploading")
|
||||||
self.uploaderDialog.get_response()
|
self.uploaderDialog.get_response(self.uploaderFunction.perform_threaded)
|
||||||
self.uploaderFunction.perform_threaded()
|
|
||||||
|
|
||||||
def get_available_services(self):
|
def get_available_services(self):
|
||||||
services = []
|
services = []
|
||||||
services.append("TwUp")
|
|
||||||
services.append("SNDUp")
|
services.append("SNDUp")
|
||||||
|
services.append("TwUp")
|
||||||
return services
|
return services
|
||||||
|
|
||||||
def on_pause(self, *args, **kwargs):
|
def on_pause(self, *args, **kwargs):
|
||||||
@@ -116,8 +114,9 @@ class audioUploader(object):
|
|||||||
if self.playing:
|
if self.playing:
|
||||||
self._stop()
|
self._stop()
|
||||||
if self.recording != None:
|
if self.recording != None:
|
||||||
self.dialog.disable_control("attach")
|
self.cleanup()
|
||||||
self.dialog.disable_control("play")
|
self.dialog.disable_control("attach")
|
||||||
|
self.dialog.disable_control("play")
|
||||||
self.file = None
|
self.file = None
|
||||||
self.dialog.enable_control("record")
|
self.dialog.enable_control("record")
|
||||||
self.dialog.enable_control("attach_exists")
|
self.dialog.enable_control("attach_exists")
|
||||||
@@ -174,10 +173,6 @@ class audioUploader(object):
|
|||||||
os.remove(self.file)
|
os.remove(self.file)
|
||||||
if hasattr(self, 'wav_file'):
|
if hasattr(self, 'wav_file'):
|
||||||
os.remove(self.wav_file)
|
os.remove(self.wav_file)
|
||||||
del(self.wav_file)
|
|
||||||
if hasattr(self, 'wav_file') and os.path.exists(self.file):
|
|
||||||
os.remove(self.file)
|
|
||||||
|
|
||||||
|
|
||||||
def on_attach_exists(self, *args, **kwargs):
|
def on_attach_exists(self, *args, **kwargs):
|
||||||
self.file = self.dialog.get_file()
|
self.file = self.dialog.get_file()
|
||||||
|
@@ -1,106 +1,68 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import pycurl
|
import sys
|
||||||
import sys
|
import threading
|
||||||
import threading
|
import time
|
||||||
import time
|
import logging
|
||||||
import json
|
from utils import convert_bytes
|
||||||
import logging
|
from pubsub import pub
|
||||||
from utils import *
|
log = logging.getLogger("extra.AudioUploader.transfer")
|
||||||
from pubsub import pub
|
from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
|
||||||
|
import requests
|
||||||
log = logging.getLogger("extra.AudioUploader.transfer")
|
import os
|
||||||
class Transfer(object):
|
class Upload(object):
|
||||||
|
def __init__(self, field=None, obj=None, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, *args, **kwargs):
|
||||||
def __init__(self, url=None, filename=None, follow_location=True, completed_callback=None, verbose=False, *args, **kwargs):
|
super(Upload, self).__init__(*args, **kwargs)
|
||||||
self.url = url
|
self.url=url
|
||||||
self.filename = filename
|
self.filename=filename
|
||||||
log.debug("Uploading audio to %s, filename %s" % (url, filename))
|
log.debug("Uploading audio to %s, filename %s" % (url, filename))
|
||||||
self.curl = pycurl.Curl()
|
self.start_time = None
|
||||||
self.start_time = None
|
self.completed_callback = completed_callback
|
||||||
self.completed_callback = completed_callback
|
self.background_thread = None
|
||||||
self.background_thread = None
|
self.transfer_rate = 0
|
||||||
self.transfer_rate = 0
|
self.m = MultipartEncoder(fields={field:(os.path.basename(self.filename), open(self.filename, 'rb'), "application/octet-stream")})
|
||||||
self.curl.setopt(self.curl.PROGRESSFUNCTION, self.progress_callback)
|
self.monitor = MultipartEncoderMonitor(self.m, self.progress_callback)
|
||||||
self.curl.setopt(self.curl.URL, url)
|
self.response=None
|
||||||
self.curl.setopt(self.curl.NOPROGRESS, 0)
|
self.obj=obj
|
||||||
self.curl.setopt(self.curl.HTTP_VERSION, self.curl.CURL_HTTP_VERSION_1_0)
|
self.follow_location=follow_location
|
||||||
self.curl.setopt(self.curl.FOLLOWLOCATION, int(follow_location))
|
#the verbose parameter is deprecated and will be removed soon
|
||||||
self.curl.setopt(self.curl.VERBOSE, int(verbose))
|
|
||||||
super(Transfer, self).__init__(*args, **kwargs)
|
def elapsed_time(self):
|
||||||
|
if not self.start_time:
|
||||||
def elapsed_time(self):
|
return 0
|
||||||
if not self.start_time:
|
return time.time() - self.start_time
|
||||||
return 0
|
|
||||||
return time.time() - self.start_time
|
def progress_callback(self, monitor):
|
||||||
|
progress = {}
|
||||||
def progress_callback(self, down_total, down_current, up_total, up_current):
|
progress["total"] = monitor.len
|
||||||
progress = {}
|
progress["current"] = monitor.bytes_read
|
||||||
progress["total"] = up_total
|
if progress["current"] == 0:
|
||||||
progress["current"] = up_current
|
progress["percent"] = 0
|
||||||
# else:
|
self.transfer_rate = 0
|
||||||
# print "Killed function"
|
else:
|
||||||
# return
|
progress["percent"] = int((float(progress["current"]) / progress["total"]) * 100)
|
||||||
if progress["current"] == 0:
|
self.transfer_rate = progress["current"] / self.elapsed_time()
|
||||||
progress["percent"] = 0
|
progress["speed"] = '%s/s' % convert_bytes(self.transfer_rate)
|
||||||
self.transfer_rate = 0
|
if self.transfer_rate:
|
||||||
else:
|
progress["eta"] = (progress["total"] - progress["current"]) / self.transfer_rate
|
||||||
progress["percent"] = int((float(progress["current"]) / progress["total"]) * 100)
|
else:
|
||||||
self.transfer_rate = progress["current"] / self.elapsed_time()
|
progress["eta"] = 0
|
||||||
progress["speed"] = '%s/s' % convert_bytes(self.transfer_rate)
|
pub.sendMessage("uploading", data=progress)
|
||||||
if self.transfer_rate:
|
|
||||||
progress["eta"] = (progress["total"] - progress["current"]) / self.transfer_rate
|
def perform_transfer(self):
|
||||||
else:
|
log.debug("starting upload...")
|
||||||
progress["eta"] = 0
|
self.start_time = time.time()
|
||||||
pub.sendMessage("uploading", data=progress)
|
self.response=requests.post(url=self.url, data=self.monitor, headers={"Content-Type":self.m.content_type}, allow_redirects=self.follow_location, stream=True)
|
||||||
|
log.debug("Upload finished.")
|
||||||
def perform_transfer(self):
|
self.complete_transfer()
|
||||||
log.debug("starting upload...")
|
|
||||||
self.start_time = time.time()
|
def perform_threaded(self, *args, **kwargs):
|
||||||
self.curl.perform()
|
self.background_thread = threading.Thread(target=self.perform_transfer)
|
||||||
self.curl.close()
|
self.background_thread.daemon = True
|
||||||
log.debug("Upload finished.")
|
self.background_thread.start()
|
||||||
self.complete_transfer()
|
|
||||||
|
def complete_transfer(self):
|
||||||
def perform_threaded(self):
|
if callable(self.completed_callback):
|
||||||
self.background_thread = threading.Thread(target=self.perform_transfer)
|
self.completed_callback(self.obj)
|
||||||
self.background_thread.daemon = True
|
|
||||||
self.background_thread.start()
|
def get_url(self):
|
||||||
|
return self.response.json()['url']
|
||||||
def complete_transfer(self):
|
|
||||||
if callable(self.completed_callback):
|
|
||||||
self.curl.close()
|
|
||||||
self.completed_callback()
|
|
||||||
|
|
||||||
class Upload(Transfer):
|
|
||||||
|
|
||||||
def __init__(self, field=None, filename=None, *args, **kwargs):
|
|
||||||
super(Upload, self).__init__(filename=filename, *args, **kwargs)
|
|
||||||
self.response = dict()
|
|
||||||
self.curl.setopt(self.curl.POST, 1)
|
|
||||||
if isinstance(filename, unicode):
|
|
||||||
local_filename = filename.encode(sys.getfilesystemencoding())
|
|
||||||
else:
|
|
||||||
local_filename = filename
|
|
||||||
self.curl.setopt(self.curl.HTTPPOST, [(field, (self.curl.FORM_FILE, local_filename, self.curl.FORM_FILENAME, filename.encode("utf-8")))])
|
|
||||||
self.curl.setopt(self.curl.HEADERFUNCTION, self.header_callback)
|
|
||||||
self.curl.setopt(self.curl.WRITEFUNCTION, self.body_callback)
|
|
||||||
|
|
||||||
def header_callback(self, content):
|
|
||||||
self.response['header'] = content
|
|
||||||
|
|
||||||
def body_callback(self, content):
|
|
||||||
self.response['body'] = content
|
|
||||||
|
|
||||||
def get_url(self):
|
|
||||||
return json.loads(self.response['body'])['url']
|
|
||||||
|
|
||||||
class Download(Transfer):
|
|
||||||
|
|
||||||
def __init__(self, follow_location=True, *args, **kwargs):
|
|
||||||
super(Download, self).__init__(*args, **kwargs)
|
|
||||||
self.download_file = open(self.filename, 'wb')
|
|
||||||
self.curl.setopt(self.curl.WRITEFUNCTION, self.download_file.write)
|
|
||||||
|
|
||||||
def complete_transfer(self):
|
|
||||||
self.download_file.close()
|
|
||||||
super(DownloadDialog, self).complete_transfer()
|
|
||||||
|
@@ -3,10 +3,10 @@ import wx
|
|||||||
from utils import *
|
from utils import *
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class TransferDialog(widgetUtils.BaseDialog):
|
class UploadDialog(widgetUtils.BaseDialog):
|
||||||
|
|
||||||
def __init__(self, filename, *args, **kwargs):
|
def __init__(self, filename, *args, **kwargs):
|
||||||
super(TransferDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs)
|
super(UploadDialog, self).__init__(parent=None, id=wx.NewId(), *args, **kwargs)
|
||||||
self.pane = wx.Panel(self)
|
self.pane = wx.Panel(self)
|
||||||
self.progress_bar = wx.Gauge(parent=self.pane)
|
self.progress_bar = wx.Gauge(parent=self.pane)
|
||||||
fileBox = wx.BoxSizer(wx.HORIZONTAL)
|
fileBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
@@ -56,18 +56,6 @@ class TransferDialog(widgetUtils.BaseDialog):
|
|||||||
def create_buttons(self):
|
def create_buttons(self):
|
||||||
self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL)
|
self.cancel_button = wx.Button(parent=self.pane, id=wx.ID_CANCEL)
|
||||||
|
|
||||||
def get_response(self):
|
def get_response(self, fn):
|
||||||
self.Show()
|
wx.CallAfter(fn, 0.01)
|
||||||
|
self.ShowModal()
|
||||||
def destroy(self):
|
|
||||||
self.Destroy()
|
|
||||||
|
|
||||||
class UploadDialog(TransferDialog):
|
|
||||||
|
|
||||||
def __init__(self, filename=None, *args, **kwargs):
|
|
||||||
super(UploadDialog, self).__init__(filename=filename, *args, **kwargs)
|
|
||||||
|
|
||||||
class DownloadDialog(TransferDialog):
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(Download, self).__init__(*args, **kwargs)
|
|
||||||
|
@@ -4,9 +4,10 @@ import sys
|
|||||||
import fix_arrow # A few new locales for Three languages in arrow.
|
import fix_arrow # A few new locales for Three languages in arrow.
|
||||||
import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
||||||
import fix_win32com
|
import fix_win32com
|
||||||
|
import fix_requests #fix cacert.pem location for TWBlue binary copies
|
||||||
def setup():
|
def setup():
|
||||||
fix_arrow.fix()
|
fix_arrow.fix()
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
fix_win32com.fix()
|
fix_win32com.fix()
|
||||||
|
fix_requests.fix()
|
||||||
fix_urllib3_warnings.fix()
|
fix_urllib3_warnings.fix()
|
10
src/fixes/fix_requests.py
Normal file
10
src/fixes/fix_requests.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from requests import certs, utils, adapters
|
||||||
|
import paths
|
||||||
|
|
||||||
|
def patched_where():
|
||||||
|
return paths.app_path(u"cacert.pem")
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
certs.where=patched_where
|
||||||
|
utils.DEFAULT_CA_BUNDLE_PATH=patched_where()
|
||||||
|
adapters.DEFAULT_CA_BUNDLE_PATH=patched_where()
|
@@ -47,7 +47,7 @@ class reportBug(object):
|
|||||||
issue.project.name = application.name
|
issue.project.name = application.name
|
||||||
issue.project.id = 0
|
issue.project.id = 0
|
||||||
issue.summary = self.dialog.get("summary"),
|
issue.summary = self.dialog.get("summary"),
|
||||||
issue.description = "Reported by @%s\n\n" % (self.user_name) + self.dialog.get("description")
|
issue.description = "Reported by @%s on version %s (snapshot = %s)\n\n" % (self.user_name, application.version, application.snapshot) + self.dialog.get("description")
|
||||||
# to do: Create getters for category, severity and reproducibility in wx_UI.
|
# to do: Create getters for category, severity and reproducibility in wx_UI.
|
||||||
issue.category = constants.categories[self.dialog.category.GetSelection()]
|
issue.category = constants.categories[self.dialog.category.GetSelection()]
|
||||||
issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()]
|
issue.reproducibility.name = constants.reproducibilities[self.dialog.reproducibility.GetSelection()]
|
||||||
|
@@ -17,7 +17,7 @@ send_dm = string(default="control+win+d")
|
|||||||
user_details = string(default="control+win+shift+u")
|
user_details = string(default="control+win+shift+u")
|
||||||
exit = string(default="control+win+q")
|
exit = string(default="control+win+q")
|
||||||
open_timeline = string(default="control+win+u")
|
open_timeline = string(default="control+win+u")
|
||||||
remove_buffer = string(default="control+win+backspace")
|
remove_buffer = string(default="control+win+back")
|
||||||
audio = string(default="control+win+return")
|
audio = string(default="control+win+return")
|
||||||
url = string(default="control+win+b")
|
url = string(default="control+win+b")
|
||||||
go_home = string(default="control+win+home")
|
go_home = string(default="control+win+home")
|
||||||
@@ -28,7 +28,7 @@ repeat_item = string(default="control+win+space")
|
|||||||
copy_to_clipboard = string(default="control+win+shift+c")
|
copy_to_clipboard = string(default="control+win+shift+c")
|
||||||
search = string(default="control+win+/")
|
search = string(default="control+win+/")
|
||||||
find = string(default="control+win+shift+/")
|
find = string(default="control+win+shift+/")
|
||||||
check_for_updates = string(default="alt+win+u)
|
check_for_updates = string(default="alt+win+u")
|
||||||
list_manager = string(default="control+win+shift+l")
|
list_manager = string(default="control+win+shift+l")
|
||||||
configuration = string(default="control+win+o")
|
configuration = string(default="control+win+o")
|
||||||
accountConfiguration = string(default="control+win+shift+o")
|
accountConfiguration = string(default="control+win+shift+o")
|
||||||
|
@@ -5,16 +5,16 @@ import exceptions
|
|||||||
from ctypes import c_char_p
|
from ctypes import c_char_p
|
||||||
from libloader import load_library
|
from libloader import load_library
|
||||||
import paths
|
import paths
|
||||||
if application.snapshot == True:
|
#if application.snapshot == True:
|
||||||
if platform.architecture()[0][:2] == "32":
|
# if platform.architecture()[0][:2] == "32":
|
||||||
lib = load_library("snapshot_api_keys32", x86_path=paths.app_path("keys/lib"))
|
# lib = load_library("snapshot_api_keys32", x86_path=paths.app_path("keys/lib"))
|
||||||
else:
|
# else:
|
||||||
lib = load_library("snapshot_api_keys64", x64_path=paths.app_path("keys/lib"))
|
# lib = load_library("snapshot_api_keys64", x64_path=paths.app_path("keys/lib"))
|
||||||
|
#else:
|
||||||
|
if platform.architecture()[0][:2] == "32":
|
||||||
|
lib = load_library("stable_api_keys32", x86_path=paths.app_path("keys/lib"))
|
||||||
else:
|
else:
|
||||||
if platform.architecture()[0][:2] == "32":
|
lib = load_library("stable_api_keys64", x64_path=paths.app_path("keys/lib"))
|
||||||
lib = load_library("stable_api_keys32", x86_path=paths.app_path("keys/lib"))
|
|
||||||
else:
|
|
||||||
lib = load_library("stable_api_keys64", x64_path=paths.app_path("keys/lib"))
|
|
||||||
|
|
||||||
# import linuxKeys
|
# import linuxKeys
|
||||||
# lib = linuxKeys
|
# lib = linuxKeys
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
from pywintypes import com_error
|
from pywintypes import com_error
|
||||||
import win32com
|
import win32com
|
||||||
import paths
|
import paths
|
||||||
win32com.__gen_path__=paths.data_path(u"com_cache")
|
win32com.__gen_path__=paths.com_path()
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||||
|
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
@@ -18,15 +18,10 @@
|
|||||||
############################################################
|
############################################################
|
||||||
from twitter import utils
|
from twitter import utils
|
||||||
|
|
||||||
def get_id(url):
|
|
||||||
return url.split("/")[-1]
|
|
||||||
|
|
||||||
def is_long(tweet):
|
def is_long(tweet):
|
||||||
long = False
|
if tweet.has_key("is_quote_status") and tweet["is_quote_status"] == True and tweet.has_key("quoted_status"):
|
||||||
for url in range(0, len(tweet["entities"]["urls"])):
|
return tweet["quoted_status_id"]
|
||||||
if "twitter.com" in tweet["entities"]["urls"][url]["expanded_url"]:
|
return False
|
||||||
long = get_id(tweet["entities"]["urls"][url]["expanded_url"])
|
|
||||||
return long
|
|
||||||
|
|
||||||
def clear_url(tweet):
|
def clear_url(tweet):
|
||||||
urls = utils.find_urls_in_text(tweet["text"])
|
urls = utils.find_urls_in_text(tweet["text"])
|
||||||
|
@@ -51,5 +51,4 @@ def create_tweet(user_token, user_secret, text, media=0):
|
|||||||
"text": text.encode("utf-8"),
|
"text": text.encode("utf-8"),
|
||||||
"media": media}
|
"media": media}
|
||||||
response = requests.post(url, data=data)
|
response = requests.post(url, data=data)
|
||||||
# print response.json()
|
|
||||||
return response.json()["text_to_tweet"]
|
return response.json()["text_to_tweet"]
|
@@ -70,7 +70,8 @@ def setup():
|
|||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
if config.app["app-settings"]["donation_dialog_displayed"] == False:
|
if config.app["app-settings"]["donation_dialog_displayed"] == False:
|
||||||
donation()
|
donation()
|
||||||
updater.do_update()
|
if config.app['app-settings']['check_for_updates']:
|
||||||
|
updater.do_update()
|
||||||
sm = sessionManager.sessionManagerController()
|
sm = sessionManager.sessionManagerController()
|
||||||
sm.fill_list()
|
sm.fill_list()
|
||||||
if len(sm.sessions) == 0: sm.show()
|
if len(sm.sessions) == 0: sm.show()
|
||||||
|
15
src/paths.py
15
src/paths.py
@@ -69,4 +69,17 @@ def locale_path():
|
|||||||
|
|
||||||
@merge_paths
|
@merge_paths
|
||||||
def sound_path():
|
def sound_path():
|
||||||
return app_path(u"sounds")
|
return app_path(u"sounds")
|
||||||
|
|
||||||
|
@merge_paths
|
||||||
|
def com_path():
|
||||||
|
global mode, directory
|
||||||
|
if mode == "portable":
|
||||||
|
if directory != None: path = os.path.join(directory, "com_cache")
|
||||||
|
elif directory == None: path = app_path(u"com_cache")
|
||||||
|
elif mode == "installed":
|
||||||
|
path = data_path(u"com_cache")
|
||||||
|
if not os.path.exists(path):
|
||||||
|
log.debug("%s path does not exist, creating..." % (path,))
|
||||||
|
os.mkdir(path)
|
||||||
|
return path
|
||||||
|
@@ -18,7 +18,7 @@ import os
|
|||||||
from mysc.thread_utils import stream_threaded
|
from mysc.thread_utils import stream_threaded
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
log = logging.getLogger("sessionmanager.session")
|
log = logging.getLogger("sessionmanager.session")
|
||||||
from long_tweets import tweets
|
from long_tweets import tweets, twishort
|
||||||
|
|
||||||
sessions = {}
|
sessions = {}
|
||||||
|
|
||||||
@@ -64,6 +64,7 @@ class Session(object):
|
|||||||
if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True:
|
if utils.find_item(i["id"], self.db[name]) == None and utils.is_allowed(i, self.settings["twitter"]["ignored_clients"]) == True:
|
||||||
try: i = self.check_quoted_status(i)
|
try: i = self.check_quoted_status(i)
|
||||||
except: pass
|
except: pass
|
||||||
|
i = self.check_long_tweet(i)
|
||||||
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
||||||
else: self.db[name].insert(0, i)
|
else: self.db[name].insert(0, i)
|
||||||
num = num+1
|
num = num+1
|
||||||
@@ -425,19 +426,17 @@ class Session(object):
|
|||||||
def check_quoted_status(self, tweet):
|
def check_quoted_status(self, tweet):
|
||||||
status = tweets.is_long(tweet)
|
status = tweets.is_long(tweet)
|
||||||
if status != False:
|
if status != False:
|
||||||
tweet["quoted"] = 1
|
|
||||||
tweet = self.get_quoted_tweet(tweet)
|
tweet = self.get_quoted_tweet(tweet)
|
||||||
return tweet
|
return tweet
|
||||||
|
|
||||||
|
|
||||||
def get_quoted_tweet(self, tweet):
|
def get_quoted_tweet(self, tweet):
|
||||||
quoted_tweet = self.twitter.twitter.show_status(id=tweet["id"])
|
quoted_tweet = tweet
|
||||||
urls = utils.find_urls_in_text(quoted_tweet["text"])
|
urls = utils.find_urls_in_text(quoted_tweet["text"])
|
||||||
for url in range(0, len(urls)):
|
for url in range(0, len(urls)):
|
||||||
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
try: quoted_tweet["text"] = quoted_tweet["text"].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||||
except IndexError: pass
|
except IndexError: pass
|
||||||
l = tweets.is_long(quoted_tweet)
|
id = tweets.is_long(quoted_tweet)
|
||||||
id = tweets.get_id(l)
|
|
||||||
try: original_tweet = self.twitter.twitter.show_status(id=id)
|
try: original_tweet = self.twitter.twitter.show_status(id=id)
|
||||||
except: return quoted_tweet
|
except: return quoted_tweet
|
||||||
urls = utils.find_urls_in_text(original_tweet["text"])
|
urls = utils.find_urls_in_text(original_tweet["text"])
|
||||||
@@ -446,3 +445,8 @@ class Session(object):
|
|||||||
except IndexError: pass
|
except IndexError: pass
|
||||||
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)
|
return compose.compose_quoted_tweet(quoted_tweet, original_tweet)
|
||||||
|
|
||||||
|
def check_long_tweet(self, tweet):
|
||||||
|
long = twishort.is_long(tweet)
|
||||||
|
if long != False:
|
||||||
|
tweet["message"] = twishort.get_full_text(long)
|
||||||
|
return tweet
|
@@ -44,6 +44,15 @@ class sessionManagerController(object):
|
|||||||
log.debug("Adding session %s" % (i,))
|
log.debug("Adding session %s" % (i,))
|
||||||
strconfig = "%s/session.conf" % (paths.config_path(i))
|
strconfig = "%s/session.conf" % (paths.config_path(i))
|
||||||
config_test = config_utils.load_config(strconfig)
|
config_test = config_utils.load_config(strconfig)
|
||||||
|
if len(config_test) == 0:
|
||||||
|
try:
|
||||||
|
log.debug("Deleting session %s" % (i,))
|
||||||
|
shutil.rmtree(paths.config_path(i))
|
||||||
|
continue
|
||||||
|
except:
|
||||||
|
output.speak("An exception was raised while attempting to clean malformed session data. See the error log for details. If this message persists, contact the developers.",True)
|
||||||
|
os.exception("Exception thrown while removing malformed session")
|
||||||
|
continue
|
||||||
name = config_test["twitter"]["user_name"]
|
name = config_test["twitter"]["user_name"]
|
||||||
if config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "":
|
if config_test["twitter"]["user_key"] != "" and config_test["twitter"]["user_secret"] != "":
|
||||||
sessionsList.append(name)
|
sessionsList.append(name)
|
||||||
|
@@ -4,7 +4,7 @@ from multiplatform_widgets import widgets
|
|||||||
import application
|
import application
|
||||||
class sessionManagerWindow(wx.Dialog):
|
class sessionManagerWindow(wx.Dialog):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super(sessionManagerWindow, self).__init__(parent=None, title="Session manager", size=wx.DefaultSize)
|
super(sessionManagerWindow, self).__init__(parent=None, title=_(u"Session manager"), size=wx.DefaultSize)
|
||||||
panel = wx.Panel(self)
|
panel = wx.Panel(self)
|
||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
label = wx.StaticText(panel, -1, _(u"Accounts list"), size=wx.DefaultSize)
|
label = wx.StaticText(panel, -1, _(u"Accounts list"), size=wx.DefaultSize)
|
||||||
|
@@ -26,6 +26,7 @@ import application
|
|||||||
import platform
|
import platform
|
||||||
from glob import glob
|
from glob import glob
|
||||||
import wx
|
import wx
|
||||||
|
from requests import certs
|
||||||
|
|
||||||
def get_architecture_files():
|
def get_architecture_files():
|
||||||
if platform.architecture()[0][:2] == "32":
|
if platform.architecture()[0][:2] == "32":
|
||||||
@@ -45,15 +46,15 @@ def get_data():
|
|||||||
import enchant
|
import enchant
|
||||||
return [
|
return [
|
||||||
("", ["conf.defaults", "app-configuration.defaults", "icon.ico"]),
|
("", ["conf.defaults", "app-configuration.defaults", "icon.ico"]),
|
||||||
("requests", ["cacert.pem"]),
|
("", [certs.where()]),
|
||||||
("accessible_output2/lib", glob("accessible_output2/lib/*.dll")),
|
("accessible_output2/lib", glob("accessible_output2/lib/*.dll")),
|
||||||
("keys/lib", glob("keys/lib/*.dll")),
|
("keys/lib", glob("keys/lib/*.dll")),
|
||||||
("keymaps", glob("keymaps/*.keymap")),
|
("keymaps", glob("keymaps/*.keymap")),
|
||||||
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()+wx_files()
|
]+get_sounds()+get_locales()+get_documentation()+sound_lib.find_datafiles()+accessible_output2.find_datafiles()+enchant.utils.win32_data_files()+get_architecture_files()+wx_files()
|
||||||
|
|
||||||
def get_documentation ():
|
def get_documentation ():
|
||||||
answer = []
|
answer = [("documentation", ["documentation/license.txt"])]
|
||||||
depth = 6
|
depth = 9
|
||||||
for root, dirs, files in os.walk('documentation'):
|
for root, dirs, files in os.walk('documentation'):
|
||||||
if depth == 0:
|
if depth == 0:
|
||||||
break
|
break
|
||||||
@@ -112,7 +113,7 @@ options = {
|
|||||||
'optimize':2,
|
'optimize':2,
|
||||||
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash"],
|
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash"],
|
||||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
|
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
|
||||||
'skip_archive': True
|
'compressed': True
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
windows = [
|
windows = [
|
||||||
|
BIN
src/sounds/FightingGames/audio.ogg
Normal file
BIN
src/sounds/FightingGames/audio.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/create_timeline.ogg
Normal file
BIN
src/sounds/FightingGames/create_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/delete_timeline.ogg
Normal file
BIN
src/sounds/FightingGames/delete_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/dm_received.ogg
Normal file
BIN
src/sounds/FightingGames/dm_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/dm_sent.ogg
Normal file
BIN
src/sounds/FightingGames/dm_sent.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/error.ogg
Normal file
BIN
src/sounds/FightingGames/error.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/favourite.ogg
Normal file
BIN
src/sounds/FightingGames/favourite.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/favourites_timeline_updated.ogg
Normal file
BIN
src/sounds/FightingGames/favourites_timeline_updated.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/geo.ogg
Normal file
BIN
src/sounds/FightingGames/geo.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/limit.ogg
Normal file
BIN
src/sounds/FightingGames/limit.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/list_tweet.ogg
Normal file
BIN
src/sounds/FightingGames/list_tweet.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/max_length.ogg
Normal file
BIN
src/sounds/FightingGames/max_length.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/mention_received.ogg
Normal file
BIN
src/sounds/FightingGames/mention_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/new_event.ogg
Normal file
BIN
src/sounds/FightingGames/new_event.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/ready.ogg
Normal file
BIN
src/sounds/FightingGames/ready.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/reply_send.ogg
Normal file
BIN
src/sounds/FightingGames/reply_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/retweet_send.ogg
Normal file
BIN
src/sounds/FightingGames/retweet_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/search_updated.ogg
Normal file
BIN
src/sounds/FightingGames/search_updated.ogg
Normal file
Binary file not shown.
1
src/sounds/FightingGames/sound notes.txt
Normal file
1
src/sounds/FightingGames/sound notes.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
These sounds do not belong to us; they are the property of their original creators.
|
BIN
src/sounds/FightingGames/trends_updated.ogg
Normal file
BIN
src/sounds/FightingGames/trends_updated.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/tweet_received.ogg
Normal file
BIN
src/sounds/FightingGames/tweet_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/tweet_send.ogg
Normal file
BIN
src/sounds/FightingGames/tweet_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/tweet_timeline.ogg
Normal file
BIN
src/sounds/FightingGames/tweet_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/update_followers.ogg
Normal file
BIN
src/sounds/FightingGames/update_followers.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FightingGames/volume_changed.ogg
Normal file
BIN
src/sounds/FightingGames/volume_changed.ogg
Normal file
Binary file not shown.
2
src/sounds/Qwitter/sound notes.txt
Normal file
2
src/sounds/Qwitter/sound notes.txt
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
These sounds do not belong to us; they are the property of their original creators.
|
||||||
|
This soundpack was adapted for TWBlue by Bill Dengler (@codeofdusk on Twitter).
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user