mirror of
https://github.com/MCV-Software/TWBlue.git
synced 2025-04-20 01:21:45 -04:00
sync fork
This commit is contained in:
commit
6b1a095ad2
@ -1,6 +1,8 @@
|
|||||||
TWBlue -
|
TWBlue -
|
||||||
======
|
======
|
||||||
|
|
||||||
|
[](https://ci.appveyor.com/project/manuelcortez/twblue)
|
||||||
|
|
||||||
TW Blue is an app designed to use Twitter simply and efficiently while using minimal system resources.
|
TW Blue is an app designed to use Twitter simply and efficiently while using minimal system resources.
|
||||||
With this app you’ll have access to twitter features such as:
|
With this app you’ll have access to twitter features such as:
|
||||||
|
|
||||||
@ -31,7 +33,6 @@ Although most dependencies can be found in the windows-dependencies directory, w
|
|||||||
|
|
||||||
* [Python,](http://python.org) version 2.7.15
|
* [Python,](http://python.org) version 2.7.15
|
||||||
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python27 and python x64 to C:\python27x64, for example.
|
If you want to build both x86 and x64 binaries, you can install python x86 to C:\python27 and python x64 to C:\python27x64, for example.
|
||||||
* [Python windows extensions (pywin32)](http://www.sourceforge.net/projects/pywin32/) for python 2.7, build 223
|
|
||||||
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
|
* [PyEnchant,](http://pythonhosted.org/pyenchant/) version 1.6.6.
|
||||||
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
|
x64 version has been built by TWBlue developers, so you only will find it in windows-dependencies folder
|
||||||
|
|
||||||
|
83
appveyor.yml
Normal file
83
appveyor.yml
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
pull_requests:
|
||||||
|
# Avoid building after pull requests. Shall we disable this option?
|
||||||
|
do_not_increment_build_number: true
|
||||||
|
|
||||||
|
# Only build whenever we add tags to the repo.
|
||||||
|
skip_non_tags: true
|
||||||
|
|
||||||
|
environment:
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
|
||||||
|
# List of python versions we want to work with.
|
||||||
|
- PYTHON: "C:\\Python27"
|
||||||
|
PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||||
|
PYTHON_ARCH: "32"
|
||||||
|
|
||||||
|
# perhaps we may enable this one in future?
|
||||||
|
# - PYTHON: "C:\\Python27-x64"
|
||||||
|
# PYTHON_VERSION: "2.7.x" # currently 2.7.9
|
||||||
|
# PYTHON_ARCH: "64"
|
||||||
|
|
||||||
|
# This is important so we will retrieve everything in submodules as opposed to default method.
|
||||||
|
clone_script:
|
||||||
|
- cmd: >-
|
||||||
|
git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/%APPVEYOR_REPO_NAME%.git %APPVEYOR_BUILD_FOLDER%
|
||||||
|
&& cd %APPVEYOR_BUILD_FOLDER%
|
||||||
|
&& git checkout -qf %APPVEYOR_REPO_COMMIT%
|
||||||
|
&& git submodule update --init --recursive
|
||||||
|
|
||||||
|
install:
|
||||||
|
# If there is a newer build queued for the same PR, cancel this one.
|
||||||
|
# The AppVeyor 'rollout builds' option is supposed to serve the same
|
||||||
|
# purpose but it is problematic because it tends to cancel builds pushed
|
||||||
|
# directly to master instead of just PR builds (or the converse).
|
||||||
|
# credits: JuliaLang developers.
|
||||||
|
- ps: if ($env:APPVEYOR_PULL_REQUEST_NUMBER -and $env:APPVEYOR_BUILD_NUMBER -ne ((Invoke-RestMethod `
|
||||||
|
https://ci.appveyor.com/api/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/history?recordsNumber=50).builds | `
|
||||||
|
Where-Object pullRequestId -eq $env:APPVEYOR_PULL_REQUEST_NUMBER)[0].buildNumber) { `
|
||||||
|
throw "There are newer queued builds for this pull request, failing early." }
|
||||||
|
- ECHO "Filesystem root:"
|
||||||
|
- ps: "ls \"C:/\""
|
||||||
|
|
||||||
|
# Check that we have the expected version and architecture for Python
|
||||||
|
- "python --version"
|
||||||
|
- "python -c \"import struct; print(struct.calcsize('P') * 8)\""
|
||||||
|
|
||||||
|
# Upgrade to the latest version of pip to avoid it displaying warnings
|
||||||
|
# about it being out of date.
|
||||||
|
- "python -m pip install --upgrade pip setuptools"
|
||||||
|
|
||||||
|
# Install the build dependencies of the project. If some dependencies contain
|
||||||
|
# compiled extensions and are not provided as pre-built wheel packages,
|
||||||
|
# pip will build them from source using the MSVC compiler matching the
|
||||||
|
# target Python version and architecture
|
||||||
|
- "%CMD_IN_ENV% pip install -r requirements.txt"
|
||||||
|
- "%CMD_IN_ENV% pip install pyenchant py2exe_py2"
|
||||||
|
|
||||||
|
build_script:
|
||||||
|
# Build documentation at first, so setup.py won't fail when copying everything.
|
||||||
|
- "cd doc"
|
||||||
|
# Import documentation before building, so strings.py will be created.
|
||||||
|
- "%CMD_IN_ENV% python documentation_importer.py"
|
||||||
|
# build doc from src folder so it will generate result files right there.
|
||||||
|
- "cd ..\\src"
|
||||||
|
- "%CMD_IN_ENV% python ..\\doc\\generator.py"
|
||||||
|
# Build distributable files.
|
||||||
|
- "%CMD_IN_ENV% python setup.py py2exe"
|
||||||
|
- "cd dist"
|
||||||
|
# Zip it all.
|
||||||
|
- cmd: 7z a ..\..\snapshot.zip *
|
||||||
|
|
||||||
|
artifacts:
|
||||||
|
- path: snapshot.zip
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
- provider: FTP
|
||||||
|
host: twblue.es
|
||||||
|
protocol: ftp
|
||||||
|
beta: true
|
||||||
|
username: twblue
|
||||||
|
password:
|
||||||
|
secure: ml/xB8YEoZ7DmjzDr+KSNw==
|
||||||
|
# folder: '//pubs'
|
@ -2,7 +2,26 @@
|
|||||||
|
|
||||||
## changes in this version
|
## changes in this version
|
||||||
|
|
||||||
|
* Added support for playing audios posted in [AnyAudio.net](http://anyaudio.net) directly from TWBlue. Thanks to [Sam Tupy](http://www.samtupy.com/)
|
||||||
|
* Custom buffer ordering will not be reset every time the application restarts after an account setting has been modified.
|
||||||
|
* When adding or removing an user from a list, it is possible to press enter in the focused list instead of having to search for the "add" or "delete" button.
|
||||||
|
* Quoted and long tweets are displayed properly in the sent tweets buffer after being send. ([#253](https://github.com/manuelcortez/TWBlue/issues/253))
|
||||||
|
* Fixed an issue that was making the list manager keystroke unable to be shown in the keystroke editor. Now the keystroke is listed properly. ([#260](https://github.com/manuelcortez/TWBlue/issues/260))
|
||||||
|
* The volume slider, located in the account settings of TWBlue, now should decrease and increase value properly when up and down arrows are pressed. Before it was doing it in inverted order. ([#261](https://github.com/manuelcortez/TWBlue/issues/261))
|
||||||
|
* autoreading has been redesigned to work in a similar way for almost all buffers. Needs testing. ([#221](https://github.com/manuelcortez/TWBlue/issues/221))
|
||||||
|
* When displaying tweets or direct messages, a new field has been added to show the date when the item has been posted to Twitter.
|
||||||
|
* Added support for deleting direct messages by using the new Twitter API methods.
|
||||||
|
* When quoting a retweet, the quote will be made to the original tweet instead of the retweet.
|
||||||
* If the sent direct messages buffer is hidden, TWBlue should keep loading everything as expected. ([#246](https://github.com/manuelcortez/TWBlue/issues/246))
|
* If the sent direct messages buffer is hidden, TWBlue should keep loading everything as expected. ([#246](https://github.com/manuelcortez/TWBlue/issues/246))
|
||||||
|
* There is a new soundpack, called FreakyBlue (Thanks to [Andre Louis](https://twitter.com/FreakyFwoof)) as a new option in TWBlue. This pack can be the default in the next stable, so users can take a look and share their opinion in snapshot versions. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||||
|
* There is a new option in the help menu that allows you to visit the soundpacks section in the TWBlue website. ([#247](https://github.com/manuelcortez/TWBlue/issues/247))
|
||||||
|
* When reading location of a geotagged tweet, it will be translated for users of other languages. ([#251](https://github.com/manuelcortez/TWBlue/pull/251))
|
||||||
|
* In the Windows 10 Keymap, the action to read location of a tweet has been remapped to Ctrl+Win+G. ([#177](https://github.com/manuelcortez/TWBlue/pull/177))
|
||||||
|
* When there are no more items to retrieve in direct messages and people buffers, a message will announce it.
|
||||||
|
* Fixed an issue reported by some users that was making them unable to load more items in their direct messages.
|
||||||
|
* It is possible to add a tweet to the likes buffer from the menu bar again.
|
||||||
|
* Tweets, replies and retweets will be added to sent tweets right after being posted in Twitter.
|
||||||
|
* Extended Tweets should be displayed properly in list buffers.
|
||||||
|
|
||||||
## Changes in version 0.94
|
## Changes in version 0.94
|
||||||
|
|
||||||
@ -12,14 +31,14 @@
|
|||||||
* The new method does not allow direct messages to be processed in real time. Direct messages will be updated periodically.
|
* The new method does not allow direct messages to be processed in real time. Direct messages will be updated periodically.
|
||||||
* After august 16 or when streaming is disabled, the events buffer will no longer be created in TWBlue.
|
* After august 16 or when streaming is disabled, the events buffer will no longer be created in TWBlue.
|
||||||
* You can configure frequency for buffer updates in TWBlue. By default, TWBlue will update all buffers every 2 minutes, but you can change this setting in the global settings dialog. ([#223](https://github.com/manuelcortez/TWBlue/issues/223))
|
* You can configure frequency for buffer updates in TWBlue. By default, TWBlue will update all buffers every 2 minutes, but you can change this setting in the global settings dialog. ([#223](https://github.com/manuelcortez/TWBlue/issues/223))
|
||||||
* Added a new tab called feedback, in the account settings dialog. This tab allows you to control wether automatic speech or Braille feedbak in certain events (mentions and direct messages received) is enabled. Take into account that this option will take preference over automatic reading of buffers and any kind of automatic output. ([#203](https://github.com/manuelcortez/TWBlue/issues/203))
|
* Added a new tab called feedback, in the account settings dialog. This tab allows you to control whether automatic speech or Braille feedbak in certain events (mentions and direct messages received) is enabled. Take into account that this option will take preference over automatic reading of buffers and any kind of automatic output. ([#203](https://github.com/manuelcortez/TWBlue/issues/203))
|
||||||
* The spell checking dialog now has access keys defined for the most important actions. ([#211](https://github.com/manuelcortez/TWBlue/issues/211))
|
* The spell checking dialog now has access keys defined for the most important actions. ([#211](https://github.com/manuelcortez/TWBlue/issues/211))
|
||||||
* TWBlue now Uses WXPython 4.0.1. This will allow us to migrate all important components to Python 3 in the future. ([#207](https://github.com/manuelcortez/TWBlue/issues/207))
|
* TWBlue now Uses WXPython 4.0.1. This will allow us to migrate all important components to Python 3 in the future. ([#207](https://github.com/manuelcortez/TWBlue/issues/207))
|
||||||
* When you quote a Tweet, if the original tweet was posted with Twishort, TWBlue should display properly the quoted tweet. Before it was displaying the original tweet only. ([#206](https://github.com/manuelcortez/TWBlue/issues/206))
|
* When you quote a Tweet, if the original tweet was posted with Twishort, TWBlue should display properly the quoted tweet. Before it was displaying the original tweet only. ([#206](https://github.com/manuelcortez/TWBlue/issues/206))
|
||||||
* It is possible to filter by retweets, quotes and replies when creating a new filter.
|
* It is possible to filter by retweets, quotes and replies when creating a new filter.
|
||||||
* Added support for playing youtube Links directly from the client. ([#94](https://github.com/manuelcortez/TWBlue/issues/94))
|
* Added support for playing youtube Links directly from the client. ([#94](https://github.com/manuelcortez/TWBlue/issues/94))
|
||||||
* Replaced Bass with libVLC for playing URL streams.
|
* Replaced Bass with libVLC for playing URL streams.
|
||||||
* the checkbox for indicating wether TWBlue will include everyone in a reply or not, will be unchecked by default.
|
* the checkbox for indicating whether TWBlue will include everyone in a reply or not, will be unchecked by default.
|
||||||
* You can request TWBlue to save the state for two checkboxes: Long tweet and mention all, from the global settings dialogue.
|
* You can request TWBlue to save the state for two checkboxes: Long tweet and mention all, from the global settings dialogue.
|
||||||
* For windows 10 users, some keystrokes in the invisible user interface have been changed or merged:
|
* For windows 10 users, some keystrokes in the invisible user interface have been changed or merged:
|
||||||
* control+Windows+alt+F will be used for toggling between adding and removing a tweet to user's likes. This function will execute the needed action based in the current status for the focused tweet.
|
* control+Windows+alt+F will be used for toggling between adding and removing a tweet to user's likes. This function will execute the needed action based in the current status for the focused tweet.
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import markdown
|
import markdown
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
from codecs import open as _open
|
from codecs import open as _open
|
||||||
import languageHandler
|
import languageHandler
|
||||||
languageHandler.setLanguage("en")
|
languageHandler.setLanguage("en")
|
||||||
@ -38,14 +39,18 @@ def generate_document(language, document_type="documentation"):
|
|||||||
""" % (language, title, title)
|
""" % (language, title, title)
|
||||||
first_html_block = first_html_block+ markdown_file
|
first_html_block = first_html_block+ markdown_file
|
||||||
first_html_block = first_html_block + "\n</body>\n</html>"
|
first_html_block = first_html_block + "\n</body>\n</html>"
|
||||||
if not os.path.exists(language):
|
if not os.path.exists(os.path.join("documentation", language)):
|
||||||
os.mkdir(language)
|
os.mkdir(os.path.join("documentation", language))
|
||||||
mdfile = _open("%s/%s" % (language, filename), "w", encoding="utf-8")
|
mdfile = _open(os.path.join("documentation", language, filename), "w", encoding="utf-8")
|
||||||
mdfile.write(first_html_block)
|
mdfile.write(first_html_block)
|
||||||
mdfile.close()
|
mdfile.close()
|
||||||
|
|
||||||
def create_documentation():
|
def create_documentation():
|
||||||
print("Creating documentation in the supported languages...\n")
|
print("Creating documentation in the supported languages...\n")
|
||||||
|
if not os.path.exists("documentation"):
|
||||||
|
os.mkdir("documentation")
|
||||||
|
if os.path.exists(os.path.join("documentation", "license.txt")) == False:
|
||||||
|
shutil.copy(os.path.join("..", "license.txt"), os.path.join("documentation", "license.txt"))
|
||||||
for i in languages:
|
for i in languages:
|
||||||
print("Creating documentation for: %s" % (i,))
|
print("Creating documentation for: %s" % (i,))
|
||||||
generate_document(i)
|
generate_document(i)
|
||||||
|
@ -20,4 +20,9 @@ idna
|
|||||||
chardet
|
chardet
|
||||||
urllib3
|
urllib3
|
||||||
youtube-dl
|
youtube-dl
|
||||||
python-vlc
|
python-vlc
|
||||||
|
pypiwin32
|
||||||
|
certifi
|
||||||
|
backports.functools_lru_cache
|
||||||
|
git+https://github.com/manuelcortez/twython
|
||||||
|
git+https://github.com/manuelcortez/libloader
|
@ -2,13 +2,13 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
name = 'TWBlue'
|
name = 'TWBlue'
|
||||||
snapshot = False
|
snapshot = True
|
||||||
if snapshot == False:
|
if snapshot == False:
|
||||||
version = "0.94"
|
version = "0.94"
|
||||||
update_url = 'https://twblue.es/updates/stable.php'
|
update_url = 'https://twblue.es/updates/stable.php'
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/stable.json'
|
||||||
else:
|
else:
|
||||||
version = "8"
|
version = "11"
|
||||||
update_url = 'https://twblue.es/updates/snapshot.php'
|
update_url = 'https://twblue.es/updates/snapshot.php'
|
||||||
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
mirror_update_url = 'https://raw.githubusercontent.com/manuelcortez/TWBlue/next-gen/updates/snapshots.json'
|
||||||
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
|
authors = [u"Manuel Cortéz", u"José Manuel Delicado"]
|
||||||
|
@ -33,5 +33,12 @@ def convert_soundcloud (url):
|
|||||||
def convert_youtube_long (url):
|
def convert_youtube_long (url):
|
||||||
return youtube_utils.get_video_url(url)
|
return youtube_utils.get_video_url(url)
|
||||||
|
|
||||||
|
@matches_url ('http://anyaudio.net/listen')
|
||||||
|
def convert_anyaudio(url):
|
||||||
|
values = url.split("audio=")
|
||||||
|
if len(values) != 2:
|
||||||
|
raise TypeError('%r is not streamable' % url)
|
||||||
|
return "http://anyaudio.net/audiodownload?audio=%s" % (values[1],)
|
||||||
|
|
||||||
def convert_generic_audio(url):
|
def convert_generic_audio(url):
|
||||||
return url
|
return url
|
||||||
|
7
src/controller/buffers/__init__.py
Normal file
7
src/controller/buffers/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
""" this package contains logic related to buffers. A buffer is a virtual representation of a group of items retrieved through the Social network API'S.
|
||||||
|
Ideally, new social networks added to TWBlue will have its own "buffers", and these buffers should be defined within this package, following the Twitter example.
|
||||||
|
Currently, the package contains the following modules:
|
||||||
|
* baseBuffers: Define a set of functions and structure to be expected in all buffers. New buffers should inherit its classes from one of the classes present here.
|
||||||
|
* twitterBuffers: All other code, specific to Twitter.
|
||||||
|
"""
|
201
src/controller/buffers/baseBuffers.py
Normal file
201
src/controller/buffers/baseBuffers.py
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
""" Common logic to all buffers in TWBlue."""
|
||||||
|
import logging
|
||||||
|
import wx
|
||||||
|
import output
|
||||||
|
import config
|
||||||
|
import sound
|
||||||
|
import widgetUtils
|
||||||
|
from pubsub import pub
|
||||||
|
from wxUI import buffers
|
||||||
|
|
||||||
|
log = logging.getLogger("controller.buffers.baseBuffers")
|
||||||
|
|
||||||
|
def _items_exist(function):
|
||||||
|
""" A decorator to execute a function only if the selected buffer contains at least one item."""
|
||||||
|
def function_(self, *args, **kwargs):
|
||||||
|
if self.buffer.list.get_count() > 0:
|
||||||
|
function(self, *args, **kwargs)
|
||||||
|
return function_
|
||||||
|
|
||||||
|
class buffer(object):
|
||||||
|
""" A basic buffer object. This should be the base class for all other derived buffers."""
|
||||||
|
|
||||||
|
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
|
||||||
|
"""Inits the main controller for this buffer:
|
||||||
|
@ parent wx.Treebook object: Container where we will put this buffer.
|
||||||
|
@ function str or None: function to be called periodically and update items on this buffer.
|
||||||
|
@ session sessionmanager.session object or None: Session handler for settings, database and data access.
|
||||||
|
"""
|
||||||
|
super(buffer, self).__init__()
|
||||||
|
self.function = function
|
||||||
|
# Compose_function will be used to render an object on this buffer. Normally, signature is as follows:
|
||||||
|
# compose_function(item, db, relative_times, show_screen_names=False, session=None)
|
||||||
|
# Read more about compose functions in twitter/compose.py.
|
||||||
|
self.compose_function = None
|
||||||
|
self.args = args
|
||||||
|
self.kwargs = kwargs
|
||||||
|
# This will be used as a reference to the wx.Panel object wich stores the buffer GUI.
|
||||||
|
self.buffer = None
|
||||||
|
# This should countains the account associated to this buffer.
|
||||||
|
self.account = ""
|
||||||
|
# This controls whether the start_stream function should be called when starting the program.
|
||||||
|
self.needs_init = True
|
||||||
|
# if this is set to False, the buffer will be ignored on the invisible interface.
|
||||||
|
self.invisible = False
|
||||||
|
# Control variable, used to track time of execution for calls to start_stream.
|
||||||
|
self.execution_time = 0
|
||||||
|
|
||||||
|
def clear_list(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_event(self, ev):
|
||||||
|
""" Catch key presses in the WX interface and generate the corresponding event names."""
|
||||||
|
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
|
||||||
|
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
||||||
|
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
||||||
|
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
|
||||||
|
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
|
||||||
|
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status"
|
||||||
|
else:
|
||||||
|
event = None
|
||||||
|
ev.Skip()
|
||||||
|
if event != None:
|
||||||
|
try:
|
||||||
|
getattr(self, event)()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def volume_down(self):
|
||||||
|
""" Decreases volume by 5%"""
|
||||||
|
if self.session.settings["sound"]["volume"] > 0.0:
|
||||||
|
if self.session.settings["sound"]["volume"] <= 0.05:
|
||||||
|
self.session.settings["sound"]["volume"] = 0.0
|
||||||
|
else:
|
||||||
|
self.session.settings["sound"]["volume"] -=0.05
|
||||||
|
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100.0))
|
||||||
|
self.session.sound.play("volume_changed.ogg")
|
||||||
|
self.session.settings.write()
|
||||||
|
|
||||||
|
def volume_up(self):
|
||||||
|
""" Increases volume by 5%."""
|
||||||
|
if self.session.settings["sound"]["volume"] < 1.0:
|
||||||
|
if self.session.settings["sound"]["volume"] >= 0.95:
|
||||||
|
self.session.settings["sound"]["volume"] = 1.0
|
||||||
|
else:
|
||||||
|
self.session.settings["sound"]["volume"] +=0.05
|
||||||
|
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100))
|
||||||
|
self.session.sound.play("volume_changed.ogg")
|
||||||
|
self.session.settings.write()
|
||||||
|
|
||||||
|
def start_stream(self, mandatory=False, play_sound=True):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_more_items(self):
|
||||||
|
output.speak(_(u"This action is not supported for this buffer"), True)
|
||||||
|
|
||||||
|
def put_items_on_list(self, items):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def remove_buffer(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def remove_item(self, item):
|
||||||
|
f = self.buffer.list.get_selected()
|
||||||
|
self.buffer.list.remove_item(item)
|
||||||
|
self.buffer.list.select_item(f)
|
||||||
|
|
||||||
|
def bind_events(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_object(self):
|
||||||
|
return self.buffer
|
||||||
|
|
||||||
|
def get_message(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def set_list_position(self, reversed=False):
|
||||||
|
if reversed == False:
|
||||||
|
self.buffer.list.select_item(-1)
|
||||||
|
else:
|
||||||
|
self.buffer.list.select_item(0)
|
||||||
|
|
||||||
|
def reply(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def send_message(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def share_item(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def destroy_status(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def post_status(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def save_positions(self):
|
||||||
|
try:
|
||||||
|
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
class accountPanel(buffer):
|
||||||
|
def __init__(self, parent, name, account, account_id):
|
||||||
|
super(accountPanel, self).__init__(parent, None, name)
|
||||||
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
|
self.buffer = buffers.accountPanel(parent, name)
|
||||||
|
self.type = self.buffer.type
|
||||||
|
self.compose_function = None
|
||||||
|
self.session = None
|
||||||
|
self.needs_init = False
|
||||||
|
self.account = account
|
||||||
|
self.buffer.account = account
|
||||||
|
self.name = name
|
||||||
|
self.account_id = account_id
|
||||||
|
|
||||||
|
def setup_account(self):
|
||||||
|
widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account)
|
||||||
|
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||||
|
self.buffer.change_autostart(False)
|
||||||
|
else:
|
||||||
|
self.buffer.change_autostart(True)
|
||||||
|
if not hasattr(self, "logged"):
|
||||||
|
self.buffer.change_login(login=False)
|
||||||
|
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout)
|
||||||
|
else:
|
||||||
|
self.buffer.change_login(login=True)
|
||||||
|
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login)
|
||||||
|
|
||||||
|
def login(self, *args, **kwargs):
|
||||||
|
del self.logged
|
||||||
|
self.setup_account()
|
||||||
|
pub.sendMessage("login", session_id=self.account_id)
|
||||||
|
|
||||||
|
def logout(self, *args, **kwargs):
|
||||||
|
self.logged = False
|
||||||
|
self.setup_account()
|
||||||
|
pub.sendMessage("logout", session_id=self.account_id)
|
||||||
|
|
||||||
|
def autostart(self, *args, **kwargs):
|
||||||
|
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
||||||
|
self.buffer.change_autostart(True)
|
||||||
|
config.app["sessions"]["ignored_sessions"].remove(self.account_id)
|
||||||
|
else:
|
||||||
|
self.buffer.change_autostart(False)
|
||||||
|
config.app["sessions"]["ignored_sessions"].append(self.account_id)
|
||||||
|
config.app.write()
|
||||||
|
|
||||||
|
class emptyPanel(buffer):
|
||||||
|
def __init__(self, parent, name, account):
|
||||||
|
super(emptyPanel, self).__init__(parent=parent)
|
||||||
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
|
self.buffer = buffers.emptyPanel(parent, name)
|
||||||
|
self.type = self.buffer.type
|
||||||
|
self.compose_function = None
|
||||||
|
self.account = account
|
||||||
|
self.buffer.account = account
|
||||||
|
self.name = name
|
||||||
|
self.session = None
|
||||||
|
self.needs_init = True
|
@ -4,11 +4,11 @@ import platform
|
|||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import wx
|
import wx
|
||||||
from wxUI import buffers, dialogs, commonMessageDialogs, menus
|
from wxUI import buffers, dialogs, commonMessageDialogs, menus
|
||||||
import user
|
from controller import user
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
from gtkUI import buffers, dialogs, commonMessageDialogs
|
from gtkUI import buffers, dialogs, commonMessageDialogs
|
||||||
import messages
|
from controller import messages
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import arrow
|
import arrow
|
||||||
import webbrowser
|
import webbrowser
|
||||||
@ -18,6 +18,7 @@ import sound
|
|||||||
import languageHandler
|
import languageHandler
|
||||||
import logging
|
import logging
|
||||||
import youtube_utils
|
import youtube_utils
|
||||||
|
from controller.buffers import baseBuffers
|
||||||
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 twython import TwythonError
|
from twython import TwythonError
|
||||||
@ -33,218 +34,7 @@ def _tweets_exist(function):
|
|||||||
function(self, *args, **kwargs)
|
function(self, *args, **kwargs)
|
||||||
return function_
|
return function_
|
||||||
|
|
||||||
class bufferController(object):
|
class baseBufferController(baseBuffers.buffer):
|
||||||
""" A basic buffer object. This should be the base class for all other derived buffers."""
|
|
||||||
|
|
||||||
def __init__(self, parent=None, function=None, session=None, *args, **kwargs):
|
|
||||||
"""Inits the main controller for this buffer:
|
|
||||||
@ parent wx.Treebook object: Container where we will put this buffer.
|
|
||||||
@ function str or None: function to be called periodically and update items on this buffer.
|
|
||||||
@ session sessionmanager.session object or None: Session handler for settings, database and Twitter access.
|
|
||||||
"""
|
|
||||||
super(bufferController, self).__init__()
|
|
||||||
self.function = function
|
|
||||||
# Compose_function will be used to render an object on this buffer. Normally, signature is as follows:
|
|
||||||
# compose_function(item, db, relative_times, show_screen_names=False, session=None)
|
|
||||||
# Compose functions will be defined in every buffer if items are different than tweets.
|
|
||||||
# Read more about compose functions in twitter/compose.py.
|
|
||||||
self.compose_function = None
|
|
||||||
self.args = args
|
|
||||||
self.kwargs = kwargs
|
|
||||||
# This will be used as a reference to the wx.Panel object wich stores the buffer GUI.
|
|
||||||
self.buffer = None
|
|
||||||
# This should countains the account associated to this buffer.
|
|
||||||
self.account = ""
|
|
||||||
# This controls wether the start_stream function should be called when starting the program.
|
|
||||||
self.needs_init = True
|
|
||||||
# if this is set to False, the buffer will be ignored on the invisible interface.
|
|
||||||
self.invisible = False
|
|
||||||
# Control variable, used to track time of execution for calls to start_stream.
|
|
||||||
self.execution_time = 0
|
|
||||||
|
|
||||||
def clear_list(self): pass
|
|
||||||
|
|
||||||
def get_event(self, ev):
|
|
||||||
""" Catches key presses in the WX interface and generate the corresponding event names."""
|
|
||||||
if ev.GetKeyCode() == wx.WXK_RETURN and ev.ControlDown(): event = "audio"
|
|
||||||
elif ev.GetKeyCode() == wx.WXK_RETURN: event = "url"
|
|
||||||
elif ev.GetKeyCode() == wx.WXK_F5: event = "volume_down"
|
|
||||||
elif ev.GetKeyCode() == wx.WXK_F6: event = "volume_up"
|
|
||||||
elif ev.GetKeyCode() == wx.WXK_DELETE and ev.ShiftDown(): event = "clear_list"
|
|
||||||
elif ev.GetKeyCode() == wx.WXK_DELETE: event = "destroy_status"
|
|
||||||
else:
|
|
||||||
event = None
|
|
||||||
ev.Skip()
|
|
||||||
if event != None:
|
|
||||||
try:
|
|
||||||
getattr(self, event)()
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
def volume_down(self):
|
|
||||||
if self.session.settings["sound"]["volume"] > 0.0:
|
|
||||||
if self.session.settings["sound"]["volume"] <= 0.05:
|
|
||||||
self.session.settings["sound"]["volume"] = 0.0
|
|
||||||
else:
|
|
||||||
self.session.settings["sound"]["volume"] -=0.05
|
|
||||||
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100.0))
|
|
||||||
self.session.sound.play("volume_changed.ogg")
|
|
||||||
self.session.settings.write()
|
|
||||||
|
|
||||||
def volume_up(self):
|
|
||||||
if self.session.settings["sound"]["volume"] < 1.0:
|
|
||||||
if self.session.settings["sound"]["volume"] >= 0.95:
|
|
||||||
self.session.settings["sound"]["volume"] = 1.0
|
|
||||||
else:
|
|
||||||
self.session.settings["sound"]["volume"] +=0.05
|
|
||||||
sound.URLPlayer.player.audio_set_volume(int(self.session.settings["sound"]["volume"]*100))
|
|
||||||
self.session.sound.play("volume_changed.ogg")
|
|
||||||
self.session.settings.write()
|
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
|
||||||
# if mandatory == True:
|
|
||||||
# output.speak(_(u"Unable to update this buffer."))
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_more_items(self):
|
|
||||||
output.speak(_(u"This action is not supported for this buffer"), True)
|
|
||||||
|
|
||||||
def put_items_on_list(self, items):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def remove_buffer(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
def remove_item(self, item):
|
|
||||||
f = self.buffer.list.get_selected()
|
|
||||||
self.buffer.list.remove_item(item)
|
|
||||||
self.buffer.list.select_item(f)
|
|
||||||
|
|
||||||
def bind_events(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def get_object(self):
|
|
||||||
return self.buffer
|
|
||||||
|
|
||||||
def get_message(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def set_list_position(self, reversed=False):
|
|
||||||
if reversed == False:
|
|
||||||
self.buffer.list.select_item(-1)
|
|
||||||
else:
|
|
||||||
self.buffer.list.select_item(0)
|
|
||||||
|
|
||||||
def reply(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def direct_message(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def retweet(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def destroy_status(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def post_tweet(self, *args, **kwargs):
|
|
||||||
title = _(u"Tweet")
|
|
||||||
caption = _(u"Write the tweet here")
|
|
||||||
tweet = messages.tweet(self.session, title, caption, "")
|
|
||||||
if tweet.message.get_response() == widgetUtils.OK:
|
|
||||||
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
|
||||||
config.app["app-settings"]["longtweet"] = tweet.message.long_tweet.GetValue()
|
|
||||||
config.app.write()
|
|
||||||
text = tweet.message.get_text()
|
|
||||||
if len(text) > 280 and tweet.message.get("long_tweet") == True:
|
|
||||||
if not hasattr(tweet, "attachments"):
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
|
||||||
else:
|
|
||||||
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
|
||||||
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
|
|
||||||
item = self.session.api_call(call_name="update_status", status=text, _sound="tweet_send.ogg")
|
|
||||||
# else:
|
|
||||||
# call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg")
|
|
||||||
if item != None:
|
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
|
||||||
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
|
||||||
self.session.settings.write()
|
|
||||||
|
|
||||||
def post_with_media(self, text, attachments):
|
|
||||||
media_ids = []
|
|
||||||
for i in attachments:
|
|
||||||
photo = open(i["file"], "rb")
|
|
||||||
img = self.session.twitter.upload_media(media=photo)
|
|
||||||
self.session.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"]))
|
|
||||||
media_ids.append(img["media_id"])
|
|
||||||
self.session.twitter.update_status(status=text, media_ids=media_ids)
|
|
||||||
|
|
||||||
def save_positions(self):
|
|
||||||
try:
|
|
||||||
self.session.db[self.name+"_pos"]=self.buffer.list.get_selected()
|
|
||||||
except AttributeError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
class accountPanel(bufferController):
|
|
||||||
def __init__(self, parent, name, account, account_id):
|
|
||||||
super(accountPanel, self).__init__(parent, None, name)
|
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
|
||||||
self.buffer = buffers.accountPanel(parent, name)
|
|
||||||
self.type = self.buffer.type
|
|
||||||
self.compose_function = None
|
|
||||||
self.session = None
|
|
||||||
self.needs_init = False
|
|
||||||
self.account = account
|
|
||||||
self.buffer.account = account
|
|
||||||
self.name = name
|
|
||||||
self.account_id = account_id
|
|
||||||
|
|
||||||
def setup_account(self):
|
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.CHECKBOX, self.autostart, menuitem=self.buffer.autostart_account)
|
|
||||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
|
||||||
self.buffer.change_autostart(False)
|
|
||||||
else:
|
|
||||||
self.buffer.change_autostart(True)
|
|
||||||
if not hasattr(self, "logged"):
|
|
||||||
self.buffer.change_login(login=False)
|
|
||||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.logout)
|
|
||||||
else:
|
|
||||||
self.buffer.change_login(login=True)
|
|
||||||
widgetUtils.connect_event(self.buffer.login, widgetUtils.BUTTON_PRESSED, self.login)
|
|
||||||
|
|
||||||
def login(self, *args, **kwargs):
|
|
||||||
del self.logged
|
|
||||||
self.setup_account()
|
|
||||||
pub.sendMessage("login", session_id=self.account_id)
|
|
||||||
|
|
||||||
def logout(self, *args, **kwargs):
|
|
||||||
self.logged = False
|
|
||||||
self.setup_account()
|
|
||||||
pub.sendMessage("logout", session_id=self.account_id)
|
|
||||||
|
|
||||||
def autostart(self, *args, **kwargs):
|
|
||||||
if self.account_id in config.app["sessions"]["ignored_sessions"]:
|
|
||||||
self.buffer.change_autostart(True)
|
|
||||||
config.app["sessions"]["ignored_sessions"].remove(self.account_id)
|
|
||||||
else:
|
|
||||||
self.buffer.change_autostart(False)
|
|
||||||
config.app["sessions"]["ignored_sessions"].append(self.account_id)
|
|
||||||
config.app.write()
|
|
||||||
|
|
||||||
class emptyPanel(bufferController):
|
|
||||||
def __init__(self, parent, name, account):
|
|
||||||
super(emptyPanel, self).__init__(parent=parent)
|
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
|
||||||
self.buffer = buffers.emptyPanel(parent, name)
|
|
||||||
self.type = self.buffer.type
|
|
||||||
self.compose_function = None
|
|
||||||
self.account = account
|
|
||||||
self.buffer.account = account
|
|
||||||
self.name = name
|
|
||||||
self.session = None
|
|
||||||
self.needs_init = True
|
|
||||||
|
|
||||||
class baseBufferController(bufferController):
|
|
||||||
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, compose_func="compose_tweet", *args, **kwargs):
|
def __init__(self, parent, function, name, sessionObject, account, sound=None, bufferType=None, compose_func="compose_tweet", *args, **kwargs):
|
||||||
super(baseBufferController, self).__init__(parent, function, *args, **kwargs)
|
super(baseBufferController, self).__init__(parent, function, *args, **kwargs)
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
||||||
@ -273,6 +63,57 @@ class baseBufferController(bufferController):
|
|||||||
self.kwargs["screen_name"] = self.kwargs["user_id"]
|
self.kwargs["screen_name"] = self.kwargs["user_id"]
|
||||||
self.kwargs.pop("user_id")
|
self.kwargs.pop("user_id")
|
||||||
|
|
||||||
|
def get_buffer_name(self):
|
||||||
|
""" Get buffer name from a set of different techniques."""
|
||||||
|
# firstly let's take the easier buffers.
|
||||||
|
basic_buffers = dict(home_timeline=_(u"Home"), mentions=_(u"Mentions"), direct_messages=_(u"Direct messages"), sent_direct_messages=_(u"Sent direct messages"), sent_tweets=_(u"Sent tweets"), favourites=_(u"Likes"), followers=_(u"Followers"), friends=_(u"Friends"), blocked=_(u"Blocked users"), muted=_(u"Muted users"))
|
||||||
|
if self.name in basic_buffers.keys():
|
||||||
|
return basic_buffers[self.name]
|
||||||
|
# Check user timelines
|
||||||
|
elif hasattr(self, "username"):
|
||||||
|
if "-timeline" in self.name:
|
||||||
|
return _(u"{username}'s timeline").format(username=self.username,)
|
||||||
|
elif "-favorite" in self.name:
|
||||||
|
return _(u"{username}'s likes").format(username=self.username,)
|
||||||
|
elif "-followers" in self.name:
|
||||||
|
return _(u"{username}'s followers").format(username=self.username,)
|
||||||
|
elif "-friends" in self.name:
|
||||||
|
return _(u"{username}'s friends").format(username=self.username,)
|
||||||
|
log.error("Error getting name for buffer %s" % (self.name,))
|
||||||
|
return _(u"Unknown buffer")
|
||||||
|
|
||||||
|
def post_status(self, *args, **kwargs):
|
||||||
|
title = _(u"Tweet")
|
||||||
|
caption = _(u"Write the tweet here")
|
||||||
|
tweet = messages.tweet(self.session, title, caption, "")
|
||||||
|
if tweet.message.get_response() == widgetUtils.OK:
|
||||||
|
if config.app["app-settings"]["remember_mention_and_longtweet"]:
|
||||||
|
config.app["app-settings"]["longtweet"] = tweet.message.long_tweet.GetValue()
|
||||||
|
config.app.write()
|
||||||
|
text = tweet.message.get_text()
|
||||||
|
if len(text) > 280 and tweet.message.get("long_tweet") == True:
|
||||||
|
if not hasattr(tweet, "attachments"):
|
||||||
|
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text)
|
||||||
|
else:
|
||||||
|
text = twishort.create_tweet(self.session.settings["twitter"]["user_key"], self.session.settings["twitter"]["user_secret"], text, 1)
|
||||||
|
if not hasattr(tweet, "attachments") or len(tweet.attachments) == 0:
|
||||||
|
item = self.session.api_call(call_name="update_status", status=text, _sound="tweet_send.ogg", tweet_mode="extended")
|
||||||
|
# else:
|
||||||
|
# call_threaded(self.post_with_media, text=text, attachments=tweet.attachments, _sound="tweet_send.ogg")
|
||||||
|
if item != None:
|
||||||
|
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||||
|
if hasattr(tweet.message, "destroy"): tweet.message.destroy()
|
||||||
|
self.session.settings.write()
|
||||||
|
|
||||||
|
def post_with_media(self, text, attachments):
|
||||||
|
media_ids = []
|
||||||
|
for i in attachments:
|
||||||
|
photo = open(i["file"], "rb")
|
||||||
|
img = self.session.twitter.upload_media(media=photo)
|
||||||
|
self.session.twitter.create_metadata(media_id=img["media_id"], alt_text=dict(text=i["description"]))
|
||||||
|
media_ids.append(img["media_id"])
|
||||||
|
self.session.twitter.update_status(status=text, media_ids=media_ids)
|
||||||
|
|
||||||
def get_formatted_message(self):
|
def get_formatted_message(self):
|
||||||
if self.type == "dm" or self.name == "direct_messages":
|
if self.type == "dm" or self.name == "direct_messages":
|
||||||
return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)[1]
|
return self.compose_function(self.get_right_tweet(), self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)[1]
|
||||||
@ -287,7 +128,7 @@ class baseBufferController(bufferController):
|
|||||||
tweetsList = []
|
tweetsList = []
|
||||||
tweet_id = tweet["id"]
|
tweet_id = tweet["id"]
|
||||||
message = None
|
message = None
|
||||||
if tweet.has_key("message"):
|
if "message" in tweet:
|
||||||
message = tweet["message"]
|
message = tweet["message"]
|
||||||
try:
|
try:
|
||||||
tweet = self.session.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
tweet = self.session.twitter.show_status(id=tweet_id, include_ext_alt_text=True, tweet_mode="extended")
|
||||||
@ -317,7 +158,7 @@ class baseBufferController(bufferController):
|
|||||||
tweetsList.append(tweet)
|
tweetsList.append(tweet)
|
||||||
return (tweet, tweetsList)
|
return (tweet, tweetsList)
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
@ -339,8 +180,22 @@ class baseBufferController(bufferController):
|
|||||||
self.finished_timeline = True
|
self.finished_timeline = True
|
||||||
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if number_of_items > 0 and self.name != "sent_tweets" and self.name != "sent_direct_messages" and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
return number_of_items
|
return number_of_items
|
||||||
|
|
||||||
|
def auto_read(self, number_of_items):
|
||||||
|
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
tweet = self.session.db[self.name][-1]
|
||||||
|
else:
|
||||||
|
tweet = self.session.db[self.name][0]
|
||||||
|
output.speak(_(u"New tweet in {0}").format(self.get_buffer_name()))
|
||||||
|
output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)))
|
||||||
|
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
output.speak(_(u"{0} new tweets in {1}.").format(number_of_items, self.get_buffer_name()))
|
||||||
|
|
||||||
def get_more_items(self):
|
def get_more_items(self):
|
||||||
elements = []
|
elements = []
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
@ -351,6 +206,8 @@ class baseBufferController(bufferController):
|
|||||||
items = self.session.get_more_items(self.function, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs)
|
items = self.session.get_more_items(self.function, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs)
|
||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
|
if items == None:
|
||||||
|
return
|
||||||
for i in items:
|
for i in items:
|
||||||
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None:
|
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None:
|
||||||
i = self.session.check_quoted_status(i)
|
i = self.session.check_quoted_status(i)
|
||||||
@ -384,7 +241,7 @@ class baseBufferController(bufferController):
|
|||||||
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
if self.name[:-9] in self.session.settings["other_buffers"]["timelines"]:
|
||||||
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
self.session.settings["other_buffers"]["timelines"].remove(self.name[:-9])
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
@ -397,7 +254,7 @@ class baseBufferController(bufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
if self.name[:-9] in self.session.settings["other_buffers"]["favourites_timelines"]:
|
||||||
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
self.session.settings["other_buffers"]["favourites_timelines"].remove(self.name[:-9])
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
return True
|
return True
|
||||||
@ -458,10 +315,10 @@ class baseBufferController(bufferController):
|
|||||||
log.debug("Binding events...")
|
log.debug("Binding events...")
|
||||||
self.buffer.set_focus_function(self.onFocus)
|
self.buffer.set_focus_function(self.onFocus)
|
||||||
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
widgetUtils.connect_event(self.buffer.list.list, widgetUtils.KEYPRESS, self.get_event)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_status, self.buffer.tweet)
|
||||||
# if self.type == "baseBuffer":
|
# if self.type == "baseBuffer":
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.retweet, self.buffer.retweet)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.share_item, self.buffer.retweet)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.direct_message, self.buffer.dm)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.send_message, self.buffer.dm)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.reply, self.buffer.reply)
|
||||||
# Replace for the correct way in other platforms.
|
# Replace for the correct way in other platforms.
|
||||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
@ -473,13 +330,13 @@ class baseBufferController(bufferController):
|
|||||||
menu = menus.sentPanelMenu()
|
menu = menus.sentPanelMenu()
|
||||||
elif self.name == "direct_messages":
|
elif self.name == "direct_messages":
|
||||||
menu = menus.dmPanelMenu()
|
menu = menus.dmPanelMenu()
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.send_message, menuitem=menu.reply)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||||
else:
|
else:
|
||||||
menu = menus.basePanelMenu()
|
menu = menus.basePanelMenu()
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.reply, menuitem=menu.reply)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.retweet, menuitem=menu.retweet)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.share_item, menuitem=menu.retweet)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.fav, menuitem=menu.fav)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.unfav, menuitem=menu.unfav)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.url_, menuitem=menu.openUrl)
|
||||||
@ -520,7 +377,7 @@ class baseBufferController(bufferController):
|
|||||||
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
self.show_menu(widgetUtils.MENU, pos=self.buffer.list.list.GetPosition())
|
||||||
|
|
||||||
def get_tweet(self):
|
def get_tweet(self):
|
||||||
if self.session.db[self.name][self.buffer.list.get_selected()].has_key("retweeted_status"):
|
if "retweeted_status" in self.session.db[self.name][self.buffer.list.get_selected()]:
|
||||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
|
tweet = self.session.db[self.name][self.buffer.list.get_selected()]["retweeted_status"]
|
||||||
else:
|
else:
|
||||||
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
tweet = self.session.db[self.name][self.buffer.list.get_selected()]
|
||||||
@ -535,7 +392,7 @@ class baseBufferController(bufferController):
|
|||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
screen_name = tweet["user"]["screen_name"]
|
screen_name = tweet["user"]["screen_name"]
|
||||||
id = tweet["id"]
|
id = tweet["id"]
|
||||||
twishort_enabled = tweet.has_key("twishort")
|
twishort_enabled = "twishort" in tweet
|
||||||
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
users = utils.get_all_mentioned(tweet, self.session.db, field="screen_name")
|
||||||
ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str")
|
ids = utils.get_all_mentioned(tweet, self.session.db, field="id_str")
|
||||||
# Build the window title
|
# Build the window title
|
||||||
@ -550,7 +407,7 @@ class baseBufferController(bufferController):
|
|||||||
if len(users) > 0:
|
if len(users) > 0:
|
||||||
config.app["app-settings"]["mention_all"] = message.message.mentionAll.GetValue()
|
config.app["app-settings"]["mention_all"] = message.message.mentionAll.GetValue()
|
||||||
config.app.write()
|
config.app.write()
|
||||||
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id,}
|
params = {"_sound": "reply_send.ogg", "in_reply_to_status_id": id, "tweet_mode": "extended"}
|
||||||
text = message.message.get_text()
|
text = message.message.get_text()
|
||||||
if twishort_enabled == False:
|
if twishort_enabled == False:
|
||||||
excluded_ids = message.get_ids()
|
excluded_ids = message.get_ids()
|
||||||
@ -570,6 +427,7 @@ class baseBufferController(bufferController):
|
|||||||
else:
|
else:
|
||||||
params["call_name"] = "update_status_with_media"
|
params["call_name"] = "update_status_with_media"
|
||||||
params["media"] = message.file
|
params["media"] = message.file
|
||||||
|
|
||||||
item = self.session.api_call(**params)
|
item = self.session.api_call(**params)
|
||||||
if item != None:
|
if item != None:
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||||
@ -577,7 +435,7 @@ class baseBufferController(bufferController):
|
|||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
|
|
||||||
@_tweets_exist
|
@_tweets_exist
|
||||||
def direct_message(self, *args, **kwargs):
|
def send_message(self, *args, **kwargs):
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
if self.type == "dm":
|
if self.type == "dm":
|
||||||
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
|
screen_name = self.session.get_user(tweet["message_create"]["sender_id"])["screen_name"]
|
||||||
@ -615,7 +473,7 @@ class baseBufferController(bufferController):
|
|||||||
if hasattr(dm.message, "destroy"): dm.message.destroy()
|
if hasattr(dm.message, "destroy"): dm.message.destroy()
|
||||||
|
|
||||||
@_tweets_exist
|
@_tweets_exist
|
||||||
def retweet(self, *args, **kwargs):
|
def share_item(self, *args, **kwargs):
|
||||||
tweet = self.get_right_tweet()
|
tweet = self.get_right_tweet()
|
||||||
id = tweet["id"]
|
id = tweet["id"]
|
||||||
if self.session.settings["general"]["retweet_mode"] == "ask":
|
if self.session.settings["general"]["retweet_mode"] == "ask":
|
||||||
@ -630,7 +488,10 @@ class baseBufferController(bufferController):
|
|||||||
self._retweet_with_comment(tweet, id)
|
self._retweet_with_comment(tweet, id)
|
||||||
|
|
||||||
def _retweet_with_comment(self, tweet, id, comment=''):
|
def _retweet_with_comment(self, tweet, id, comment=''):
|
||||||
if tweet.has_key("full_text"):
|
# If quoting a retweet, let's quote the original tweet instead the retweet.
|
||||||
|
if "retweeted_status" in tweet:
|
||||||
|
tweet = tweet["retweeted_status"]
|
||||||
|
if "full_text" in tweet:
|
||||||
comments = tweet["full_text"]
|
comments = tweet["full_text"]
|
||||||
else:
|
else:
|
||||||
comments = tweet["text"]
|
comments = tweet["text"]
|
||||||
@ -641,16 +502,20 @@ class baseBufferController(bufferController):
|
|||||||
text = retweet.message.get_text()
|
text = retweet.message.get_text()
|
||||||
text = text+" https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id)
|
text = text+" https://twitter.com/{0}/status/{1}".format(tweet["user"]["screen_name"], id)
|
||||||
if retweet.image == None:
|
if retweet.image == None:
|
||||||
item = self.session.api_call(call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id)
|
item = self.session.api_call(call_name="update_status", _sound="retweet_send.ogg", status=text, in_reply_to_status_id=id, tweet_mode="extended")
|
||||||
if item != None:
|
if item != None:
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
new_item = self.session.twitter.show_status(id=item["id"], include_ext_alt_text=True, tweet_mode="extended")
|
||||||
|
pub.sendMessage("sent-tweet", data=new_item, user=self.session.db["user_name"])
|
||||||
else:
|
else:
|
||||||
call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image)
|
call_threaded(self.session.api_call, call_name="update_status", _sound="retweet_send.ogg", status=text, media=retweet.image)
|
||||||
if hasattr(retweet.message, "destroy"): retweet.message.destroy()
|
if hasattr(retweet.message, "destroy"): retweet.message.destroy()
|
||||||
|
|
||||||
def _direct_retweet(self, id):
|
def _direct_retweet(self, id):
|
||||||
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id)
|
item = self.session.api_call(call_name="retweet", _sound="retweet_send.ogg", id=id, tweet_mode="extended")
|
||||||
if item != None:
|
if item != None:
|
||||||
|
# Retweets are returned as non-extended tweets, so let's get the object as extended
|
||||||
|
# just before sending the event message. See https://github.com/manuelcortez/TWBlue/issues/253
|
||||||
|
item = self.session.twitter.show_status(id=item["id"], include_ext_alt_text=True, tweet_mode="extended")
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||||
|
|
||||||
def onFocus(self, *args, **kwargs):
|
def onFocus(self, *args, **kwargs):
|
||||||
@ -725,7 +590,6 @@ class baseBufferController(bufferController):
|
|||||||
self.session.twitter.destroy_status(id=self.get_right_tweet()["id"])
|
self.session.twitter.destroy_status(id=self.get_right_tweet()["id"])
|
||||||
self.session.db[self.name].pop(index)
|
self.session.db[self.name].pop(index)
|
||||||
self.buffer.list.remove_item(index)
|
self.buffer.list.remove_item(index)
|
||||||
# if index > 0:
|
|
||||||
except TwythonError:
|
except TwythonError:
|
||||||
self.session.sound.play("error.ogg")
|
self.session.sound.play("error.ogg")
|
||||||
|
|
||||||
@ -771,6 +635,8 @@ class directMessagesController(baseBufferController):
|
|||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
return
|
return
|
||||||
|
if items == None:
|
||||||
|
return
|
||||||
sent = []
|
sent = []
|
||||||
for i in items:
|
for i in items:
|
||||||
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
|
if i["message_create"]["sender_id"] == self.session.db["user_id"]:
|
||||||
@ -817,7 +683,7 @@ class directMessagesController(baseBufferController):
|
|||||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
||||||
config.app.write()
|
config.app.write()
|
||||||
if message.image == None:
|
if message.image == None:
|
||||||
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
|
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text(), tweet_mode="extended")
|
||||||
if item != None:
|
if item != None:
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||||
else:
|
else:
|
||||||
@ -842,11 +708,22 @@ class directMessagesController(baseBufferController):
|
|||||||
self.session.db[self.name]["items"] = []
|
self.session.db[self.name]["items"] = []
|
||||||
self.buffer.list.clear()
|
self.buffer.list.clear()
|
||||||
|
|
||||||
|
def auto_read(self, number_of_items):
|
||||||
|
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
tweet = self.session.db[self.name]["items"][-1]
|
||||||
|
else:
|
||||||
|
tweet = self.session.db[self.name]["items"][0]
|
||||||
|
output.speak(_(u"New direct message"))
|
||||||
|
output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)))
|
||||||
|
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
output.speak(_(u"{0} new direct messages.").format(number_of_items,))
|
||||||
|
|
||||||
class sentDirectMessagesController(directMessagesController):
|
class sentDirectMessagesController(directMessagesController):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
|
super(sentDirectMessagesController, self).__init__(*args, **kwargs)
|
||||||
if self.session.db.has_key("sent_direct_messages") == False:
|
if ("sent_direct_messages" in self.session.db) == False:
|
||||||
self.session.db["sent_direct_messages"] = {"items": []}
|
self.session.db["sent_direct_messages"] = {"items": []}
|
||||||
|
|
||||||
def get_more_items(self):
|
def get_more_items(self):
|
||||||
@ -872,9 +749,9 @@ class listBufferController(baseBufferController):
|
|||||||
self.list_id = list_id
|
self.list_id = list_id
|
||||||
self.kwargs["list_id"] = list_id
|
self.kwargs["list_id"] = list_id
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
self.get_user_ids()
|
self.get_user_ids()
|
||||||
super(listBufferController, self).start_stream(mandatory, play_sound)
|
super(listBufferController, self).start_stream(mandatory, play_sound, avoid_autoreading)
|
||||||
|
|
||||||
def get_user_ids(self):
|
def get_user_ids(self):
|
||||||
next_cursor = -1
|
next_cursor = -1
|
||||||
@ -893,65 +770,13 @@ class listBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
if self.name[:-5] in self.session.settings["other_buffers"]["lists"]:
|
||||||
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
self.session.settings["other_buffers"]["lists"].remove(self.name[:-5])
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class eventsBufferController(bufferController):
|
|
||||||
def __init__(self, parent, name, session, account, *args, **kwargs):
|
|
||||||
super(eventsBufferController, self).__init__(parent, *args, **kwargs)
|
|
||||||
log.debug("Initializing buffer %s, account %s" % (name, account,))
|
|
||||||
self.invisible = True
|
|
||||||
self.buffer = buffers.eventsPanel(parent, name)
|
|
||||||
self.name = name
|
|
||||||
self.account = account
|
|
||||||
self.buffer.account = self.account
|
|
||||||
self.compose_function = compose.compose_event
|
|
||||||
self.session = session
|
|
||||||
self.type = self.buffer.type
|
|
||||||
self.get_formatted_message = self.get_message
|
|
||||||
|
|
||||||
def get_message(self):
|
|
||||||
if self.buffer.list.get_count() == 0: return _(u"Empty")
|
|
||||||
# fix this:
|
|
||||||
return "%s. %s" % (self.buffer.list.list.GetItemText(self.buffer.list.get_selected()), self.buffer.list.list.GetItemText(self.buffer.list.get_selected(), 1))
|
|
||||||
|
|
||||||
def add_new_item(self, item):
|
|
||||||
tweet = self.compose_function(item, self.session.db["user_name"], self.session.settings["general"]["show_screen_names"])
|
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
|
||||||
self.buffer.list.insert_item(False, *tweet)
|
|
||||||
else:
|
|
||||||
self.buffer.list.insert_item(True, *tweet)
|
|
||||||
if self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
|
||||||
output.speak(" ".join(tweet), speech=self.session.settings["reporting"]["speech_reporting"], braille=self.session.settings["reporting"]["braille_reporting"])
|
|
||||||
if self.buffer.list.get_count() == 1:
|
|
||||||
self.buffer.list.select_item(0)
|
|
||||||
|
|
||||||
def clear_list(self):
|
|
||||||
dlg = commonMessageDialogs.clear_list()
|
|
||||||
if dlg == widgetUtils.YES:
|
|
||||||
self.buffer.list.clear()
|
|
||||||
|
|
||||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
|
||||||
if self.buffer.list.get_count() == 0: return
|
|
||||||
menu = menus.eventsPanelMenu()
|
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.view, menuitem=menu.view)
|
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.copy, menuitem=menu.copy)
|
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.destroy_status, menuitem=menu.remove)
|
|
||||||
if pos != 0:
|
|
||||||
self.buffer.PopupMenu(menu, pos)
|
|
||||||
else:
|
|
||||||
self.buffer.PopupMenu(menu, ev.GetPosition())
|
|
||||||
|
|
||||||
def view(self, *args, **kwargs):
|
|
||||||
pub.sendMessage("execute-action", action="view_item")
|
|
||||||
|
|
||||||
def copy(self, *args, **kwargs):
|
|
||||||
pub.sendMessage("execute-action", action="copy_to_clipboard")
|
|
||||||
|
|
||||||
class peopleBufferController(baseBufferController):
|
class peopleBufferController(baseBufferController):
|
||||||
def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs):
|
def __init__(self, parent, function, name, sessionObject, account, bufferType=None, *args, **kwargs):
|
||||||
super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs)
|
super(peopleBufferController, self).__init__(parent, function, name, sessionObject, account, bufferType="peoplePanel", *args, **kwargs)
|
||||||
@ -980,7 +805,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
if self.name[:-10] in self.session.settings["other_buffers"]["followers_timelines"]:
|
||||||
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
self.session.settings["other_buffers"]["followers_timelines"].remove(self.name[:-10])
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
return True
|
return True
|
||||||
@ -994,7 +819,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
if self.name[:-8] in self.session.settings["other_buffers"]["friends_timelines"]:
|
||||||
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
self.session.settings["other_buffers"]["friends_timelines"].remove(self.name[:-8])
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
return True
|
return True
|
||||||
@ -1022,14 +847,14 @@ class peopleBufferController(baseBufferController):
|
|||||||
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
config.app["app-settings"]["longtweet"] = message.message.long_tweet.GetValue()
|
||||||
config.app.write()
|
config.app.write()
|
||||||
if message.image == None:
|
if message.image == None:
|
||||||
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text())
|
item = self.session.api_call(call_name="update_status", _sound="reply_send.ogg", status=message.message.get_text(), tweet_mode="extended")
|
||||||
if item != None:
|
if item != None:
|
||||||
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
pub.sendMessage("sent-tweet", data=item, user=self.session.db["user_name"])
|
||||||
else:
|
else:
|
||||||
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
call_threaded(self.session.api_call, call_name="update_status_with_media", _sound="reply_send.ogg", status=message.message.get_text(), media=message.file)
|
||||||
if hasattr(message.message, "destroy"): message.message.destroy()
|
if hasattr(message.message, "destroy"): message.message.destroy()
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
@ -1043,6 +868,9 @@ class peopleBufferController(baseBufferController):
|
|||||||
self.finished_timeline = True
|
self.finished_timeline = True
|
||||||
if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if val > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and val > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(val)
|
||||||
return val
|
return val
|
||||||
|
|
||||||
def get_more_items(self):
|
def get_more_items(self):
|
||||||
@ -1051,6 +879,8 @@ class peopleBufferController(baseBufferController):
|
|||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
return
|
return
|
||||||
|
if items == None:
|
||||||
|
return
|
||||||
for i in items:
|
for i in items:
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
self.session.db[self.name]["items"].insert(0, i)
|
self.session.db[self.name]["items"].insert(0, i)
|
||||||
@ -1115,7 +945,7 @@ class peopleBufferController(baseBufferController):
|
|||||||
|
|
||||||
def show_menu(self, ev, pos=0, *args, **kwargs):
|
def show_menu(self, ev, pos=0, *args, **kwargs):
|
||||||
menu = menus.peoplePanelMenu()
|
menu = menus.peoplePanelMenu()
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.direct_message, menuitem=menu.reply)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.send_message, menuitem=menu.reply)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.user_actions, menuitem=menu.userActions)
|
||||||
widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details)
|
widgetUtils.connect_event(menu, widgetUtils.MENU, self.details, menuitem=menu.details)
|
||||||
# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists)
|
# widgetUtils.connect_event(menu, widgetUtils.MENU, self.lists, menuitem=menu.lists)
|
||||||
@ -1129,8 +959,18 @@ class peopleBufferController(baseBufferController):
|
|||||||
def details(self, *args, **kwargs):
|
def details(self, *args, **kwargs):
|
||||||
pub.sendMessage("execute-action", action="user_details")
|
pub.sendMessage("execute-action", action="user_details")
|
||||||
|
|
||||||
|
def auto_read(self, number_of_items):
|
||||||
|
if number_of_items == 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
|
tweet = self.session.db[self.name]["items"][-1]
|
||||||
|
else:
|
||||||
|
tweet = self.session.db[self.name["items"]][0]
|
||||||
|
output.speak(" ".join(self.compose_function(tweet, self.session.db, self.session.settings["general"]["relative_times"], self.session.settings["general"]["show_screen_names"], self.session)))
|
||||||
|
elif number_of_items > 1 and self.name in self.session.settings["other_buffers"]["autoread_buffers"] and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and self.session.settings["sound"]["session_mute"] == False:
|
||||||
|
output.speak(_(u"{0} new followers.").format(number_of_items))
|
||||||
|
|
||||||
class searchBufferController(baseBufferController):
|
class searchBufferController(baseBufferController):
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
@ -1146,6 +986,9 @@ class searchBufferController(baseBufferController):
|
|||||||
self.put_items_on_list(num)
|
self.put_items_on_list(num)
|
||||||
if num > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if num > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and num > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(num)
|
||||||
return num
|
return num
|
||||||
|
|
||||||
def remove_buffer(self, force=False):
|
def remove_buffer(self, force=False):
|
||||||
@ -1157,7 +1000,7 @@ class searchBufferController(baseBufferController):
|
|||||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
@ -1173,6 +1016,8 @@ class searchBufferController(baseBufferController):
|
|||||||
items = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs)
|
items = self.session.search(self.name, count=self.session.settings["general"]["max_tweets_per_call"], max_id=last_id, *self.args, **self.kwargs)
|
||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
|
if items == None:
|
||||||
|
return
|
||||||
for i in items:
|
for i in items:
|
||||||
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None:
|
if utils.is_allowed(i, self.session.settings, self.name) == True and utils.find_item(i["id"], self.session.db[self.name]) == None:
|
||||||
i = self.session.check_quoted_status(i)
|
i = self.session.check_quoted_status(i)
|
||||||
@ -1206,10 +1051,10 @@ class searchPeopleBufferController(peopleBufferController):
|
|||||||
self.args = args
|
self.args = args
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.function = function
|
self.function = function
|
||||||
if self.kwargs.has_key("page") == False:
|
if ("page" in self.kwargs) == False:
|
||||||
self.kwargs["page"] = 1
|
self.kwargs["page"] = 1
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=True):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory==True:
|
||||||
@ -1226,6 +1071,9 @@ class searchPeopleBufferController(peopleBufferController):
|
|||||||
self.put_items_on_list(number_of_items)
|
self.put_items_on_list(number_of_items)
|
||||||
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
return number_of_items
|
return number_of_items
|
||||||
|
|
||||||
def get_more_items(self, *args, **kwargs):
|
def get_more_items(self, *args, **kwargs):
|
||||||
@ -1235,6 +1083,8 @@ class searchPeopleBufferController(peopleBufferController):
|
|||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message, True)
|
output.speak(e.message, True)
|
||||||
return
|
return
|
||||||
|
if items == None:
|
||||||
|
return
|
||||||
for i in items:
|
for i in items:
|
||||||
if self.session.settings["general"]["reverse_timelines"] == False:
|
if self.session.settings["general"]["reverse_timelines"] == False:
|
||||||
self.session.db[self.name]["items"].insert(0, i)
|
self.session.db[self.name]["items"].insert(0, i)
|
||||||
@ -1265,13 +1115,13 @@ class searchPeopleBufferController(peopleBufferController):
|
|||||||
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
if self.name[:-11] in self.session.settings["other_buffers"]["tweet_searches"]:
|
||||||
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
self.session.settings["other_buffers"]["tweet_searches"].remove(self.name[:-11])
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
class trendsBufferController(bufferController):
|
class trendsBufferController(baseBuffers.buffer):
|
||||||
def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs):
|
def __init__(self, parent, name, session, account, trendsFor, *args, **kwargs):
|
||||||
super(trendsBufferController, self).__init__(parent=parent, session=session)
|
super(trendsBufferController, self).__init__(parent=parent, session=session)
|
||||||
self.trendsFor = trendsFor
|
self.trendsFor = trendsFor
|
||||||
@ -1290,7 +1140,7 @@ class trendsBufferController(bufferController):
|
|||||||
self.get_formatted_message = self.get_message
|
self.get_formatted_message = self.get_message
|
||||||
self.reply = self.search_topic
|
self.reply = self.search_topic
|
||||||
|
|
||||||
def start_stream(self, mandatory=False, play_sound=True):
|
def start_stream(self, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
||||||
@ -1321,7 +1171,7 @@ class trendsBufferController(bufferController):
|
|||||||
log.debug("Binding events...")
|
log.debug("Binding events...")
|
||||||
self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event)
|
self.buffer.list.list.Bind(wx.EVT_CHAR_HOOK, self.get_event)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.tweet_about_this_trend, self.buffer.tweetTrendBtn)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_tweet, self.buffer.tweet)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.post_status, self.buffer.tweet)
|
||||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_ITEM_RIGHT_CLICK, self.show_menu)
|
||||||
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
widgetUtils.connect_event(self.buffer.list.list, wx.EVT_LIST_KEY_DOWN, self.show_menu_by_key)
|
||||||
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic)
|
widgetUtils.connect_event(self.buffer, widgetUtils.BUTTON_PRESSED, self.search_topic, self.buffer.search_topic)
|
||||||
@ -1338,7 +1188,7 @@ class trendsBufferController(bufferController):
|
|||||||
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
if self.name[:-3] in self.session.settings["other_buffers"]["trending_topic_buffers"]:
|
||||||
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
self.session.settings["other_buffers"]["trending_topic_buffers"].remove(self.name[:-3])
|
||||||
self.session.settings.write()
|
self.session.settings.write()
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
||||||
@ -1395,7 +1245,7 @@ class trendsBufferController(bufferController):
|
|||||||
|
|
||||||
class conversationBufferController(searchBufferController):
|
class conversationBufferController(searchBufferController):
|
||||||
|
|
||||||
def start_stream(self, start=False, mandatory=False, play_sound=True):
|
def start_stream(self, start=False, mandatory=False, play_sound=True, avoid_autoreading=False):
|
||||||
# starts stream every 3 minutes.
|
# starts stream every 3 minutes.
|
||||||
current_time = time.time()
|
current_time = time.time()
|
||||||
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
if self.execution_time == 0 or current_time-self.execution_time >= 180 or mandatory == True:
|
||||||
@ -1427,6 +1277,9 @@ class conversationBufferController(searchBufferController):
|
|||||||
self.put_items_on_list(number_of_items)
|
self.put_items_on_list(number_of_items)
|
||||||
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
if number_of_items > 0 and self.sound != None and self.session.settings["sound"]["session_mute"] == False and self.name not in self.session.settings["other_buffers"]["muted_buffers"] and play_sound == True:
|
||||||
self.session.sound.play(self.sound)
|
self.session.sound.play(self.sound)
|
||||||
|
# Autoread settings
|
||||||
|
if avoid_autoreading == False and mandatory == True and number_of_items > 0 and self.name in self.session.settings["other_buffers"]["autoread_buffers"]:
|
||||||
|
self.auto_read(number_of_items)
|
||||||
return number_of_items
|
return number_of_items
|
||||||
|
|
||||||
def remove_buffer(self, force=False):
|
def remove_buffer(self, force=False):
|
||||||
@ -1435,7 +1288,7 @@ class conversationBufferController(searchBufferController):
|
|||||||
else:
|
else:
|
||||||
dlg = widgetUtils.YES
|
dlg = widgetUtils.YES
|
||||||
if dlg == widgetUtils.YES:
|
if dlg == widgetUtils.YES:
|
||||||
if self.session.db.has_key(self.name):
|
if self.name in self.session.db:
|
||||||
self.session.db.pop(self.name)
|
self.session.db.pop(self.name)
|
||||||
return True
|
return True
|
||||||
elif dlg == widgetUtils.NO:
|
elif dlg == widgetUtils.NO:
|
@ -30,7 +30,7 @@ class filter(object):
|
|||||||
if i["name"] in langs:
|
if i["name"] in langs:
|
||||||
langcodes.append(i["code"])
|
langcodes.append(i["code"])
|
||||||
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains, allow_rts=allow_rts, allow_quotes=allow_quotes, allow_replies=allow_replies)
|
d = dict(in_buffer=self.buffer.name, word=term, regexp=regexp, in_lang=lang_option, languages=langcodes, if_word_exists=contains, allow_rts=allow_rts, allow_quotes=allow_quotes, allow_replies=allow_replies)
|
||||||
if self.buffer.session.settings["filters"].has_key(title):
|
if title in self.buffer.session.settings["filters"]:
|
||||||
return commonMessageDialogs.existing_filter()
|
return commonMessageDialogs.existing_filter()
|
||||||
self.buffer.session.settings["filters"][title] = d
|
self.buffer.session.settings["filters"][title] = d
|
||||||
self.buffer.session.settings.write()
|
self.buffer.session.settings.write()
|
||||||
|
@ -1,28 +1,31 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
import application
|
import application
|
||||||
|
import requests
|
||||||
import youtube_utils
|
import youtube_utils
|
||||||
|
import arrow
|
||||||
if system == "Windows":
|
if system == "Windows":
|
||||||
from update import updater
|
from update import updater
|
||||||
from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon)
|
from wxUI import (view, dialogs, commonMessageDialogs, sysTrayIcon)
|
||||||
import settings
|
from . import settings
|
||||||
from extra import SoundsTutorial, ocr
|
from extra import SoundsTutorial, ocr
|
||||||
import keystrokeEditor
|
import keystrokeEditor
|
||||||
from keyboard_handler.wx_handler import WXKeyboardHandler
|
from keyboard_handler.wx_handler import WXKeyboardHandler
|
||||||
import userActionsController
|
from . import userActionsController
|
||||||
import trendingTopics
|
from . import trendingTopics
|
||||||
import user
|
from . import user
|
||||||
import listsController
|
from . import listsController
|
||||||
import filterController
|
from . import filterController
|
||||||
# from issueReporter import issueReporter
|
# from issueReporter import issueReporter
|
||||||
elif system == "Linux":
|
elif system == "Linux":
|
||||||
from gtkUI import (view, commonMessageDialogs)
|
from gtkUI import (view, commonMessageDialogs)
|
||||||
from sessions.twitter import utils, compose
|
from sessions.twitter import utils, compose
|
||||||
from sessionmanager import manager, sessionManager
|
from sessionmanager import manager, sessionManager
|
||||||
|
|
||||||
import buffersController
|
from controller.buffers import baseBuffers, twitterBuffers
|
||||||
import messages
|
from . import messages
|
||||||
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
|
||||||
@ -40,6 +43,7 @@ import logging
|
|||||||
import webbrowser
|
import webbrowser
|
||||||
from mysc import localization
|
from mysc import localization
|
||||||
import os
|
import os
|
||||||
|
import languageHandler
|
||||||
|
|
||||||
log = logging.getLogger("mainController")
|
log = logging.getLogger("mainController")
|
||||||
|
|
||||||
@ -55,13 +59,13 @@ class Controller(object):
|
|||||||
name_ str: The name for the buffer
|
name_ str: The name for the buffer
|
||||||
user str: The account for the buffer.
|
user str: The account for the buffer.
|
||||||
for example you may want to search the home_timeline buffer for the tw_blue2 user.
|
for example you may want to search the home_timeline buffer for the tw_blue2 user.
|
||||||
Return type: buffersController.buffer object."""
|
Return type: buffers.buffer object."""
|
||||||
for i in self.buffers:
|
for i in self.buffers:
|
||||||
if i.name == name_ and i.account == user: return i
|
if i.name == name_ and i.account == user: return i
|
||||||
|
|
||||||
def get_current_buffer(self):
|
def get_current_buffer(self):
|
||||||
""" Get the current focused bufferObject.
|
""" Get the current focused bufferObject.
|
||||||
Return type: BuffersController.buffer object."""
|
Return type: buffers.buffer object."""
|
||||||
buffer = self.view.get_current_buffer()
|
buffer = self.view.get_current_buffer()
|
||||||
if hasattr(buffer, "account"):
|
if hasattr(buffer, "account"):
|
||||||
buffer = self.search_buffer(buffer.name, buffer.account)
|
buffer = self.search_buffer(buffer.name, buffer.account)
|
||||||
@ -70,7 +74,7 @@ class Controller(object):
|
|||||||
def get_best_buffer(self):
|
def get_best_buffer(self):
|
||||||
""" Get the best buffer for doing something using the session object.
|
""" Get the best buffer for doing something using the session object.
|
||||||
This function is useful when you need to open a timeline or post a tweet, and the user is in a buffer without a session, for example the events buffer.
|
This function is useful when you need to open a timeline or post a tweet, and the user is in a buffer without a session, for example the events buffer.
|
||||||
Return type: buffersController.buffer object."""
|
Return type: twitterBuffers.buffer object."""
|
||||||
# Gets the parent buffer to know what account is doing an action
|
# Gets the parent buffer to know what account is doing an action
|
||||||
view_buffer = self.view.get_current_buffer()
|
view_buffer = self.view.get_current_buffer()
|
||||||
# If the account has no session attached, we will need to search the first available non-empty buffer for that account to use its session.
|
# If the account has no session attached, we will need to search the first available non-empty buffer for that account to use its session.
|
||||||
@ -152,7 +156,7 @@ class Controller(object):
|
|||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_reply, self.view.reply)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.post_retweet, self.view.retweet)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.add_to_favourites, self.view.fav)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.fav)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.remove_from_favourites, self.view.unfav)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.view_item, self.view.view)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.reverse_geocode, menuitem=self.view.view_coordinates)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.reverse_geocode, menuitem=self.view.view_coordinates)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.delete, self.view.delete)
|
||||||
@ -166,6 +170,7 @@ class Controller(object):
|
|||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.check_for_updates, self.view.check_for_updates)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.about, menuitem=self.view.about)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.about, menuitem=self.view.about)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.visit_website, menuitem=self.view.visit_website)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.visit_website, menuitem=self.view.visit_website)
|
||||||
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.get_soundpacks, menuitem=self.view.get_soundpacks)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.manage_accounts, self.view.manage_accounts)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.manage_accounts, self.view.manage_accounts)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_profile, menuitem=self.view.updateProfile)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.update_profile, menuitem=self.view.updateProfile)
|
||||||
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.user_details, menuitem=self.view.details)
|
widgetUtils.connect_event(self.view, widgetUtils.MENU, self.user_details, menuitem=self.view.details)
|
||||||
@ -270,7 +275,7 @@ class Controller(object):
|
|||||||
|
|
||||||
def create_ignored_session_buffer(self, session):
|
def create_ignored_session_buffer(self, session):
|
||||||
self.accounts.append(session.settings["twitter"]["user_name"])
|
self.accounts.append(session.settings["twitter"]["user_name"])
|
||||||
account = buffersController.accountPanel(self.view.nb, session.settings["twitter"]["user_name"], session.settings["twitter"]["user_name"], session.session_id)
|
account = baseBuffers.accountPanel(self.view.nb, session.settings["twitter"]["user_name"], session.settings["twitter"]["user_name"], session.session_id)
|
||||||
account.logged = False
|
account.logged = False
|
||||||
account.setup_account()
|
account.setup_account()
|
||||||
self.buffers.append(account)
|
self.buffers.append(account)
|
||||||
@ -290,96 +295,96 @@ class Controller(object):
|
|||||||
session.get_user_info()
|
session.get_user_info()
|
||||||
if createAccounts == True:
|
if createAccounts == True:
|
||||||
self.accounts.append(session.db["user_name"])
|
self.accounts.append(session.db["user_name"])
|
||||||
account = buffersController.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"], session.session_id)
|
account = baseBuffers.accountPanel(self.view.nb, session.db["user_name"], session.db["user_name"], session.session_id)
|
||||||
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"])
|
||||||
for i in session.settings['general']['buffer_order']:
|
for i in session.settings['general']['buffer_order']:
|
||||||
if i == 'home':
|
if i == 'home':
|
||||||
home = buffersController.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended")
|
home = twitterBuffers.baseBufferController(self.view.nb, "get_home_timeline", "home_timeline", session, session.db["user_name"], sound="tweet_received.ogg", tweet_mode="extended")
|
||||||
self.buffers.append(home)
|
self.buffers.append(home)
|
||||||
self.view.insert_buffer(home.buffer, name=_(u"Home"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
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 = buffersController.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended")
|
mentions = twitterBuffers.baseBufferController(self.view.nb, "get_mentions_timeline", "mentions", session, session.db["user_name"], sound="mention_received.ogg", tweet_mode="extended")
|
||||||
self.buffers.append(mentions)
|
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"]))
|
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 = buffersController.directMessagesController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events")
|
dm = twitterBuffers.directMessagesController(self.view.nb, "get_direct_messages", "direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message", sound="dm_received.ogg", full_text=True, items="events")
|
||||||
self.buffers.append(dm)
|
self.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"]))
|
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 = buffersController.sentDirectMessagesController(self.view.nb, "", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message")
|
sent_dm = twitterBuffers.sentDirectMessagesController(self.view.nb, "", "sent_direct_messages", session, session.db["user_name"], bufferType="dmPanel", compose_func="compose_direct_message")
|
||||||
self.buffers.append(sent_dm)
|
self.buffers.append(sent_dm)
|
||||||
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
self.view.insert_buffer(sent_dm.buffer, name=_(u"Sent direct messages"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
||||||
elif i == 'sent_tweets':
|
elif i == 'sent_tweets':
|
||||||
sent_tweets = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
|
sent_tweets = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "sent_tweets", session, session.db["user_name"], screen_name=session.db["user_name"], tweet_mode="extended")
|
||||||
self.buffers.append(sent_tweets)
|
self.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"]))
|
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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended")
|
favourites = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "favourites", session, session.db["user_name"], sound="favourite.ogg", tweet_mode="extended")
|
||||||
self.buffers.append(favourites)
|
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"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"])
|
followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", session, session.db["user_name"], sound="update_followers.ogg", screen_name=session.db["user_name"])
|
||||||
self.buffers.append(followers)
|
self.buffers.append(followers)
|
||||||
self.view.insert_buffer(followers.buffer, name=_(u"Followers"), pos=self.view.search(session.db["user_name"], session.db["user_name"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "friends", session, session.db["user_name"], screen_name=session.db["user_name"])
|
friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", session, session.db["user_name"], screen_name=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(session.db["user_name"], session.db["user_name"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "list_blocks", "blocked", session, session.db["user_name"])
|
blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_blocks", "blocked", session, 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(session.db["user_name"], session.db["user_name"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "list_mutes", "muted", session, session.db["user_name"])
|
muted = twitterBuffers.peopleBufferController(self.view.nb, "list_mutes", "muted", session, 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(session.db["user_name"], 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 = buffersController.emptyPanel(self.view.nb, "timelines", session.db["user_name"])
|
timelines = baseBuffers.emptyPanel(self.view.nb, "timelines", session.db["user_name"])
|
||||||
self.buffers.append(timelines)
|
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"]))
|
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 = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended")
|
tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (i,), session, session.db["user_name"], sound="tweet_timeline.ogg", bufferType=None, user_id=i, tweet_mode="extended")
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"Timeline for {}").format(i,), pos=self.view.search("timelines", 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 = buffersController.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
|
favs_timelines = baseBuffers.emptyPanel(self.view.nb, "favs_timelines", session.db["user_name"])
|
||||||
self.buffers.append(favs_timelines)
|
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"]))
|
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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended")
|
tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (i,), session, session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=i, tweet_mode="extended")
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
|
self.view.insert_buffer(tl.buffer, name=_(u"Likes for {}").format(i,), pos=self.view.search("favs_timelines", session.db["user_name"]))
|
||||||
followers_timelines = buffersController.emptyPanel(self.view.nb, "followers_timelines", session.db["user_name"])
|
followers_timelines = baseBuffers.emptyPanel(self.view.nb, "followers_timelines", session.db["user_name"])
|
||||||
self.buffers.append(followers_timelines)
|
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"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
|
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"]))
|
self.view.insert_buffer(tl.buffer, name=_(u"Followers for {}").format(i,), pos=self.view.search("followers_timelines", session.db["user_name"]))
|
||||||
friends_timelines = buffersController.emptyPanel(self.view.nb, "friends_timelines", session.db["user_name"])
|
friends_timelines = baseBuffers.emptyPanel(self.view.nb, "friends_timelines", session.db["user_name"])
|
||||||
self.buffers.append(friends_timelines)
|
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"]))
|
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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
|
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (i,), session, session.db["user_name"], sound="new_event.ogg", user_id=i)
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"]))
|
self.view.insert_buffer(tl.buffer, name=_(u"Friends for {}").format(i,), pos=self.view.search("friends_timelines", session.db["user_name"]))
|
||||||
lists = buffersController.emptyPanel(self.view.nb, "lists", session.db["user_name"])
|
lists = baseBuffers.emptyPanel(self.view.nb, "lists", session.db["user_name"])
|
||||||
self.buffers.append(lists)
|
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"]))
|
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 = buffersController.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
|
tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", "%s-list" % (i,), session, session.db["user_name"], bufferType=None, sound="list_tweet.ogg", list_id=utils.find_list(i, session.db["lists"]), tweet_mode="extended")
|
||||||
session.lists.append(tl)
|
session.lists.append(tl)
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"]))
|
self.view.insert_buffer(tl.buffer, name=_(u"List for {}").format(i), pos=self.view.search("lists", session.db["user_name"]))
|
||||||
searches = buffersController.emptyPanel(self.view.nb, "searches", session.db["user_name"])
|
searches = baseBuffers.emptyPanel(self.view.nb, "searches", session.db["user_name"])
|
||||||
self.buffers.append(searches)
|
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"]))
|
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 = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended")
|
tl = twitterBuffers.searchBufferController(self.view.nb, "search", "%s-searchterm" % (i,), session, session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=i, tweet_mode="extended")
|
||||||
self.buffers.append(tl)
|
self.buffers.append(tl)
|
||||||
self.view.insert_buffer(tl.buffer, name=_(u"Search for {}").format(i), pos=self.view.search("searches", session.db["user_name"]))
|
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 = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i, sound="trends_updated.ogg")
|
buffer = twitterBuffers.trendsBufferController(self.view.nb, "%s_tt" % (i,), session, session.db["user_name"], i, sound="trends_updated.ogg")
|
||||||
buffer.start_stream(play_sound=False)
|
buffer.start_stream(play_sound=False)
|
||||||
buffer.searchfunction = self.search
|
buffer.searchfunction = self.search
|
||||||
self.buffers.append(buffer)
|
self.buffers.append(buffer)
|
||||||
@ -388,7 +393,7 @@ class Controller(object):
|
|||||||
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."
|
||||||
for i in self.buffers:
|
for i in self.buffers:
|
||||||
if i.account == session.db["user_name"] and session.db.has_key(i.name+"_pos") and hasattr(i.buffer,'list'):
|
if i.account == session.db["user_name"] and i.name+"_pos" in session.db and hasattr(i.buffer,'list'):
|
||||||
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
i.buffer.list.select_item(session.db[str(i.name+"_pos")])
|
||||||
|
|
||||||
def logout_account(self, session_id):
|
def logout_account(self, session_id):
|
||||||
@ -427,12 +432,12 @@ class Controller(object):
|
|||||||
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 = buffersController.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, tweet_mode="extended", **args)
|
search = twitterBuffers.searchBufferController(self.view.nb, "search", "%s-searchterm" % (term,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", q=term, tweet_mode="extended", **args)
|
||||||
else:
|
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 = buffersController.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, sound="search_updated.ogg", q=term)
|
search = twitterBuffers.searchPeopleBufferController(self.view.nb, "search_users", "%s-searchUser" % (term,), buffer.session, buffer.session.db["user_name"], bufferType=None, sound="search_updated.ogg", q=term)
|
||||||
search.start_stream(mandatory=True)
|
search.start_stream(mandatory=True)
|
||||||
pos=self.view.search("searches", buffer.session.db["user_name"])
|
pos=self.view.search("searches", buffer.session.db["user_name"])
|
||||||
self.insert_buffer(search, pos)
|
self.insert_buffer(search, pos)
|
||||||
@ -739,25 +744,25 @@ class Controller(object):
|
|||||||
|
|
||||||
def post_tweet(self, event=None):
|
def post_tweet(self, event=None):
|
||||||
buffer = self.get_best_buffer()
|
buffer = self.get_best_buffer()
|
||||||
buffer.post_tweet()
|
buffer.post_status()
|
||||||
|
|
||||||
def post_reply(self, *args, **kwargs):
|
def post_reply(self, *args, **kwargs):
|
||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
if buffer.name == "direct_messages":
|
if buffer.name == "direct_messages":
|
||||||
buffer.direct_message()
|
buffer.send_message()
|
||||||
else:
|
else:
|
||||||
buffer.reply()
|
buffer.reply()
|
||||||
|
|
||||||
def send_dm(self, *args, **kwargs):
|
def send_dm(self, *args, **kwargs):
|
||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
buffer.direct_message()
|
buffer.send_message()
|
||||||
|
|
||||||
def post_retweet(self, *args, **kwargs):
|
def post_retweet(self, *args, **kwargs):
|
||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
|
if buffer.type == "dm" or buffer.type == "people" or buffer.type == "events":
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
buffer.retweet()
|
buffer.share_item()
|
||||||
|
|
||||||
def add_to_favourites(self, *args, **kwargs):
|
def add_to_favourites(self, *args, **kwargs):
|
||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
@ -789,14 +794,17 @@ class Controller(object):
|
|||||||
|
|
||||||
def view_item(self, *args, **kwargs):
|
def view_item(self, *args, **kwargs):
|
||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
if buffer.type == "baseBuffer" or buffer.type == "favourites_timeline" or buffer.type == "list" or buffer.type == "search":
|
if buffer.type == "account" or buffer.type == "empty":
|
||||||
tweet, tweetsList = buffer.get_full_tweet()
|
|
||||||
msg = messages.viewTweet(tweet, tweetsList)
|
|
||||||
elif buffer.type == "account" or buffer.type == "empty":
|
|
||||||
return
|
return
|
||||||
elif buffer.name == "sent_tweets":
|
elif buffer.type == "baseBuffer" or buffer.type == "favourites_timeline" or buffer.type == "list" or buffer.type == "search":
|
||||||
tweet, tweetsList = buffer.get_full_tweet()
|
tweet, tweetsList = buffer.get_full_tweet()
|
||||||
msg = messages.viewTweet(tweet, tweetsList)
|
msg = messages.viewTweet(tweet, tweetsList, utc_offset=buffer.session.db["utc_offset"])
|
||||||
|
elif buffer.type == "dm":
|
||||||
|
non_tweet = buffer.get_formatted_message()
|
||||||
|
item = buffer.get_right_tweet()
|
||||||
|
original_date = arrow.get(item["created_timestamp"][:-3])
|
||||||
|
date = original_date.replace(seconds=buffer.session.db["utc_offset"]).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||||
|
msg = messages.viewTweet(non_tweet, [], False, date=date)
|
||||||
else:
|
else:
|
||||||
non_tweet = buffer.get_formatted_message()
|
non_tweet = buffer.get_formatted_message()
|
||||||
msg = messages.viewTweet(non_tweet, [], False)
|
msg = messages.viewTweet(non_tweet, [], False)
|
||||||
@ -833,7 +841,7 @@ class Controller(object):
|
|||||||
if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]:
|
if usr["id_str"] in buff.session.settings["other_buffers"]["timelines"]:
|
||||||
commonMessageDialogs.timeline_exist()
|
commonMessageDialogs.timeline_exist()
|
||||||
return
|
return
|
||||||
tl = buffersController.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr["id_str"], tweet_mode="extended")
|
tl = twitterBuffers.baseBufferController(self.view.nb, "get_user_timeline", "%s-timeline" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="tweet_timeline.ogg", user_id=usr["id_str"], tweet_mode="extended")
|
||||||
try:
|
try:
|
||||||
tl.start_stream(play_sound=False)
|
tl.start_stream(play_sound=False)
|
||||||
except TwythonAuthError:
|
except TwythonAuthError:
|
||||||
@ -852,7 +860,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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr["id_str"], tweet_mode="extended")
|
tl = twitterBuffers.baseBufferController(self.view.nb, "get_favorites", "%s-favorite" % (usr["id_str"],), buff.session, buff.session.db["user_name"], bufferType=None, sound="favourites_timeline_updated.ogg", user_id=usr["id_str"], tweet_mode="extended")
|
||||||
try:
|
try:
|
||||||
tl.start_stream(play_sound=False)
|
tl.start_stream(play_sound=False)
|
||||||
except TwythonAuthError:
|
except TwythonAuthError:
|
||||||
@ -871,7 +879,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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
|
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "%s-followers" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
|
||||||
try:
|
try:
|
||||||
tl.start_stream(play_sound=False)
|
tl.start_stream(play_sound=False)
|
||||||
except TwythonAuthError:
|
except TwythonAuthError:
|
||||||
@ -890,7 +898,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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
|
tl = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "%s-friends" % (usr["id_str"],), buff.session, buff.session.db["user_name"], sound="new_event.ogg", user_id=usr["id_str"])
|
||||||
try:
|
try:
|
||||||
tl.start_stream(play_sound=False)
|
tl.start_stream(play_sound=False)
|
||||||
except TwythonAuthError:
|
except TwythonAuthError:
|
||||||
@ -910,7 +918,7 @@ class Controller(object):
|
|||||||
buffer = self.get_current_buffer()
|
buffer = self.get_current_buffer()
|
||||||
id = buffer.get_right_tweet()["id_str"]
|
id = buffer.get_right_tweet()["id_str"]
|
||||||
user = buffer.get_right_tweet()["user"]["screen_name"]
|
user = buffer.get_right_tweet()["user"]["screen_name"]
|
||||||
search = buffersController.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,))
|
search = twitterBuffers.conversationBufferController(self.view.nb, "search", "%s-searchterm" % (id,), buffer.session, buffer.session.db["user_name"], bufferType="searchPanel", sound="search_updated.ogg", since_id=id, q="@{0}".format(user,))
|
||||||
search.tweet = buffer.get_right_tweet()
|
search.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"])
|
||||||
@ -937,7 +945,7 @@ class Controller(object):
|
|||||||
if trends.dialog.get_response() == widgetUtils.OK:
|
if trends.dialog.get_response() == widgetUtils.OK:
|
||||||
woeid = trends.get_woeid()
|
woeid = trends.get_woeid()
|
||||||
if woeid in buff.session.settings["other_buffers"]["trending_topic_buffers"]: return
|
if woeid in buff.session.settings["other_buffers"]["trending_topic_buffers"]: return
|
||||||
buffer = buffersController.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid, sound="trends_updated.ogg")
|
buffer = twitterBuffers.trendsBufferController(self.view.nb, "%s_tt" % (woeid,), buff.session, buff.account, woeid, sound="trends_updated.ogg")
|
||||||
buffer.searchfunction = self.search
|
buffer.searchfunction = self.search
|
||||||
pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])
|
pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"])
|
||||||
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos)
|
self.view.insert_buffer(buffer.buffer, name=_(u"Trending topics for %s") % (trends.get_string()), pos=pos)
|
||||||
@ -952,7 +960,7 @@ class Controller(object):
|
|||||||
if tweet["coordinates"] != None:
|
if tweet["coordinates"] != None:
|
||||||
x = tweet["coordinates"]["coordinates"][0]
|
x = tweet["coordinates"]["coordinates"][0]
|
||||||
y = tweet["coordinates"]["coordinates"][1]
|
y = tweet["coordinates"]["coordinates"][1]
|
||||||
address = geocoder.reverse_geocode(y, x)
|
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
|
||||||
if event == None: output.speak(address[0].__str__().decode("utf-8"))
|
if event == None: output.speak(address[0].__str__().decode("utf-8"))
|
||||||
else: self.view.show_address(address[0].__str__().decode("utf-8"))
|
else: self.view.show_address(address[0].__str__().decode("utf-8"))
|
||||||
else:
|
else:
|
||||||
@ -972,7 +980,7 @@ class Controller(object):
|
|||||||
if tweet["coordinates"] != None:
|
if tweet["coordinates"] != None:
|
||||||
x = tweet["coordinates"]["coordinates"][0]
|
x = tweet["coordinates"]["coordinates"][0]
|
||||||
y = tweet["coordinates"]["coordinates"][1]
|
y = tweet["coordinates"]["coordinates"][1]
|
||||||
address = geocoder.reverse_geocode(y, x)
|
address = geocoder.reverse_geocode(y, x, language = languageHandler.curLang)
|
||||||
dlg = commonMessageDialogs.view_geodata(address[0].__str__())
|
dlg = commonMessageDialogs.view_geodata(address[0].__str__())
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"There are no coordinates in this tweet"))
|
output.speak(_(u"There are no coordinates in this tweet"))
|
||||||
@ -1255,6 +1263,10 @@ class Controller(object):
|
|||||||
if buffer == None: return
|
if buffer == None: return
|
||||||
# if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
# if "sent_tweets" not in buffer.session.settings["other_buffers"]["muted_buffers"]:
|
||||||
# self.notify(buffer.session, play_sound=play_sound)
|
# self.notify(buffer.session, play_sound=play_sound)
|
||||||
|
data = buffer.session.check_quoted_status(data)
|
||||||
|
data = buffer.session.check_long_tweet(data)
|
||||||
|
if data == False: # Long tweet deleted from twishort.
|
||||||
|
return
|
||||||
if buffer.session.settings["general"]["reverse_timelines"] == False:
|
if buffer.session.settings["general"]["reverse_timelines"] == False:
|
||||||
buffer.session.db[buffer.name].append(data)
|
buffer.session.db[buffer.name].append(data)
|
||||||
else:
|
else:
|
||||||
@ -1338,32 +1350,32 @@ class Controller(object):
|
|||||||
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 = buffersController.baseBufferController(self.view.nb, "get_favorites", "favourites", buff.session, buff.session.db["user_name"])
|
favourites = twitterBuffers.baseBufferController(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 = buffersController.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
|
followers = twitterBuffers.peopleBufferController(self.view.nb, "get_followers_list", "followers", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
|
||||||
self.buffers.append(followers)
|
self.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 = buffersController.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
|
friends = twitterBuffers.peopleBufferController(self.view.nb, "get_friends_list", "friends", buff.session, buff.session.db["user_name"], screen_name=buff.session.db["user_name"])
|
||||||
self.buffers.append(friends)
|
self.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 = buffersController.peopleBufferController(self.view.nb, "list_blocks", "blocked", buff.session, buff.session.db["user_name"])
|
blocks = twitterBuffers.peopleBufferController(self.view.nb, "list_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 = buffersController.peopleBufferController(self.view.nb, "get_muted_users_list", "muted", buff.session, buff.session.db["user_name"])
|
muted = twitterBuffers.peopleBufferController(self.view.nb, "get_muted_users_list", "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)
|
||||||
elif buffer == "events":
|
elif buffer == "events":
|
||||||
events = buffersController.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"])
|
events = twitterBuffers.eventsBufferController(self.view.nb, "events", buff.session, buff.session.db["user_name"], bufferType="dmPanel", screen_name=buff.session.db["user_name"])
|
||||||
self.buffers.append(events)
|
self.buffers.append(events)
|
||||||
self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
self.view.insert_buffer(events.buffer, name=_(u"Events"), pos=self.view.search(buff.session.db["user_name"], buff.session.db["user_name"]))
|
||||||
elif create == False:
|
elif create == False:
|
||||||
@ -1372,7 +1384,7 @@ class Controller(object):
|
|||||||
if create in buff.session.settings["other_buffers"]["lists"]:
|
if create in buff.session.settings["other_buffers"]["lists"]:
|
||||||
output.speak(_(u"This list is already opened"), True)
|
output.speak(_(u"This list is already opened"), True)
|
||||||
return
|
return
|
||||||
tl = buffersController.listBufferController(self.view.nb, "get_list_statuses", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]))
|
tl = twitterBuffers.listBufferController(self.view.nb, "get_list_statuses", create+"-list", buff.session, buff.session.db["user_name"], bufferType=None, list_id=utils.find_list(create, buff.session.db["lists"]), tweet_mode="extended")
|
||||||
buff.session.lists.append(tl)
|
buff.session.lists.append(tl)
|
||||||
pos=self.view.search("lists", buff.session.db["user_name"])
|
pos=self.view.search("lists", buff.session.db["user_name"])
|
||||||
self.insert_buffer(tl, pos)
|
self.insert_buffer(tl, pos)
|
||||||
@ -1392,8 +1404,37 @@ class Controller(object):
|
|||||||
def about(self, *args, **kwargs):
|
def about(self, *args, **kwargs):
|
||||||
self.view.about_dialog()
|
self.view.about_dialog()
|
||||||
|
|
||||||
|
def get_soundpacks(self, *args, **kwargs):
|
||||||
|
# This should redirect users of other languages to the right version of the TWBlue website.
|
||||||
|
lang = languageHandler.curLang[:2]
|
||||||
|
url = application.url
|
||||||
|
final_url = "{0}/{1}/soundpacks".format(url, lang)
|
||||||
|
try:
|
||||||
|
response = requests.get(final_url)
|
||||||
|
except:
|
||||||
|
output.speak(_(u"An error happened while trying to connect to the server. Please try later."))
|
||||||
|
return
|
||||||
|
# There is no twblue.es/en, so if English is the language used this should be False anyway.
|
||||||
|
if response.status_code == 200 and lang != "en":
|
||||||
|
webbrowser.open_new_tab(final_url)
|
||||||
|
else:
|
||||||
|
webbrowser.open_new_tab(application.url+"/soundpacks")
|
||||||
|
|
||||||
def visit_website(self, *args, **kwargs):
|
def visit_website(self, *args, **kwargs):
|
||||||
webbrowser.open(application.url)
|
# This should redirect users of other languages to the right version of the TWBlue website.
|
||||||
|
lang = languageHandler.curLang[:2]
|
||||||
|
url = application.url
|
||||||
|
final_url = "{0}/{1}".format(url, lang)
|
||||||
|
try:
|
||||||
|
response = requests.get(final_url)
|
||||||
|
except:
|
||||||
|
output.speak(_(u"An error happened while trying to connect to the server. Please try later."))
|
||||||
|
return
|
||||||
|
# There is no twblue.es/en, so if English is the language used this should be False anyway.
|
||||||
|
if response.status_code == 200 and lang != "en":
|
||||||
|
webbrowser.open_new_tab(final_url)
|
||||||
|
else:
|
||||||
|
webbrowser.open_new_tab(application.url)
|
||||||
|
|
||||||
def manage_accounts(self, *args, **kwargs):
|
def manage_accounts(self, *args, **kwargs):
|
||||||
sm = sessionManager.sessionManagerController(started=True)
|
sm = sessionManager.sessionManagerController(started=True)
|
||||||
@ -1501,7 +1542,7 @@ class Controller(object):
|
|||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
output.speak(_(u"Updating buffer..."))
|
output.speak(_(u"Updating buffer..."))
|
||||||
n = bf.start_stream(mandatory=True)
|
n = bf.start_stream(mandatory=True, avoid_autoreading=True)
|
||||||
if n != None:
|
if n != None:
|
||||||
output.speak(_(u"{0} items retrieved").format(n,))
|
output.speak(_(u"{0} items retrieved").format(n,))
|
||||||
|
|
||||||
@ -1523,7 +1564,7 @@ class Controller(object):
|
|||||||
output.speak(_(u"Invalid buffer"))
|
output.speak(_(u"Invalid buffer"))
|
||||||
return
|
return
|
||||||
tweet = buffer.get_tweet()
|
tweet = buffer.get_tweet()
|
||||||
if tweet.has_key("entities") == False or tweet["entities"].has_key("media") == False:
|
if ("entities" in tweet) == False or ("media" in tweet["entities"]) == False:
|
||||||
output.speak(_(u"This tweet doesn't contain images"))
|
output.speak(_(u"This tweet doesn't contain images"))
|
||||||
return
|
return
|
||||||
if len(tweet["entities"]["media"]) > 1:
|
if len(tweet["entities"]["media"]) > 1:
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import re
|
import re
|
||||||
import platform
|
import platform
|
||||||
import attach
|
from . import attach
|
||||||
|
import arrow
|
||||||
|
import languageHandler
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import output
|
import output
|
||||||
@ -193,7 +196,7 @@ class dm(basicTweet):
|
|||||||
c.show_menu("dm")
|
c.show_menu("dm")
|
||||||
|
|
||||||
class viewTweet(basicTweet):
|
class viewTweet(basicTweet):
|
||||||
def __init__(self, tweet, tweetList, is_tweet=True):
|
def __init__(self, tweet, tweetList, is_tweet=True, utc_offset=0, date=""):
|
||||||
""" This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event.
|
""" This represents a tweet displayer. However it could be used for showing something wich is not a tweet, like a direct message or an event.
|
||||||
param tweet: A dictionary that represents a full tweet or a string for non-tweets.
|
param tweet: A dictionary that represents a full tweet or a string for non-tweets.
|
||||||
param tweetList: If is_tweet is set to True, this could be a list of quoted tweets.
|
param tweetList: If is_tweet is set to True, this could be a list of quoted tweets.
|
||||||
@ -204,59 +207,61 @@ class viewTweet(basicTweet):
|
|||||||
text = ""
|
text = ""
|
||||||
for i in xrange(0, len(tweetList)):
|
for i in xrange(0, len(tweetList)):
|
||||||
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
# tweets with message keys are longer tweets, the message value is the full messaje taken from twishort.
|
||||||
if tweetList[i].has_key("message") and tweetList[i]["is_quote_status"] == False:
|
if "message" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||||
value = "message"
|
value = "message"
|
||||||
else:
|
else:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["is_quote_status"] == False:
|
if "retweeted_status" in tweetList[i] and tweetList[i]["is_quote_status"] == False:
|
||||||
if tweetList[i].has_key("message") == False:
|
if ("message" in tweetList[i]) == False:
|
||||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
|
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i]["retweeted_status"]["full_text"])
|
||||||
else:
|
else:
|
||||||
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
text = text + "rt @%s: %s\n" % (tweetList[i]["retweeted_status"]["user"]["screen_name"], tweetList[i][value])
|
||||||
else:
|
else:
|
||||||
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
text = text + " @%s: %s\n" % (tweetList[i]["user"]["screen_name"], tweetList[i][value])
|
||||||
# tweets with extended_entities could include image descriptions.
|
# tweets with extended_entities could include image descriptions.
|
||||||
if tweetList[i].has_key("extended_entities") and tweetList[i]["extended_entities"].has_key("media"):
|
if "extended_entities" in tweetList[i] and "media" in tweetList[i]["extended_entities"]:
|
||||||
for z in tweetList[i]["extended_entities"]["media"]:
|
for z in tweetList[i]["extended_entities"]["media"]:
|
||||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||||
image_description.append(z["ext_alt_text"])
|
image_description.append(z["ext_alt_text"])
|
||||||
if tweetList[i].has_key("retweeted_status") and tweetList[i]["retweeted_status"].has_key("extended_entities") and tweetList[i]["retweeted_status"]["extended_entities"].has_key("media"):
|
if "retweeted_status" in tweetList[i] and "extended_entities" in tweetList[i]["retweeted_status"] and "media" in tweetList[i]["retweeted_status"]["extended_entities"]:
|
||||||
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
|
for z in tweetList[i]["retweeted_status"]["extended_entities"]["media"]:
|
||||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||||
image_description.append(z["ext_alt_text"])
|
image_description.append(z["ext_alt_text"])
|
||||||
# set rt and likes counters.
|
# set rt and likes counters.
|
||||||
rt_count = str(tweet["retweet_count"])
|
rt_count = str(tweet["retweet_count"])
|
||||||
favs_count = str(tweet["favorite_count"])
|
favs_count = str(tweet["favorite_count"])
|
||||||
# Gets the client from where this tweet was made.
|
# Gets the client from where this tweet was made.
|
||||||
source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8")))
|
source = str(re.sub(r"(?s)<.*?>", "", tweet["source"].encode("utf-8")))
|
||||||
|
original_date = arrow.get(tweet["created_at"], "ddd MMM DD H:m:s Z YYYY", locale="en")
|
||||||
|
date = original_date.replace(seconds=utc_offset).format(_(u"MMM D, YYYY. H:m"), locale=languageHandler.getLanguage())
|
||||||
if text == "":
|
if text == "":
|
||||||
if tweet.has_key("message"):
|
if "message" in tweet:
|
||||||
value = "message"
|
value = "message"
|
||||||
else:
|
else:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
if tweet.has_key("message") == False:
|
if ("message" in tweet) == False:
|
||||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
|
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet["retweeted_status"]["full_text"])
|
||||||
else:
|
else:
|
||||||
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
text = "rt @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], tweet[value])
|
||||||
else:
|
else:
|
||||||
text = tweet[value]
|
text = tweet[value]
|
||||||
text = self.clear_text(text)
|
text = self.clear_text(text)
|
||||||
if tweet.has_key("extended_entities") and tweet["extended_entities"].has_key("media"):
|
if "extended_entities" in tweet and "media" in tweet["extended_entities"]:
|
||||||
for z in tweet["extended_entities"]["media"]:
|
for z in tweet["extended_entities"]["media"]:
|
||||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||||
image_description.append(z["ext_alt_text"])
|
image_description.append(z["ext_alt_text"])
|
||||||
if tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("extended_entities") and tweet["retweeted_status"]["extended_entities"].has_key("media"):
|
if "retweeted_status" in tweet and "extended_entities" in tweet["retweeted_status"] and "media" in tweet["retweeted_status"]["extended_entities"]:
|
||||||
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
|
for z in tweet["retweeted_status"]["extended_entities"]["media"]:
|
||||||
if z.has_key("ext_alt_text") and z["ext_alt_text"] != None:
|
if "ext_alt_text" in z and z["ext_alt_text"] != None:
|
||||||
image_description.append(z["ext_alt_text"])
|
image_description.append(z["ext_alt_text"])
|
||||||
self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8"))
|
self.message = message.viewTweet(text, rt_count, favs_count, source.decode("utf-8"), date)
|
||||||
self.message.set_title(len(text))
|
self.message.set_title(len(text))
|
||||||
[self.message.set_image_description(i) for i in image_description]
|
[self.message.set_image_description(i) for i in image_description]
|
||||||
else:
|
else:
|
||||||
self.title = _(u"View item")
|
self.title = _(u"View item")
|
||||||
text = tweet
|
text = tweet
|
||||||
self.message = message.viewNonTweet(text)
|
self.message = message.viewNonTweet(text, date)
|
||||||
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
widgetUtils.connect_event(self.message.spellcheck, widgetUtils.BUTTON_PRESSED, self.spellcheck)
|
||||||
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
widgetUtils.connect_event(self.message.translateButton, widgetUtils.BUTTON_PRESSED, self.translate)
|
||||||
if self.contain_urls() == True:
|
if self.contain_urls() == True:
|
||||||
|
@ -211,7 +211,7 @@ class accountSettingsController(globalSettingsController):
|
|||||||
else:
|
else:
|
||||||
self.config["general"]["retweet_mode"] = "comment"
|
self.config["general"]["retweet_mode"] = "comment"
|
||||||
buffers_list = self.dialog.buffers.get_list()
|
buffers_list = self.dialog.buffers.get_list()
|
||||||
if set(self.config["general"]["buffer_order"]) != set(buffers_list) or buffers_list != self.config["general"]["buffer_order"]:
|
if buffers_list != self.config["general"]["buffer_order"]:
|
||||||
self.needs_restart = True
|
self.needs_restart = True
|
||||||
self.config["general"]["buffer_order"] = buffers_list
|
self.config["general"]["buffer_order"] = buffers_list
|
||||||
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
self.config["reporting"]["speech_reporting"] = self.dialog.get_value("reporting", "speech_reporting")
|
||||||
@ -291,10 +291,14 @@ class accountSettingsController(globalSettingsController):
|
|||||||
all_buffers['muted']=_(u"Muted users")
|
all_buffers['muted']=_(u"Muted users")
|
||||||
list_buffers = []
|
list_buffers = []
|
||||||
hidden_buffers=[]
|
hidden_buffers=[]
|
||||||
for i in all_buffers.keys():
|
all_buffers_keys = all_buffers.keys()
|
||||||
if i in self.config["general"]["buffer_order"]:
|
# Check buffers shown first.
|
||||||
|
for i in self.config["general"]["buffer_order"]:
|
||||||
|
if i in all_buffers_keys:
|
||||||
list_buffers.append((i, all_buffers[i], True))
|
list_buffers.append((i, all_buffers[i], True))
|
||||||
else:
|
# This second pass will retrieve all hidden buffers.
|
||||||
|
for i in all_buffers_keys:
|
||||||
|
if i not in self.config["general"]["buffer_order"]:
|
||||||
hidden_buffers.append((i, all_buffers[i], False))
|
hidden_buffers.append((i, all_buffers[i], False))
|
||||||
list_buffers.extend(hidden_buffers)
|
list_buffers.extend(hidden_buffers)
|
||||||
return list_buffers
|
return list_buffers
|
||||||
|
@ -71,7 +71,7 @@ class userActionsController(object):
|
|||||||
|
|
||||||
def ignore_client(self, user):
|
def ignore_client(self, user):
|
||||||
tweet = self.buffer.get_right_tweet()
|
tweet = self.buffer.get_right_tweet()
|
||||||
if tweet.has_key("sender"):
|
if "sender" in tweet:
|
||||||
output.speak(_(u"You can't ignore direct messages"))
|
output.speak(_(u"You can't ignore direct messages"))
|
||||||
return
|
return
|
||||||
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
client = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||||
|
@ -16,10 +16,11 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
############################################################
|
############################################################
|
||||||
|
from __future__ import absolute_import
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import wx_ui
|
from . import wx_ui
|
||||||
import wx_transfer_dialogs
|
from . import wx_transfer_dialogs
|
||||||
import transfer
|
from . import transfer
|
||||||
import output
|
import output
|
||||||
import tempfile
|
import tempfile
|
||||||
import sound
|
import sound
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
from utils import convert_bytes
|
from .utils import convert_bytes
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
log = logging.getLogger("extra.AudioUploader.transfer")
|
log = logging.getLogger("extra.AudioUploader.transfer")
|
||||||
from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
|
from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
|
||||||
@ -75,9 +76,9 @@ class Upload(object):
|
|||||||
data = self.response.json()
|
data = self.response.json()
|
||||||
except:
|
except:
|
||||||
return _("Error in file upload: {0}").format(self.data.content,)
|
return _("Error in file upload: {0}").format(self.data.content,)
|
||||||
if data.has_key("url") and data["url"] != "0":
|
if "url" in data and data["url"] != "0":
|
||||||
return data["url"]
|
return data["url"]
|
||||||
elif data.has_key("error") and data["error"] != "0":
|
elif "error" in data and data["error"] != "0":
|
||||||
return data["error"]
|
return data["error"]
|
||||||
else:
|
else:
|
||||||
return _("Error in file upload: {0}").format(self.data.content,)
|
return _("Error in file upload: {0}").format(self.data.content,)
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from utils import *
|
from .utils import *
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
|
|
||||||
class UploadDialog(widgetUtils.BaseDialog):
|
class UploadDialog(widgetUtils.BaseDialog):
|
||||||
|
@ -1 +1,2 @@
|
|||||||
from soundsTutorial import soundsTutorial
|
from __future__ import absolute_import
|
||||||
|
from .soundsTutorial import soundsTutorial
|
||||||
|
@ -1,15 +1,16 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import os
|
import os
|
||||||
import paths
|
import paths
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
log = logging.getLogger("extra.SoundsTutorial.soundsTutorial")
|
||||||
import soundsTutorial_constants
|
from . import soundsTutorial_constants
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import wx_ui as UI
|
from . import wx_ui as UI
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
import gtk_ui as UI
|
from . import gtk_ui as UI
|
||||||
|
|
||||||
class soundsTutorial(object):
|
class soundsTutorial(object):
|
||||||
def __init__(self, sessionObject):
|
def __init__(self, sessionObject):
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#-*- coding: utf-8 -*-
|
#-*- coding: utf-8 -*-
|
||||||
import reverse_sort
|
from __future__ import absolute_import
|
||||||
|
#-*- coding: utf-8 -*-
|
||||||
|
from . import reverse_sort
|
||||||
import application
|
import application
|
||||||
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
actions = reverse_sort.reverse_sort([ ("audio", _(u"Audio tweet.")),
|
||||||
("create_timeline", _(u"User timeline buffer created.")),
|
("create_timeline", _(u"User timeline buffer created.")),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import spellchecker
|
from __future__ import absolute_import
|
||||||
|
from . import spellchecker
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from wx_ui import *
|
from .wx_ui import *
|
@ -1,14 +1,15 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import wx_ui
|
from . import wx_ui
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import output
|
import output
|
||||||
import config
|
import config
|
||||||
import languageHandler
|
import languageHandler
|
||||||
import enchant
|
import enchant
|
||||||
import paths
|
import paths
|
||||||
import twitterFilter
|
from . import twitterFilter
|
||||||
from enchant.checker import SpellChecker
|
from enchant.checker import SpellChecker
|
||||||
from enchant.errors import DictNotFoundError
|
from enchant.errors import DictNotFoundError
|
||||||
from enchant import tokenize
|
from enchant import tokenize
|
||||||
@ -52,7 +53,7 @@ class spellChecker(object):
|
|||||||
|
|
||||||
def check(self):
|
def check(self):
|
||||||
try:
|
try:
|
||||||
self.checker.next()
|
next(self.checker)
|
||||||
textToSay = _(u"Misspelled word: %s") % (self.checker.word,)
|
textToSay = _(u"Misspelled word: %s") % (self.checker.word,)
|
||||||
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
context = u"... %s %s %s" % (self.checker.leading_context(10), self.checker.word, self.checker.trailing_context(10))
|
||||||
self.dialog.set_title(textToSay)
|
self.dialog.set_title(textToSay)
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import completion, settings
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import completion, settings
|
@ -1,7 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import output
|
import output
|
||||||
import storage
|
from . import storage
|
||||||
import wx_menu
|
from . import wx_menu
|
||||||
|
|
||||||
class autocompletionUsers(object):
|
class autocompletionUsers(object):
|
||||||
def __init__(self, window, session_id):
|
def __init__(self, window, session_id):
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import storage
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import storage
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import wx_manage
|
from . import wx_manage
|
||||||
from wxUI import commonMessageDialogs
|
from wxUI import commonMessageDialogs
|
||||||
|
|
||||||
class autocompletionManage(object):
|
class autocompletionManage(object):
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import storage
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import storage
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import wx_settings
|
from . import wx_settings
|
||||||
import manage
|
from . import manage
|
||||||
import output
|
import output
|
||||||
from mysc.thread_utils import call_threaded
|
from mysc.thread_utils import call_threaded
|
||||||
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import OCRSpace
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import OCRSpace
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import translator
|
from __future__ import absolute_import
|
||||||
|
from . import translator
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import wx_ui as gui
|
from . import wx_ui as gui
|
||||||
|
|
@ -16,7 +16,26 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
############################################################
|
############################################################
|
||||||
import translator
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
############################################################
|
||||||
|
# Copyright (c) 2013, 2014 Manuel Eduardo Cortéz Vallejo <manuel@manuelcortez.net>
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation, either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
#
|
||||||
|
############################################################
|
||||||
|
from . import translator
|
||||||
import wx
|
import wx
|
||||||
from wxUI.dialogs import baseDialog
|
from wxUI.dialogs import baseDialog
|
||||||
|
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
""" This module contains some bugfixes for packages used in TWBlue."""
|
""" This module contains some bugfixes for packages used in TWBlue."""
|
||||||
|
from __future__ import absolute_import
|
||||||
import sys
|
import sys
|
||||||
import fix_arrow # A few new locales for Three languages in arrow.
|
from . import fix_arrow # A few new locales for Three languages in arrow.
|
||||||
import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
from . import fix_libloader # Regenerates comcache properly.
|
||||||
import fix_win32com
|
from . import fix_urllib3_warnings # Avoiding some SSL warnings related to Twython.
|
||||||
import fix_requests #fix cacert.pem location for TWBlue binary copies
|
from . import fix_win32com
|
||||||
|
from . import fix_requests #fix cacert.pem location for TWBlue binary copies
|
||||||
def setup():
|
def setup():
|
||||||
fix_arrow.fix()
|
fix_arrow.fix()
|
||||||
if hasattr(sys, "frozen"):
|
if hasattr(sys, "frozen"):
|
||||||
fix_win32com.fix()
|
fix_win32com.fix()
|
||||||
fix_requests.fix(True)
|
fix_requests.fix(True)
|
||||||
|
fix_libloader.fix()
|
||||||
else:
|
else:
|
||||||
fix_requests.fix(False)
|
fix_requests.fix(False)
|
||||||
fix_urllib3_warnings.fix()
|
fix_urllib3_warnings.fix()
|
36
src/fixes/fix_libloader.py
Normal file
36
src/fixes/fix_libloader.py
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import win32com
|
||||||
|
import paths
|
||||||
|
win32com.__gen_path__=paths.com_path()
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
||||||
|
from win32com.client import gencache
|
||||||
|
from pywintypes import com_error
|
||||||
|
from libloader import com
|
||||||
|
|
||||||
|
fixed=False
|
||||||
|
|
||||||
|
def patched_getmodule(modname):
|
||||||
|
mod=__import__(modname)
|
||||||
|
return sys.modules[modname]
|
||||||
|
|
||||||
|
def load_com(*names):
|
||||||
|
global fixed
|
||||||
|
if fixed==False:
|
||||||
|
gencache._GetModule=patched_getmodule
|
||||||
|
com.prepare_gencache()
|
||||||
|
fixed=True
|
||||||
|
result = None
|
||||||
|
for name in names:
|
||||||
|
try:
|
||||||
|
result = gencache.EnsureDispatch(name)
|
||||||
|
break
|
||||||
|
except com_error:
|
||||||
|
continue
|
||||||
|
if result is None:
|
||||||
|
raise com_error("Unable to load any of the provided com objects.")
|
||||||
|
return result
|
||||||
|
|
||||||
|
def fix():
|
||||||
|
com.load_com = load_com
|
@ -1,4 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from builtins import object
|
||||||
import application
|
import application
|
||||||
import platform
|
import platform
|
||||||
import exceptions
|
import exceptions
|
||||||
|
@ -1 +1,2 @@
|
|||||||
from keystrokeEditor import KeystrokeEditor
|
from __future__ import absolute_import
|
||||||
|
from .keystrokeEditor import KeystrokeEditor
|
@ -50,6 +50,7 @@ actions = {
|
|||||||
"check_for_updates": _(u"Check and download updates"),
|
"check_for_updates": _(u"Check and download updates"),
|
||||||
"lists_manager": _(u"Opens the list manager, which allows you to create, edit, delete and open lists in buffers."),
|
"lists_manager": _(u"Opens the list manager, which allows you to create, edit, delete and open lists in buffers."),
|
||||||
"configuration": _(u"Opens the global settings dialogue"),
|
"configuration": _(u"Opens the global settings dialogue"),
|
||||||
|
"list_manager": _(u"Opens the list manager"),
|
||||||
"accountConfiguration": _(u"Opens the account settings dialogue"),
|
"accountConfiguration": _(u"Opens the account settings dialogue"),
|
||||||
"audio": _(u"Try to play an audio file"),
|
"audio": _(u"Try to play an audio file"),
|
||||||
"update_buffer": _(u"Updates the buffer and retrieves possible lost items there."),
|
"update_buffer": _(u"Updates the buffer and retrieves possible lost items there."),
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import config
|
import config
|
||||||
import wx_ui
|
from . import wx_ui
|
||||||
import constants
|
from . import constants
|
||||||
from pubsub import pub
|
from pubsub import pub
|
||||||
|
|
||||||
class KeystrokeEditor(object):
|
class KeystrokeEditor(object):
|
||||||
|
@ -32,7 +32,7 @@ class keystrokeEditorDialog(baseDialog.BaseWXDialog):
|
|||||||
selection = self.keys.get_selected()
|
selection = self.keys.get_selected()
|
||||||
self.keys.clear()
|
self.keys.clear()
|
||||||
for i in keystrokes:
|
for i in keystrokes:
|
||||||
if actions.has_key(i) == False:
|
if (i in actions) == False:
|
||||||
continue
|
continue
|
||||||
action = actions[i]
|
action = actions[i]
|
||||||
self.actions.append(i)
|
self.actions.append(i)
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
from .libloader import *
|
|
||||||
|
|
||||||
__version__ = 0.1
|
|
||||||
__author__ = 'Christopher Toth <q@q-continuum.net>'
|
|
||||||
__doc__ = """
|
|
||||||
Quickly and easily load shared libraries from various platforms. Also includes a libloader.com module for loading com modules on Windows.
|
|
||||||
"""
|
|
@ -1,35 +0,0 @@
|
|||||||
from pywintypes import com_error
|
|
||||||
import win32com
|
|
||||||
import paths
|
|
||||||
win32com.__gen_path__=paths.com_path()
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
sys.path.append(os.path.join(win32com.__gen_path__, "."))
|
|
||||||
from win32com.client import gencache
|
|
||||||
fixed=False
|
|
||||||
|
|
||||||
def prepare_gencache():
|
|
||||||
gencache.is_readonly = False
|
|
||||||
gencache.GetGeneratePath()
|
|
||||||
|
|
||||||
def patched_getmodule(modname):
|
|
||||||
mod=__import__(modname)
|
|
||||||
return sys.modules[modname]
|
|
||||||
|
|
||||||
def load_com(*names):
|
|
||||||
global fixed
|
|
||||||
if fixed==False:
|
|
||||||
gencache._GetModule=patched_getmodule
|
|
||||||
prepare_gencache()
|
|
||||||
fixed=True
|
|
||||||
result = None
|
|
||||||
for name in names:
|
|
||||||
try:
|
|
||||||
result = gencache.EnsureDispatch(name)
|
|
||||||
break
|
|
||||||
except com_error:
|
|
||||||
continue
|
|
||||||
if result is None:
|
|
||||||
raise com_error("Unable to load any of the provided com objects.")
|
|
||||||
return result
|
|
||||||
|
|
@ -1,56 +0,0 @@
|
|||||||
import ctypes
|
|
||||||
import collections
|
|
||||||
import platform
|
|
||||||
import os
|
|
||||||
|
|
||||||
TYPES = {
|
|
||||||
'Linux': {
|
|
||||||
'loader': ctypes.CDLL,
|
|
||||||
'functype': ctypes.CFUNCTYPE,
|
|
||||||
'prefix': 'lib',
|
|
||||||
'extension': '.so'
|
|
||||||
},
|
|
||||||
'Darwin': {
|
|
||||||
'loader': ctypes.CDLL,
|
|
||||||
'functype': ctypes.CFUNCTYPE,
|
|
||||||
'prefix': 'lib',
|
|
||||||
'extension': '.dylib'
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
TYPES['Windows'] = {
|
|
||||||
'loader': ctypes.WinDLL,
|
|
||||||
'functype': ctypes.WINFUNCTYPE,
|
|
||||||
'prefix': "",
|
|
||||||
'extension': '.dll'
|
|
||||||
}
|
|
||||||
|
|
||||||
class LibraryLoadError(OSError): pass
|
|
||||||
|
|
||||||
def load_library(library, x86_path='.', x64_path='.', *args, **kwargs):
|
|
||||||
lib = find_library_path(library, x86_path=x86_path, x64_path=x64_path)
|
|
||||||
loaded = _do_load(str(lib), *args, **kwargs)
|
|
||||||
if loaded is not None:
|
|
||||||
return loaded
|
|
||||||
raise LibraryLoadError('unable to load %r. Provided library path: %r' % (library, lib))
|
|
||||||
|
|
||||||
def _do_load(file, *args, **kwargs):
|
|
||||||
loader = TYPES[platform.system()]['loader']
|
|
||||||
return loader(file, *args, **kwargs)
|
|
||||||
|
|
||||||
def find_library_path(libname, x86_path='.', x64_path='.'):
|
|
||||||
libname = '%s%s' % (TYPES[platform.system()]['prefix'], libname)
|
|
||||||
if platform.architecture()[0] == '64bit':
|
|
||||||
path = os.path.join(x64_path, libname)
|
|
||||||
else:
|
|
||||||
path = os.path.join(x86_path, libname)
|
|
||||||
ext = get_library_extension()
|
|
||||||
path = '%s%s' % (path, ext)
|
|
||||||
return os.path.abspath(path)
|
|
||||||
|
|
||||||
|
|
||||||
def get_functype():
|
|
||||||
return TYPES[platform.system()]['functype']
|
|
||||||
|
|
||||||
def get_library_extension():
|
|
||||||
return TYPES[platform.system()]['extension']
|
|
@ -1 +1,2 @@
|
|||||||
import widgets
|
from __future__ import absolute_import
|
||||||
|
from . import widgets
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
""" A cross platform notification system.
|
""" A cross platform notification system.
|
||||||
Under Linux, the wx.NotificationMessage does not show a notification on the taskbar, so we decided to use dbus for showing notifications for linux and wx for Windows."""
|
Under Linux, the wx.NotificationMessage does not show a notification on the taskbar, so we decided to use dbus for showing notifications for linux and wx for Windows."""
|
||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
|
|
||||||
notify = None
|
notify = None
|
||||||
@ -8,10 +9,10 @@ notify = None
|
|||||||
def setup():
|
def setup():
|
||||||
global notify
|
global notify
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import windows
|
from . import windows
|
||||||
notify = windows.notification()
|
notify = windows.notification()
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
import linux
|
from . import linux
|
||||||
notify = linux.notification()
|
notify = linux.notification()
|
||||||
|
|
||||||
def send(title, text):
|
def send(title, text):
|
||||||
|
@ -1,20 +1,21 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import shutil
|
import shutil
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
import platform
|
import platform
|
||||||
import output
|
import output
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
import wxUI as view
|
from . import wxUI as view
|
||||||
from controller import settings
|
from controller import settings
|
||||||
elif platform.system() == "Linux":
|
elif platform.system() == "Linux":
|
||||||
import gtkUI as view
|
from . import gtkUI as view
|
||||||
import paths
|
import paths
|
||||||
import time
|
import time
|
||||||
import os
|
import os
|
||||||
import logging
|
import logging
|
||||||
import sessions
|
import sessions
|
||||||
from sessions.twitter import session
|
from sessions.twitter import session
|
||||||
import manager
|
from . import manager
|
||||||
import config_utils
|
import config_utils
|
||||||
import config
|
import config
|
||||||
|
|
||||||
@ -77,7 +78,7 @@ class sessionManagerController(object):
|
|||||||
def do_ok(self):
|
def do_ok(self):
|
||||||
log.debug("Starting sessions...")
|
log.debug("Starting sessions...")
|
||||||
for i in self.sessions:
|
for i in self.sessions:
|
||||||
if sessions.sessions.has_key(i) == True: continue
|
if (i in sessions.sessions) == True: continue
|
||||||
s = session.Session(i)
|
s = session.Session(i)
|
||||||
s.get_configuration()
|
s.get_configuration()
|
||||||
if i not in config.app["sessions"]["ignored_sessions"]:
|
if i not in config.app["sessions"]["ignored_sessions"]:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
""" A base class to be derived in possible new sessions for TWBlue and services."""
|
""" A base class to be derived in possible new sessions for TWBlue and services."""
|
||||||
|
from __future__ import absolute_import
|
||||||
import paths
|
import paths
|
||||||
import output
|
import output
|
||||||
import time
|
import time
|
||||||
@ -9,7 +10,7 @@ import config_utils
|
|||||||
import shelve
|
import shelve
|
||||||
import application
|
import application
|
||||||
import os
|
import os
|
||||||
import session_exceptions as Exceptions
|
from . import session_exceptions as Exceptions
|
||||||
log = logging.getLogger("sessionmanager.session")
|
log = logging.getLogger("sessionmanager.session")
|
||||||
|
|
||||||
class baseSession(object):
|
class baseSession(object):
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
system = platform.system()
|
system = platform.system()
|
||||||
import utils
|
from . import utils
|
||||||
import re
|
import re
|
||||||
import htmlentitydefs
|
import htmlentitydefs
|
||||||
import time
|
import time
|
||||||
@ -10,7 +11,7 @@ import languageHandler
|
|||||||
import arrow
|
import arrow
|
||||||
import logging
|
import logging
|
||||||
import config
|
import config
|
||||||
from long_tweets import twishort, tweets
|
from .long_tweets import twishort, tweets
|
||||||
log = logging.getLogger("compose")
|
log = logging.getLogger("compose")
|
||||||
|
|
||||||
def StripChars(s):
|
def StripChars(s):
|
||||||
@ -38,13 +39,13 @@ def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=No
|
|||||||
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
||||||
else:
|
else:
|
||||||
ts = tweet["created_at"]
|
ts = tweet["created_at"]
|
||||||
if tweet.has_key("message"):
|
if "message" in tweet:
|
||||||
value = "message"
|
value = "message"
|
||||||
elif tweet.has_key("full_text"):
|
elif "full_text" in tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
if tweet.has_key("retweeted_status") and value != "message":
|
if "retweeted_status" in tweet and value != "message":
|
||||||
text = StripChars(tweet["retweeted_status"][value])
|
text = StripChars(tweet["retweeted_status"][value])
|
||||||
else:
|
else:
|
||||||
text = StripChars(tweet[value])
|
text = StripChars(tweet[value])
|
||||||
@ -53,16 +54,16 @@ def compose_tweet(tweet, db, relative_times, show_screen_names=False, session=No
|
|||||||
else:
|
else:
|
||||||
user = tweet["user"]["name"]
|
user = tweet["user"]["name"]
|
||||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
if tweet.has_key("message") == False and tweet["retweeted_status"]["is_quote_status"] == False:
|
if ("message" in tweet) == False and tweet["retweeted_status"]["is_quote_status"] == False:
|
||||||
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||||
elif tweet["retweeted_status"]["is_quote_status"]:
|
elif tweet["retweeted_status"]["is_quote_status"]:
|
||||||
text = "%s" % (text)
|
text = "%s" % (text)
|
||||||
else:
|
else:
|
||||||
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
text = "RT @%s: %s" % (tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||||
if tweet.has_key("message") == False:
|
if ("message" in tweet) == False:
|
||||||
urls = utils.find_urls_in_text(text)
|
urls = utils.find_urls_in_text(text)
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
for url in range(0, len(urls)):
|
for url in range(0, len(urls)):
|
||||||
try:
|
try:
|
||||||
text = text.replace(urls[url], tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"])
|
text = text.replace(urls[url], tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"])
|
||||||
@ -110,14 +111,14 @@ def compose_direct_message(item, db, relative_times, show_screen_names=False, se
|
|||||||
|
|
||||||
def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None):
|
def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False, session=None):
|
||||||
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
|
""" It receives a tweet and returns a list with the user, text for the tweet or message, date and the client where user is."""
|
||||||
if quoted_tweet.has_key("retweeted_status"):
|
if "retweeted_status" in quoted_tweet:
|
||||||
if quoted_tweet["retweeted_status"].has_key("full_text"):
|
if "full_text" in quoted_tweet["retweeted_status"]:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
text = StripChars(quoted_tweet["retweeted_status"][value])
|
text = StripChars(quoted_tweet["retweeted_status"][value])
|
||||||
else:
|
else:
|
||||||
if quoted_tweet.has_key("full_text"):
|
if "full_text" in quoted_tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
@ -127,13 +128,13 @@ def compose_quoted_tweet(quoted_tweet, original_tweet, show_screen_names=False,
|
|||||||
else:
|
else:
|
||||||
quoting_user = quoted_tweet["user"]["name"]
|
quoting_user = quoted_tweet["user"]["name"]
|
||||||
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
|
source = re.sub(r"(?s)<.*?>", "", quoted_tweet["source"])
|
||||||
if quoted_tweet.has_key("retweeted_status"):
|
if "retweeted_status" in quoted_tweet:
|
||||||
text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], text)
|
text = "rt @%s: %s" % (quoted_tweet["retweeted_status"]["user"]["screen_name"], text)
|
||||||
if text[-1] in chars: text=text+"."
|
if text[-1] in chars: text=text+"."
|
||||||
original_user = original_tweet["user"]["screen_name"]
|
original_user = original_tweet["user"]["screen_name"]
|
||||||
if original_tweet.has_key("message"):
|
if "message" in original_tweet:
|
||||||
original_text = original_tweet["message"]
|
original_text = original_tweet["message"]
|
||||||
elif original_tweet.has_key("full_text"):
|
elif "full_text" in original_tweet:
|
||||||
original_text = StripChars(original_tweet["full_text"])
|
original_text = StripChars(original_tweet["full_text"])
|
||||||
else:
|
else:
|
||||||
original_text = StripChars(original_tweet["text"])
|
original_text = StripChars(original_tweet["text"])
|
||||||
@ -151,7 +152,7 @@ def compose_followers_list(tweet, db, relative_times=True, show_screen_names=Fal
|
|||||||
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
ts = original_date.replace(seconds=db["utc_offset"]).format(_(u"dddd, MMMM D, YYYY H:m:s"), locale=languageHandler.getLanguage())
|
||||||
else:
|
else:
|
||||||
ts = tweet["created_at"]
|
ts = tweet["created_at"]
|
||||||
if tweet.has_key("status"):
|
if "status" in tweet:
|
||||||
if len(tweet["status"]) > 4 and system == "Windows":
|
if len(tweet["status"]) > 4 and system == "Windows":
|
||||||
original_date2 = arrow.get(tweet["status"]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
|
original_date2 = arrow.get(tweet["status"]["created_at"], "ddd MMM D H:m:s Z YYYY", locale="en")
|
||||||
if relative_times:
|
if relative_times:
|
||||||
|
@ -22,9 +22,9 @@ def is_long(tweet):
|
|||||||
""" Check if the passed tweet contains a quote in its metadata.
|
""" Check if the passed tweet contains a quote in its metadata.
|
||||||
tweet dict: a tweet dictionary.
|
tweet dict: a tweet dictionary.
|
||||||
returns True if a quote is detected, False otherwise."""
|
returns True if a quote is detected, False otherwise."""
|
||||||
if tweet.has_key("quoted_status_id") and tweet.has_key("quoted_status"):
|
if "quoted_status_id" in tweet and "quoted_status" in tweet:
|
||||||
return tweet["quoted_status_id"]
|
return tweet["quoted_status_id"]
|
||||||
elif tweet.has_key("retweeted_status") and tweet["retweeted_status"].has_key("quoted_status_id") and tweet["retweeted_status"].has_key("quoted_status"):
|
elif "retweeted_status" in tweet and "quoted_status_id" in tweet["retweeted_status"] and "quoted_status" in tweet["retweeted_status"]:
|
||||||
return tweet["retweeted_status"]["quoted_status_id"]
|
return tweet["retweeted_status"]["quoted_status_id"]
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ def clear_url(tweet):
|
|||||||
""" Reads data from a quoted tweet and removes the link to the Status from the tweet's text.
|
""" Reads data from a quoted tweet and removes the link to the Status from the tweet's text.
|
||||||
tweet dict: a tweet dictionary.
|
tweet dict: a tweet dictionary.
|
||||||
returns a tweet dictionary without the URL to the status ID in its text to display."""
|
returns a tweet dictionary without the URL to the status ID in its text to display."""
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
if tweet["retweeted_status"].has_key("full_text"):
|
if "full_text" in tweet["retweeted_status"]:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
@ -41,7 +41,7 @@ def clear_url(tweet):
|
|||||||
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
|
try: tweet["message"] = tweet["message"].replace(urls[-1], "")
|
||||||
except IndexError: pass
|
except IndexError: pass
|
||||||
else:
|
else:
|
||||||
if tweet.has_key("full_text"):
|
if "full_text" in tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
############################################################
|
############################################################
|
||||||
|
from __future__ import print_function
|
||||||
import logging
|
import logging
|
||||||
import requests
|
import requests
|
||||||
import keys
|
import keys
|
||||||
@ -47,7 +48,7 @@ def is_long(tweet):
|
|||||||
# see https://github.com/manuelcortez/TWBlue/issues/103
|
# see https://github.com/manuelcortez/TWBlue/issues/103
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass
|
pass
|
||||||
if long == False and tweet.has_key("retweeted_status"):
|
if long == False and "retweeted_status" in tweet:
|
||||||
for url in range(0, len(tweet["retweeted_status"]["entities"]["urls"])):
|
for url in range(0, len(tweet["retweeted_status"]["entities"]["urls"])):
|
||||||
try:
|
try:
|
||||||
if tweet["retweeted_status"]["entities"]["urls"][url] != None and "twishort.com" in tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]:
|
if tweet["retweeted_status"]["entities"]["urls"][url] != None and "twishort.com" in tweet["retweeted_status"]["entities"]["urls"][url]["expanded_url"]:
|
||||||
@ -97,5 +98,5 @@ def create_tweet(user_token, user_secret, text, media=0):
|
|||||||
try:
|
try:
|
||||||
return response.json()["text_to_tweet"]
|
return response.json()["text_to_tweet"]
|
||||||
except:
|
except:
|
||||||
print "There was a problem creating a long tweet"
|
print("There was a problem creating a long tweet")
|
||||||
return 0
|
return 0
|
@ -1,5 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
""" This is the main session needed to access all Twitter Features."""
|
""" This is the main session needed to access all Twitter Features."""
|
||||||
|
from __future__ import absolute_import
|
||||||
import os
|
import os
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
@ -15,7 +16,7 @@ from keys import keyring
|
|||||||
from sessions import base
|
from sessions import base
|
||||||
from sessions.twitter import utils, compose
|
from sessions.twitter import utils, compose
|
||||||
from sessions.twitter.long_tweets import tweets, twishort
|
from sessions.twitter.long_tweets import tweets, twishort
|
||||||
from wxUI import authorisationDialog
|
from .wxUI import authorisationDialog
|
||||||
|
|
||||||
log = logging.getLogger("sessions.twitterSession")
|
log = logging.getLogger("sessions.twitterSession")
|
||||||
|
|
||||||
@ -30,9 +31,9 @@ class Session(base.baseSession):
|
|||||||
returns the number of items that have been added in this execution"""
|
returns the number of items that have been added in this execution"""
|
||||||
num = 0
|
num = 0
|
||||||
last_id = None
|
last_id = None
|
||||||
if self.db.has_key(name) == False:
|
if (name in self.db) == False:
|
||||||
self.db[name] = []
|
self.db[name] = []
|
||||||
if self.db.has_key("users") == False:
|
if ("users" in self.db) == False:
|
||||||
self.db["users"] = {}
|
self.db["users"] = {}
|
||||||
if ignore_older and len(self.db[name]) > 0:
|
if ignore_older and len(self.db[name]) > 0:
|
||||||
if self.settings["general"]["reverse_timelines"] == False:
|
if self.settings["general"]["reverse_timelines"] == False:
|
||||||
@ -51,8 +52,8 @@ class Session(base.baseSession):
|
|||||||
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
if self.settings["general"]["reverse_timelines"] == False: self.db[name].append(i)
|
||||||
else: self.db[name].insert(0, i)
|
else: self.db[name].insert(0, i)
|
||||||
num = num+1
|
num = num+1
|
||||||
if i.has_key("user") == True:
|
if ("user" in i) == True:
|
||||||
if self.db["users"].has_key(i["user"]["id"]) == False:
|
if (i["user"]["id"] in self.db["users"]) == False:
|
||||||
self.db["users"][i["user"]["id"]] = i["user"]
|
self.db["users"][i["user"]["id"]] = i["user"]
|
||||||
return num
|
return num
|
||||||
|
|
||||||
@ -66,7 +67,7 @@ class Session(base.baseSession):
|
|||||||
if name == "direct_messages":
|
if name == "direct_messages":
|
||||||
return self.order_direct_messages(data)
|
return self.order_direct_messages(data)
|
||||||
num = 0
|
num = 0
|
||||||
if self.db.has_key(name) == False:
|
if (name in self.db) == False:
|
||||||
self.db[name] = {}
|
self.db[name] = {}
|
||||||
self.db[name]["items"] = []
|
self.db[name]["items"] = []
|
||||||
for i in data:
|
for i in data:
|
||||||
@ -82,12 +83,12 @@ class Session(base.baseSession):
|
|||||||
returns the number of incoming messages processed in this execution, and sends an event with data regarding amount of sent direct messages added."""
|
returns the number of incoming messages processed in this execution, and sends an event with data regarding amount of sent direct messages added."""
|
||||||
incoming = 0
|
incoming = 0
|
||||||
sent = 0
|
sent = 0
|
||||||
if self.db.has_key("direct_messages") == False:
|
if ("direct_messages" in self.db) == False:
|
||||||
self.db["direct_messages"] = {}
|
self.db["direct_messages"] = {}
|
||||||
self.db["direct_messages"]["items"] = []
|
self.db["direct_messages"]["items"] = []
|
||||||
for i in data:
|
for i in data:
|
||||||
if i["message_create"]["sender_id"] == self.db["user_id"]:
|
if i["message_create"]["sender_id"] == self.db["user_id"]:
|
||||||
if self.db.has_key("sent_direct_messages") and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
|
if "sent_direct_messages" in self.db and utils.find_item(i["id"], self.db["sent_direct_messages"]["items"]) == None:
|
||||||
if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i)
|
if self.settings["general"]["reverse_timelines"] == False: self.db["sent_direct_messages"]["items"].append(i)
|
||||||
else: self.db["sent_direct_messages"]["items"].insert(0, i)
|
else: self.db["sent_direct_messages"]["items"].insert(0, i)
|
||||||
sent = sent+1
|
sent = sent+1
|
||||||
@ -164,15 +165,24 @@ class Session(base.baseSession):
|
|||||||
users, dm bool: If any of these is set to True, the function will treat items as users or dm (they need different handling).
|
users, dm bool: If any of these is set to True, the function will treat items as users or dm (they need different handling).
|
||||||
name str: name of the database item to put new element in."""
|
name str: name of the database item to put new element in."""
|
||||||
results = []
|
results = []
|
||||||
|
if "cursor" in kwargs and kwargs["cursor"] == 0:
|
||||||
|
output.speak(_(u"There are no more items to retrieve in this buffer."))
|
||||||
|
return
|
||||||
data = getattr(self.twitter, update_function)(*args, **kwargs)
|
data = getattr(self.twitter, update_function)(*args, **kwargs)
|
||||||
if users == True:
|
if users == True:
|
||||||
if type(data) == dict and data.has_key("next_cursor"):
|
if type(data) == dict and "next_cursor" in data:
|
||||||
self.db[name]["cursor"] = data["next_cursor"]
|
if "next_cursor" in data: # There are more objects to retrieve.
|
||||||
|
self.db[name]["cursor"] = data["next_cursor"]
|
||||||
|
else: # Set cursor to 0, wich means no more items available.
|
||||||
|
self.db[name]["cursor"] = 0
|
||||||
for i in data["users"]: results.append(i)
|
for i in data["users"]: results.append(i)
|
||||||
elif type(data) == list:
|
elif type(data) == list:
|
||||||
results.extend(data[1:])
|
results.extend(data[1:])
|
||||||
elif dm == True:
|
elif dm == True:
|
||||||
self.db[name]["cursor"] = data["next_cursor"]
|
if "next_cursor" in data: # There are more objects to retrieve.
|
||||||
|
self.db[name]["cursor"] = data["next_cursor"]
|
||||||
|
else: # Set cursor to 0, wich means no more items available.
|
||||||
|
self.db[name]["cursor"] = 0
|
||||||
for i in data["events"]: results.append(i)
|
for i in data["events"]: results.append(i)
|
||||||
else:
|
else:
|
||||||
results.extend(data[1:])
|
results.extend(data[1:])
|
||||||
@ -197,6 +207,7 @@ class Session(base.baseSession):
|
|||||||
finished = True
|
finished = True
|
||||||
except TwythonError as e:
|
except TwythonError as e:
|
||||||
output.speak(e.message)
|
output.speak(e.message)
|
||||||
|
val = None
|
||||||
if e.error_code != 403 and e.error_code != 404:
|
if e.error_code != 403 and e.error_code != 404:
|
||||||
tries = tries+1
|
tries = tries+1
|
||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
@ -279,7 +290,7 @@ class Session(base.baseSession):
|
|||||||
name str: Name to save items to the database.
|
name str: Name to save items to the database.
|
||||||
function str: A function to get the items."""
|
function str: A function to get the items."""
|
||||||
last_id = -1
|
last_id = -1
|
||||||
if self.db.has_key(name):
|
if name in self.db:
|
||||||
try:
|
try:
|
||||||
if self.db[name][0]["id"] > self.db[name][-1]["id"]:
|
if self.db[name][0]["id"] > self.db[name][-1]["id"]:
|
||||||
last_id = self.db[name][0]["id"]
|
last_id = self.db[name][0]["id"]
|
||||||
@ -299,7 +310,7 @@ class Session(base.baseSession):
|
|||||||
returns number of items retrieved."""
|
returns number of items retrieved."""
|
||||||
items_ = []
|
items_ = []
|
||||||
try:
|
try:
|
||||||
if self.db[name].has_key("cursor") and get_previous:
|
if "cursor" in self.db[name] and get_previous:
|
||||||
cursor = self.db[name]["cursor"]
|
cursor = self.db[name]["cursor"]
|
||||||
else:
|
else:
|
||||||
cursor = -1
|
cursor = -1
|
||||||
@ -312,8 +323,10 @@ class Session(base.baseSession):
|
|||||||
tl[items].reverse()
|
tl[items].reverse()
|
||||||
num = self.order_cursored_buffer(name, tl[items])
|
num = self.order_cursored_buffer(name, tl[items])
|
||||||
# Recently, Twitter's new endpoints have cursor if there are more results.
|
# Recently, Twitter's new endpoints have cursor if there are more results.
|
||||||
if tl.has_key("next_cursor"):
|
if "next_cursor" in tl:
|
||||||
self.db[name]["cursor"] = tl["next_cursor"]
|
self.db[name]["cursor"] = tl["next_cursor"]
|
||||||
|
else:
|
||||||
|
self.db[name]["cursor"] = 0
|
||||||
return num
|
return num
|
||||||
|
|
||||||
def check_connection(self):
|
def check_connection(self):
|
||||||
@ -340,7 +353,7 @@ class Session(base.baseSession):
|
|||||||
def get_quoted_tweet(self, tweet):
|
def get_quoted_tweet(self, tweet):
|
||||||
""" Process a tweet and extract all information related to the quote."""
|
""" Process a tweet and extract all information related to the quote."""
|
||||||
quoted_tweet = tweet
|
quoted_tweet = tweet
|
||||||
if tweet.has_key("full_text"):
|
if "full_text" in tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
@ -348,16 +361,16 @@ class Session(base.baseSession):
|
|||||||
for url in range(0, len(urls)):
|
for url in range(0, len(urls)):
|
||||||
try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
try: quoted_tweet[value] = quoted_tweet[value].replace(urls[url], quoted_tweet["entities"]["urls"][url]["expanded_url"])
|
||||||
except IndexError: pass
|
except IndexError: pass
|
||||||
if quoted_tweet.has_key("quoted_status"):
|
if "quoted_status" in quoted_tweet:
|
||||||
original_tweet = quoted_tweet["quoted_status"]
|
original_tweet = quoted_tweet["quoted_status"]
|
||||||
elif quoted_tweet.has_key("retweeted_status") and quoted_tweet["retweeted_status"].has_key("quoted_status"):
|
elif "retweeted_status" in quoted_tweet and "quoted_status" in quoted_tweet["retweeted_status"]:
|
||||||
original_tweet = quoted_tweet["retweeted_status"]["quoted_status"]
|
original_tweet = quoted_tweet["retweeted_status"]["quoted_status"]
|
||||||
else:
|
else:
|
||||||
return quoted_tweet
|
return quoted_tweet
|
||||||
original_tweet = self.check_long_tweet(original_tweet)
|
original_tweet = self.check_long_tweet(original_tweet)
|
||||||
if original_tweet.has_key("full_text"):
|
if "full_text" in original_tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
elif original_tweet.has_key("message"):
|
elif "message" in original_tweet:
|
||||||
value = "message"
|
value = "message"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
@ -374,13 +387,13 @@ class Session(base.baseSession):
|
|||||||
long = twishort.is_long(tweet)
|
long = twishort.is_long(tweet)
|
||||||
if long != False and config.app["app-settings"]["handle_longtweets"]:
|
if long != False and config.app["app-settings"]["handle_longtweets"]:
|
||||||
message = twishort.get_full_text(long)
|
message = twishort.get_full_text(long)
|
||||||
if tweet.has_key("quoted_status"):
|
if "quoted_status" in tweet:
|
||||||
tweet["quoted_status"]["message"] = message
|
tweet["quoted_status"]["message"] = message
|
||||||
if tweet["quoted_status"]["message"] == False: return False
|
if tweet["quoted_status"]["message"] == False: return False
|
||||||
tweet["quoted_status"]["twishort"] = True
|
tweet["quoted_status"]["twishort"] = True
|
||||||
for i in tweet["quoted_status"]["entities"]["user_mentions"]:
|
for i in tweet["quoted_status"]["entities"]["user_mentions"]:
|
||||||
if "@%s" % (i["screen_name"]) not in tweet["quoted_status"]["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
if "@%s" % (i["screen_name"]) not in tweet["quoted_status"]["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
||||||
if tweet["quoted_status"].has_key("retweeted_status") and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
if "retweeted_status" in tweet["quoted_status"] and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||||
continue
|
continue
|
||||||
tweet["quoted_status"]["message"] = u"@%s %s" % (i["screen_name"], tweet["message"])
|
tweet["quoted_status"]["message"] = u"@%s %s" % (i["screen_name"], tweet["message"])
|
||||||
else:
|
else:
|
||||||
@ -389,7 +402,7 @@ class Session(base.baseSession):
|
|||||||
tweet["twishort"] = True
|
tweet["twishort"] = True
|
||||||
for i in tweet["entities"]["user_mentions"]:
|
for i in tweet["entities"]["user_mentions"]:
|
||||||
if "@%s" % (i["screen_name"]) not in tweet["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
if "@%s" % (i["screen_name"]) not in tweet["message"] and i["screen_name"] != tweet["user"]["screen_name"]:
|
||||||
if tweet.has_key("retweeted_status") and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
if "retweeted_status" in tweet and tweet["retweeted_status"]["user"]["screen_name"] == i["screen_name"]:
|
||||||
continue
|
continue
|
||||||
return tweet
|
return tweet
|
||||||
|
|
||||||
@ -397,7 +410,7 @@ class Session(base.baseSession):
|
|||||||
""" Returns an user object associated with an ID.
|
""" Returns an user object associated with an ID.
|
||||||
id str: User identifier, provided by Twitter.
|
id str: User identifier, provided by Twitter.
|
||||||
returns an user dict."""
|
returns an user dict."""
|
||||||
if self.db.has_key("users") == False or self.db["users"].has_key(id) == False:
|
if ("users" in self.db) == False or (id in self.db["users"]) == False:
|
||||||
user = self.twitter.show_user(id=id)
|
user = self.twitter.show_user(id=id)
|
||||||
self.db["users"][user["id_str"]] = user
|
self.db["users"][user["id_str"]] = user
|
||||||
return user
|
return user
|
||||||
@ -408,7 +421,7 @@ class Session(base.baseSession):
|
|||||||
""" Returns an user identifier associated with a screen_name.
|
""" Returns an user identifier associated with a screen_name.
|
||||||
screen_name str: User name, such as tw_blue2, provided by Twitter.
|
screen_name str: User name, such as tw_blue2, provided by Twitter.
|
||||||
returns an user ID."""
|
returns an user ID."""
|
||||||
if self.db.has_key("users") == False:
|
if ("users" in self.db) == False:
|
||||||
user = utils.if_user_exists(self.twitter, screen_name)
|
user = utils.if_user_exists(self.twitter, screen_name)
|
||||||
self.db["users"][user["id_str"]] = user
|
self.db["users"][user["id_str"]] = user
|
||||||
return user["id_str"]
|
return user["id_str"]
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import print_function
|
||||||
import url_shortener, re
|
import url_shortener, re
|
||||||
import output
|
import output
|
||||||
from twython import TwythonError
|
from twython import TwythonError
|
||||||
@ -24,32 +25,32 @@ def find_urls_in_text(text):
|
|||||||
def find_urls (tweet):
|
def find_urls (tweet):
|
||||||
urls = []
|
urls = []
|
||||||
# Let's add URLS from tweet entities.
|
# Let's add URLS from tweet entities.
|
||||||
if tweet.has_key("message_create"):
|
if "message_create" in tweet:
|
||||||
entities = tweet["message_create"]["message_data"]["entities"]
|
entities = tweet["message_create"]["message_data"]["entities"]
|
||||||
else:
|
else:
|
||||||
entities = tweet["entities"]
|
entities = tweet["entities"]
|
||||||
for i in entities["urls"]:
|
for i in entities["urls"]:
|
||||||
if i["expanded_url"] not in urls:
|
if i["expanded_url"] not in urls:
|
||||||
urls.append(i["expanded_url"])
|
urls.append(i["expanded_url"])
|
||||||
if tweet.has_key("quoted_status"):
|
if "quoted_status" in tweet:
|
||||||
for i in tweet["quoted_status"]["entities"]["urls"]:
|
for i in tweet["quoted_status"]["entities"]["urls"]:
|
||||||
if i["expanded_url"] not in urls:
|
if i["expanded_url"] not in urls:
|
||||||
urls.append(i["expanded_url"])
|
urls.append(i["expanded_url"])
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
for i in tweet["retweeted_status"]["entities"]["urls"]:
|
for i in tweet["retweeted_status"]["entities"]["urls"]:
|
||||||
if i["expanded_url"] not in urls:
|
if i["expanded_url"] not in urls:
|
||||||
urls.append(i["expanded_url"])
|
urls.append(i["expanded_url"])
|
||||||
if tweet["retweeted_status"].has_key("quoted_status"):
|
if "quoted_status" in tweet["retweeted_status"]:
|
||||||
for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]:
|
for i in tweet["retweeted_status"]["quoted_status"]["entities"]["urls"]:
|
||||||
if i["expanded_url"] not in urls:
|
if i["expanded_url"] not in urls:
|
||||||
urls.append(i["expanded_url"])
|
urls.append(i["expanded_url"])
|
||||||
if tweet.has_key("message"):
|
if "message" in tweet:
|
||||||
i = "message"
|
i = "message"
|
||||||
elif tweet.has_key("full_text"):
|
elif "full_text" in tweet:
|
||||||
i = "full_text"
|
i = "full_text"
|
||||||
else:
|
else:
|
||||||
i = "text"
|
i = "text"
|
||||||
if tweet.has_key("message_create"):
|
if "message_create" in tweet:
|
||||||
extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"])
|
extracted_urls = find_urls_in_text(tweet["message_create"]["message_data"]["text"])
|
||||||
else:
|
else:
|
||||||
extracted_urls = find_urls_in_text(tweet[i])
|
extracted_urls = find_urls_in_text(tweet[i])
|
||||||
@ -82,7 +83,7 @@ def is_audio(tweet):
|
|||||||
try:
|
try:
|
||||||
if len(find_urls(tweet)) < 1:
|
if len(find_urls(tweet)) < 1:
|
||||||
return False
|
return False
|
||||||
if tweet.has_key("message_create"):
|
if "message_create" in tweet:
|
||||||
entities = tweet["message_create"]["message_data"]["entities"]
|
entities = tweet["message_create"]["message_data"]["entities"]
|
||||||
else:
|
else:
|
||||||
entities = tweet["entities"]
|
entities = tweet["entities"]
|
||||||
@ -91,22 +92,22 @@ def is_audio(tweet):
|
|||||||
if i["text"] == "audio":
|
if i["text"] == "audio":
|
||||||
return True
|
return True
|
||||||
except IndexError:
|
except IndexError:
|
||||||
print tweet["entities"]["hashtags"]
|
print(tweet["entities"]["hashtags"])
|
||||||
log.exception("Exception while executing is_audio hashtag algorithm")
|
log.exception("Exception while executing is_audio hashtag algorithm")
|
||||||
|
|
||||||
def is_geocoded(tweet):
|
def is_geocoded(tweet):
|
||||||
if tweet.has_key("coordinates") and tweet["coordinates"] != None:
|
if "coordinates" in tweet and tweet["coordinates"] != None:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def is_media(tweet):
|
def is_media(tweet):
|
||||||
if tweet.has_key("message_create"):
|
if "message_create" in tweet:
|
||||||
entities = tweet["message_create"]["message_data"]["entities"]
|
entities = tweet["message_create"]["message_data"]["entities"]
|
||||||
else:
|
else:
|
||||||
entities = tweet["entities"]
|
entities = tweet["entities"]
|
||||||
if entities.has_key("media") == False:
|
if ("media" in entities) == False:
|
||||||
return False
|
return False
|
||||||
for i in entities["media"]:
|
for i in entities["media"]:
|
||||||
if i.has_key("type") and i["type"] == "photo":
|
if "type" in i and i["type"] == "photo":
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
@ -121,10 +122,10 @@ def get_all_mentioned(tweet, conf, field="screen_name"):
|
|||||||
|
|
||||||
def get_all_users(tweet, conf):
|
def get_all_users(tweet, conf):
|
||||||
string = []
|
string = []
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
string.append(tweet["user"]["screen_name"])
|
string.append(tweet["user"]["screen_name"])
|
||||||
tweet = tweet["retweeted_status"]
|
tweet = tweet["retweeted_status"]
|
||||||
if tweet.has_key("sender"):
|
if "sender" in tweet:
|
||||||
string.append(tweet["sender"]["screen_name"])
|
string.append(tweet["sender"]["screen_name"])
|
||||||
else:
|
else:
|
||||||
if tweet["user"]["screen_name"] != conf["user_name"]:
|
if tweet["user"]["screen_name"] != conf["user_name"]:
|
||||||
@ -161,16 +162,16 @@ def api_call(parent=None, call_name=None, preexec_message="", success="", succes
|
|||||||
|
|
||||||
def is_allowed(tweet, settings, buffer_name):
|
def is_allowed(tweet, settings, buffer_name):
|
||||||
clients = settings["twitter"]["ignored_clients"]
|
clients = settings["twitter"]["ignored_clients"]
|
||||||
if tweet.has_key("sender"): return True
|
if "sender" in tweet: return True
|
||||||
allowed = True
|
allowed = True
|
||||||
tweet_data = {}
|
tweet_data = {}
|
||||||
if tweet.has_key("retweeted_status"):
|
if "retweeted_status" in tweet:
|
||||||
tweet_data["retweet"] = True
|
tweet_data["retweet"] = True
|
||||||
if tweet["in_reply_to_status_id_str"] != None:
|
if tweet["in_reply_to_status_id_str"] != None:
|
||||||
tweet_data["reply"] = True
|
tweet_data["reply"] = True
|
||||||
if tweet.has_key("quoted_status"):
|
if "quoted_status" in tweet:
|
||||||
tweet_data["quote"] = True
|
tweet_data["quote"] = True
|
||||||
if tweet.has_key("retweeted_status"): tweet = tweet["retweeted_status"]
|
if "retweeted_status" in tweet: tweet = tweet["retweeted_status"]
|
||||||
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
source = re.sub(r"(?s)<.*?>", "", tweet["source"])
|
||||||
for i in clients:
|
for i in clients:
|
||||||
if i.lower() == source.lower():
|
if i.lower() == source.lower():
|
||||||
@ -178,7 +179,7 @@ def is_allowed(tweet, settings, buffer_name):
|
|||||||
return filter_tweet(tweet, tweet_data, settings, buffer_name)
|
return filter_tweet(tweet, tweet_data, settings, buffer_name)
|
||||||
|
|
||||||
def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
||||||
if tweet.has_key("full_text"):
|
if "full_text" in tweet:
|
||||||
value = "full_text"
|
value = "full_text"
|
||||||
else:
|
else:
|
||||||
value = "text"
|
value = "text"
|
||||||
@ -187,23 +188,23 @@ def filter_tweet(tweet, tweet_data, settings, buffer_name):
|
|||||||
regexp = settings["filters"][i]["regexp"]
|
regexp = settings["filters"][i]["regexp"]
|
||||||
word = settings["filters"][i]["word"]
|
word = settings["filters"][i]["word"]
|
||||||
# Added if/else for compatibility reasons.
|
# Added if/else for compatibility reasons.
|
||||||
if settings["filters"][i].has_key("allow_rts"):
|
if "allow_rts" in settings["filters"][i]:
|
||||||
allow_rts = settings["filters"][i]["allow_rts"]
|
allow_rts = settings["filters"][i]["allow_rts"]
|
||||||
else:
|
else:
|
||||||
allow_rts = "True"
|
allow_rts = "True"
|
||||||
if settings["filters"][i].has_key("allow_quotes"):
|
if "allow_quotes" in settings["filters"][i]:
|
||||||
allow_quotes = settings["filters"][i]["allow_quotes"]
|
allow_quotes = settings["filters"][i]["allow_quotes"]
|
||||||
else:
|
else:
|
||||||
allow_quotes = "True"
|
allow_quotes = "True"
|
||||||
if settings["filters"][i].has_key("allow_replies"):
|
if "allow_replies" in settings["filters"][i]:
|
||||||
allow_replies = settings["filters"][i]["allow_replies"]
|
allow_replies = settings["filters"][i]["allow_replies"]
|
||||||
else:
|
else:
|
||||||
allow_replies = "True"
|
allow_replies = "True"
|
||||||
if allow_rts == "False" and tweet_data.has_key("retweet"):
|
if allow_rts == "False" and "retweet" in tweet_data:
|
||||||
return False
|
return False
|
||||||
if allow_quotes == "False" and tweet_data.has_key("quote"):
|
if allow_quotes == "False" and "quote" in tweet_data:
|
||||||
return False
|
return False
|
||||||
if allow_replies == "False" and tweet_data.has_key("reply"):
|
if allow_replies == "False" and "reply" in tweet_data:
|
||||||
return False
|
return False
|
||||||
if word != "" and settings["filters"][i]["if_word_exists"]:
|
if word != "" and settings["filters"][i]["if_word_exists"]:
|
||||||
if word in tweet[value]:
|
if word in tweet[value]:
|
||||||
|
@ -112,7 +112,7 @@ data_files = get_data(),
|
|||||||
options = {
|
options = {
|
||||||
'py2exe': {
|
'py2exe': {
|
||||||
'optimize':2,
|
'optimize':2,
|
||||||
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash"],
|
'packages': ["pubsub", "pubsub.core", "pubsub.core.kwargs", "dbhash", "oauthlib.oauth1.rfc5849.endpoints.resource", "oauthlib.oauth2.rfc6749.endpoints.resource"],
|
||||||
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
|
'dll_excludes': ["MPR.dll", "api-ms-win-core-apiquery-l1-1-0.dll", "api-ms-win-core-console-l1-1-0.dll", "api-ms-win-core-delayload-l1-1-1.dll", "api-ms-win-core-errorhandling-l1-1-1.dll", "api-ms-win-core-file-l1-2-0.dll", "api-ms-win-core-handle-l1-1-0.dll", "api-ms-win-core-heap-obsolete-l1-1-0.dll", "api-ms-win-core-libraryloader-l1-1-1.dll", "api-ms-win-core-localization-l1-2-0.dll", "api-ms-win-core-processenvironment-l1-2-0.dll", "api-ms-win-core-processthreads-l1-1-1.dll", "api-ms-win-core-profile-l1-1-0.dll", "api-ms-win-core-registry-l1-1-0.dll", "api-ms-win-core-synch-l1-2-0.dll", "api-ms-win-core-sysinfo-l1-2-0.dll", "api-ms-win-security-base-l1-2-0.dll", "api-ms-win-core-heap-l1-2-0.dll", "api-ms-win-core-interlocked-l1-2-0.dll", "api-ms-win-core-localization-obsolete-l1-1-0.dll", "api-ms-win-core-string-l1-1-0.dll", "api-ms-win-core-string-obsolete-l1-1-0.dll", "WLDAP32.dll", "MSVCP90.dll", "CRYPT32.dll", "mfc90.dll"],
|
||||||
'compressed': True
|
'compressed': True
|
||||||
},
|
},
|
||||||
|
BIN
src/sounds/FreakyBlue/Image.ogg
Normal file
BIN
src/sounds/FreakyBlue/Image.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/audio.ogg
Normal file
BIN
src/sounds/FreakyBlue/audio.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/create_timeline.ogg
Normal file
BIN
src/sounds/FreakyBlue/create_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/delete_timeline.ogg
Normal file
BIN
src/sounds/FreakyBlue/delete_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/dm_received.ogg
Normal file
BIN
src/sounds/FreakyBlue/dm_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/dm_sent.ogg
Normal file
BIN
src/sounds/FreakyBlue/dm_sent.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/error.ogg
Normal file
BIN
src/sounds/FreakyBlue/error.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/favourite.ogg
Normal file
BIN
src/sounds/FreakyBlue/favourite.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/favourites_timeline_updated.ogg
Normal file
BIN
src/sounds/FreakyBlue/favourites_timeline_updated.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/geo.ogg
Normal file
BIN
src/sounds/FreakyBlue/geo.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/limit.ogg
Normal file
BIN
src/sounds/FreakyBlue/limit.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/list_tweet.ogg
Normal file
BIN
src/sounds/FreakyBlue/list_tweet.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/max_length.ogg
Normal file
BIN
src/sounds/FreakyBlue/max_length.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/mention_received.ogg
Normal file
BIN
src/sounds/FreakyBlue/mention_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/new_event.ogg
Normal file
BIN
src/sounds/FreakyBlue/new_event.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/ready.ogg
Normal file
BIN
src/sounds/FreakyBlue/ready.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/reply_send.ogg
Normal file
BIN
src/sounds/FreakyBlue/reply_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/retweet_send.ogg
Normal file
BIN
src/sounds/FreakyBlue/retweet_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/search_updated.ogg
Normal file
BIN
src/sounds/FreakyBlue/search_updated.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/trends_updated.ogg
Normal file
BIN
src/sounds/FreakyBlue/trends_updated.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/tweet_received.ogg
Normal file
BIN
src/sounds/FreakyBlue/tweet_received.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/tweet_send.ogg
Normal file
BIN
src/sounds/FreakyBlue/tweet_send.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/tweet_timeline.ogg
Normal file
BIN
src/sounds/FreakyBlue/tweet_timeline.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/update_followers.ogg
Normal file
BIN
src/sounds/FreakyBlue/update_followers.ogg
Normal file
Binary file not shown.
BIN
src/sounds/FreakyBlue/volume_changed.ogg
Normal file
BIN
src/sounds/FreakyBlue/volume_changed.ogg
Normal file
Binary file not shown.
@ -1,29 +0,0 @@
|
|||||||
# ______ __ __
|
|
||||||
# /_ __/_ __ __ __ / /_ / /_ ____ ____
|
|
||||||
# / / | | /| / // / / // __// __ \ / __ \ / __ \
|
|
||||||
# / / | |/ |/ // /_/ // /_ / / / // /_/ // / / /
|
|
||||||
# /_/ |__/|__/ \__, / \__//_/ /_/ \____//_/ /_/
|
|
||||||
# /____/
|
|
||||||
|
|
||||||
"""
|
|
||||||
Twython
|
|
||||||
-------
|
|
||||||
|
|
||||||
Twython is a library for Python that wraps the Twitter API.
|
|
||||||
|
|
||||||
It aims to abstract away all the API endpoints, so that
|
|
||||||
additions to the library and/or the Twitter API won't
|
|
||||||
cause any overall problems.
|
|
||||||
|
|
||||||
Questions, comments? ryan@venodesigns.net
|
|
||||||
"""
|
|
||||||
|
|
||||||
__author__ = 'Ryan McGrath <ryan@venodesigns.net>'
|
|
||||||
__version__ = '3.6.0'
|
|
||||||
|
|
||||||
from .api import Twython
|
|
||||||
from .streaming import TwythonStreamer
|
|
||||||
from .exceptions import (
|
|
||||||
TwythonError, TwythonRateLimitError, TwythonAuthError,
|
|
||||||
TwythonStreamError
|
|
||||||
)
|
|
@ -1,22 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.advisory
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains Warning classes for Twython to specifically
|
|
||||||
alert the user about.
|
|
||||||
|
|
||||||
This mainly is because Python 2.7 > mutes DeprecationWarning and when
|
|
||||||
we deprecate a method or variable in Twython, we want to use to see
|
|
||||||
the Warning but don't want ALL DeprecationWarnings to appear,
|
|
||||||
only TwythonDeprecationWarnings.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonDeprecationWarning(DeprecationWarning):
|
|
||||||
"""Custom DeprecationWarning to be raised when methods/variables
|
|
||||||
are being deprecated in Twython. Python 2.7 > ignores DeprecationWarning
|
|
||||||
so we want to specifcally bubble up ONLY Twython Deprecation Warnings
|
|
||||||
"""
|
|
||||||
pass
|
|
@ -1,687 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.api
|
|
||||||
~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains functionality for access to core Twitter API calls,
|
|
||||||
Twitter Authentication, and miscellaneous methods that are useful when
|
|
||||||
dealing with the Twitter API
|
|
||||||
"""
|
|
||||||
|
|
||||||
import warnings
|
|
||||||
import re
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from requests.auth import HTTPBasicAuth
|
|
||||||
from requests_oauthlib import OAuth1, OAuth2
|
|
||||||
|
|
||||||
from . import __version__
|
|
||||||
from .advisory import TwythonDeprecationWarning
|
|
||||||
from .compat import json, urlencode, parse_qsl, quote_plus, str, is_py2
|
|
||||||
from .endpoints import EndpointsMixin
|
|
||||||
from .exceptions import TwythonError, TwythonAuthError, TwythonRateLimitError
|
|
||||||
from .helpers import _transparent_params
|
|
||||||
|
|
||||||
warnings.simplefilter('always', TwythonDeprecationWarning) # For Python 2.7 >
|
|
||||||
|
|
||||||
|
|
||||||
class Twython(EndpointsMixin, object):
|
|
||||||
def __init__(self, app_key=None, app_secret=None, oauth_token=None,
|
|
||||||
oauth_token_secret=None, access_token=None,
|
|
||||||
token_type='bearer', oauth_version=1, api_version='1.1',
|
|
||||||
client_args=None, auth_endpoint='authenticate'):
|
|
||||||
"""Instantiates an instance of Twython. Takes optional parameters for
|
|
||||||
authentication and such (see below).
|
|
||||||
|
|
||||||
:param app_key: (optional) Your applications key
|
|
||||||
:param app_secret: (optional) Your applications secret key
|
|
||||||
:param oauth_token: (optional) When using **OAuth 1**, combined with
|
|
||||||
oauth_token_secret to make authenticated calls
|
|
||||||
:param oauth_token_secret: (optional) When using **OAuth 1** combined
|
|
||||||
with oauth_token to make authenticated calls
|
|
||||||
:param access_token: (optional) When using **OAuth 2**, provide a
|
|
||||||
valid access token if you have one
|
|
||||||
:param token_type: (optional) When using **OAuth 2**, provide your
|
|
||||||
token type. Default: bearer
|
|
||||||
:param oauth_version: (optional) Choose which OAuth version to use.
|
|
||||||
Default: 1
|
|
||||||
:param api_version: (optional) Choose which Twitter API version to
|
|
||||||
use. Default: 1.1
|
|
||||||
|
|
||||||
:param client_args: (optional) Accepts some requests Session parameters
|
|
||||||
and some requests Request parameters.
|
|
||||||
See http://docs.python-requests.org/en/latest/api/#sessionapi
|
|
||||||
and requests section below it for details.
|
|
||||||
[ex. headers, proxies, verify(SSL verification)]
|
|
||||||
:param auth_endpoint: (optional) Lets you select which authentication
|
|
||||||
endpoint will use your application.
|
|
||||||
This will allow the application to have DM access
|
|
||||||
if the endpoint is 'authorize'.
|
|
||||||
Default: authenticate.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# API urls, OAuth urls and API version; needed for hitting that there
|
|
||||||
# API.
|
|
||||||
self.api_version = api_version
|
|
||||||
self.api_url = 'https://api.twitter.com/%s'
|
|
||||||
|
|
||||||
self.app_key = app_key
|
|
||||||
self.app_secret = app_secret
|
|
||||||
self.oauth_token = oauth_token
|
|
||||||
self.oauth_token_secret = oauth_token_secret
|
|
||||||
self.access_token = access_token
|
|
||||||
|
|
||||||
# OAuth 1
|
|
||||||
self.request_token_url = self.api_url % 'oauth/request_token'
|
|
||||||
self.access_token_url = self.api_url % 'oauth/access_token'
|
|
||||||
self.authenticate_url = self.api_url % ('oauth/%s' % auth_endpoint)
|
|
||||||
|
|
||||||
if self.access_token: # If they pass an access token, force OAuth 2
|
|
||||||
oauth_version = 2
|
|
||||||
|
|
||||||
self.oauth_version = oauth_version
|
|
||||||
|
|
||||||
# OAuth 2
|
|
||||||
if oauth_version == 2:
|
|
||||||
self.request_token_url = self.api_url % 'oauth2/token'
|
|
||||||
|
|
||||||
self.client_args = client_args or {}
|
|
||||||
default_headers = {'User-Agent': 'Twython v' + __version__}
|
|
||||||
if 'headers' not in self.client_args:
|
|
||||||
# If they didn't set any headers, set our defaults for them
|
|
||||||
self.client_args['headers'] = default_headers
|
|
||||||
elif 'User-Agent' not in self.client_args['headers']:
|
|
||||||
# If they set headers, but didn't include User-Agent.. set
|
|
||||||
# it for them
|
|
||||||
self.client_args['headers'].update(default_headers)
|
|
||||||
|
|
||||||
# Generate OAuth authentication object for the request
|
|
||||||
# If no keys/tokens are passed to __init__, auth=None allows for
|
|
||||||
# unauthenticated requests, although I think all v1.1 requests
|
|
||||||
# need auth
|
|
||||||
auth = None
|
|
||||||
if oauth_version == 1:
|
|
||||||
# User Authentication is through OAuth 1
|
|
||||||
if self.app_key is not None and self.app_secret is not None:
|
|
||||||
auth = OAuth1(self.app_key, self.app_secret,
|
|
||||||
self.oauth_token, self.oauth_token_secret)
|
|
||||||
|
|
||||||
elif oauth_version == 2 and self.access_token:
|
|
||||||
# Application Authentication is through OAuth 2
|
|
||||||
token = {'token_type': token_type,
|
|
||||||
'access_token': self.access_token}
|
|
||||||
auth = OAuth2(self.app_key, token=token)
|
|
||||||
|
|
||||||
self.client = requests.Session()
|
|
||||||
self.client.auth = auth
|
|
||||||
|
|
||||||
# Make a copy of the client args and iterate over them
|
|
||||||
# Pop out all the acceptable args at this point because they will
|
|
||||||
# Never be used again.
|
|
||||||
client_args_copy = self.client_args.copy()
|
|
||||||
for k, v in client_args_copy.items():
|
|
||||||
if k in ('cert', 'hooks', 'max_redirects', 'proxies'):
|
|
||||||
setattr(self.client, k, v)
|
|
||||||
self.client_args.pop(k) # Pop, pop!
|
|
||||||
|
|
||||||
# Headers are always present, so we unconditionally pop them and merge
|
|
||||||
# them into the session headers.
|
|
||||||
self.client.headers.update(self.client_args.pop('headers'))
|
|
||||||
|
|
||||||
self._last_call = None
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return '<Twython: %s>' % (self.app_key)
|
|
||||||
|
|
||||||
def _request(self, url, method='GET', params=None, api_call=None, encode_json=False):
|
|
||||||
"""Internal request method"""
|
|
||||||
method = method.lower()
|
|
||||||
params = params or {}
|
|
||||||
|
|
||||||
func = getattr(self.client, method)
|
|
||||||
if type(params) is dict and encode_json == False:
|
|
||||||
params, files = _transparent_params(params)
|
|
||||||
else:
|
|
||||||
params = params
|
|
||||||
files = list()
|
|
||||||
|
|
||||||
requests_args = {}
|
|
||||||
for k, v in self.client_args.items():
|
|
||||||
# Maybe this should be set as a class variable and only done once?
|
|
||||||
if k in ('timeout', 'allow_redirects', 'stream', 'verify'):
|
|
||||||
requests_args[k] = v
|
|
||||||
|
|
||||||
if method == 'get':
|
|
||||||
requests_args['params'] = params
|
|
||||||
else:
|
|
||||||
|
|
||||||
if encode_json == False:
|
|
||||||
requests_args.update({
|
|
||||||
'files': files,
|
|
||||||
'data': params,
|
|
||||||
})
|
|
||||||
else:
|
|
||||||
requests_args.update({
|
|
||||||
'json': params,
|
|
||||||
})
|
|
||||||
try:
|
|
||||||
response = func(url, **requests_args)
|
|
||||||
except requests.RequestException as e:
|
|
||||||
raise TwythonError(str(e))
|
|
||||||
|
|
||||||
# create stash for last function intel
|
|
||||||
self._last_call = {
|
|
||||||
'api_call': api_call,
|
|
||||||
'api_error': None,
|
|
||||||
'cookies': response.cookies,
|
|
||||||
'headers': response.headers,
|
|
||||||
'status_code': response.status_code,
|
|
||||||
'url': response.url,
|
|
||||||
'content': response.text,
|
|
||||||
}
|
|
||||||
|
|
||||||
# greater than 304 (not modified) is an error
|
|
||||||
if response.status_code > 304:
|
|
||||||
error_message = self._get_error_message(response)
|
|
||||||
self._last_call['api_error'] = error_message
|
|
||||||
|
|
||||||
ExceptionType = TwythonError
|
|
||||||
if response.status_code == 429:
|
|
||||||
# Twitter API 1.1, always return 429 when
|
|
||||||
# rate limit is exceeded
|
|
||||||
ExceptionType = TwythonRateLimitError
|
|
||||||
elif response.status_code == 401 or 'Bad Authentication data' \
|
|
||||||
in error_message:
|
|
||||||
# Twitter API 1.1, returns a 401 Unauthorized or
|
|
||||||
# a 400 "Bad Authentication data" for invalid/expired
|
|
||||||
# app keys/user tokens
|
|
||||||
ExceptionType = TwythonAuthError
|
|
||||||
|
|
||||||
raise ExceptionType(
|
|
||||||
error_message,
|
|
||||||
error_code=response.status_code,
|
|
||||||
retry_after=response.headers.get('X-Rate-Limit-Reset'))
|
|
||||||
content=""
|
|
||||||
try:
|
|
||||||
if response.status_code == 204:
|
|
||||||
content = response.content
|
|
||||||
else:
|
|
||||||
content = response.json()
|
|
||||||
except ValueError:
|
|
||||||
if response.content!="":
|
|
||||||
raise TwythonError('Response was not valid JSON. \
|
|
||||||
Unable to decode.')
|
|
||||||
|
|
||||||
return content
|
|
||||||
|
|
||||||
def _get_error_message(self, response):
|
|
||||||
"""Parse and return the first error message"""
|
|
||||||
|
|
||||||
error_message = 'An error occurred processing your request.'
|
|
||||||
try:
|
|
||||||
content = response.json()
|
|
||||||
# {"errors":[{"code":34,"message":"Sorry,
|
|
||||||
# that page does not exist"}]}
|
|
||||||
error_message = content['errors'][0]['message']
|
|
||||||
except TypeError:
|
|
||||||
error_message = content['errors']
|
|
||||||
except ValueError:
|
|
||||||
# bad json data from Twitter for an error
|
|
||||||
pass
|
|
||||||
except (KeyError, IndexError):
|
|
||||||
# missing data so fallback to default message
|
|
||||||
pass
|
|
||||||
|
|
||||||
return error_message
|
|
||||||
|
|
||||||
def request(self, endpoint, method='GET', params=None, version='1.1', encode_json=False):
|
|
||||||
"""Return dict of response received from Twitter's API
|
|
||||||
|
|
||||||
:param endpoint: (required) Full url or Twitter API endpoint
|
|
||||||
(e.g. search/tweets)
|
|
||||||
:type endpoint: string
|
|
||||||
:param method: (optional) Method of accessing data, either
|
|
||||||
GET or POST. (default GET)
|
|
||||||
:type method: string
|
|
||||||
:param params: (optional) Dict of parameters (if any) accepted
|
|
||||||
the by Twitter API endpoint you are trying to
|
|
||||||
access (default None)
|
|
||||||
:type params: dict or None
|
|
||||||
:param version: (optional) Twitter API version to access
|
|
||||||
(default 1.1)
|
|
||||||
:type version: string
|
|
||||||
|
|
||||||
:rtype: dict
|
|
||||||
"""
|
|
||||||
|
|
||||||
if endpoint.startswith('http://'):
|
|
||||||
raise TwythonError('api.twitter.com is restricted to SSL/TLS traffic.')
|
|
||||||
|
|
||||||
# In case they want to pass a full Twitter URL
|
|
||||||
# i.e. https://api.twitter.com/1.1/search/tweets.json
|
|
||||||
if endpoint.startswith('https://'):
|
|
||||||
url = endpoint
|
|
||||||
else:
|
|
||||||
url = '%s/%s.json' % (self.api_url % version, endpoint)
|
|
||||||
|
|
||||||
content = self._request(url, method=method, params=params,
|
|
||||||
api_call=url, encode_json=encode_json)
|
|
||||||
|
|
||||||
return content
|
|
||||||
|
|
||||||
def get(self, endpoint, params=None, version='1.1'):
|
|
||||||
"""Shortcut for GET requests via :class:`request`"""
|
|
||||||
return self.request(endpoint, params=params, version=version)
|
|
||||||
|
|
||||||
def post(self, endpoint, params=None, version='1.1', encode_json=False):
|
|
||||||
"""Shortcut for POST requests via :class:`request`"""
|
|
||||||
return self.request(endpoint, 'POST', params=params, version=version, encode_json=encode_json)
|
|
||||||
|
|
||||||
def get_lastfunction_header(self, header, default_return_value=None):
|
|
||||||
"""Returns a specific header from the last API call
|
|
||||||
This will return None if the header is not present
|
|
||||||
|
|
||||||
:param header: (required) The name of the header you want to get
|
|
||||||
the value of
|
|
||||||
|
|
||||||
Most useful for the following header information:
|
|
||||||
x-rate-limit-limit,
|
|
||||||
x-rate-limit-remaining,
|
|
||||||
x-rate-limit-class,
|
|
||||||
x-rate-limit-reset
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self._last_call is None:
|
|
||||||
raise TwythonError('This function must be called after an API call. \
|
|
||||||
It delivers header information.')
|
|
||||||
|
|
||||||
return self._last_call['headers'].get(header, default_return_value)
|
|
||||||
|
|
||||||
def get_authentication_tokens(self, callback_url=None, force_login=False,
|
|
||||||
screen_name=''):
|
|
||||||
"""Returns a dict including an authorization URL, ``auth_url``, to
|
|
||||||
direct a user to
|
|
||||||
|
|
||||||
:param callback_url: (optional) Url the user is returned to after
|
|
||||||
they authorize your app (web clients only)
|
|
||||||
:param force_login: (optional) Forces the user to enter their
|
|
||||||
credentials to ensure the correct users
|
|
||||||
account is authorized.
|
|
||||||
:param screen_name: (optional) If forced_login is set OR user is
|
|
||||||
not currently logged in, Prefills the username
|
|
||||||
input box of the OAuth login screen with the
|
|
||||||
given value
|
|
||||||
|
|
||||||
:rtype: dict
|
|
||||||
"""
|
|
||||||
if self.oauth_version != 1:
|
|
||||||
raise TwythonError('This method can only be called when your \
|
|
||||||
OAuth version is 1.0.')
|
|
||||||
|
|
||||||
request_args = {}
|
|
||||||
if callback_url:
|
|
||||||
request_args['oauth_callback'] = callback_url
|
|
||||||
response = self.client.get(self.request_token_url, params=request_args)
|
|
||||||
|
|
||||||
if response.status_code == 401:
|
|
||||||
raise TwythonAuthError(response.content,
|
|
||||||
error_code=response.status_code)
|
|
||||||
elif response.status_code != 200:
|
|
||||||
raise TwythonError(response.content,
|
|
||||||
error_code=response.status_code)
|
|
||||||
|
|
||||||
request_tokens = dict(parse_qsl(response.content.decode('utf-8')))
|
|
||||||
if not request_tokens:
|
|
||||||
raise TwythonError('Unable to decode request tokens.')
|
|
||||||
|
|
||||||
oauth_callback_confirmed = request_tokens.get('oauth_callback_confirmed') \
|
|
||||||
== 'true'
|
|
||||||
|
|
||||||
auth_url_params = {
|
|
||||||
'oauth_token': request_tokens['oauth_token'],
|
|
||||||
}
|
|
||||||
|
|
||||||
if force_login:
|
|
||||||
auth_url_params.update({
|
|
||||||
'force_login': force_login,
|
|
||||||
'screen_name': screen_name
|
|
||||||
})
|
|
||||||
|
|
||||||
# Use old-style callback argument if server didn't accept new-style
|
|
||||||
if callback_url and not oauth_callback_confirmed:
|
|
||||||
auth_url_params['oauth_callback'] = self.callback_url
|
|
||||||
|
|
||||||
request_tokens['auth_url'] = self.authenticate_url + \
|
|
||||||
'?' + urlencode(auth_url_params)
|
|
||||||
|
|
||||||
return request_tokens
|
|
||||||
|
|
||||||
def get_authorized_tokens(self, oauth_verifier):
|
|
||||||
"""Returns a dict of authorized tokens after they go through the
|
|
||||||
:class:`get_authentication_tokens` phase.
|
|
||||||
|
|
||||||
:param oauth_verifier: (required) The oauth_verifier (or a.k.a PIN
|
|
||||||
for non web apps) retrieved from the callback url querystring
|
|
||||||
:rtype: dict
|
|
||||||
|
|
||||||
"""
|
|
||||||
if self.oauth_version != 1:
|
|
||||||
raise TwythonError('This method can only be called when your \
|
|
||||||
OAuth version is 1.0.')
|
|
||||||
|
|
||||||
response = self.client.get(self.access_token_url,
|
|
||||||
params={'oauth_verifier': oauth_verifier},
|
|
||||||
headers={'Content-Type': 'application/\
|
|
||||||
json'})
|
|
||||||
|
|
||||||
if response.status_code == 401:
|
|
||||||
try:
|
|
||||||
try:
|
|
||||||
# try to get json
|
|
||||||
content = response.json()
|
|
||||||
except AttributeError: # pragma: no cover
|
|
||||||
# if unicode detected
|
|
||||||
content = json.loads(response.content)
|
|
||||||
except ValueError:
|
|
||||||
content = {}
|
|
||||||
|
|
||||||
raise TwythonError(content.get('error', 'Invalid / expired To \
|
|
||||||
ken'), error_code=response.status_code)
|
|
||||||
|
|
||||||
authorized_tokens = dict(parse_qsl(response.content.decode('utf-8')))
|
|
||||||
if not authorized_tokens:
|
|
||||||
raise TwythonError('Unable to decode authorized tokens.')
|
|
||||||
|
|
||||||
return authorized_tokens # pragma: no cover
|
|
||||||
|
|
||||||
def obtain_access_token(self):
|
|
||||||
"""Returns an OAuth 2 access token to make OAuth 2 authenticated
|
|
||||||
read-only calls.
|
|
||||||
|
|
||||||
:rtype: string
|
|
||||||
"""
|
|
||||||
if self.oauth_version != 2:
|
|
||||||
raise TwythonError('This method can only be called when your \
|
|
||||||
OAuth version is 2.0.')
|
|
||||||
|
|
||||||
data = {'grant_type': 'client_credentials'}
|
|
||||||
basic_auth = HTTPBasicAuth(self.app_key, self.app_secret)
|
|
||||||
try:
|
|
||||||
response = self.client.post(self.request_token_url,
|
|
||||||
data=data, auth=basic_auth)
|
|
||||||
content = response.content.decode('utf-8')
|
|
||||||
try:
|
|
||||||
content = content.json()
|
|
||||||
except AttributeError:
|
|
||||||
content = json.loads(content)
|
|
||||||
access_token = content['access_token']
|
|
||||||
except (KeyError, ValueError, requests.exceptions.RequestException):
|
|
||||||
raise TwythonAuthError('Unable to obtain OAuth 2 access token.')
|
|
||||||
else:
|
|
||||||
return access_token
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def construct_api_url(api_url, **params):
|
|
||||||
"""Construct a Twitter API url, encoded, with parameters
|
|
||||||
|
|
||||||
:param api_url: URL of the Twitter API endpoint you are attempting
|
|
||||||
to construct
|
|
||||||
:param \*\*params: Parameters that are accepted by Twitter for the
|
|
||||||
endpoint you're requesting
|
|
||||||
:rtype: string
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
>>> from twython import Twython
|
|
||||||
>>> twitter = Twython()
|
|
||||||
|
|
||||||
>>> api_url = 'https://api.twitter.com/1.1/search/tweets.json'
|
|
||||||
>>> constructed_url = twitter.construct_api_url(api_url, q='python',
|
|
||||||
result_type='popular')
|
|
||||||
>>> print constructed_url
|
|
||||||
https://api.twitter.com/1.1/search/tweets.json?q=python&result_type=popular
|
|
||||||
|
|
||||||
"""
|
|
||||||
querystring = []
|
|
||||||
params, _ = _transparent_params(params or {})
|
|
||||||
params = requests.utils.to_key_val_list(params)
|
|
||||||
for (k, v) in params:
|
|
||||||
querystring.append(
|
|
||||||
'%s=%s' % (Twython.encode(k), quote_plus(Twython.encode(v)))
|
|
||||||
)
|
|
||||||
return '%s?%s' % (api_url, '&'.join(querystring))
|
|
||||||
|
|
||||||
def search_gen(self, search_query, **params): # pragma: no cover
|
|
||||||
warnings.warn(
|
|
||||||
'This method is deprecated. You should use Twython.cursor instead. \
|
|
||||||
[eg. Twython.cursor(Twython.search, q=\'your_query\')]',
|
|
||||||
TwythonDeprecationWarning,
|
|
||||||
stacklevel=2
|
|
||||||
)
|
|
||||||
return self.cursor(self.search, q=search_query, **params)
|
|
||||||
|
|
||||||
def cursor(self, function, return_pages=False, **params):
|
|
||||||
"""Returns a generator for results that match a specified query.
|
|
||||||
|
|
||||||
:param function: Instance of a Twython function
|
|
||||||
(Twython.get_home_timeline, Twython.search)
|
|
||||||
:param \*\*params: Extra parameters to send with your request
|
|
||||||
(usually parameters accepted by the Twitter API endpoint)
|
|
||||||
:rtype: generator
|
|
||||||
|
|
||||||
Usage::
|
|
||||||
|
|
||||||
>>> from twython import Twython
|
|
||||||
>>> twitter = Twython(APP_KEY, APP_SECRET, OAUTH_TOKEN,
|
|
||||||
OAUTH_TOKEN_SECRET)
|
|
||||||
|
|
||||||
>>> results = twitter.cursor(twitter.search, q='python')
|
|
||||||
>>> for result in results:
|
|
||||||
>>> print result
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not callable(function):
|
|
||||||
raise TypeError('.cursor() takes a Twython function as its first \
|
|
||||||
argument. Did you provide the result of a \
|
|
||||||
function call?')
|
|
||||||
|
|
||||||
if not hasattr(function, 'iter_mode'):
|
|
||||||
raise TwythonError('Unable to create generator for Twython \
|
|
||||||
method "%s"' % function.__name__)
|
|
||||||
|
|
||||||
while True:
|
|
||||||
content = function(**params)
|
|
||||||
|
|
||||||
if not content:
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
if hasattr(function, 'iter_key'):
|
|
||||||
results = content.get(function.iter_key)
|
|
||||||
else:
|
|
||||||
results = content
|
|
||||||
|
|
||||||
if return_pages:
|
|
||||||
yield results
|
|
||||||
else:
|
|
||||||
for result in results:
|
|
||||||
yield result
|
|
||||||
|
|
||||||
if function.iter_mode == 'cursor' and \
|
|
||||||
content['next_cursor_str'] == '0':
|
|
||||||
raise StopIteration
|
|
||||||
|
|
||||||
try:
|
|
||||||
if function.iter_mode == 'id':
|
|
||||||
if 'max_id' not in params:
|
|
||||||
# Add 1 to the id because since_id and
|
|
||||||
# max_id are inclusive
|
|
||||||
if hasattr(function, 'iter_metadata'):
|
|
||||||
since_id = content[function.iter_metadata].get('since_id_str')
|
|
||||||
else:
|
|
||||||
since_id = content[0]['id_str']
|
|
||||||
params['since_id'] = (int(since_id) - 1)
|
|
||||||
elif function.iter_mode == 'cursor':
|
|
||||||
params['cursor'] = content['next_cursor_str']
|
|
||||||
except (TypeError, ValueError): # pragma: no cover
|
|
||||||
raise TwythonError('Unable to generate next page of search \
|
|
||||||
results, `page` is not a number.')
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def unicode2utf8(text):
|
|
||||||
try:
|
|
||||||
if is_py2 and isinstance(text, str):
|
|
||||||
text = text.encode('utf-8')
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
return text
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def encode(text):
|
|
||||||
if is_py2 and isinstance(text, (str)):
|
|
||||||
return Twython.unicode2utf8(text)
|
|
||||||
return str(text)
|
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def html_for_tweet(tweet, use_display_url=True, use_expanded_url=False, expand_quoted_status=False):
|
|
||||||
"""Return HTML for a tweet (urls, mentions, hashtags, symbols replaced with links)
|
|
||||||
|
|
||||||
:param tweet: Tweet object from received from Twitter API
|
|
||||||
:param use_display_url: Use display URL to represent link
|
|
||||||
(ex. google.com, github.com). Default: True
|
|
||||||
:param use_expanded_url: Use expanded URL to represent link
|
|
||||||
(e.g. http://google.com). Default False
|
|
||||||
|
|
||||||
If use_expanded_url is True, it overrides use_display_url.
|
|
||||||
If use_display_url and use_expanded_url is False, short url will
|
|
||||||
be used (t.co/xxxxx)
|
|
||||||
|
|
||||||
"""
|
|
||||||
if 'retweeted_status' in tweet:
|
|
||||||
tweet = tweet['retweeted_status']
|
|
||||||
|
|
||||||
if 'extended_tweet' in tweet:
|
|
||||||
tweet = tweet['extended_tweet']
|
|
||||||
|
|
||||||
orig_tweet_text = tweet.get('full_text') or tweet['text']
|
|
||||||
|
|
||||||
display_text_range = tweet.get('display_text_range') or [0, len(orig_tweet_text)]
|
|
||||||
display_text_start, display_text_end = display_text_range[0], display_text_range[1]
|
|
||||||
display_text = orig_tweet_text[display_text_start:display_text_end]
|
|
||||||
prefix_text = orig_tweet_text[0:display_text_start]
|
|
||||||
suffix_text = orig_tweet_text[display_text_end:len(orig_tweet_text)]
|
|
||||||
|
|
||||||
if 'entities' in tweet:
|
|
||||||
# We'll put all the bits of replacement HTML and their starts/ends
|
|
||||||
# in this list:
|
|
||||||
entities = []
|
|
||||||
|
|
||||||
# Mentions
|
|
||||||
if 'user_mentions' in tweet['entities']:
|
|
||||||
for entity in tweet['entities']['user_mentions']:
|
|
||||||
temp = {}
|
|
||||||
temp['start'] = entity['indices'][0]
|
|
||||||
temp['end'] = entity['indices'][1]
|
|
||||||
|
|
||||||
mention_html = '<a href="https://twitter.com/%(screen_name)s" class="twython-mention">@%(screen_name)s</a>' % {'screen_name': entity['screen_name']}
|
|
||||||
|
|
||||||
if display_text_start <= temp['start'] <= display_text_end:
|
|
||||||
temp['replacement'] = mention_html
|
|
||||||
entities.append(temp)
|
|
||||||
else:
|
|
||||||
# Make the '@username' at the start, before
|
|
||||||
# display_text, into a link:
|
|
||||||
sub_expr = r'(?<!>)' + orig_tweet_text[temp['start']:temp['end']] + '(?!</a>)'
|
|
||||||
prefix_text = re.sub(sub_expr, mention_html, prefix_text)
|
|
||||||
|
|
||||||
# Hashtags
|
|
||||||
if 'hashtags' in tweet['entities']:
|
|
||||||
for entity in tweet['entities']['hashtags']:
|
|
||||||
temp = {}
|
|
||||||
temp['start'] = entity['indices'][0]
|
|
||||||
temp['end'] = entity['indices'][1]
|
|
||||||
|
|
||||||
url_html = '<a href="https://twitter.com/search?q=%%23%(hashtag)s" class="twython-hashtag">#%(hashtag)s</a>' % {'hashtag': entity['text']}
|
|
||||||
|
|
||||||
temp['replacement'] = url_html
|
|
||||||
entities.append(temp)
|
|
||||||
|
|
||||||
# Symbols
|
|
||||||
if 'symbols' in tweet['entities']:
|
|
||||||
for entity in tweet['entities']['symbols']:
|
|
||||||
temp = {}
|
|
||||||
temp['start'] = entity['indices'][0]
|
|
||||||
temp['end'] = entity['indices'][1]
|
|
||||||
|
|
||||||
url_html = '<a href="https://twitter.com/search?q=%%24%(symbol)s" class="twython-symbol">$%(symbol)s</a>' % {'symbol': entity['text']}
|
|
||||||
|
|
||||||
temp['replacement'] = url_html
|
|
||||||
entities.append(temp)
|
|
||||||
|
|
||||||
# URLs
|
|
||||||
if 'urls' in tweet['entities']:
|
|
||||||
for entity in tweet['entities']['urls']:
|
|
||||||
temp = {}
|
|
||||||
temp['start'] = entity['indices'][0]
|
|
||||||
temp['end'] = entity['indices'][1]
|
|
||||||
|
|
||||||
if use_display_url and entity.get('display_url') and not use_expanded_url:
|
|
||||||
shown_url = entity['display_url']
|
|
||||||
elif use_expanded_url and entity.get('expanded_url'):
|
|
||||||
shown_url = entity['expanded_url']
|
|
||||||
else:
|
|
||||||
shown_url = entity['url']
|
|
||||||
|
|
||||||
url_html = '<a href="%s" class="twython-url">%s</a>' % (entity['url'], shown_url)
|
|
||||||
|
|
||||||
if display_text_start <= temp['start'] <= display_text_end:
|
|
||||||
temp['replacement'] = url_html
|
|
||||||
entities.append(temp)
|
|
||||||
else:
|
|
||||||
suffix_text = suffix_text.replace(orig_tweet_text[temp['start']:temp['end']], url_html)
|
|
||||||
|
|
||||||
if 'media' in tweet['entities']:
|
|
||||||
for entity in tweet['entities']['media']:
|
|
||||||
temp = {}
|
|
||||||
temp['start'] = entity['indices'][0]
|
|
||||||
temp['end'] = entity['indices'][1]
|
|
||||||
|
|
||||||
if use_display_url and entity.get('display_url') and not use_expanded_url:
|
|
||||||
shown_url = entity['display_url']
|
|
||||||
elif use_expanded_url and entity.get('expanded_url'):
|
|
||||||
shown_url = entity['expanded_url']
|
|
||||||
else:
|
|
||||||
shown_url = entity['url']
|
|
||||||
|
|
||||||
url_html = '<a href="%s" class="twython-media">%s</a>' % (entity['url'], shown_url)
|
|
||||||
|
|
||||||
if display_text_start <= temp['start'] <= display_text_end:
|
|
||||||
temp['replacement'] = url_html
|
|
||||||
entities.append(temp)
|
|
||||||
else:
|
|
||||||
suffix_text = suffix_text.replace(orig_tweet_text[temp['start']:temp['end']], url_html)
|
|
||||||
|
|
||||||
# Now do all the replacements, starting from the end, so that the
|
|
||||||
# start/end indices still work:
|
|
||||||
for entity in sorted(entities, key=lambda e: e['start'], reverse=True):
|
|
||||||
display_text = display_text[0:entity['start']] + entity['replacement'] + display_text[entity['end']:]
|
|
||||||
|
|
||||||
quote_text = ''
|
|
||||||
if expand_quoted_status and tweet.get('is_quote_status') and tweet.get('quoted_status'):
|
|
||||||
quoted_status = tweet['quoted_status']
|
|
||||||
quote_text += '<blockquote class="twython-quote">%(quote)s<cite><a href="%(quote_tweet_link)s">' \
|
|
||||||
'<span class="twython-quote-user-name">%(quote_user_name)s</span>' \
|
|
||||||
'<span class="twython-quote-user-screenname">@%(quote_user_screen_name)s</span></a>' \
|
|
||||||
'</cite></blockquote>' % \
|
|
||||||
{'quote': Twython.html_for_tweet(quoted_status, use_display_url, use_expanded_url, False),
|
|
||||||
'quote_tweet_link': 'https://twitter.com/%s/status/%s' %
|
|
||||||
(quoted_status['user']['screen_name'], quoted_status['id_str']),
|
|
||||||
'quote_user_name': quoted_status['user']['name'],
|
|
||||||
'quote_user_screen_name': quoted_status['user']['screen_name']}
|
|
||||||
|
|
||||||
return '%(prefix)s%(display)s%(suffix)s%(quote)s' % {
|
|
||||||
'prefix': '<span class="twython-tweet-prefix">%s</span>' % prefix_text if prefix_text else '',
|
|
||||||
'display': display_text,
|
|
||||||
'suffix': '<span class="twython-tweet-suffix">%s</span>' % suffix_text if suffix_text else '',
|
|
||||||
'quote': quote_text
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.compat
|
|
||||||
~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains imports and declarations for seamless Python 2 and
|
|
||||||
Python 3 compatibility.
|
|
||||||
"""
|
|
||||||
|
|
||||||
import sys
|
|
||||||
|
|
||||||
_ver = sys.version_info
|
|
||||||
|
|
||||||
#: Python 2.x?
|
|
||||||
is_py2 = (_ver[0] == 2)
|
|
||||||
|
|
||||||
#: Python 3.x?
|
|
||||||
is_py3 = (_ver[0] == 3)
|
|
||||||
|
|
||||||
try:
|
|
||||||
import simplejson as json
|
|
||||||
except ImportError:
|
|
||||||
import json
|
|
||||||
|
|
||||||
if is_py2:
|
|
||||||
from urllib import urlencode, quote_plus
|
|
||||||
from urlparse import parse_qsl
|
|
||||||
|
|
||||||
str = unicode
|
|
||||||
basestring = basestring
|
|
||||||
numeric_types = (int, long, float)
|
|
||||||
|
|
||||||
|
|
||||||
elif is_py3:
|
|
||||||
from urllib.parse import urlencode, quote_plus, parse_qsl
|
|
||||||
|
|
||||||
str = str
|
|
||||||
basestring = (str, bytes)
|
|
||||||
numeric_types = (int, float)
|
|
File diff suppressed because it is too large
Load Diff
@ -1,61 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.exceptions
|
|
||||||
~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains Twython specific Exception classes.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .endpoints import TWITTER_HTTP_STATUS_CODE
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonError(Exception):
|
|
||||||
"""Generic error class, catch-all for most Twython issues.
|
|
||||||
Special cases are handled by TwythonAuthError & TwythonRateLimitError.
|
|
||||||
|
|
||||||
from twython import TwythonError, TwythonRateLimitError, TwythonAuthError
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, msg, error_code=None, retry_after=None):
|
|
||||||
self.error_code = error_code
|
|
||||||
|
|
||||||
if error_code is not None and error_code in TWITTER_HTTP_STATUS_CODE:
|
|
||||||
msg = 'Twitter API returned a %s (%s), %s' % \
|
|
||||||
(error_code,
|
|
||||||
TWITTER_HTTP_STATUS_CODE[error_code][0],
|
|
||||||
msg)
|
|
||||||
|
|
||||||
super(TwythonError, self).__init__(msg)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def msg(self): # pragma: no cover
|
|
||||||
return self.args[0]
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonAuthError(TwythonError):
|
|
||||||
"""Raised when you try to access a protected resource and it fails due to
|
|
||||||
some issue with your authentication.
|
|
||||||
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonRateLimitError(TwythonError): # pragma: no cover
|
|
||||||
"""Raised when you've hit a rate limit.
|
|
||||||
|
|
||||||
The amount of seconds to retry your request in will be appended
|
|
||||||
to the message.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, msg, error_code, retry_after=None):
|
|
||||||
if isinstance(retry_after, int):
|
|
||||||
msg = '%s (Retry after %d seconds)' % (msg, retry_after)
|
|
||||||
TwythonError.__init__(self, msg, error_code=error_code)
|
|
||||||
|
|
||||||
self.retry_after = retry_after
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonStreamError(TwythonError):
|
|
||||||
"""Raised when an invalid response from the Stream API is received"""
|
|
||||||
pass
|
|
@ -1,34 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.helpers
|
|
||||||
~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains functions that are repeatedly used throughout
|
|
||||||
the Twython library.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .compat import basestring, numeric_types
|
|
||||||
|
|
||||||
|
|
||||||
def _transparent_params(_params):
|
|
||||||
params = {}
|
|
||||||
files = {}
|
|
||||||
for k, v in _params.items():
|
|
||||||
if hasattr(v, 'read') and callable(v.read):
|
|
||||||
files[k] = v # pragma: no cover
|
|
||||||
elif isinstance(v, bool):
|
|
||||||
if v:
|
|
||||||
params[k] = 'true'
|
|
||||||
else:
|
|
||||||
params[k] = 'false'
|
|
||||||
elif isinstance(v, basestring) or isinstance(v, numeric_types):
|
|
||||||
params[k] = v
|
|
||||||
elif isinstance(v, list):
|
|
||||||
try:
|
|
||||||
params[k] = ','.join(v)
|
|
||||||
except TypeError:
|
|
||||||
params[k] = ','.join(map(str, v))
|
|
||||||
else:
|
|
||||||
continue # pragma: no cover
|
|
||||||
return params, files
|
|
@ -1 +0,0 @@
|
|||||||
from .api import TwythonStreamer
|
|
@ -1,201 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.streaming.api
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains functionality for interfacing with streaming
|
|
||||||
Twitter API calls.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from .. import __version__
|
|
||||||
from ..compat import json, is_py3
|
|
||||||
from ..helpers import _transparent_params
|
|
||||||
from .types import TwythonStreamerTypes
|
|
||||||
|
|
||||||
import requests
|
|
||||||
from requests_oauthlib import OAuth1
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonStreamer(object):
|
|
||||||
def __init__(self, app_key, app_secret, oauth_token, oauth_token_secret,
|
|
||||||
timeout=300, retry_count=None, retry_in=10, client_args=None,
|
|
||||||
handlers=None, chunk_size=1):
|
|
||||||
"""Streaming class for a friendly streaming user experience
|
|
||||||
Authentication IS required to use the Twitter Streaming API
|
|
||||||
|
|
||||||
:param app_key: (required) Your applications key
|
|
||||||
:param app_secret: (required) Your applications secret key
|
|
||||||
:param oauth_token: (required) Used with oauth_token_secret to make
|
|
||||||
authenticated calls
|
|
||||||
:param oauth_token_secret: (required) Used with oauth_token to make
|
|
||||||
authenticated calls
|
|
||||||
:param timeout: (optional) How long (in secs) the streamer should wait
|
|
||||||
for a response from Twitter Streaming API
|
|
||||||
:param retry_count: (optional) Number of times the API call should be
|
|
||||||
retired
|
|
||||||
:param retry_in: (optional) Amount of time (in secs) the previous
|
|
||||||
API call should be tried again
|
|
||||||
:param client_args: (optional) Accepts some requests Session
|
|
||||||
parameters and some requests Request parameters.
|
|
||||||
See
|
|
||||||
http://docs.python-requests.org/en/latest/api/#sessionapi
|
|
||||||
and requests section below it for details.
|
|
||||||
[ex. headers, proxies, verify(SSL verification)]
|
|
||||||
:param handlers: (optional) Array of message types for which
|
|
||||||
corresponding handlers will be called
|
|
||||||
|
|
||||||
:param chunk_size: (optional) Define the buffer size before data is
|
|
||||||
actually returned from the Streaming API. Default: 1
|
|
||||||
"""
|
|
||||||
|
|
||||||
self.auth = OAuth1(app_key, app_secret,
|
|
||||||
oauth_token, oauth_token_secret)
|
|
||||||
|
|
||||||
self.client_args = client_args or {}
|
|
||||||
default_headers = {'User-Agent': 'Twython Streaming v' + __version__}
|
|
||||||
if 'headers' not in self.client_args:
|
|
||||||
# If they didn't set any headers, set our defaults for them
|
|
||||||
self.client_args['headers'] = default_headers
|
|
||||||
elif 'User-Agent' not in self.client_args['headers']:
|
|
||||||
# If they set headers, but didn't include User-Agent..
|
|
||||||
# set it for them
|
|
||||||
self.client_args['headers'].update(default_headers)
|
|
||||||
self.client_args['timeout'] = timeout
|
|
||||||
|
|
||||||
self.client = requests.Session()
|
|
||||||
self.client.auth = self.auth
|
|
||||||
self.client.stream = True
|
|
||||||
|
|
||||||
# Make a copy of the client args and iterate over them
|
|
||||||
# Pop out all the acceptable args at this point because they will
|
|
||||||
# Never be used again.
|
|
||||||
client_args_copy = self.client_args.copy()
|
|
||||||
for k, v in client_args_copy.items():
|
|
||||||
if k in ('cert', 'headers', 'hooks', 'max_redirects', 'proxies'):
|
|
||||||
setattr(self.client, k, v)
|
|
||||||
self.client_args.pop(k) # Pop, pop!
|
|
||||||
|
|
||||||
self.api_version = '1.1'
|
|
||||||
|
|
||||||
self.retry_in = retry_in
|
|
||||||
self.retry_count = retry_count
|
|
||||||
|
|
||||||
# Set up type methods
|
|
||||||
StreamTypes = TwythonStreamerTypes(self)
|
|
||||||
self.statuses = StreamTypes.statuses
|
|
||||||
self.user = StreamTypes.user
|
|
||||||
self.site = StreamTypes.site
|
|
||||||
|
|
||||||
self.connected = False
|
|
||||||
|
|
||||||
self.handlers = handlers if handlers else \
|
|
||||||
['delete', 'limit', 'disconnect']
|
|
||||||
|
|
||||||
self.chunk_size = chunk_size
|
|
||||||
|
|
||||||
def _request(self, url, method='GET', params=None):
|
|
||||||
"""Internal stream request handling"""
|
|
||||||
self.connected = True
|
|
||||||
retry_counter = 0
|
|
||||||
|
|
||||||
method = method.lower()
|
|
||||||
func = getattr(self.client, method)
|
|
||||||
params, _ = _transparent_params(params)
|
|
||||||
|
|
||||||
def _send(retry_counter):
|
|
||||||
requests_args = {}
|
|
||||||
for k, v in self.client_args.items():
|
|
||||||
# Maybe this should be set as a class
|
|
||||||
# variable and only done once?
|
|
||||||
if k in ('timeout', 'allow_redirects', 'verify'):
|
|
||||||
requests_args[k] = v
|
|
||||||
|
|
||||||
while self.connected:
|
|
||||||
try:
|
|
||||||
if method == 'get':
|
|
||||||
requests_args['params'] = params
|
|
||||||
else:
|
|
||||||
requests_args['data'] = params
|
|
||||||
|
|
||||||
response = func(url, **requests_args)
|
|
||||||
except requests.exceptions.Timeout:
|
|
||||||
self.on_timeout()
|
|
||||||
else:
|
|
||||||
if response.status_code != 200:
|
|
||||||
self.on_error(response.status_code, response.content)
|
|
||||||
|
|
||||||
if self.retry_count and \
|
|
||||||
(self.retry_count - retry_counter) > 0:
|
|
||||||
time.sleep(self.retry_in)
|
|
||||||
retry_counter += 1
|
|
||||||
_send(retry_counter)
|
|
||||||
|
|
||||||
return response
|
|
||||||
|
|
||||||
while self.connected:
|
|
||||||
response = _send(retry_counter)
|
|
||||||
|
|
||||||
for line in response.iter_lines(self.chunk_size):
|
|
||||||
if not self.connected:
|
|
||||||
break
|
|
||||||
if line:
|
|
||||||
try:
|
|
||||||
if is_py3:
|
|
||||||
line = line.decode('utf-8')
|
|
||||||
data = json.loads(line)
|
|
||||||
except ValueError: # pragma: no cover
|
|
||||||
self.on_error(response.status_code,
|
|
||||||
'Unable to decode response, \
|
|
||||||
not valid JSON.')
|
|
||||||
else:
|
|
||||||
if self.on_success(data): # pragma: no cover
|
|
||||||
for message_type in self.handlers:
|
|
||||||
if message_type in data:
|
|
||||||
handler = getattr(self,
|
|
||||||
'on_' + message_type,
|
|
||||||
None)
|
|
||||||
if handler \
|
|
||||||
and callable(handler) \
|
|
||||||
and not handler(data.get(message_type)):
|
|
||||||
break
|
|
||||||
|
|
||||||
response.close()
|
|
||||||
|
|
||||||
def on_success(self, data): # pragma: no cover
|
|
||||||
"""Called when data has been successfully received from the stream.
|
|
||||||
Returns True if other handlers for this message should be invoked.
|
|
||||||
|
|
||||||
Feel free to override this to handle your streaming data how you
|
|
||||||
want it handled.
|
|
||||||
See https://dev.twitter.com/docs/streaming-apis/messages for messages
|
|
||||||
sent along in stream responses.
|
|
||||||
|
|
||||||
:param data: data recieved from the stream
|
|
||||||
:type data: dict
|
|
||||||
"""
|
|
||||||
return True
|
|
||||||
|
|
||||||
def on_error(self, status_code, data): # pragma: no cover
|
|
||||||
"""Called when stream returns non-200 status code
|
|
||||||
|
|
||||||
Feel free to override this to handle your streaming data how you
|
|
||||||
want it handled.
|
|
||||||
|
|
||||||
:param status_code: Non-200 status code sent from stream
|
|
||||||
:type status_code: int
|
|
||||||
|
|
||||||
:param data: Error message sent from stream
|
|
||||||
:type data: dict
|
|
||||||
"""
|
|
||||||
return
|
|
||||||
|
|
||||||
def on_timeout(self): # pragma: no cover
|
|
||||||
""" Called when the request has timed out """
|
|
||||||
return
|
|
||||||
|
|
||||||
def disconnect(self):
|
|
||||||
"""Used to disconnect the streaming client manually"""
|
|
||||||
self.connected = False
|
|
@ -1,107 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
"""
|
|
||||||
twython.streaming.types
|
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
This module contains classes and methods for :class:`TwythonStreamer` to use.
|
|
||||||
"""
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonStreamerTypes(object):
|
|
||||||
"""Class for different stream endpoints
|
|
||||||
|
|
||||||
Not all streaming endpoints have nested endpoints.
|
|
||||||
User Streams and Site Streams are single streams with no nested endpoints
|
|
||||||
Status Streams include filter, sample and firehose endpoints
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, streamer):
|
|
||||||
self.streamer = streamer
|
|
||||||
self.statuses = TwythonStreamerTypesStatuses(streamer)
|
|
||||||
|
|
||||||
def user(self, **params):
|
|
||||||
"""Stream user
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/get/user
|
|
||||||
"""
|
|
||||||
url = 'https://userstream.twitter.com/%s/user.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, params=params)
|
|
||||||
|
|
||||||
def site(self, **params):
|
|
||||||
"""Stream site
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/get/site
|
|
||||||
"""
|
|
||||||
url = 'https://sitestream.twitter.com/%s/site.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, params=params)
|
|
||||||
|
|
||||||
|
|
||||||
class TwythonStreamerTypesStatuses(object):
|
|
||||||
"""Class for different statuses endpoints
|
|
||||||
|
|
||||||
Available so TwythonStreamer.statuses.filter() is available.
|
|
||||||
Just a bit cleaner than TwythonStreamer.statuses_filter(),
|
|
||||||
statuses_sample(), etc. all being single methods in TwythonStreamer
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, streamer):
|
|
||||||
self.streamer = streamer
|
|
||||||
self.params = None
|
|
||||||
|
|
||||||
def filter(self, **params):
|
|
||||||
"""Stream statuses/filter
|
|
||||||
|
|
||||||
:param \*\*params: Parameters to send with your stream request
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/post/statuses/filter
|
|
||||||
"""
|
|
||||||
url = 'https://stream.twitter.com/%s/statuses/filter.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, 'POST', params=params)
|
|
||||||
|
|
||||||
def sample(self, **params):
|
|
||||||
"""Stream statuses/sample
|
|
||||||
|
|
||||||
:param \*\*params: Parameters to send with your stream request
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/get/statuses/sample
|
|
||||||
"""
|
|
||||||
url = 'https://stream.twitter.com/%s/statuses/sample.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, params=params)
|
|
||||||
|
|
||||||
def firehose(self, **params):
|
|
||||||
"""Stream statuses/firehose
|
|
||||||
|
|
||||||
:param \*\*params: Parameters to send with your stream request
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/get/statuses/firehose
|
|
||||||
"""
|
|
||||||
url = 'https://stream.twitter.com/%s/statuses/firehose.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, params=params)
|
|
||||||
|
|
||||||
def set_dynamic_filter(self, **params):
|
|
||||||
"""Set/update statuses/filter
|
|
||||||
|
|
||||||
:param \*\*params: Parameters to send with your stream request
|
|
||||||
|
|
||||||
Accepted params found at:
|
|
||||||
https://dev.twitter.com/docs/api/1.1/post/statuses/filter
|
|
||||||
"""
|
|
||||||
self.params = params
|
|
||||||
|
|
||||||
def dynamic_filter(self):
|
|
||||||
"""Stream statuses/filter with dynamic parameters"""
|
|
||||||
|
|
||||||
url = 'https://stream.twitter.com/%s/statuses/filter.json' \
|
|
||||||
% self.streamer.api_version
|
|
||||||
self.streamer._request(url, 'POST', params=self.params)
|
|
@ -1,11 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import application
|
import application
|
||||||
import update
|
from . import update
|
||||||
import platform
|
import platform
|
||||||
import logging
|
import logging
|
||||||
import output
|
import output
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError
|
||||||
from wxUpdater import *
|
from .wxUpdater import *
|
||||||
logger = logging.getLogger("updater")
|
logger = logging.getLogger("updater")
|
||||||
|
|
||||||
def do_update(endpoint=application.update_url):
|
def do_update(endpoint=application.update_url):
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
import application
|
import application
|
||||||
import utils
|
from . import utils
|
||||||
|
|
||||||
progress_dialog = None
|
progress_dialog = None
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
from __future__ import absolute_import
|
||||||
import platform
|
import platform
|
||||||
if platform.system() == "Windows":
|
if platform.system() == "Windows":
|
||||||
from wxUtils import *
|
from .wxUtils import *
|
||||||
#elif platform.system() == "Linux":
|
#elif platform.system() == "Linux":
|
||||||
# from gtkUtils import *
|
# from gtkUtils import *
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
from base import basePanel
|
from __future__ import absolute_import
|
||||||
from dm import dmPanel
|
from .base import basePanel
|
||||||
from events import eventsPanel
|
from .dm import dmPanel
|
||||||
from favourites import favsPanel
|
from .events import eventsPanel
|
||||||
from lists import listPanel
|
from .favourites import favsPanel
|
||||||
from panels import accountPanel, emptyPanel
|
from .lists import listPanel
|
||||||
from people import peoplePanel
|
from .panels import accountPanel, emptyPanel
|
||||||
from trends import trendsPanel
|
from .people import peoplePanel
|
||||||
from tweet_searches import searchPanel
|
from .trends import trendsPanel
|
||||||
from user_searches import searchUsersPanel
|
from .tweet_searches import searchPanel
|
||||||
|
from .user_searches import searchUsersPanel
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from base import basePanel
|
from .base import basePanel
|
||||||
|
|
||||||
class dmPanel(basePanel):
|
class dmPanel(basePanel):
|
||||||
def __init__(self, parent, name):
|
def __init__(self, parent, name):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from base import basePanel
|
from .base import basePanel
|
||||||
|
|
||||||
class favsPanel(basePanel):
|
class favsPanel(basePanel):
|
||||||
def __init__(self, parent, name):
|
def __init__(self, parent, name):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from base import basePanel
|
from .base import basePanel
|
||||||
|
|
||||||
class listPanel(basePanel):
|
class listPanel(basePanel):
|
||||||
def __init__(self, parent, name):
|
def __init__(self, parent, name):
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from multiplatform_widgets import widgets
|
from multiplatform_widgets import widgets
|
||||||
from base import basePanel
|
from .base import basePanel
|
||||||
|
|
||||||
class peoplePanel(basePanel):
|
class peoplePanel(basePanel):
|
||||||
""" Buffer used to show people."""
|
""" Buffer used to show people."""
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from base import basePanel
|
from .base import basePanel
|
||||||
|
|
||||||
class searchPanel(basePanel):
|
class searchPanel(basePanel):
|
||||||
def __init__(self, parent, name):
|
def __init__(self, parent, name):
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import wx
|
import wx
|
||||||
from tweet_searches import searchPanel
|
from .tweet_searches import searchPanel
|
||||||
from multiplatform_widgets import widgets
|
from multiplatform_widgets import widgets
|
||||||
|
|
||||||
class searchUsersPanel(searchPanel):
|
class searchUsersPanel(searchPanel):
|
||||||
|
@ -1 +1,2 @@
|
|||||||
import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils, filterDialogs
|
from __future__ import absolute_import
|
||||||
|
from . import baseDialog, trends, configuration, lists, message, search, find, show_user, update_profile, urlList, userSelection, utils, filterDialogs
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from __future__ import absolute_import
|
||||||
import logging as original_logger
|
import logging as original_logger
|
||||||
import wx
|
import wx
|
||||||
import application
|
import application
|
||||||
import output
|
import output
|
||||||
import config
|
import config
|
||||||
import baseDialog
|
import widgetUtils
|
||||||
|
from . import baseDialog
|
||||||
from multiplatform_widgets import widgets
|
from multiplatform_widgets import widgets
|
||||||
|
|
||||||
class general(wx.Panel, baseDialog.BaseWXDialog):
|
class general(wx.Panel, baseDialog.BaseWXDialog):
|
||||||
@ -268,6 +270,9 @@ class sound(wx.Panel):
|
|||||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||||
volume = wx.StaticText(self, -1, _(u"Volume"))
|
volume = wx.StaticText(self, -1, _(u"Volume"))
|
||||||
self.volumeCtrl = wx.Slider(self)
|
self.volumeCtrl = wx.Slider(self)
|
||||||
|
# Connect a key handler here to handle volume slider being inverted when moving with up and down arrows.
|
||||||
|
# see https://github.com/manuelcortez/TWBlue/issues/261
|
||||||
|
widgetUtils.connect_event(self.volumeCtrl, widgetUtils.KEYPRESS, self.on_keypress)
|
||||||
self.volumeCtrl.SetRange(0, 100)
|
self.volumeCtrl.SetRange(0, 100)
|
||||||
self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize())
|
self.volumeCtrl.SetSize(self.volumeCtrl.GetBestSize())
|
||||||
volumeBox = wx.BoxSizer(wx.HORIZONTAL)
|
volumeBox = wx.BoxSizer(wx.HORIZONTAL)
|
||||||
@ -305,6 +310,18 @@ class sound(wx.Panel):
|
|||||||
sizer.Add(self.indicate_img, 0, wx.ALL, 5)
|
sizer.Add(self.indicate_img, 0, wx.ALL, 5)
|
||||||
self.SetSizer(sizer)
|
self.SetSizer(sizer)
|
||||||
|
|
||||||
|
def on_keypress(self, event, *args, **kwargs):
|
||||||
|
""" Invert movement of up and down arrow keys when dealing with a wX Slider.
|
||||||
|
See https://github.com/manuelcortez/TWBlue/issues/261
|
||||||
|
and http://trac.wxwidgets.org/ticket/2068
|
||||||
|
"""
|
||||||
|
keycode = event.GetKeyCode()
|
||||||
|
if keycode == wx.WXK_UP:
|
||||||
|
return self.volumeCtrl.SetValue(self.volumeCtrl.GetValue()+1)
|
||||||
|
elif keycode == wx.WXK_DOWN:
|
||||||
|
return self.volumeCtrl.SetValue(self.volumeCtrl.GetValue()-1)
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
def get(self, control):
|
def get(self, control):
|
||||||
return getattr(self, control).GetStringSelection()
|
return getattr(self, control).GetStringSelection()
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import baseDialog
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import baseDialog
|
||||||
import wx
|
import wx
|
||||||
import widgetUtils
|
import widgetUtils
|
||||||
from multiplatform_widgets import widgets
|
from multiplatform_widgets import widgets
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
import baseDialog
|
from __future__ import absolute_import
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from . import baseDialog
|
||||||
import wx
|
import wx
|
||||||
|
|
||||||
class findDialog(baseDialog.BaseWXDialog):
|
class findDialog(baseDialog.BaseWXDialog):
|
||||||
|
@ -113,6 +113,13 @@ class addUserListDialog(listViewer):
|
|||||||
# self.subscriptors.Disable()
|
# self.subscriptors.Disable()
|
||||||
# self.members.Disable()
|
# self.members.Disable()
|
||||||
self.deleteBtn.Disable()
|
self.deleteBtn.Disable()
|
||||||
|
widgetUtils.connect_event(self.lista.list, widgetUtils.KEYPRESS, self.on_keypress)
|
||||||
|
|
||||||
|
def on_keypress(self, event):
|
||||||
|
"""Catch return and execute ok()"""
|
||||||
|
if event.GetKeyCode() == wx.WXK_RETURN:
|
||||||
|
return self.ok()
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
def ok(self, *args, **kwargs):
|
def ok(self, *args, **kwargs):
|
||||||
self.EndModal(wx.ID_OK)
|
self.EndModal(wx.ID_OK)
|
||||||
@ -129,6 +136,13 @@ class removeUserListDialog(listViewer):
|
|||||||
# self.subscriptors.Disable()
|
# self.subscriptors.Disable()
|
||||||
# self.members.Disable()
|
# self.members.Disable()
|
||||||
self.deleteBtn.Disable()
|
self.deleteBtn.Disable()
|
||||||
|
widgetUtils.connect_event(self.lista.list, widgetUtils.KEYPRESS, self.on_keypress)
|
||||||
|
|
||||||
|
def on_keypress(self, event):
|
||||||
|
"""Catch return and execute EndModal()"""
|
||||||
|
if event.GetKeyCode() == wx.WXK_RETURN:
|
||||||
|
return self.EndModal(wx.ID_OK)
|
||||||
|
event.Skip()
|
||||||
|
|
||||||
def remove_list():
|
def remove_list():
|
||||||
return wx.MessageDialog(None, _("Do you really want to delete this list?"), _("Delete"), wx.YES_NO).ShowModal()
|
return wx.MessageDialog(None, _("Do you really want to delete this list?"), _("Delete"), wx.YES_NO).ShowModal()
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user