Compare commits

..

44 Commits

Author SHA1 Message Date
e23a52e38f Changes in TWBlue keys 2021-10-27 15:29:15 -05:00
a5ba80feee Final touches 2021-10-26 16:18:53 -05:00
528ecc2a33 Updated NSI file 2021-10-26 16:16:03 -05:00
3519746078 Move installer Nsis file to a new name 2021-10-26 15:47:03 -05:00
ef79e0696e Move updated Nsis script to artifacts in build stage 2021-10-26 15:19:57 -05:00
b9ee0dae5b Fixed a typo in installer script 2021-10-26 14:48:58 -05:00
f31575a733 Merge pull request #408 from manuelcortez/calendar_versioning
Switch to Calendar versioning
2021-10-26 13:52:21 -05:00
e451bbd5e9 Merge pull request #407 from manuelcortez/alias_manager
Alias manager Dialog. Closes #401
2021-10-26 13:51:09 -05:00
f7f303929e Updated CI config 2021-10-26 13:41:22 -05:00
9f48784ce4 Added script to add next version in application.py and installer generation files 2021-10-26 13:39:50 -05:00
cb1312d0c9 Changed version in installer so it will be easier to replace it later by the authomatic script 2021-10-26 13:38:21 -05:00
a82efd4dcc Fixed a typo 2021-10-26 13:16:31 -05:00
72e6d030d5 Updater no longer will try to compare float numbers for updates 2021-10-26 13:10:57 -05:00
d222740887 Updated gitlab CI 2021-10-26 13:04:49 -05:00
2b059ee42e Modified Nsis scripts to remove references to old snapshots code 2021-10-26 13:02:24 -05:00
daac312658 Removes snapshot information from app info 2021-10-26 12:43:03 -05:00
b23be9c896 Started to remove stable and snapshot update information files 2021-10-26 12:40:57 -05:00
61b0dc34b8 Merge branch 'next-gen' into alias_manager 2021-10-26 10:48:43 -05:00
c5d13369eb Merge branch 'next-gen' of github.com:manuelcortez/twblue into next-gen 2021-10-26 10:47:55 -05:00
856ecf5eb9 Merge branch 'next-gen' of github.com:manuelcortez/twblue into alias_manager 2021-10-26 10:46:30 -05:00
e3e0ac9457 Added an alias manager dialog in the application menu 2021-10-26 10:45:11 -05:00
34c1f69ec1 Merge pull request #404 from nidza07/SerbianTranslation
Updated Serbian translation
2021-10-22 12:57:58 -05:00
7326ff88f9 Merge pull request #405 from Oreonan/fr_211021
Update french interface
2021-10-22 12:56:55 -05:00
Oreonan
a8d876a7b7 Fix last-translator e-mail 2021-10-21 17:02:03 +02:00
Oreonan
89fa6435b4 Update french interface 2021-10-21 16:58:32 +02:00
Nikola Jovic
d1bd393be2 Updated Serbian translation 2021-10-21 16:30:46 +02:00
301bd5fd39 Pushed a new snapshot 2021-10-20 15:52:58 -05:00
José Manuel Delicado Alcolea
a2f25bfbb5 Added charset-normalizer to requirements 2021-10-12 17:05:09 +02:00
286e030f40 Handle new Tweepy exceptions properly. #403 2021-10-07 09:20:06 -05:00
d8fca3b31a Initial work to Support Tweepy 4 2021-09-26 03:58:25 -05:00
0c27427843 Merge branch 'next-gen' of github.com:manuelcortez/twblue into next-gen 2021-09-10 15:05:28 -05:00
dfdbe3c5f4 Close VLC window after video playback ends. Close #399 2021-09-10 15:05:05 -05:00
José Manuel Delicado
2222a97451 Merge pull request #394 from Oreonan/fr_020821
Update french interface translation
2021-09-03 11:38:50 +02:00
fbe93ea4be Made FreakyBlue The default soundpack for new twitter sessions 2021-09-02 09:59:13 -05:00
4bcae1aa97 Fixed search filters. Closes #397 2021-09-02 09:38:05 -05:00
4cabf5b9cd Added code to handle user timelines in buffer creator 2021-08-31 10:31:18 -05:00
a9a4189295 Added improvements to tweet condense feature 2021-08-31 10:05:21 -05:00
c7b6d69518 Fixed an error in new buffer creation. Closes #396 2021-08-30 13:19:15 -05:00
65512a9862 Added a pubsub event to create sessions buffers 2021-08-30 10:51:26 -05:00
Oreonan
17ea8af050 Update translation 2021-08-28 08:37:26 +02:00
Oreonan
43578a32eb Merge remote-tracking branch 'origin/next-gen' into fr_020821 2021-08-28 08:33:40 +02:00
7c34204d17 Allow to specify alternative configuration specs for sessions 2021-08-27 13:45:59 -05:00
3a5c1c10d3 Released a new snapshot 2021-08-26 15:13:34 -05:00
Oreonan
ddc80a29fd Update french interface translation 2021-08-02 19:30:24 +02:00
36 changed files with 2195 additions and 1958 deletions

View File

@@ -8,7 +8,7 @@ stages:
- make_installer - make_installer
- upload - upload
snapshot32: twblue32:
tags: tags:
- shared-windows - shared-windows
- windows - windows
@@ -21,7 +21,6 @@ snapshot32:
- '&$env:PYTHON -V' - '&$env:PYTHON -V'
- '&$env:PYTHON -m pip install --upgrade pip' - '&$env:PYTHON -m pip install --upgrade pip'
- '&$env:PYTHON -m pip install --upgrade -r requirements.txt' - '&$env:PYTHON -m pip install --upgrade -r requirements.txt'
- '&$env:PYTHON -m pip uninstall enum34 -y'
stage: build stage: build
interruptible: true interruptible: true
script: script:
@@ -30,6 +29,7 @@ snapshot32:
- '&$env:PYTHON documentation_importer.py' - '&$env:PYTHON documentation_importer.py'
- cd ..\src - cd ..\src
- '&$env:PYTHON ..\doc\generator.py' - '&$env:PYTHON ..\doc\generator.py'
- '&$env:PYTHON write_version_data.py'
- '&$env:PYTHON setup.py build' - '&$env:PYTHON setup.py build'
- cd .. - cd ..
- mkdir artifacts - mkdir artifacts
@@ -37,7 +37,9 @@ snapshot32:
- '&$env:PYTHON make_archive.py' - '&$env:PYTHON make_archive.py'
- cd .. - cd ..
- mv src/dist artifacts/TWBlue - mv src/dist artifacts/TWBlue
- move src/twblue.zip artifacts/twblue_snapshot_x86.zip - move src/twblue.zip artifacts/twblue_x86.zip
# Move the generated script nsis file to artifacts, so we won't need python when generating the installer.
- move scripts/twblue.nsi artifacts/twblue.nsi
only: only:
- tags - tags
artifacts: artifacts:
@@ -45,7 +47,7 @@ snapshot32:
- artifacts - artifacts
expire_in: 1 day expire_in: 1 day
snapshot64: twblue64:
tags: tags:
- shared-windows - shared-windows
- windows - windows
@@ -66,6 +68,7 @@ snapshot64:
- '&$env:PYTHON documentation_importer.py' - '&$env:PYTHON documentation_importer.py'
- cd ..\src - cd ..\src
- '&$env:PYTHON ..\doc\generator.py' - '&$env:PYTHON ..\doc\generator.py'
- '&$env:PYTHON write_version_data.py'
- '&$env:PYTHON setup.py build' - '&$env:PYTHON setup.py build'
- cd .. - cd ..
- mkdir artifacts - mkdir artifacts
@@ -73,7 +76,7 @@ snapshot64:
- '&$env:PYTHON make_archive.py' - '&$env:PYTHON make_archive.py'
- cd .. - cd ..
- mv src/dist artifacts/TWBlue64 - mv src/dist artifacts/TWBlue64
- move src/twblue.zip artifacts/twblue_snapshot_x64.zip - move src/twblue.zip artifacts/twblue_x64.zip
only: only:
- tags - tags
artifacts: artifacts:
@@ -95,9 +98,10 @@ generate_versions:
script: script:
- move artifacts/TWBlue scripts/ - move artifacts/TWBlue scripts/
- move artifacts/TWBlue64 scripts/ - move artifacts/TWBlue64 scripts/
- move artifacts/twblue.nsi scripts/installer.nsi
- cd scripts - cd scripts
- '&$env:NSIS twblue_snapshot.nsi' - '&$env:NSIS installer.nsi'
- move twblue_snapshot_setup.exe ../artifacts - move twblue_setup.exe ../artifacts
only: only:
- tags - tags
artifacts: artifacts:

View File

@@ -2,6 +2,9 @@
## changes in this version ## changes in this version
* Added an user alias manager, located in the application menu in the menu bar. From this dialog, it is possible to review, add, edit or remove user aliases for the current account. ([#401](https://github.com/manuelcortez/TWBlue/issues/401))
* TWBlue now closes the VLC player window automatically when a video reaches its end. ([#399](https://github.com/manuelcortez/TWBlue/issues/399))
* After a lot of time, TWBlue now uses a new default Soundpack, called FreakyBlue. This soundpack will be set by default in all new sessions created in the application. Thanks to [Andre Louis](https://twitter.com/FreakyFwoof) for the pack. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
* When reading a tweet, if the tweet contains more than 2 consecutive mentions, TWBlue will announce how many more users the tweet includes, as opposed to read every user in the conversation. You still can display the tweet to read all users. * When reading a tweet, if the tweet contains more than 2 consecutive mentions, TWBlue will announce how many more users the tweet includes, as opposed to read every user in the conversation. You still can display the tweet to read all users.
* In the tweet displayer, It is possible to copy a link to the current tweet or person by pressing a button called "copy link to clipboard". * In the tweet displayer, It is possible to copy a link to the current tweet or person by pressing a button called "copy link to clipboard".
* Added a keymap capable to work under Windows 11. ([#391](https://github.com/manuelcortez/TWBlue/pull/391)) * Added a keymap capable to work under Windows 11. ([#391](https://github.com/manuelcortez/TWBlue/pull/391))

View File

@@ -47,6 +47,7 @@ attrs
importlib-metadata importlib-metadata
numpy numpy
pillow pillow
charset-normalizer
git+https://github.com/accessibleapps/libloader git+https://github.com/accessibleapps/libloader
git+https://github.com/accessibleapps/platform_utils git+https://github.com/accessibleapps/platform_utils
git+https://github.com/accessibleapps/accessible_output2 git+https://github.com/accessibleapps/accessible_output2

View File

@@ -15,10 +15,10 @@ SetCompressor /solid lzma
SetDatablockOptimize on SetDatablockOptimize on
VIAddVersionKey ProductName "TWBlue" VIAddVersionKey ProductName "TWBlue"
VIAddVersionKey LegalCopyright "Copyright 2014-2021 Manuel Cortéz." VIAddVersionKey LegalCopyright "Copyright 2014-2021 Manuel Cortéz."
VIAddVersionKey ProductVersion "0.95" VIAddVersionKey ProductVersion "0.95.0"
VIAddVersionKey FileVersion "0.95" VIAddVersionKey FileVersion "0.95.0"
VIProductVersion "0.95.0.0" VIProductVersion "0.95.0"
VIFileVersion "0.95.0.0" VIFileVersion "0.95.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"
@@ -32,7 +32,7 @@ var StartMenuFolder
!insertmacro MUI_PAGE_FINISH !insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES !insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English" !insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "French" !insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "Spanish" !insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "Italian" !insertmacro MUI_LANGUAGE "Italian"
@@ -73,9 +73,9 @@ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "U
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.95" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "0.95"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "http://twblue.es" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "https://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" 95 WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 0
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

View File

@@ -1,95 +0,0 @@
!include "MUI2.nsh"
!include "LogicLib.nsh"
!include "x64.nsh"
Unicode true
CRCCheck on
ManifestSupportedOS all
XPStyle on
Name "TWBlue"
OutFile "TWBlue_snapshot_setup.exe"
InstallDir "$PROGRAMFILES\twblue"
InstallDirRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "InstallLocation"
RequestExecutionLevel admin
SetCompress auto
SetCompressor /solid lzma
SetDatablockOptimize on
VIAddVersionKey ProductName "TWBlue Snapshot version"
VIAddVersionKey LegalCopyright "Copyright 2014-2021 Manuel Cortéz."
VIAddVersionKey ProductVersion "9"
VIAddVersionKey FileVersion "9"
VIProductVersion "9.0.0.0"
VIFileVersion "9.0.0.0"
!insertmacro MUI_PAGE_WELCOME
!define MUI_LICENSEPAGE_RADIOBUTTONS
!insertmacro MUI_PAGE_LICENSE "license.txt"
!insertmacro MUI_PAGE_DIRECTORY
var StartMenuFolder
!insertmacro MUI_PAGE_STARTMENU startmenu $StartMenuFolder
!insertmacro MUI_PAGE_INSTFILES
!define MUI_FINISHPAGE_LINK "Visit TWBlue website"
!define MUI_FINISHPAGE_LINK_LOCATION "https://twblue.es"
!define MUI_FINISHPAGE_RUN "$INSTDIR\TWBlue.exe"
!insertmacro MUI_PAGE_FINISH
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "French"
!insertmacro MUI_LANGUAGE "Spanish"
!insertmacro MUI_LANGUAGE "Italian"
!insertmacro MUI_LANGUAGE "Finnish"
!insertmacro MUI_LANGUAGE "Russian"
!insertmacro MUI_LANGUAGE "PortugueseBR"
!insertmacro MUI_LANGUAGE "Polish"
!insertmacro MUI_LANGUAGE "German"
!insertmacro MUI_LANGUAGE "Hungarian"
!insertmacro MUI_LANGUAGE "Turkish"
!insertmacro MUI_LANGUAGE "Arabic"
!insertmacro MUI_LANGUAGE "Galician"
!insertmacro MUI_LANGUAGE "Catalan"
!insertmacro MUI_LANGUAGE "Basque"
!insertmacro MUI_LANGUAGE "Croatian"
!insertmacro MUI_LANGUAGE "Japanese"
!insertmacro MUI_LANGUAGE "SerbianLatin"
!insertmacro MUI_LANGUAGE "Romanian"
!insertmacro MUI_RESERVEFILE_LANGDLL
Section
SetShellVarContext All
SetOutPath "$INSTDIR"
${If} ${RunningX64}
File /r TWBlue64\*
${Else}
File /r TWBlue\*
${EndIf}
CreateShortCut "$DESKTOP\TWBlue.lnk" "$INSTDIR\TWBlue.exe"
!insertmacro MUI_STARTMENU_WRITE_BEGIN startmenu
CreateDirectory "$SMPROGRAMS\$StartMenuFolder"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue.lnk" "$INSTDIR\TWBlue.exe"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\TWBlue on the web.lnk" "http://twblue.es"
CreateShortCut "$SMPROGRAMS\$StartMenuFolder\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
!insertmacro MUI_STARTMENU_WRITE_END
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayName" "TWBlue"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "InstallLocation" $INSTDIR
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall" "Publisher" "Manuel Cortéz"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "DisplayVersion" "9"
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "URLInfoAbout" "https://twblue.es"
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMajor" 0
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "VersionMinor" 0
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoModify" 1
WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue" "NoRepair" 1
SectionEnd
Section "Uninstall"
SetShellVarContext All
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\twblue"
RMDir /r /REBOOTOK $INSTDIR
Delete "$DESKTOP\TWBlue.lnk"
!insertmacro MUI_STARTMENU_GETFOLDER startmenu $StartMenuFolder
RMDir /r "$SMPROGRAMS\$StartMenuFolder"
SectionEnd
Function .onInit
${If} ${RunningX64}
StrCpy $instdir "$programfiles64\twblue"
${EndIf}
!insertmacro MUI_LANGDLL_DISPLAY
FunctionEnd

View File

@@ -21,7 +21,7 @@ volume = float(default=1.0)
input_device = string(default="Default") input_device = string(default="Default")
output_device = string(default="Default") output_device = string(default="Default")
session_mute = boolean(default=False) session_mute = boolean(default=False)
current_soundpack = string(default="default") current_soundpack = string(default="FreakyBlue")
indicate_audio = boolean(default=True) indicate_audio = boolean(default=True)
indicate_geo = boolean(default=True) indicate_geo = boolean(default=True)
indicate_img = boolean(default=True) indicate_img = boolean(default=True)

View File

@@ -3,15 +3,8 @@ import datetime
name = 'TWBlue' name = 'TWBlue'
short_name='twblue' short_name='twblue'
snapshot = True update_url = 'https://twblue.es/updates/updates.php'
if snapshot == False: mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/updates.json'
version = "0.95"
update_url = 'https://twblue.es/updates/stable.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
else:
version = "9"
update_url = 'https://twblue.es/updates/snapshot.php'
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
authors = ["Manuel Cortéz", "José Manuel Delicado"] authors = ["Manuel Cortéz", "José Manuel Delicado"]
authorEmail = "manuel@manuelcortez.net" authorEmail = "manuel@manuelcortez.net"
copyright = "Copyright (C) 2013-2021, Manuel cortéz." copyright = "Copyright (C) 2013-2021, Manuel cortéz."
@@ -20,3 +13,4 @@ translators = ["Manuel Cortéz (English)", "Mohammed Al Shara, Hatoun Felemban (
url = u"https://twblue.es" url = u"https://twblue.es"
report_bugs_url = "https://github.com/manuelcortez/twblue/issues" report_bugs_url = "https://github.com/manuelcortez/twblue/issues"
supported_languages = [] supported_languages = []
version = "11"

View File

@@ -21,7 +21,7 @@ from audio_services import youtube_utils
from controller.buffers.base import base from controller.buffers.base import base
from sessions.twitter import compose, utils, reduce from sessions.twitter import compose, utils, reduce
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from tweepy.error import TweepError from tweepy.errors import TweepyException
from tweepy.cursor import Cursor from tweepy.cursor import Cursor
from pubsub import pub from pubsub import pub
from sessions.twitter.long_tweets import twishort, tweets from sessions.twitter.long_tweets import twishort, tweets
@@ -140,7 +140,7 @@ class BaseBuffer(base.Buffer):
try: try:
tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended") tweet = self.session.twitter.get_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
except TweepError as e: except TweepyException as e:
utils.twitter_error(e) utils.twitter_error(e)
return return
if message != None: if message != None:
@@ -151,7 +151,7 @@ class BaseBuffer(base.Buffer):
try: try:
tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True, tweet_mode="extended") tweet = self.session.twitter.get_status(id=l, include_ext_alt_text=True, tweet_mode="extended")
tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities) tweet.full_text = utils.expand_urls(tweet.full_text, tweet.entities)
except TweepError as e: except TweepyException as e:
utils.twitter_error(e) utils.twitter_error(e)
return return
l = tweets.is_long(tweet) l = tweets.is_long(tweet)
@@ -191,8 +191,8 @@ class BaseBuffer(base.Buffer):
log.debug("Retrieved %d items from the cursored search on function %s." %(len(val), self.function)) log.debug("Retrieved %d items from the cursored search on function %s." %(len(val), self.function))
user_ids = [item.message_create["sender_id"] for item in val] user_ids = [item.message_create["sender_id"] for item in val]
self.session.save_users(user_ids) self.session.save_users(user_ids)
except TweepError as e: except TweepyException as e:
log.error("Error %s: %s" % (e.api_code, e.reason)) log.exception("Error %s" % (str(e)))
return return
number_of_items = self.session.order_buffer(self.name, val) number_of_items = self.session.order_buffer(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,)) log.debug("Number of items retrieved: %d" % (number_of_items,))
@@ -229,8 +229,8 @@ class BaseBuffer(base.Buffer):
last_id = self.session.db[self.name][-1].id last_id = self.session.db[self.name][-1].id
try: try:
items = getattr(self.session.twitter, self.function)(max_id=last_id, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs) items = getattr(self.session.twitter, self.function)(max_id=last_id, count=self.session.settings["general"]["max_tweets_per_call"], *self.args, **self.kwargs)
except TweepError as e: except TweepyException as e:
log.error("Error %s: %s" % (e.api_code, e.reason)) log.exception("Error %s" % (str(e)))
return return
if items == None: if items == None:
return return
@@ -611,13 +611,13 @@ class BaseBuffer(base.Buffer):
items = self.session.db[self.name] items = self.session.db[self.name]
try: try:
if self.name == "direct_messages" or self.name == "sent_direct_messages": if self.name == "direct_messages" or self.name == "sent_direct_messages":
self.session.twitter.destroy_direct_message(id=self.get_right_tweet().id) self.session.twitter.delete_direct_message(id=self.get_right_tweet().id)
items.pop(index) items.pop(index)
else: else:
self.session.twitter.destroy_status(id=self.get_right_tweet().id) self.session.twitter.destroy_status(id=self.get_right_tweet().id)
items.pop(index) items.pop(index)
self.buffer.list.remove_item(index) self.buffer.list.remove_item(index)
except TweepError: except TweepyException:
self.session.sound.play("error.ogg") self.session.sound.play("error.ogg")
self.session.db[self.name] = items self.session.db[self.name] = items

View File

@@ -10,7 +10,7 @@ import logging
from controller import messages from controller import messages
from sessions.twitter import compose, utils from sessions.twitter import compose, utils
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from tweepy.error import TweepError from tweepy.errors import TweepyException
from pubsub import pub from pubsub import pub
from . import base from . import base
@@ -40,8 +40,8 @@ class DirectMessagesBuffer(base.BaseBuffer):
results = [i for i in items] results = [i for i in items]
items = results items = results
log.debug("Retrieved %d items for cursored search in function %s" % (len(items), self.function)) log.debug("Retrieved %d items for cursored search in function %s" % (len(items), self.function))
except TweepError as e: except TweepyException as e:
log.error("Error %s: %s" % (e.api_code, e.reason)) log.exception("Error %s" % (str(e)))
return return
if items == None: if items == None:
return return

View File

@@ -24,7 +24,7 @@ class ListBuffer(base.BaseBuffer):
super(ListBuffer, self).start_stream(mandatory, play_sound, avoid_autoreading) super(ListBuffer, self).start_stream(mandatory, play_sound, avoid_autoreading)
def get_user_ids(self): def get_user_ids(self):
for i in Cursor(self.session.twitter.list_members, list_id=self.list_id, include_entities=False, skip_status=True, count=5000).items(): for i in Cursor(self.session.twitter.get_list_members, list_id=self.list_id, include_entities=False, skip_status=True, count=5000).items():
if i.id not in self.users: if i.id not in self.users:
self.users.append(i.id) self.users.append(i.id)

View File

@@ -14,7 +14,7 @@ import output
import config import config
import logging import logging
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from tweepy.error import TweepError from tweepy.errors import TweepyException
from pubsub import pub from pubsub import pub
from sessions.twitter import compose from sessions.twitter import compose
from . import base from . import base
@@ -125,8 +125,8 @@ class PeopleBuffer(base.BaseBuffer):
val = results val = results
val.reverse() val.reverse()
log.debug("Retrieved %d items from cursored search in function %s" % (len(val), self.function)) log.debug("Retrieved %d items from cursored search in function %s" % (len(val), self.function))
except TweepError as e: except TweepyException as e:
log.error("Error %s: %s" % (e.api_code, e.reason)) log.exception("Error %s" % (str(e)))
return return
number_of_items = self.session.order_people(self.name, val) number_of_items = self.session.order_people(self.name, val)
log.debug("Number of items retrieved: %d" % (number_of_items,)) log.debug("Number of items retrieved: %d" % (number_of_items,))
@@ -155,8 +155,8 @@ class PeopleBuffer(base.BaseBuffer):
results = [i for i in items] results = [i for i in items]
items = results items = results
log.debug("Retrieved %d items from cursored search in function %s" % (len(items), self.function)) log.debug("Retrieved %d items from cursored search in function %s" % (len(items), self.function))
except TweepError as e: except TweepyException as e:
log.error("Error %s: %s" % (e.api_code, e.reason)) log.exception("Error %s" % (str(e)))
return return
if items == None: if items == None:
return return

View File

@@ -13,17 +13,17 @@ import widgetUtils
import output import output
import logging import logging
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from tweepy.error import TweepError from tweepy.errors import TweepyException
from pubsub import pub from pubsub import pub
from controller.buffers import base from controller.buffers import base
log = logging.getLogger("controller.buffers.twitter.trends") log = logging.getLogger("controller.buffers.twitter.trends")
class TrendsBuffer(base.Buffer): class TrendsBuffer(base.Buffer):
def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs): def __init__(self, parent, name, sessionObject, account, trendsFor, *args, **kwargs):
super(TrendsBuffer, self).__init__(parent=parent, session=session) super(TrendsBuffer, self).__init__(parent=parent, sessionObject=sessionObject)
self.trendsFor = trendsFor self.trendsFor = trendsFor
self.session = session self.session = sessionObject
self.account = account self.account = account
self.invisible = True self.invisible = True
self.buffer = buffers.trendsPanel(parent, name) self.buffer = buffers.trendsPanel(parent, name)
@@ -44,9 +44,9 @@ class TrendsBuffer(base.Buffer):
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True: 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.twitter.trends_place(id=self.trendsFor) data = self.session.twitter.get_place_trends(id=self.trendsFor)
except TweepError as err: except TweepyException as err:
log.error("Error %s: %s" % (err.api_code, err.reason)) log.exception("Error %s" % (str(err)))
if not hasattr(self, "name_"): if not hasattr(self, "name_"):
self.name_ = data[0]["locations"][0]["name"] self.name_ = data[0]["locations"][0]["name"]
self.trends = data[0]["trends"] self.trends = data[0]["trends"]

View File

@@ -3,7 +3,7 @@ import widgetUtils
import output import output
import logging import logging
from wxUI.dialogs import lists from wxUI.dialogs import lists
from tweepy.error import TweepError from tweepy.errors import TweepyException
from sessions.twitter import compose, utils from sessions.twitter import compose, utils
from pubsub import pub from pubsub import pub
@@ -49,9 +49,9 @@ class listsController(object):
new_list = self.session.twitter.create_list(name=name, description=description, mode=mode) new_list = self.session.twitter.create_list(name=name, description=description, mode=mode)
self.session.db["lists"].append(new_list) self.session.db["lists"].append(new_list)
self.dialog.lista.insert_item(False, *compose.compose_list(new_list)) self.dialog.lista.insert_item(False, *compose.compose_list(new_list))
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s: %s" % (e.api_code, e.reason)) log.exception("error %s" % (str(e)))
dialog.destroy() dialog.destroy()
def edit_list(self, *args, **kwargs): def edit_list(self, *args, **kwargs):
@@ -70,8 +70,9 @@ class listsController(object):
self.session.twitter.update_list(list_id=list.id, name=name, description=description, mode=mode) self.session.twitter.update_list(list_id=list.id, name=name, description=description, mode=mode)
self.session.get_lists() self.session.get_lists()
self.dialog.populate_list(self.get_all_lists(), True) self.dialog.populate_list(self.get_all_lists(), True)
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s" % (str(e)))
dialog.destroy() dialog.destroy()
def remove_list(self, *args, **kwargs): def remove_list(self, *args, **kwargs):
@@ -82,8 +83,9 @@ class listsController(object):
self.session.twitter.destroy_list(list_id=list) self.session.twitter.destroy_list(list_id=list)
self.session.db["lists"].pop(self.dialog.get_item()) self.session.db["lists"].pop(self.dialog.get_item())
self.dialog.lista.remove_item(self.dialog.get_item()) self.dialog.lista.remove_item(self.dialog.get_item())
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s" % (str(e)))
def open_list_as_buffer(self, *args, **kwargs): def open_list_as_buffer(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return if self.dialog.lista.get_count() == 0: return
@@ -97,8 +99,9 @@ class listsController(object):
list = self.session.twitter.subscribe_list(list_id=list_id) list = self.session.twitter.subscribe_list(list_id=list_id)
item = utils.find_item(list.id, self.session.db["lists"]) item = utils.find_item(list.id, self.session.db["lists"])
self.session.db["lists"].append(list) self.session.db["lists"].append(list)
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s" % (str(e)))
def unsubscribe(self, *args, **kwargs): def unsubscribe(self, *args, **kwargs):
if self.dialog.lista.get_count() == 0: return if self.dialog.lista.get_count() == 0: return
@@ -106,5 +109,6 @@ class listsController(object):
try: try:
list = self.session.twitter.unsubscribe_list(list_id=list_id) list = self.session.twitter.unsubscribe_list(list_id=list_id)
self.session.db["lists"].remove(list) self.session.db["lists"].remove(list)
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s" % (str(e)))

View File

@@ -2,6 +2,7 @@
import platform import platform
system = platform.system() system = platform.system()
import application import application
import wx
import requests import requests
from audio_services import youtube_utils from audio_services import youtube_utils
import arrow import arrow
@@ -24,12 +25,13 @@ from sessions.twitter import utils, compose
from sessionmanager import manager, sessionManager from sessionmanager import manager, sessionManager
from controller import buffers from controller import buffers
from . import messages from . import messages
from . import userAliasController
import sessions import sessions
from sessions.twitter import session as session_ from sessions.twitter import session as session_
from pubsub import pub from pubsub import pub
import sound import sound
import output import output
from tweepy.error import TweepError from tweepy.errors import TweepyException, Forbidden
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from mysc.repeating_timer import RepeatingTimer from mysc.repeating_timer import RepeatingTimer
from mysc import restart from mysc import restart
@@ -131,6 +133,7 @@ class Controller(object):
pub.subscribe(self.manage_unfavourite, "unfavourite") pub.subscribe(self.manage_unfavourite, "unfavourite")
pub.subscribe(self.manage_blocked_user, "blocked-user") pub.subscribe(self.manage_blocked_user, "blocked-user")
pub.subscribe(self.manage_unblocked_user, "unblocked-user") pub.subscribe(self.manage_unblocked_user, "unblocked-user")
pub.subscribe(self.create_buffer, "createBuffer")
if system == "Windows": if system == "Windows":
pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed") pub.subscribe(self.invisible_shorcuts_changed, "invisible-shorcuts-changed")
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.show_hide, menuitem=self.view.show_hide)
@@ -188,6 +191,7 @@ class Controller(object):
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_list, self.view.addToList)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_list, self.view.removeFromList)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_buffer, self.view.update_buffer) widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_buffer, self.view.update_buffer)
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.manage_aliases, self.view.manageAliases)
def set_systray_icon(self): def set_systray_icon(self):
self.systrayIcon = sysTrayIcon.SysTrayIcon() self.systrayIcon = sysTrayIcon.SysTrayIcon()
@@ -292,6 +296,31 @@ class Controller(object):
self.create_buffers(session, False) self.create_buffers(session, False)
self.start_buffers(session) self.start_buffers(session)
def create_buffer(self, buffer_type="baseBuffer", session_type="twitter", buffer_title="", parent_tab=None, start=False, kwargs={}):
log.debug("Creating buffer of type {0} with parent_tab of {2} arguments {1}".format(buffer_type, kwargs, parent_tab))
if not hasattr(buffers, session_type):
raise AttributeError("Session type %s does not exist yet." % (session_type))
available_buffers = getattr(buffers, session_type)
if not hasattr(available_buffers, buffer_type):
raise AttributeError("Specified buffer type does not exist: %s" % (buffer_type,))
buffer = getattr(available_buffers, buffer_type)(**kwargs)
if start:
if kwargs.get("function") == "user_timeline":
try:
buffer.start_stream(play_sound=False)
except ValueError:
commonMessageDialogs.unauthorized()
return
else:
call_threaded(buffer.start_stream)
self.buffers.append(buffer)
if parent_tab == None:
log.debug("Appending buffer {}...".format(buffer,))
self.view.add_buffer(buffer.buffer, buffer_title)
else:
self.view.insert_buffer(buffer.buffer, buffer_title, parent_tab)
log.debug("Inserting buffer {0} into control {1}".format(buffer, parent_tab))
def create_buffers(self, session, createAccounts=True): def create_buffers(self, session, createAccounts=True):
""" Generates buffer objects for an user account. """ Generates buffer objects for an user account.
session SessionObject: a sessionmanager.session.Session Object""" session SessionObject: a sessionmanager.session.Session Object"""
@@ -302,96 +331,54 @@ class Controller(object):
account.setup_account() account.setup_account()
self.buffers.append(account) self.buffers.append(account)
self.view.add_buffer(account.buffer , name=session.db["user_name"]) self.view.add_buffer(account.buffer , name=session.db["user_name"])
root_position =self.view.search(session.db["user_name"], session.db["user_name"])
for i in session.settings['general']['buffer_order']: for i in session.settings['general']['buffer_order']:
if i == 'home': if i == 'home':
home = buffers.twitter.BaseBuffer(self.view.nb, "home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Home"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="home_timeline", name="home_timeline", sessionObject=session, account=session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended"))
self.buffers.append(home)
self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'mentions': elif i == 'mentions':
mentions = buffers.twitter.BaseBuffer(self.view.nb, "mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Mentions"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="mentions_timeline", name="mentions", sessionObject=session, account=session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended"))
self.buffers.append(mentions)
self.view.insert_buffer(mentions.buffer, name=_(u"Mentions"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'dm': elif i == 'dm':
dm = buffers.twitter.DirectMessagesBuffer(self.view.nb, "list_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg") pub.sendMessage("createBuffer", buffer_type="DirectMessagesBuffer", session_type=session.type, buffer_title=_("Direct messages"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_direct_messages", name="direct_messages", sessionObject=session, account=session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg"))
self.buffers.append(dm)
self.view.insert_buffer(dm.buffer, name=_(u"Direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_dm': elif i == 'sent_dm':
sent_dm = buffers.twitter.SentDirectMessagesBuffer(self.view.nb, "", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message") pub.sendMessage("createBuffer", buffer_type="SentDirectMessagesBuffer", session_type=session.type, buffer_title=_("Sent direct messages"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function=None, name="sent_direct_messages", sessionObject=session, account=session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message"))
self.buffers.append(sent_dm)
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'sent_tweets': elif i == 'sent_tweets':
sent_tweets = buffers.twitter.BaseBuffer(self.view.nb, "user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Sent tweets"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="sent_tweets", sessionObject=session, account=session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended"))
self.buffers.append(sent_tweets)
self.view.insert_buffer(sent_tweets.buffer, name=_(u"Sent tweets"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'favorites': elif i == 'favorites':
favourites = buffers.twitter.BaseBuffer(self.view.nb, "favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="favourites", sessionObject=session, account=session.db["user_name"], sound="favourite.ogg", tweet_mode="extended"))
self.buffers.append(favourites)
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'followers': elif i == 'followers':
followers = buffers.twitter.PeopleBuffer(self.view.nb, "followers", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"]) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Followers"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_followers", name="followers", sessionObject=session, account=session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"]))
self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'friends': elif i == 'friends':
friends = buffers.twitter.PeopleBuffer(self.view.nb, "friends", "friends", session, session.db["user_name"], screen_name=session.db["user_name"]) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Following"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_friends", name="friends", sessionObject=session, account=session.db["user_name"], screen_name=session.db["user_name"]))
self.buffers.append(friends)
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'blocks': elif i == 'blocks':
blocks = buffers.twitter.PeopleBuffer(self.view.nb, "blocks", "blocked", session, session.db["user_name"]) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Blocked users"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_blocks", name="blocked", sessionObject=session, account=session.db["user_name"]))
self.buffers.append(blocks)
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
elif i == 'muted': elif i == 'muted':
muted = buffers.twitter.PeopleBuffer(self.view.nb, "mutes", "muted", session, session.db["user_name"]) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Muted users"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, function="get_mutes", name="muted", sessionObject=session, account=session.db["user_name"]))
self.buffers.append(muted) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="timelines", account=session.db["user_name"]))
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(session.db["user_name"], session.db["user_name"])) timelines_position =self.view.search("timelines", session.db["user_name"])
timelines = buffers.base.EmptyBuffer(self.view.nb, "timelines", session.db["user_name"])
self.buffers.append(timelines)
self.view.insert_buffer(timelines.buffer , name=_(u"Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["timelines"]: for i in session.settings["other_buffers"]["timelines"]:
tl = buffers.twitter.BaseBuffer(self.view.nb, "user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_(u"Timeline for {}").format(i,), parent_tab=timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="user_timeline", name="%s-timeline" % (i,), sessionObject=session, account=session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended"))
self.buffers.append(tl) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Likes timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="favs_timelines", account=session.db["user_name"]))
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", session.db["user_name"])) favs_timelines_position =self.view.search("favs_timelines", session.db["user_name"])
favs_timelines = buffers.base.EmptyBuffer(self.view.nb, "favs_timelines", session.db["user_name"])
self.buffers.append(favs_timelines)
self.view.insert_buffer(favs_timelines.buffer , name=_(u"Likes timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["favourites_timelines"]: for i in session.settings["other_buffers"]["favourites_timelines"]:
tl = buffers.twitter.BaseBuffer(self.view.nb, "favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="BaseBuffer", session_type=session.type, buffer_title=_("Likes for {}").format(i,), parent_tab=favs_timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="get_favorites", name="%s-favorite" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended"))
self.buffers.append(tl) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Followers timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="followers_timelines", account=session.db["user_name"]))
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"])) followers_timelines_position =self.view.search("followers_timelines", session.db["user_name"])
followers_timelines = buffers.base.EmptyBuffer(self.view.nb, "followers_timelines", session.db["user_name"])
self.buffers.append(followers_timelines)
self.view.insert_buffer(followers_timelines.buffer , name=_(u"Followers' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["followers_timelines"]: for i in session.settings["other_buffers"]["followers_timelines"]:
tl = buffers.twitter.PeopleBuffer(self.view.nb, "followers", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_("Followers for {}").format(i,), parent_tab=followers_timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="get_followers", name="%s-followers" % (i,), sessionObject=session, account=session.db["user_name"], sound="new_event.ogg", user_id=i))
self.buffers.append(tl) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Following timelines"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="friends_timelines", account=session.db["user_name"]))
self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"])) friends_timelines_position =self.view.search("friends_timelines", session.db["user_name"])
friends_timelines = buffers.base.EmptyBuffer(self.view.nb, "friends_timelines", session.db["user_name"])
self.buffers.append(friends_timelines)
self.view.insert_buffer(friends_timelines.buffer , name=_(u"Friends' Timelines"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["friends_timelines"]: for i in session.settings["other_buffers"]["friends_timelines"]:
tl = buffers.twitter.PeopleBuffer(self.view.nb, "friends", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i) pub.sendMessage("createBuffer", buffer_type="PeopleBuffer", session_type=session.type, buffer_title=_(u"Friends for {}").format(i,), parent_tab=friends_timelines_position, start=False, kwargs=dict(parent=self.view.nb, function="get_friends", name="%s-friends" % (i,), sessionObject=session, account=session.db["user_name"], sound="new_event.ogg", user_id=i))
self.buffers.append(tl) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Lists"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="lists", account=session.db["user_name"]))
self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"])) lists_position =self.view.search("lists", session.db["user_name"])
lists = buffers.base.EmptyBuffer(self.view.nb, "lists", session.db["user_name"])
self.buffers.append(lists)
self.view.insert_buffer(lists.buffer , name=_(u"Lists"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["lists"]: for i in session.settings["other_buffers"]["lists"]:
tl = buffers.twitter.ListBuffer(self.view.nb, "list_timeline", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="ListBuffer", session_type=session.type, buffer_title=_(u"List for {}").format(i), parent_tab=lists_position, start=False, kwargs=dict(parent=self.view.nb, function="list_timeline", name="%s-list" % (i,), sessionObject=session, account=session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended"))
session.lists.append(tl) pub.sendMessage("createBuffer", buffer_type="EmptyBuffer", session_type="base", buffer_title=_("Searches"), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="searches", account=session.db["user_name"]))
self.buffers.append(tl) searches_position =self.view.search("searches", session.db["user_name"])
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"]))
searches = buffers.base.EmptyBuffer(self.view.nb, "searches", session.db["user_name"])
self.buffers.append(searches)
self.view.insert_buffer(searches.buffer , name=_(u"Searches"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
for i in session.settings["other_buffers"]["tweet_searches"]: for i in session.settings["other_buffers"]["tweet_searches"]:
tl = buffers.twitter.SearchBuffer(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended") pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=session.type, buffer_title=_(u"Search for {}").format(i), parent_tab=searches_position, start=False, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (i,), sessionObject=session, account=session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended"))
self.buffers.append(tl)
self.view.insert_buffer(tl.buffer, name=_(u"Search for {}").format(i), pos=self.view.search("searches", session.db["user_name"]))
for i in session.settings["other_buffers"]["trending_topic_buffers"]: for i in session.settings["other_buffers"]["trending_topic_buffers"]:
buffer = buffers.twitter.TrendsBuffer(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i, sound="trends_updated.ogg") pub.sendMessage("createBuffer", buffer_type="TrendsBuffer", session_type=session.type, buffer_title=_("Trending topics for %s") % (i), parent_tab=root_position, start=False, kwargs=dict(parent=self.view.nb, name="%s_tt" % (i,), sessionObject=session, account=session.db["user_name"], trendsFor=i, sound="trends_updated.ogg"))
buffer.start_stream(play_sound=False)
buffer.searchfunction = self.search
self.buffers.append(buffer)
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (buffer.name_), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
def set_buffer_positions(self, session): def set_buffer_positions(self, session):
"Sets positions for buffers if values exist in the database." "Sets positions for buffers if values exist in the database."
@@ -430,21 +417,18 @@ class Controller(object):
if dlg.get_response() == widgetUtils.OK and dlg.get("term") != "": if dlg.get_response() == widgetUtils.OK and dlg.get("term") != "":
term = dlg.get("term") term = dlg.get("term")
buffer = self.get_best_buffer() buffer = self.get_best_buffer()
searches_position =self.view.search("searches", buffer.session.db["user_name"])
if dlg.get("tweets") == True: if dlg.get("tweets") == True:
if term not in buffer.session.settings["other_buffers"]["tweet_searches"]: if term not in buffer.session.settings["other_buffers"]["tweet_searches"]:
buffer.session.settings["other_buffers"]["tweet_searches"].append(term) buffer.session.settings["other_buffers"]["tweet_searches"].append(term)
buffer.session.settings.write() buffer.session.settings.write()
args = {"lang": dlg.get_language(), "result_type": dlg.get_result_type()} args = {"lang": dlg.get_language(), "result_type": dlg.get_result_type()}
search = buffers.twitter.SearchBuffer(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, tweet_mode="extended", **args) pub.sendMessage("createBuffer", buffer_type="SearchBuffer", session_type=buffer.session.type, buffer_title=_("Search for {}").format(term), parent_tab=searches_position, start=True, kwargs=dict(parent=self.view.nb, function="search_tweets", name="%s-searchterm" % (term,), sessionObject=buffer.session, account=buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, tweet_mode="extended", **args))
else: else:
log.error("A buffer for the %s search term is already created. You can't create a duplicate buffer." % (term,)) log.error("A buffer for the %s search term is already created. You can't create a duplicate buffer." % (term,))
return return
elif dlg.get("users") == True: elif dlg.get("users") == True:
search = buffers.twitter.SearchPeopleBuffer(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, sound="search_updated.ogg", q=term) pub.sendMessage("createBuffer", buffer_type="SearchPeopleBuffer", session_type=buffer.session.type, buffer_title=_("Search for {}").format(term), parent_tab=searches_position, start=True, kwargs=dict(parent=self.view.nb, function="search_users", name="%s-searchUser" % (term,), sessionObject=buffer.session, account=buffer.session.db["user_name"], bufferType=None, sound="search_updated.ogg", q=term))
search.start_stream(mandatory=True)
pos=self.view.search("searches", buffer.session.db["user_name"])
self.insert_buffer(search, pos)
self.view.insert_buffer(search.buffer, name=_(u"Search for {}").format(term), pos=pos)
dlg.Destroy() dlg.Destroy()
def find(self, *args, **kwargs): def find(self, *args, **kwargs):
@@ -567,8 +551,9 @@ class Controller(object):
if listBuffer != None: listBuffer.get_user_ids() if listBuffer != None: listBuffer.get_user_ids()
buff.session.db["lists"].pop(older_list) buff.session.db["lists"].pop(older_list)
buff.session.db["lists"].append(list) buff.session.db["lists"].append(list)
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) log.exception("error %s" % (str(e)))
output.speak("error %s" % (str(e)))
def remove_from_list(self, *args, **kwargs): def remove_from_list(self, *args, **kwargs):
buff = self.get_best_buffer() buff = self.get_best_buffer()
@@ -595,8 +580,9 @@ class Controller(object):
if listBuffer != None: listBuffer.get_user_ids() if listBuffer != None: listBuffer.get_user_ids()
buff.session.db["lists"].pop(older_list) buff.session.db["lists"].pop(older_list)
buff.session.db["lists"].append(list) buff.session.db["lists"].append(list)
except TweepError as e: except TweepyException as e:
output.speak("error %s: %s" % (e.api_code, e.reason)) output.speak("error %s" % (str(e)))
log.exception("error %s" % (str(e)))
def list_manager(self, *args, **kwargs): def list_manager(self, *args, **kwargs):
s = self.get_best_buffer().session s = self.get_best_buffer().session
@@ -764,7 +750,7 @@ class Controller(object):
users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name] users = [buff.session.get_user(tweet.message_create["sender_id"]).screen_name]
else: else:
users = utils.get_all_users(tweet, buff.session) users = utils.get_all_users(tweet, buff.session)
dlg = dialogs.utils.addAliasDialog(_("Add an user alias"), users) dlg = dialogs.userAliasDialogs.addAliasDialog(_("Add an user alias"), users)
if dlg.get_response() == widgetUtils.OK: if dlg.get_response() == widgetUtils.OK:
user, alias = dlg.get_user() user, alias = dlg.get_user()
if user == "" or alias == "": if user == "" or alias == "":
@@ -773,6 +759,11 @@ class Controller(object):
buff.session.settings["user-aliases"][str(user_id)] = alias buff.session.settings["user-aliases"][str(user_id)] = alias
buff.session.settings.write() buff.session.settings.write()
output.speak(_("Alias has been set correctly for {}.").format(user)) output.speak(_("Alias has been set correctly for {}.").format(user))
pub.sendMessage("alias-added")
def manage_aliases(self, *args, **kwargs):
buff = self.get_best_buffer()
alias_controller = userAliasController.userAliasController(buff.session.settings)
def post_tweet(self, event=None): def post_tweet(self, event=None):
buffer = self.get_best_buffer() buffer = self.get_best_buffer()
@@ -900,7 +891,7 @@ class Controller(object):
if usr.id_str in buff.session.settings["other_buffers"]["favourites_timelines"]: if usr.id_str in buff.session.settings["other_buffers"]["favourites_timelines"]:
commonMessageDialogs.timeline_exist() commonMessageDialogs.timeline_exist()
return return
tl = buffers.twitter.BaseBuffer(self.view.nb, "favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, tweet_mode="extended") tl = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "%s-favorite" % (usr.id_str,), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr.id_str, tweet_mode="extended")
try: try:
tl.start_stream(play_sound=False) tl.start_stream(play_sound=False)
except ValueError: except ValueError:
@@ -919,7 +910,7 @@ class Controller(object):
if usr.id_str in buff.session.settings["other_buffers"]["followers_timelines"]: if usr.id_str in buff.session.settings["other_buffers"]["followers_timelines"]:
commonMessageDialogs.timeline_exist() commonMessageDialogs.timeline_exist()
return return
tl = buffers.twitter.PeopleBuffer(self.view.nb, "followers", "%s-followers" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str) tl = buffers.twitter.PeopleBuffer(self.view.nb, "get_followers", "%s-followers" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str)
try: try:
tl.start_stream(play_sound=False) tl.start_stream(play_sound=False)
except ValueError: except ValueError:
@@ -938,7 +929,7 @@ class Controller(object):
if usr.id_str in buff.session.settings["other_buffers"]["friends_timelines"]: if usr.id_str in buff.session.settings["other_buffers"]["friends_timelines"]:
commonMessageDialogs.timeline_exist() commonMessageDialogs.timeline_exist()
return return
tl = buffers.twitter.PeopleBuffer(self.view.nb, "friends", "%s-friends" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str) tl = buffers.twitter.PeopleBuffer(self.view.nb, "get_friends", "%s-friends" % (usr.id_str,), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr.id_str)
try: try:
tl.start_stream(play_sound=False) tl.start_stream(play_sound=False)
except ValueError: except ValueError:
@@ -958,7 +949,7 @@ class Controller(object):
buffer = self.get_current_buffer() buffer = self.get_current_buffer()
id = buffer.get_right_tweet().id id = buffer.get_right_tweet().id
user = buffer.session.get_user(buffer.get_right_tweet().user).screen_name user = buffer.session.get_user(buffer.get_right_tweet().user).screen_name
search = buffers.twitter.ConversationBuffer(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,)) search = buffers.twitter.ConversationBuffer(self.view.nb, "search_tweets", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,))
search.tweet = buffer.get_right_tweet() search.tweet = buffer.get_right_tweet()
search.start_stream(start=True) search.start_stream(start=True)
pos=self.view.search("searches", buffer.session.db["user_name"]) pos=self.view.search("searches", buffer.session.db["user_name"])
@@ -1360,11 +1351,10 @@ class Controller(object):
i.start_stream() i.start_stream()
else: else:
i.start_stream(play_sound=False) i.start_stream(play_sound=False)
except TweepError as err: except TweepyException as err:
log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r due to the following reason: %s" % (err.api_code, i.name, i.account, i.args, i.kwargs, err.reason)) log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r." % (str(err), i.name, i.account, i.args, i.kwargs))
# Determine if this error was caused by a block applied to the current user (IE permission errors). # Determine if this error was caused by a block applied to the current user (IE permission errors).
errors_allowed = [130] if type(err) == Forbidden:
if (err.api_code != None and err.api_code not in errors_allowed) or (err.api_code == None and 'Not authorized' in err.reason): # A twitter error, so safely try to remove the buffer.
buff = self.view.search(i.name, i.account) buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True) i.remove_buffer(force=True)
commonMessageDialogs.blocked_timeline() commonMessageDialogs.blocked_timeline()
@@ -1388,34 +1378,34 @@ class Controller(object):
try: try:
if sessions.sessions[i].is_logged == False: continue if sessions.sessions[i].is_logged == False: continue
sessions.sessions[i].check_connection() sessions.sessions[i].check_connection()
except TweepError: # We shouldn't allow this function to die. except TweepyException: # We shouldn't allow this function to die.
pass pass
def create_new_buffer(self, buffer, account, create): def create_new_buffer(self, buffer, account, create):
buff = self.search_buffer("home_timeline", account) buff = self.search_buffer("home_timeline", account)
if create == True: if create == True:
if buffer == "favourites": if buffer == "favourites":
favourites = buffers.twitter.BaseBuffer(self.view.nb, "favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended") favourites = buffers.twitter.BaseBuffer(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"], tweet_mode="extended")
self.buffers.append(favourites) self.buffers.append(favourites)
self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) self.view.insert_buffer(favourites.buffer, name=_(u"Likes"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
favourites.start_stream(play_sound=False) favourites.start_stream(play_sound=False)
if buffer == "followers": if buffer == "followers":
followers = buffers.twitter.PeopleBuffer(self.view.nb, "followers", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) followers = buffers.twitter.PeopleBuffer(self.view.nb, "get_followers", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(followers) self.buffers.append(followers)
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
followers.start_stream(play_sound=False) followers.start_stream(play_sound=False)
elif buffer == "friends": elif buffer == "friends":
friends = buffers.twitter.PeopleBuffer(self.view.nb, "friends", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"]) friends = buffers.twitter.PeopleBuffer(self.view.nb, "get_friends", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
self.buffers.append(friends) self.buffers.append(friends)
self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) self.view.insert_buffer(friends.buffer, name=_(u"Friends"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
friends.start_stream(play_sound=False) friends.start_stream(play_sound=False)
elif buffer == "blocked": elif buffer == "blocked":
blocks = buffers.twitter.PeopleBuffer(self.view.nb, "blocks", "blocked", buff.session, buff.session.db["user_name"]) blocks = buffers.twitter.PeopleBuffer(self.view.nb, "get_blocks", "blocked", buff.session, buff.session.db["user_name"])
self.buffers.append(blocks) self.buffers.append(blocks)
self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) self.view.insert_buffer(blocks.buffer, name=_(u"Blocked users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
blocks.start_stream(play_sound=False) blocks.start_stream(play_sound=False)
elif buffer == "muted": elif buffer == "muted":
muted = buffers.twitter.PeopleBuffer(self.view.nb, "mutes", "muted", buff.session, buff.session.db["user_name"]) muted = buffers.twitter.PeopleBuffer(self.view.nb, "get_mutes", "muted", buff.session, buff.session.db["user_name"])
self.buffers.append(muted) self.buffers.append(muted)
self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])) self.view.insert_buffer(muted.buffer, name=_(u"Muted users"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
muted.start_stream(play_sound=False) muted.start_stream(play_sound=False)
@@ -1566,11 +1556,10 @@ class Controller(object):
if i.session != None and i.session.is_logged == True: if i.session != None and i.session.is_logged == True:
try: try:
i.start_stream(mandatory=True) i.start_stream(mandatory=True)
except TweepError as err: except TweepyException as err:
log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r due to the following reason: %s" % (err.api_code, i.name, i.account, i.args, i.kwargs, err.reason)) log.exception("Error %s starting buffer %s on account %s, with args %r and kwargs %r." % (str(err), i.name, i.account, i.args, i.kwargs))
# Determine if this error was caused by a block applied to the current user (IE permission errors). # Determine if this error was caused by a block applied to the current user (IE permission errors).
errors_allowed = [130] if type(err) == Forbidden:
if (err.api_code != None and err.api_code not in errors_allowed) or (err.api_code == None and 'Not authorized' in err.reason): # A twitter error, so safely try to remove the buffer.
buff = self.view.search(i.name, i.account) buff = self.view.search(i.name, i.account)
i.remove_buffer(force=True) i.remove_buffer(force=True)
commonMessageDialogs.blocked_timeline() commonMessageDialogs.blocked_timeline()
@@ -1676,5 +1665,5 @@ class Controller(object):
try: try:
if sessions.sessions[i].is_logged == False: continue if sessions.sessions[i].is_logged == False: continue
sessions.sessions[i].check_streams() sessions.sessions[i].check_streams()
except TweepError: # We shouldn't allow this function to die. except TweepyException: # We shouldn't allow this function to die.
pass pass

View File

@@ -8,7 +8,7 @@ class trendingTopicsController(object):
self.countries = {} self.countries = {}
self.cities = {} self.cities = {}
self.dialog = trends.trendingTopicsDialog() self.dialog = trends.trendingTopicsDialog()
self.information = session.twitter.trends_available() self.information = session.twitter.available_trends()
self.split_information() self.split_information()
widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places) widgetUtils.connect_event(self.dialog.country, widgetUtils.RADIOBUTTON, self.get_places)
widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places) widgetUtils.connect_event(self.dialog.city, widgetUtils.RADIOBUTTON, self.get_places)

View File

@@ -6,7 +6,7 @@ import output
from wxUI.dialogs import update_profile, show_user from wxUI.dialogs import update_profile, show_user
import logging import logging
log = logging.getLogger("controller.user") log = logging.getLogger("controller.user")
from tweepy.error import TweepError from tweepy.errors import TweepyException, Forbidden, NotFound
from sessions.twitter import utils from sessions.twitter import utils
class profileController(object): class profileController(object):
@@ -24,12 +24,12 @@ class profileController(object):
else: else:
try: try:
self.get_data(screen_name=self.user) self.get_data(screen_name=self.user)
except TweepError as err: except TweepyException as err:
if err.api_code == 50: if type(err) == NotFound:
wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal() wx.MessageDialog(None, _(u"That user does not exist"), _(u"Error"), wx.ICON_ERROR).ShowModal()
if err.api_code == 63: if type(err) == Forbidden:
wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal() wx.MessageDialog(None, _(u"User has been suspended"), _(u"Error"), wx.ICON_ERROR).ShowModal()
log.error("error %d: %s" % (err.api_code, err.reason)) log.error("error %s" % (str(err)))
return return
self.dialog = show_user.showUserProfile() self.dialog = show_user.showUserProfile()
string = self.get_user_info() string = self.get_user_info()
@@ -44,7 +44,7 @@ class profileController(object):
def get_data(self, screen_name): def get_data(self, screen_name):
self.data = self.session.twitter.get_user(screen_name=screen_name) self.data = self.session.twitter.get_user(screen_name=screen_name)
if screen_name != self.session.db["user_name"]: if screen_name != self.session.db["user_name"]:
self.friendship_status = self.session.twitter.show_friendship(source_screen_name=self.session.db["user_name"], target_screen_name=screen_name) self.friendship_status = self.session.twitter.get_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)
@@ -83,12 +83,12 @@ class profileController(object):
if self.file != None: if self.file != None:
try: try:
self.session.twitter.update_profile_image(image=self.file) self.session.twitter.update_profile_image(image=self.file)
except TweepError as e: except TweepyException as e:
output.speak(u"Error %s. %s" % (e.api_code, e.reason)) output.speak(u"Error %s" % (str(e)))
try: try:
self.session.twitter.update_profile(name=name, description=description, location=location, url=url) self.session.twitter.update_profile(name=name, description=description, location=location, url=url)
except TweepError as e: except TweepyException as e:
output.speak(u"Error %s. %s" % (e.api_code, e.reason)) output.speak(u"Error %s." % (str(e)))
def get_user_info(self): def get_user_info(self):
string = u"" string = u""

View File

@@ -3,7 +3,7 @@ import widgetUtils
import output import output
from wxUI.dialogs import userActions from wxUI.dialogs import userActions
from pubsub import pub from pubsub import pub
from tweepy.error import TweepError from tweepy.errors import TweepyException
from extra import autocompletionUsers from extra import autocompletionUsers
class userActionsController(object): class userActionsController(object):
@@ -29,44 +29,44 @@ class userActionsController(object):
def follow(self, user): def follow(self, user):
try: try:
self.session.twitter.create_friendship(screen_name=user ) self.session.twitter.create_friendship(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def unfollow(self, user): def unfollow(self, user):
try: try:
id = self.session.twitter.destroy_friendship(screen_name=user ) id = self.session.twitter.destroy_friendship(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def mute(self, user): def mute(self, user):
try: try:
id = self.session.twitter.create_mute(screen_name=user ) id = self.session.twitter.create_mute(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def unmute(self, user): def unmute(self, user):
try: try:
id = self.session.twitter.destroy_mute(screen_name=user ) id = self.session.twitter.destroy_mute(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def report(self, user): def report(self, user):
try: try:
id = self.session.twitter.report_spam(screen_name=user ) id = self.session.twitter.report_spam(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def block(self, user): def block(self, user):
try: try:
id = self.session.twitter.create_block(screen_name=user ) id = self.session.twitter.create_block(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def unblock(self, user): def unblock(self, user):
try: try:
id = self.session.twitter.destroy_block(screen_name=user ) id = self.session.twitter.destroy_block(screen_name=user )
except TweepError as err: except TweepyException as err:
output.speak("Error %s: %s" % (err.api_code, err.reason), True) output.speak("Error %s" % (str(err)), True)
def ignore_client(self, user): def ignore_client(self, user):
tweet = self.buffer.get_right_tweet() tweet = self.buffer.get_right_tweet()

View File

@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*-
import widgetUtils
from pubsub import pub
from wxUI.dialogs import userAliasDialogs
from extra import autocompletionUsers
class userAliasController(object):
def __init__(self, settings):
super(userAliasController, self).__init__()
self.settings = settings
self.dialog = userAliasDialogs.userAliasEditorDialog()
self.update_aliases_manager()
widgetUtils.connect_event(self.dialog.add, widgetUtils.BUTTON_PRESSED, self.on_add)
widgetUtils.connect_event(self.dialog.edit, widgetUtils.BUTTON_PRESSED, self.on_edit)
widgetUtils.connect_event(self.dialog.remove, widgetUtils.BUTTON_PRESSED, self.on_remove)
pub.subscribe(self.update_aliases_manager, "alias-added")
self.dialog.ShowModal()
def update_aliases_manager(self):
self.dialog.users.Clear()
aliases = [self.settings["user-aliases"].get(k) for k in self.settings["user-aliases"].keys()]
if len(aliases) > 0:
self.dialog.users.InsertItems(aliases, 0)
self.dialog.on_selection_changes()
def on_add(self, *args, **kwargs):
pub.sendMessage("execute-action", action="add_alias")
def on_edit(self, *args, **kwargs):
selection = self.dialog.get_selected_user()
if selection != "":
edited = self.dialog.edit_alias_dialog(_("Edit alias for {}").format(selection))
if edited == None or edited == "":
return
for user_key in self.settings["user-aliases"].keys():
if self.settings["user-aliases"][user_key] == selection:
self.settings["user-aliases"][user_key] = edited
self.settings.write()
self.update_aliases_manager()
break
def on_remove(self, *args, **kwargs):
selection = self.dialog.get_selected_user()
if selection == None or selection == "":
return
should_remove = self.dialog.remove_alias_dialog()
if should_remove:
for user_key in self.settings["user-aliases"].keys():
if self.settings["user-aliases"][user_key] == selection:
self.settings["user-aliases"].pop(user_key)
self.settings.write()
self.update_aliases_manager()
break

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -17,7 +17,7 @@ from sessions.twitter import session
from . import manager from . import manager
import config_utils import config_utils
import config import config
from tweepy.error import TweepError from tweepy.errors import TweepyException
log = logging.getLogger("sessionmanager.sessionManager") log = logging.getLogger("sessionmanager.sessionManager")
class sessionManagerController(object): class sessionManagerController(object):
@@ -83,7 +83,7 @@ class sessionManagerController(object):
if i not in config.app["sessions"]["ignored_sessions"]: if i not in config.app["sessions"]["ignored_sessions"]:
try: try:
s.login() s.login()
except TweepError: except TweepyException:
self.show_auth_error(s.settings["twitter"]["user_name"]) self.show_auth_error(s.settings["twitter"]["user_name"])
continue continue
sessions.sessions[i] = s sessions.sessions[i] = s

View File

@@ -43,6 +43,10 @@ class baseSession(object):
self.logged = False self.logged = False
self.settings = None self.settings = None
self.db={} self.db={}
# Config specification file.
self.config_spec = "conf.defaults"
# Session type.
self.type = "base"
@property @property
def is_logged(self): def is_logged(self):
@@ -52,7 +56,7 @@ class baseSession(object):
""" Get settings for a session.""" """ Get settings for a session."""
file_ = "%s/session.conf" % (self.session_id,) file_ = "%s/session.conf" % (self.session_id,)
log.debug("Creating config file %s" % (file_,)) log.debug("Creating config file %s" % (file_,))
self.settings = config_utils.load_config(os.path.join(paths.config_path(), file_), os.path.join(paths.app_path(), "Conf.defaults")) self.settings = config_utils.load_config(os.path.join(paths.config_path(), file_), os.path.join(paths.app_path(), self.config_spec))
self.init_sound() self.init_sound()
self.load_persistent_data() self.load_persistent_data()

View File

@@ -8,9 +8,10 @@ import wx
import config import config
import output import output
import application import application
import appkeys
from pubsub import pub from pubsub import pub
import tweepy import tweepy
from tweepy.error import TweepError from tweepy.errors import TweepyException, Forbidden, NotFound
from tweepy.models import User as UserModel from tweepy.models import User as UserModel
from mysc.thread_utils import call_threaded from mysc.thread_utils import call_threaded
from keys import keyring from keys import keyring
@@ -124,6 +125,7 @@ class Session(base.baseSession):
# This will be especially useful because if the user reactivates their account later, TWblue will try to retrieve such user again at startup. # This will be especially useful because if the user reactivates their account later, TWblue will try to retrieve such user again at startup.
# If we wouldn't implement this approach, TWBlue would save permanently the "deleted user" object. # If we wouldn't implement this approach, TWBlue would save permanently the "deleted user" object.
self.deleted_users = {} self.deleted_users = {}
self.type = "twitter"
pub.subscribe(self.handle_new_status, "newStatus") pub.subscribe(self.handle_new_status, "newStatus")
pub.subscribe(self.handle_connected, "streamConnected") pub.subscribe(self.handle_connected, "streamConnected")
@@ -134,9 +136,10 @@ class Session(base.baseSession):
if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None: if self.settings["twitter"]["user_key"] != None and self.settings["twitter"]["user_secret"] != None:
try: try:
log.debug("Logging in to twitter...") log.debug("Logging in to twitter...")
self.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret")) self.auth = tweepy.OAuthHandler(appkeys.twitter_api_key, appkeys.twitter_api_secret)
self.auth.set_access_token(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"]) self.auth.set_access_token(self.settings["twitter"]["user_key"], self.settings["twitter"]["user_secret"])
self.twitter = tweepy.API(self.auth) self.twitter = tweepy.API(self.auth)
self.twitter_v2 = tweepy.Client(consumer_key=appkeys.twitter_api_key, consumer_secret=appkeys.twitter_api_secret, access_token=self.settings["twitter"]["user_key"], access_token_secret=self.settings["twitter"]["user_secret"])
if verify_credentials == True: if verify_credentials == True:
self.credentials = self.twitter.verify_credentials() self.credentials = self.twitter.verify_credentials()
self.logged = True self.logged = True
@@ -155,7 +158,7 @@ class Session(base.baseSession):
if self.logged == True: if self.logged == True:
raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.") raise Exceptions.AlreadyAuthorisedError("The authorisation process is not needed at this time.")
else: else:
self.auth = tweepy.OAuthHandler(keyring.get("api_key"), keyring.get("api_secret")) self.auth = tweepy.OAuthHandler(appkeys.twitter_api_key, appkeys.twitter_api_secret)
redirect_url = self.auth.get_authorization_url() redirect_url = self.auth.get_authorization_url()
webbrowser.open_new_tab(redirect_url) webbrowser.open_new_tab(redirect_url)
self.authorisation_dialog = authorisationDialog() self.authorisation_dialog = authorisationDialog()
@@ -198,14 +201,14 @@ class Session(base.baseSession):
try: try:
val = getattr(self.twitter, call_name)(*args, **kwargs) val = getattr(self.twitter, call_name)(*args, **kwargs)
finished = True finished = True
except TweepError as e: except TweepyException as e:
output.speak(e.reason) output.speak(str(e))
val = None val = None
if e.error_code != 403 and e.error_code != 404: if type(e) != NotFound and type(e) != Forvidden:
tries = tries+1 tries = tries+1
time.sleep(5) time.sleep(5)
elif report_failure and hasattr(e, 'reason'): elif report_failure:
output.speak(_("%s failed. Reason: %s") % (action, e.reason)) output.speak(_("%s failed. Reason: %s") % (action, str(e)))
finished = True finished = True
# except: # except:
# tries = tries + 1 # tries = tries + 1
@@ -217,7 +220,7 @@ class Session(base.baseSession):
def search(self, name, *args, **kwargs): def search(self, name, *args, **kwargs):
""" Search in twitter, passing args and kwargs as arguments to the Twython function.""" """ Search in twitter, passing args and kwargs as arguments to the Twython function."""
tl = self.twitter.search(*args, **kwargs) tl = self.twitter.search_tweets(*args, **kwargs)
tl.reverse() tl.reverse()
return tl return tl
@@ -270,12 +273,12 @@ class Session(base.baseSession):
# @_require_login # @_require_login
def get_lists(self): def get_lists(self):
""" Gets the lists that the user is subscribed to and stores them in the database. Returns None.""" """ Gets the lists that the user is subscribed to and stores them in the database. Returns None."""
self.db["lists"] = self.twitter.lists_all(reverse=True) self.db["lists"] = self.twitter.get_lists(reverse=True)
# @_require_login # @_require_login
def get_muted_users(self): def get_muted_users(self):
""" Gets muted users (oh really?).""" """ Gets muted users (oh really?)."""
self.db["muted_users"] = self.twitter.mutes_ids() self.db["muted_users"] = self.twitter.get_muted_ids()
# @_require_login # @_require_login
def get_stream(self, name, function, *args, **kwargs): def get_stream(self, name, function, *args, **kwargs):
@@ -416,12 +419,12 @@ class Session(base.baseSession):
log.debug("Requesting user id {} as it is not present in the users database.".format(id)) log.debug("Requesting user id {} as it is not present in the users database.".format(id))
try: try:
user = self.twitter.get_user(id=id) user = self.twitter.get_user(id=id)
except TweepError as err: except TweepyException as err:
user = UserModel(None) user = UserModel(None)
user.screen_name = "deleted_user" user.screen_name = "deleted_user"
user.id = id user.id = id
user.name = _("Deleted account") user.name = _("Deleted account")
if hasattr(err, "api_code") and err.api_code == 50: if type(err) == NotFound:
self.deleted_users[id] = user self.deleted_users[id] = user
return user return user
else: else:
@@ -482,14 +485,14 @@ class Session(base.baseSession):
return return
log.debug("TWBlue will get %d new users from Twitter." % (len(users_to_retrieve))) log.debug("TWBlue will get %d new users from Twitter." % (len(users_to_retrieve)))
try: try:
users = self.twitter.lookup_users(user_ids=users_to_retrieve, tweet_mode="extended") users = self.twitter.lookup_users(user_id=users_to_retrieve, tweet_mode="extended")
users_db = self.db["users"] users_db = self.db["users"]
for user in users: for user in users:
users_db[user.id_str] = user users_db[user.id_str] = user
log.debug("Added %d new users" % (len(users))) log.debug("Added %d new users" % (len(users)))
self.db["users"] = users_db self.db["users"] = users_db
except TweepError as err: except TweepyException as err:
if hasattr(err, "api_code") and err.api_code == 17: # Users not found. if type(err) == NotFound: # User not found.
log.error("The specified users {} were not found in twitter.".format(user_ids)) log.error("The specified users {} were not found in twitter.".format(user_ids))
# Creates a deleted user object for every user_id not found here. # Creates a deleted user object for every user_id not found here.
# This will make TWBlue to not waste Twitter API calls when attempting to retrieve those users again. # This will make TWBlue to not waste Twitter API calls when attempting to retrieve those users again.
@@ -522,9 +525,8 @@ class Session(base.baseSession):
def start_streaming(self): def start_streaming(self):
if config.app["app-settings"]["no_streaming"]: if config.app["app-settings"]["no_streaming"]:
return return
self.stream_listener = streaming.StreamListener(twitter_api=self.twitter, user=self.db["user_name"], user_id=self.db["user_id"], muted_users=self.db["muted_users"]) self.stream = streaming.Stream(twitter_api=self.twitter, user=self.db["user_name"], user_id=self.db["user_id"], muted_users=self.db["muted_users"], consumer_key=appkeys.twitter_api_key, consumer_secret=appkeys.twitter_api_secret, access_token=self.settings["twitter"]["user_key"], access_token_secret=self.settings["twitter"]["user_secret"], chunk_size=1025)
self.stream = streaming.Stream(auth = self.auth, listener=self.stream_listener, chunk_size=1025) self.stream_thread = call_threaded(self.stream.filter, follow=self.stream.users, stall_warnings=True)
self.stream_thread = call_threaded(self.stream.filter, follow=self.stream_listener.users, stall_warnings=True)
def stop_streaming(self): def stop_streaming(self):
if config.app["app-settings"]["no_streaming"]: if config.app["app-settings"]["no_streaming"]:
@@ -553,7 +555,7 @@ class Session(base.baseSession):
status._json = {**status._json, **status._json["extended_tweet"]} status._json = {**status._json, **status._json["extended_tweet"]}
# Sends status to database, where it will be reduced and changed according to our needs. # Sends status to database, where it will be reduced and changed according to our needs.
buffers_to_send = [] buffers_to_send = []
if status.user.id_str in self.stream_listener.users: if status.user.id_str in self.stream.users:
buffers_to_send.append("home_timeline") buffers_to_send.append("home_timeline")
if status.user.id == self.db["user_id"]: if status.user.id == self.db["user_id"]:
buffers_to_send.append("sent_tweets") buffers_to_send.append("sent_tweets")

View File

@@ -12,17 +12,17 @@ from pubsub import pub
log = logging.getLogger("sessions.twitter.streaming") log = logging.getLogger("sessions.twitter.streaming")
class StreamListener(tweepy.StreamListener): class Stream(tweepy.Stream):
def __init__(self, twitter_api, user, user_id, muted_users=[], *args, **kwargs): def __init__(self, twitter_api, user, user_id, muted_users=[], *args, **kwargs):
super(StreamListener, self).__init__(*args, **kwargs) super(Stream, self).__init__(*args, **kwargs)
log.debug("Starting streaming listener for account {}".format(user)) log.debug("Starting streaming listener for account {}".format(user))
self.started = False self.started = False
self.users = [] self.users = []
self.api = twitter_api self.api = twitter_api
self.user = user self.user = user
self.user_id = user_id self.user_id = user_id
friends = self.api.friends_ids() friends = self.api.get_friend_ids()
log.debug("Retrieved {} friends to add to the streaming listener.".format(len(friends))) log.debug("Retrieved {} friends to add to the streaming listener.".format(len(friends)))
self.users.append(str(self.user_id)) self.users.append(str(self.user_id))
log.debug("Got {} muted users.".format(len(muted_users))) log.debug("Got {} muted users.".format(len(muted_users)))
@@ -45,78 +45,3 @@ class StreamListener(tweepy.StreamListener):
return return
if status.user.id_str in self.users: if status.user.id_str in self.users:
pub.sendMessage("newStatus", status=status, user=self.user) pub.sendMessage("newStatus", status=status, user=self.user)
class Stream(tweepy.Stream):
def _run(self):
# Authenticate
url = "https://%s%s" % (self.host, self.url)
# Connect and process the stream
error_counter = 0
resp = None
exc_info = None
while self.running:
if self.retry_count is not None:
if error_counter > self.retry_count:
# quit if error count greater than retry count
break
try:
auth = self.auth.apply_auth()
resp = self.session.request('POST',
url,
data=self.body,
timeout=self.timeout,
stream=True,
auth=auth,
verify=self.verify,
proxies = self.proxies)
if resp.status_code != 200:
if self.listener.on_error(resp.status_code) is False:
break
error_counter += 1
if resp.status_code == 420:
self.retry_time = max(self.retry_420_start,
self.retry_time)
time.sleep(self.retry_time)
self.retry_time = min(self.retry_time * 2,
self.retry_time_cap)
else:
error_counter = 0
self.retry_time = self.retry_time_start
self.snooze_time = self.snooze_time_step
self.listener.on_connect()
self._read_loop(resp)
except (requests.ConnectionError, requests.Timeout, ssl.SSLError, urllib3.exceptions.ReadTimeoutError, urllib3.exceptions.ProtocolError) as exc:
# This is still necessary, as a SSLError can actually be
# thrown when using Requests
# If it's not time out treat it like any other exception
if isinstance(exc, ssl.SSLError):
if not (exc.args and 'timed out' in str(exc.args[0])):
exc_info = sys.exc_info()
break
if self.listener.on_timeout() is False:
break
if self.running is False:
break
time.sleep(self.snooze_time)
self.snooze_time = min(self.snooze_time + self.snooze_time_step,
self.snooze_time_cap)
except Exception as exc:
exc_info = sys.exc_info()
# any other exception is fatal, so kill loop
break
# cleanup
self.running = False
if resp:
resp.close()
self.new_session()
if exc_info:
# call a handler first so that the exception can be logged.
self.listener.on_exception(exc_info[1])
six.reraise(*exc_info)

View File

@@ -6,7 +6,7 @@ import logging
import requests import requests
import time import time
import sound import sound
from tweepy.error import TweepError from tweepy.errors import TweepyException, NotFound, Forbidden
log = logging.getLogger("twitter.utils") log = logging.getLogger("twitter.utils")
""" Some utilities for the twitter interface.""" """ Some utilities for the twitter interface."""
@@ -159,8 +159,8 @@ def if_user_exists(twitter, user):
try: try:
data = twitter.get_user(screen_name=user) data = twitter.get_user(screen_name=user)
return data return data
except TweepError as err: except TweepyException as err:
if err.api_code == 50: if type(err) == NotFound:
return None return None
else: else:
return user return user
@@ -227,12 +227,12 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name):
return True return True
def twitter_error(error): def twitter_error(error):
if error.api_code == 179: if type(error) == Forbidden:
msg = _(u"Sorry, you are not authorised to see this status.") msg = _(u"Sorry, you are not authorised to see this status.")
elif error.api_code == 144: elif type(error) == NotFound:
msg = _(u"No status found with that ID") msg = _(u"No status found with that ID")
else: else:
msg = _(u"Error code {0}").format(error.api_code,) msg = _(u"Error {0}").format(str(error),)
output.speak(msg) output.speak(msg)
def expand_urls(text, entities): def expand_urls(text, entities):
@@ -254,10 +254,10 @@ def clean_mentions(text):
total_users = 0 total_users = 0
for user in mentionned_people: for user in mentionned_people:
if abs(user.start()-end) < 3: if abs(user.start()-end) < 3:
new_text = new_text.replace(user.group(0), "") new_text = new_text.replace(user.group(0), "", 1)
total_users = total_users+1 total_users = total_users+1
end = user.end() end = user.end()
if total_users < 1: if total_users-2 < 1:
return text return text
new_text = _("{user_1}, {user_2} and {all_users} more: {text}").format(user_1=mentionned_people[0].group(0), user_2=mentionned_people[1].group(0), all_users=total_users-2, text=new_text) new_text = _("{user_1}, {user_2} and {all_users} more: {text}").format(user_1=mentionned_people[0].group(0), user_2=mentionned_people[1].group(0), all_users=total_users-2, text=new_text)
return new_text return new_text

View File

@@ -114,6 +114,8 @@ class URLStream(object):
# LibVLC controls. # LibVLC controls.
self.instance = vlc.Instance() self.instance = vlc.Instance()
self.player = self.instance.media_player_new() self.player = self.instance.media_player_new()
self.event_manager = self.player.event_manager()
self.event_manager.event_attach(vlc.EventType.MediaPlayerEndReached, self.end_callback)
def prepare(self, url): def prepare(self, url):
""" Takes an URL and prepares it to be streamed. This function will try to unshorten the passed URL and, if needed, to transform it into a valid URL.""" """ Takes an URL and prepares it to be streamed. This function will try to unshorten the passed URL and, if needed, to transform it into a valid URL."""
@@ -158,3 +160,9 @@ class URLStream(object):
def stop_audio(self): def stop_audio(self):
output.speak(_(u"Stopped."), True) output.speak(_(u"Stopped."), True)
self.player.stop() self.player.stop()
def end_callback(self, event, *args, **kwargs):
call_threaded(self.player.stop)
def __del__(self):
self.event_manager.event_detach(vlc.EventType.MediaPlayerEndReached)

View File

@@ -1,4 +1,3 @@
from __future__ import unicode_literals
from logging import getLogger from logging import getLogger
logger = getLogger('update') logger = getLogger('update')
@@ -24,8 +23,8 @@ def perform_update(endpoint, current_version, app_name='', password=None, update
if not available_update: if not available_update:
logger.debug("No update available") logger.debug("No update available")
return False return False
available_version = float(available_update['current_version']) available_version = available_update['current_version']
if not float(available_version) > float(current_version) or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']: if available_version == current_version or platform.system()+platform.architecture()[0][:2] not in available_update['downloads']:
logger.debug("No update for this architecture") logger.debug("No update for this architecture")
return False return False
available_description = available_update.get('description', None) available_description = available_update.get('description', None)
@@ -42,10 +41,10 @@ def perform_update(endpoint, current_version, app_name='', password=None, update
downloaded = download_update(update_url, download_path, requests_session=requests_session, progress_callback=progress_callback) downloaded = download_update(update_url, download_path, requests_session=requests_session, progress_callback=progress_callback)
extracted = extract_update(downloaded, update_path, password=password) extracted = extract_update(downloaded, update_path, password=password)
bootstrap_path = move_bootstrap(extracted) bootstrap_path = move_bootstrap(extracted)
execute_bootstrap(bootstrap_path, extracted)
logger.info("Update prepared for installation.")
if callable(update_complete_callback): if callable(update_complete_callback):
update_complete_callback() update_complete_callback()
execute_bootstrap(bootstrap_path, extracted)
logger.info("Update prepared for installation.")
def create_requests_session(app_name=None, version=None): def create_requests_session(app_name=None, version=None):
user_agent = '' user_agent = ''

View File

@@ -1,6 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import unicode_literals
import application import application
from . import update from . import update
import platform import platform

35
src/write_version_data.py Normal file
View File

@@ -0,0 +1,35 @@
#! /usr/bin/env python# -*- coding: iso-8859-1 -*-
""" Write version info (taken from the last commit) to application.py. This method has been implemented this way for running updates.
This file is not intended to be called by the user. It will be used only by the Gitlab CI runner."""
import requests
from codecs import open
print("Writing version data for update...")
commit_info = requests.get("https://gitlab.com/api/v4/projects/23482196/repository/commits/next-gen")
commit_info = commit_info.json()
commit = commit_info["short_id"]
print("Got new version info: {commit}".format(commit=commit,))
file = open("application.py", "r", encoding="utf-8")
lines = file.readlines()
lines[-1] = 'version = "{}"'.format(commit_info["created_at"][:10].replace("-", "."))
file.close()
file2 = open("application.py", "w", encoding="utf-8")
file2.writelines(lines)
file2.close()
print("Wrote application.py with the new version info.")
print("Updating next version on installer setup...")
file = open("..\\scripts\\twblue.nsi", "r", encoding="utf-8")
contents = file.read()
contents = contents.replace("0.95", commit_info["created_at"][:10].replace("-", "."))
file.close()
file2 = open("..\\scripts\\twblue.nsi", "w", encoding="utf-8")
file2.write(contents)
file2.close()
print("done")
file3 = open("appkeys.py", "w")
keys = """twitter_api_key = "daMHlXsFlalEWtaqTL7xd6TqZ"
twitter_api_secret = "lOcpsIlhr1lBpA53oNWwmKh9yM6Gqk3IRFOzq9TvAO8B5gisFD"
"""
file3.write(keys)
file3.close()

View File

@@ -1,3 +1,3 @@
from __future__ import absolute_import from __future__ import absolute_import
from __future__ import unicode_literals from __future__ import unicode_literals
from . import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils, filterDialogs from . import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils, filterDialogs, userAliasDialogs

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-
import wx
import gettext
from . import baseDialog
class addAliasDialog(baseDialog.BaseWXDialog):
def __init__(self, title, users):
super(addAliasDialog, self).__init__(parent=None, id=wx.ID_ANY, title=title)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
aliasSizer = wx.BoxSizer(wx.HORIZONTAL)
aliasLabel = wx.StaticText(panel, wx.ID_ANY, _("Alias"))
self.alias = wx.TextCtrl(panel, wx.ID_ANY)
aliasSizer.Add(aliasLabel, 0, wx.ALL, 5)
aliasSizer.Add(self.alias, 0, wx.ALL, 5)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(userSizer, 0, wx.ALL, 5)
sizer.Add(aliasSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_user(self):
return (self.cb.GetValue(), self.alias.GetValue())
class userAliasEditorDialog(wx.Dialog):
def __init__(self, *args, **kwds):
super(userAliasEditorDialog, self).__init__(parent=None)
self.SetTitle(_("Edit user aliases"))
main_sizer = wx.BoxSizer(wx.VERTICAL)
userListSizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Users")), wx.VERTICAL)
main_sizer.Add(userListSizer, 1, wx.EXPAND, 0)
self.users = wx.ListBox(self, wx.ID_ANY, choices=[])
self.users.Bind(wx.EVT_LISTBOX, self.on_selection_changes)
userListSizer.Add(self.users, 0, 0, 0)
actionsSizer = wx.StaticBoxSizer(wx.StaticBox(self, wx.ID_ANY, _("Actions")), wx.HORIZONTAL)
main_sizer.Add(actionsSizer, 1, wx.EXPAND, 0)
self.add = wx.Button(self, wx.ID_ANY, _("Add alias"))
self.add.SetToolTip(_("Adds a new user alias"))
actionsSizer.Add(self.add, 0, 0, 0)
self.edit = wx.Button(self, wx.ID_ANY, _("Edit"))
self.edit.SetToolTip(_("Edit the currently focused user Alias."))
self.edit.Enable(False)
actionsSizer.Add(self.edit, 0, 0, 0)
self.remove = wx.Button(self, wx.ID_ANY, _("Remove"))
self.remove.SetToolTip(_("Remove the currently focused user alias."))
self.remove.Enable(False)
actionsSizer.Add(self.remove, 0, 0, 0)
btnSizer = wx.StdDialogButtonSizer()
main_sizer.Add(btnSizer, 0, wx.ALIGN_RIGHT | wx.ALL, 4)
self.button_CLOSE = wx.Button(self, wx.ID_CLOSE, "")
btnSizer.AddButton(self.button_CLOSE)
btnSizer.Realize()
self.SetSizer(main_sizer)
main_sizer.Fit(self)
self.SetEscapeId(self.button_CLOSE.GetId())
self.Layout()
def on_selection_changes(self, *args, **kwargs):
selection = self.users.GetSelection()
if selection == -1:
self.enable_action_buttons(False)
else:
self.enable_action_buttons(True)
def get_selected_user(self):
return self.users.GetStringSelection()
def remove_alias_dialog(self, *args, **kwargs):
dlg = wx.MessageDialog(self, _("Are you sure you want to delete this user alias?"), _("Remove user alias"), wx.YES_NO)
if dlg.ShowModal() == wx.ID_YES:
return True
else:
return False
def enable_action_buttons(self, enabled=True):
self.edit.Enable(enabled)
self.remove.Enable(enabled)
def edit_alias_dialog(self, title):
dlg = wx.TextEntryDialog(self, title, _("User alias"))
if dlg.ShowModal() == wx.ID_OK:
return dlg.GetValue()

View File

@@ -46,38 +46,4 @@ class selectUserDialog(baseDialog.BaseWXDialog):
self.SetClientSize(sizer.CalcMin()) self.SetClientSize(sizer.CalcMin())
def get_user(self): def get_user(self):
return self.cb.GetValue() return self.cb.GetValue()
class addAliasDialog(baseDialog.BaseWXDialog):
def __init__(self, title, users):
super(addAliasDialog, self).__init__(parent=None, id=wx.ID_ANY, title=title)
panel = wx.Panel(self)
userSizer = wx.BoxSizer()
self.cb = wx.ComboBox(panel, -1, choices=users, value=users[0], size=wx.DefaultSize)
self.cb.SetFocus()
self.autocompletion = wx.Button(panel, -1, _(u"&Autocomplete users"))
userSizer.Add(wx.StaticText(panel, -1, _(u"User")), 0, wx.ALL, 5)
userSizer.Add(self.cb, 0, wx.ALL, 5)
userSizer.Add(self.autocompletion, 0, wx.ALL, 5)
aliasSizer = wx.BoxSizer(wx.HORIZONTAL)
aliasLabel = wx.StaticText(panel, wx.ID_ANY, _("Alias"))
self.alias = wx.TextCtrl(panel, wx.ID_ANY)
aliasSizer.Add(aliasLabel, 0, wx.ALL, 5)
aliasSizer.Add(self.alias, 0, wx.ALL, 5)
sizer = wx.BoxSizer(wx.VERTICAL)
ok = wx.Button(panel, wx.ID_OK, _(u"OK"))
ok.SetDefault()
# ok.Bind(wx.EVT_BUTTON, self.onok)
cancel = wx.Button(panel, wx.ID_CANCEL, _(u"Close"))
btnsizer = wx.BoxSizer()
btnsizer.Add(ok, 0, wx.ALL, 5)
btnsizer.Add(cancel, 0, wx.ALL, 5)
sizer.Add(userSizer, 0, wx.ALL, 5)
sizer.Add(aliasSizer, 0, wx.ALL, 5)
sizer.Add(btnsizer, 0, wx.ALL, 5)
panel.SetSizer(sizer)
self.SetClientSize(sizer.CalcMin())
def get_user(self):
return (self.cb.GetValue(), self.alias.GetValue())

View File

@@ -20,6 +20,7 @@ class mainFrame(wx.Frame):
self.show_hide = app.Append(wx.ID_ANY, _(u"&Hide window")) self.show_hide = app.Append(wx.ID_ANY, _(u"&Hide window"))
self.menuitem_search = app.Append(wx.ID_ANY, _(u"&Search")) self.menuitem_search = app.Append(wx.ID_ANY, _(u"&Search"))
self.lists = app.Append(wx.ID_ANY, _(u"&Lists manager")) self.lists = app.Append(wx.ID_ANY, _(u"&Lists manager"))
self.manageAliases = app.Append(wx.ID_ANY, _("Manage user aliases"))
self.keystroke_editor = app.Append(wx.ID_ANY, _(u"&Edit keystrokes")) self.keystroke_editor = app.Append(wx.ID_ANY, _(u"&Edit keystrokes"))
self.account_settings = app.Append(wx.ID_ANY, _(u"Account se&ttings")) self.account_settings = app.Append(wx.ID_ANY, _(u"Account se&ttings"))
self.prefs = app.Append(wx.ID_PREFERENCES, _(u"&Global settings")) self.prefs = app.Append(wx.ID_PREFERENCES, _(u"&Global settings"))

View File

@@ -1,6 +0,0 @@
{"current_version": "0.95",
"description": "The first version for the new generation of TWBlue.",
"date": "day_name_abr month day_numb, 2016",
"downloads":
{"Windows32": "http://twblue.es/pubs/twblue_ngen_0.80_x86.zip",
"Windows64": "http://twblue.es/pubs/twblue_ngen_0.80_x64.zip"}}

View File

@@ -1,4 +1,4 @@
{"current_version": "8", {"current_version": "11",
"description": "Snapshot version.", "description": "Snapshot version.",
"date": "unknown", "date": "unknown",
"downloads": "downloads":